meshy-node 0.0.8 → 0.1.1

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
@@ -1460,8 +1460,8 @@ var require_node = __commonJS({
1460
1460
  }
1461
1461
  break;
1462
1462
  case "FILE":
1463
- var fs17 = require("fs");
1464
- stream2 = new fs17.SyncWriteStream(fd2, { autoClose: false });
1463
+ var fs16 = require("fs");
1464
+ stream2 = new fs16.SyncWriteStream(fd2, { autoClose: false });
1465
1465
  stream2._type = "fs";
1466
1466
  break;
1467
1467
  case "PIPE":
@@ -14251,11 +14251,11 @@ var require_mime_types = __commonJS({
14251
14251
  }
14252
14252
  return exts[0];
14253
14253
  }
14254
- function lookup(path17) {
14255
- if (!path17 || typeof path17 !== "string") {
14254
+ function lookup(path16) {
14255
+ if (!path16 || typeof path16 !== "string") {
14256
14256
  return false;
14257
14257
  }
14258
- var extension2 = extname3("x." + path17).toLowerCase().substr(1);
14258
+ var extension2 = extname3("x." + path16).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(path17, keys, options) {
17776
+ function pathToRegexp(path16, 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 (path17 instanceof RegExp) {
17791
- while (m = MATCHING_GROUP_REGEXP.exec(path17.source)) {
17790
+ if (path16 instanceof RegExp) {
17791
+ while (m = MATCHING_GROUP_REGEXP.exec(path16.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 path17;
17799
+ return path16;
17800
17800
  }
17801
- if (Array.isArray(path17)) {
17802
- path17 = path17.map(function(value) {
17801
+ if (Array.isArray(path16)) {
17802
+ path16 = path16.map(function(value) {
17803
17803
  return pathToRegexp(value, keys, options).source;
17804
17804
  });
17805
- return new RegExp(path17.join("|"), flags);
17805
+ return new RegExp(path16.join("|"), flags);
17806
17806
  }
17807
- if (typeof path17 !== "string") {
17807
+ if (typeof path16 !== "string") {
17808
17808
  throw new TypeError("path must be a string, array of strings, or regular expression");
17809
17809
  }
17810
- path17 = path17.replace(
17810
+ path16 = path16.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 += path17.slice(pos, offset);
17827
+ backtrack += path16.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(path17)) {
17857
+ while (m = MATCHING_GROUP_REGEXP.exec(path16)) {
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
- path17 += strict ? "" : path17[path17.length - 1] === "/" ? "?" : "/?";
17869
+ path16 += strict ? "" : path16[path16.length - 1] === "/" ? "?" : "/?";
17870
17870
  if (end) {
17871
- path17 += "$";
17872
- } else if (path17[path17.length - 1] !== "/") {
17873
- path17 += lookahead ? "(?=/|$)" : "(?:/|$)";
17871
+ path16 += "$";
17872
+ } else if (path16[path16.length - 1] !== "/") {
17873
+ path16 += lookahead ? "(?=/|$)" : "(?:/|$)";
17874
17874
  }
17875
- return new RegExp("^" + path17, flags);
17875
+ return new RegExp("^" + path16, 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(path17, options, fn) {
17888
+ function Layer(path16, options, fn) {
17889
17889
  if (!(this instanceof Layer)) {
17890
- return new Layer(path17, options, fn);
17890
+ return new Layer(path16, options, fn);
17891
17891
  }
17892
- debug("new %o", path17);
17892
+ debug("new %o", path16);
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(path17, this.keys = [], opts);
17899
- this.regexp.fast_star = path17 === "*";
17900
- this.regexp.fast_slash = path17 === "/" && opts.end === false;
17898
+ this.regexp = pathRegexp(path16, this.keys = [], opts);
17899
+ this.regexp.fast_star = path16 === "*";
17900
+ this.regexp.fast_slash = path16 === "/" && 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(path17) {
17924
+ Layer.prototype.match = function match(path16) {
17925
17925
  var match2;
17926
- if (path17 != null) {
17926
+ if (path16 != 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(path17) };
17934
- this.path = path17;
17933
+ this.params = { "0": decode_param(path16) };
17934
+ this.path = path16;
17935
17935
  return true;
17936
17936
  }
17937
- match2 = this.regexp.exec(path17);
17937
+ match2 = this.regexp.exec(path16);
17938
17938
  }
17939
17939
  if (!match2) {
17940
17940
  this.params = void 0;
@@ -17976,10 +17976,10 @@ var require_layer = __commonJS({
17976
17976
  var require_methods = __commonJS({
17977
17977
  "../../node_modules/.pnpm/methods@1.1.2/node_modules/methods/index.js"(exports2, module2) {
17978
17978
  "use strict";
17979
- var http2 = require("http");
17979
+ var http3 = require("http");
17980
17980
  module2.exports = getCurrentNodeMethods() || getBasicNodeMethods();
17981
17981
  function getCurrentNodeMethods() {
17982
- return http2.METHODS && http2.METHODS.map(function lowerCaseMethod(method) {
17982
+ return http3.METHODS && http3.METHODS.map(function lowerCaseMethod(method) {
17983
17983
  return method.toLowerCase();
17984
17984
  });
17985
17985
  }
@@ -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(path17) {
18031
- this.path = path17;
18030
+ function Route(path16) {
18031
+ this.path = path16;
18032
18032
  this.stack = [];
18033
- debug("new %o", path17);
18033
+ debug("new %o", path16);
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 path17 = getPathname(req);
18247
- if (path17 == null) {
18246
+ var path16 = getPathname(req);
18247
+ if (path16 == 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, path17);
18255
+ match = matchLayer(layer, path16);
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, path17);
18293
+ trim_prefix(layer, layerError, layerPath, path16);
18294
18294
  }
18295
18295
  sync = 0;
18296
18296
  });
18297
18297
  }
18298
- function trim_prefix(layer, layerError, layerPath, path17) {
18298
+ function trim_prefix(layer, layerError, layerPath, path16) {
18299
18299
  if (layerPath.length !== 0) {
18300
- if (layerPath !== path17.slice(0, layerPath.length)) {
18300
+ if (layerPath !== path16.slice(0, layerPath.length)) {
18301
18301
  next(layerError);
18302
18302
  return;
18303
18303
  }
18304
- var c = path17[layerPath.length];
18304
+ var c = path16[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 path17 = "/";
18382
+ var path16 = "/";
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
- path17 = fn;
18390
+ path16 = 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", path17, fn.name || "<anonymous>");
18403
- var layer = new Layer(path17, {
18402
+ debug("use %o %s", path16, fn.name || "<anonymous>");
18403
+ var layer = new Layer(path16, {
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(path17) {
18414
- var route2 = new Route(path17);
18415
- var layer = new Layer(path17, {
18413
+ proto.route = function route(path16) {
18414
+ var route2 = new Route(path16);
18415
+ var layer = new Layer(path16, {
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(path17) {
18426
- var route = this.route(path17);
18425
+ proto[method] = function(path16) {
18426
+ var route = this.route(path16);
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, path17) {
18462
+ function matchLayer(layer, path16) {
18463
18463
  try {
18464
- return layer.match(path17);
18464
+ return layer.match(path16);
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 path17 = require("path");
18583
- var fs17 = require("fs");
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;
18582
+ var path16 = require("path");
18583
+ var fs16 = require("fs");
18584
+ var dirname3 = path16.dirname;
18585
+ var basename3 = path16.basename;
18586
+ var extname3 = path16.extname;
18587
+ var join13 = path16.join;
18588
+ var resolve10 = path16.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 path18;
18617
+ var path17;
18618
18618
  var roots = [].concat(this.root);
18619
18619
  debug('lookup "%s"', name);
18620
- for (var i = 0; i < roots.length && !path18; i++) {
18620
+ for (var i = 0; i < roots.length && !path17; i++) {
18621
18621
  var root = roots[i];
18622
18622
  var loc = resolve10(root, name);
18623
18623
  var dir = dirname3(loc);
18624
- var file = basename4(loc);
18625
- path18 = this.resolve(dir, file);
18624
+ var file = basename3(loc);
18625
+ path17 = this.resolve(dir, file);
18626
18626
  }
18627
- return path18;
18627
+ return path17;
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 path18 = join13(dir, file);
18636
- var stat = tryStat(path18);
18635
+ var path17 = join13(dir, file);
18636
+ var stat = tryStat(path17);
18637
18637
  if (stat && stat.isFile()) {
18638
- return path18;
18638
+ return path17;
18639
18639
  }
18640
- path18 = join13(dir, basename4(file, ext), "index" + ext);
18641
- stat = tryStat(path18);
18640
+ path17 = join13(dir, basename3(file, ext), "index" + ext);
18641
+ stat = tryStat(path17);
18642
18642
  if (stat && stat.isFile()) {
18643
- return path18;
18643
+ return path17;
18644
18644
  }
18645
18645
  };
18646
- function tryStat(path18) {
18647
- debug('stat "%s"', path18);
18646
+ function tryStat(path17) {
18647
+ debug('stat "%s"', path17);
18648
18648
  try {
18649
- return fs17.statSync(path18);
18649
+ return fs16.statSync(path17);
18650
18650
  } catch (e) {
18651
18651
  return void 0;
18652
18652
  }
@@ -18719,7 +18719,7 @@ var require_content_disposition = __commonJS({
18719
18719
  "use strict";
18720
18720
  module2.exports = contentDisposition;
18721
18721
  module2.exports.parse = parse;
18722
- var basename4 = require("path").basename;
18722
+ var basename3 = require("path").basename;
18723
18723
  var Buffer2 = require_safe_buffer().Buffer;
18724
18724
  var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g;
18725
18725
  var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/;
@@ -18755,9 +18755,9 @@ var require_content_disposition = __commonJS({
18755
18755
  if (typeof fallback === "string" && NON_LATIN1_REGEXP.test(fallback)) {
18756
18756
  throw new TypeError("fallback must be ISO-8859-1 string");
18757
18757
  }
18758
- var name = basename4(filename);
18758
+ var name = basename3(filename);
18759
18759
  var isQuotedString = TEXT_REGEXP.test(name);
18760
- var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name) : basename4(fallback);
18760
+ var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name) : basename3(fallback);
18761
18761
  var hasFallback = typeof fallbackName === "string" && fallbackName !== name;
18762
18762
  if (hasFallback || !isQuotedString || HEX_ESCAPE_REGEXP.test(name)) {
18763
18763
  params["filename*"] = name;
@@ -19002,8 +19002,8 @@ 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 path17 = require("path");
19006
- var fs17 = require("fs");
19005
+ var path16 = require("path");
19006
+ var fs16 = require("fs");
19007
19007
  function Mime() {
19008
19008
  this.types = /* @__PURE__ */ Object.create(null);
19009
19009
  this.extensions = /* @__PURE__ */ Object.create(null);
@@ -19024,7 +19024,7 @@ var require_mime = __commonJS({
19024
19024
  };
19025
19025
  Mime.prototype.load = function(file) {
19026
19026
  this._loading = file;
19027
- var map = {}, content = fs17.readFileSync(file, "ascii"), lines = content.split(/[\r\n]+/);
19027
+ var map = {}, content = fs16.readFileSync(file, "ascii"), lines = content.split(/[\r\n]+/);
19028
19028
  lines.forEach(function(line) {
19029
19029
  var fields = line.replace(/\s*#.*|^\s*|\s*$/g, "").split(/\s+/);
19030
19030
  map[fields.shift()] = fields;
@@ -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(path18, fallback) {
19036
- var ext = path18.replace(/^.*[\.\/\\]/, "").toLowerCase();
19035
+ Mime.prototype.lookup = function(path17, fallback) {
19036
+ var ext = path17.replace(/^.*[\.\/\\]/, "").toLowerCase();
19037
19037
  return this.types[ext] || fallback || this.default_type;
19038
19038
  };
19039
19039
  Mime.prototype.extension = function(mimeType) {
@@ -19263,33 +19263,33 @@ var require_send = __commonJS({
19263
19263
  var escapeHtml = require_escape_html();
19264
19264
  var etag = require_etag();
19265
19265
  var fresh = require_fresh();
19266
- var fs17 = require("fs");
19266
+ var fs16 = require("fs");
19267
19267
  var mime = require_mime();
19268
19268
  var ms = require_ms2();
19269
19269
  var onFinished = require_on_finished();
19270
19270
  var parseRange = require_range_parser();
19271
- var path17 = require("path");
19271
+ var path16 = require("path");
19272
19272
  var statuses = require_statuses();
19273
19273
  var Stream = require("stream");
19274
19274
  var util2 = require("util");
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;
19275
+ var extname3 = path16.extname;
19276
+ var join13 = path16.join;
19277
+ var normalize = path16.normalize;
19278
+ var resolve10 = path16.resolve;
19279
+ var sep3 = path16.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, path18, options) {
19286
- return new SendStream(req, path18, options);
19285
+ function send(req, path17, options) {
19286
+ return new SendStream(req, path17, options);
19287
19287
  }
19288
- function SendStream(req, path18, options) {
19288
+ function SendStream(req, path17, options) {
19289
19289
  Stream.call(this);
19290
19290
  var opts = options || {};
19291
19291
  this.options = opts;
19292
- this.path = path18;
19292
+ this.path = path17;
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(path18) {
19339
- this._root = resolve10(String(path18));
19338
+ SendStream.prototype.root = function root(path17) {
19339
+ this._root = resolve10(String(path17));
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(path18) {
19452
+ SendStream.prototype.redirect = function redirect(path17) {
19453
19453
  var res = this.res;
19454
19454
  if (hasListeners(this, "directory")) {
19455
- this.emit("directory", res, path18);
19455
+ this.emit("directory", res, path17);
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 path18 = decode(this.path);
19476
- if (path18 === -1) {
19475
+ var path17 = decode(this.path);
19476
+ if (path17 === -1) {
19477
19477
  this.error(400);
19478
19478
  return res;
19479
19479
  }
19480
- if (~path18.indexOf("\0")) {
19480
+ if (~path17.indexOf("\0")) {
19481
19481
  this.error(400);
19482
19482
  return res;
19483
19483
  }
19484
19484
  var parts;
19485
19485
  if (root !== null) {
19486
- if (path18) {
19487
- path18 = normalize("." + sep3 + path18);
19486
+ if (path17) {
19487
+ path17 = normalize("." + sep3 + path17);
19488
19488
  }
19489
- if (UP_PATH_REGEXP.test(path18)) {
19490
- debug('malicious path "%s"', path18);
19489
+ if (UP_PATH_REGEXP.test(path17)) {
19490
+ debug('malicious path "%s"', path17);
19491
19491
  this.error(403);
19492
19492
  return res;
19493
19493
  }
19494
- parts = path18.split(sep3);
19495
- path18 = normalize(join13(root, path18));
19494
+ parts = path17.split(sep3);
19495
+ path17 = normalize(join13(root, path17));
19496
19496
  } else {
19497
- if (UP_PATH_REGEXP.test(path18)) {
19498
- debug('malicious path "%s"', path18);
19497
+ if (UP_PATH_REGEXP.test(path17)) {
19498
+ debug('malicious path "%s"', path17);
19499
19499
  this.error(403);
19500
19500
  return res;
19501
19501
  }
19502
- parts = normalize(path18).split(sep3);
19503
- path18 = resolve10(path18);
19502
+ parts = normalize(path17).split(sep3);
19503
+ path17 = resolve10(path17);
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, path18);
19510
+ debug('%s dotfile "%s"', access, path17);
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(path18);
19524
+ this.sendIndex(path17);
19525
19525
  return res;
19526
19526
  }
19527
- this.sendFile(path18);
19527
+ this.sendFile(path17);
19528
19528
  return res;
19529
19529
  };
19530
- SendStream.prototype.send = function send2(path18, stat) {
19530
+ SendStream.prototype.send = function send2(path17, 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"', path18);
19543
- this.setHeader(path18, stat);
19544
- this.type(path18);
19542
+ debug('pipe "%s"', path17);
19543
+ this.setHeader(path17, stat);
19544
+ this.type(path17);
19545
19545
  if (this.isConditionalGET()) {
19546
19546
  if (this.isPreconditionFailure()) {
19547
19547
  this.error(412);
@@ -19590,28 +19590,28 @@ var require_send = __commonJS({
19590
19590
  res.end();
19591
19591
  return;
19592
19592
  }
19593
- this.stream(path18, opts);
19593
+ this.stream(path17, opts);
19594
19594
  };
19595
- SendStream.prototype.sendFile = function sendFile(path18) {
19595
+ SendStream.prototype.sendFile = function sendFile(path17) {
19596
19596
  var i = 0;
19597
19597
  var self = this;
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) {
19598
+ debug('stat "%s"', path17);
19599
+ fs16.stat(path17, function onstat(err, stat) {
19600
+ if (err && err.code === "ENOENT" && !extname3(path17) && path17[path17.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(path18);
19605
- self.emit("file", path18, stat);
19606
- self.send(path18, stat);
19604
+ if (stat.isDirectory()) return self.redirect(path17);
19605
+ self.emit("file", path17, stat);
19606
+ self.send(path17, 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 = path18 + "." + self._extensions[i++];
19612
+ var p = path17 + "." + self._extensions[i++];
19613
19613
  debug('stat "%s"', p);
19614
- fs17.stat(p, function(err2, stat) {
19614
+ fs16.stat(p, function(err2, stat) {
19615
19615
  if (err2) return next(err2);
19616
19616
  if (stat.isDirectory()) return next();
19617
19617
  self.emit("file", p, stat);
@@ -19619,7 +19619,7 @@ var require_send = __commonJS({
19619
19619
  });
19620
19620
  }
19621
19621
  };
19622
- SendStream.prototype.sendIndex = function sendIndex(path18) {
19622
+ SendStream.prototype.sendIndex = function sendIndex(path17) {
19623
19623
  var i = -1;
19624
19624
  var self = this;
19625
19625
  function next(err) {
@@ -19627,9 +19627,9 @@ var require_send = __commonJS({
19627
19627
  if (err) return self.onStatError(err);
19628
19628
  return self.error(404);
19629
19629
  }
19630
- var p = join13(path18, self._index[i]);
19630
+ var p = join13(path17, self._index[i]);
19631
19631
  debug('stat "%s"', p);
19632
- fs17.stat(p, function(err2, stat) {
19632
+ fs16.stat(p, function(err2, stat) {
19633
19633
  if (err2) return next(err2);
19634
19634
  if (stat.isDirectory()) return next();
19635
19635
  self.emit("file", p, stat);
@@ -19638,10 +19638,10 @@ var require_send = __commonJS({
19638
19638
  }
19639
19639
  next();
19640
19640
  };
19641
- SendStream.prototype.stream = function stream(path18, options) {
19641
+ SendStream.prototype.stream = function stream(path17, options) {
19642
19642
  var self = this;
19643
19643
  var res = this.res;
19644
- var stream2 = fs17.createReadStream(path18, options);
19644
+ var stream2 = fs16.createReadStream(path17, 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(path18) {
19659
+ SendStream.prototype.type = function type(path17) {
19660
19660
  var res = this.res;
19661
19661
  if (res.getHeader("Content-Type")) return;
19662
- var type2 = mime.lookup(path18);
19662
+ var type2 = mime.lookup(path17);
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(path18, stat) {
19671
+ SendStream.prototype.setHeader = function setHeader(path17, stat) {
19672
19672
  var res = this.res;
19673
- this.emit("headers", res, path18, stat);
19673
+ this.emit("headers", res, path17, 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(path18) {
19732
+ function decode(path17) {
19733
19733
  try {
19734
- return decodeURIComponent(path18);
19734
+ return decodeURIComponent(path17);
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(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;
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;
20648
20648
  };
20649
20649
  exports2.flatten = deprecate.function(
20650
20650
  flatten,
@@ -20767,13 +20767,13 @@ var require_application = __commonJS({
20767
20767
  "../../node_modules/.pnpm/express@4.22.1/node_modules/express/lib/application.js"(exports2, module2) {
20768
20768
  "use strict";
20769
20769
  var finalhandler = require_finalhandler();
20770
- var Router7 = require_router();
20770
+ var Router8 = require_router();
20771
20771
  var methods = require_methods();
20772
20772
  var middleware = require_init();
20773
20773
  var query = require_query();
20774
20774
  var debug = require_src()("express:application");
20775
20775
  var View = require_view();
20776
- var http2 = require("http");
20776
+ var http3 = require("http");
20777
20777
  var compileETag = require_utils2().compileETag;
20778
20778
  var compileQueryParser = require_utils2().compileQueryParser;
20779
20779
  var compileTrust = require_utils2().compileTrust;
@@ -20832,7 +20832,7 @@ var require_application = __commonJS({
20832
20832
  };
20833
20833
  app.lazyrouter = function lazyrouter() {
20834
20834
  if (!this._router) {
20835
- this._router = new Router7({
20835
+ this._router = new Router8({
20836
20836
  caseSensitive: this.enabled("case sensitive routing"),
20837
20837
  strict: this.enabled("strict routing")
20838
20838
  });
@@ -20855,7 +20855,7 @@ var require_application = __commonJS({
20855
20855
  };
20856
20856
  app.use = function use(fn) {
20857
20857
  var offset = 0;
20858
- var path17 = "/";
20858
+ var path16 = "/";
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
- path17 = fn;
20866
+ path16 = 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(path17, fn2);
20877
+ return router.use(path16, fn2);
20878
20878
  }
20879
- debug(".use app under %s", path17);
20880
- fn2.mountpath = path17;
20879
+ debug(".use app under %s", path16);
20880
+ fn2.mountpath = path16;
20881
20881
  fn2.parent = this;
20882
- router.use(path17, function mounted_app(req, res, next) {
20882
+ router.use(path16, 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(path17) {
20894
+ app.route = function route(path16) {
20895
20895
  this.lazyrouter();
20896
- return this._router.route(path17);
20896
+ return this._router.route(path16);
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 path17() {
20947
+ app.path = function path16() {
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(path17) {
20963
+ app[method] = function(path16) {
20964
20964
  if (method === "get" && arguments.length === 1) {
20965
- return this.set(path17);
20965
+ return this.set(path16);
20966
20966
  }
20967
20967
  this.lazyrouter();
20968
- var route = this._router.route(path17);
20968
+ var route = this._router.route(path16);
20969
20969
  route[method].apply(route, slice.call(arguments, 1));
20970
20970
  return this;
20971
20971
  };
20972
20972
  });
20973
- app.all = function all(path17) {
20973
+ app.all = function all(path16) {
20974
20974
  this.lazyrouter();
20975
- var route = this._router.route(path17);
20975
+ var route = this._router.route(path16);
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);
@@ -21022,7 +21022,7 @@ var require_application = __commonJS({
21022
21022
  tryRender(view, renderOptions, done);
21023
21023
  };
21024
21024
  app.listen = function listen() {
21025
- var server = http2.createServer(this);
21025
+ var server = http3.createServer(this);
21026
21026
  return server.listen.apply(server, arguments);
21027
21027
  };
21028
21028
  function logerror(err) {
@@ -21624,12 +21624,12 @@ var require_request = __commonJS({
21624
21624
  var deprecate = require_depd()("express");
21625
21625
  var isIP = require("net").isIP;
21626
21626
  var typeis = require_type_is();
21627
- var http2 = require("http");
21627
+ var http3 = require("http");
21628
21628
  var fresh = require_fresh();
21629
21629
  var parseRange = require_range_parser();
21630
21630
  var parse = require_parseurl();
21631
21631
  var proxyaddr = require_proxy_addr();
21632
- var req = Object.create(http2.IncomingMessage.prototype);
21632
+ var req = Object.create(http3.IncomingMessage.prototype);
21633
21633
  module2.exports = req;
21634
21634
  req.get = req.header = function header(name) {
21635
21635
  if (!name) {
@@ -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 path17() {
21734
+ defineGetter(req, "path", function path16() {
21735
21735
  return parse(this).pathname;
21736
21736
  });
21737
21737
  defineGetter(req, "hostname", function hostname2() {
@@ -22051,10 +22051,10 @@ var require_response = __commonJS({
22051
22051
  var deprecate = require_depd()("express");
22052
22052
  var encodeUrl = require_encodeurl();
22053
22053
  var escapeHtml = require_escape_html();
22054
- var http2 = require("http");
22054
+ var http3 = require("http");
22055
22055
  var isAbsolute2 = require_utils2().isAbsolute;
22056
22056
  var onFinished = require_on_finished();
22057
- var path17 = require("path");
22057
+ var path16 = require("path");
22058
22058
  var statuses = require_statuses();
22059
22059
  var merge = require_utils_merge();
22060
22060
  var sign = require_cookie_signature().sign;
@@ -22063,11 +22063,11 @@ 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 = path17.extname;
22066
+ var extname3 = path16.extname;
22067
22067
  var mime = send.mime;
22068
- var resolve10 = path17.resolve;
22068
+ var resolve10 = path16.resolve;
22069
22069
  var vary = require_vary();
22070
- var res = Object.create(http2.ServerResponse.prototype);
22070
+ var res = Object.create(http3.ServerResponse.prototype);
22071
22071
  module2.exports = res;
22072
22072
  var charsetRegExp = /;\s*charset\s*=/;
22073
22073
  res.status = function status(code) {
@@ -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(path18, options, callback) {
22245
+ res.sendFile = function sendFile(path17, 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 (!path18) {
22251
+ if (!path17) {
22252
22252
  throw new TypeError("path argument is required to res.sendFile");
22253
22253
  }
22254
- if (typeof path18 !== "string") {
22254
+ if (typeof path17 !== "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(path18)) {
22261
+ if (!opts.root && !isAbsolute2(path17)) {
22262
22262
  throw new TypeError("path must be absolute or specify root to res.sendFile");
22263
22263
  }
22264
- var pathname = encodeURI(path18);
22264
+ var pathname = encodeURI(path17);
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(path18, options, callback) {
22274
+ res.sendfile = function(path17, 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, path18, opts);
22284
+ var file = send(req, path17, 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(path18, filename, options, callback) {
22297
+ res.download = function download(path17, 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 || path18)
22314
+ "Content-Disposition": contentDisposition(name || path17)
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(path18) : path18;
22327
+ var fullPath = !opts.root ? resolve10(path17) : path17;
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 path17 = parseUrl(req).pathname;
22629
- if (path17 === "/" && originalUrl.pathname.substr(-1) !== "/") {
22630
- path17 = "";
22628
+ var path16 = parseUrl(req).pathname;
22629
+ if (path16 === "/" && originalUrl.pathname.substr(-1) !== "/") {
22630
+ path16 = "";
22631
22631
  }
22632
- var stream = send(req, path17, opts);
22632
+ var stream = send(req, path16, opts);
22633
22633
  stream.on("directory", onDirectory);
22634
22634
  if (setHeaders) {
22635
22635
  stream.on("headers", setHeaders);
@@ -22697,7 +22697,7 @@ var require_express = __commonJS({
22697
22697
  var mixin = require_merge_descriptors();
22698
22698
  var proto = require_application();
22699
22699
  var Route = require_route();
22700
- var Router7 = require_router();
22700
+ var Router8 = require_router();
22701
22701
  var req = require_request();
22702
22702
  var res = require_response();
22703
22703
  exports2 = module2.exports = createApplication;
@@ -22720,7 +22720,7 @@ var require_express = __commonJS({
22720
22720
  exports2.request = req;
22721
22721
  exports2.response = res;
22722
22722
  exports2.Route = Route;
22723
- exports2.Router = Router7;
22723
+ exports2.Router = Router8;
22724
22724
  exports2.json = bodyParser.json;
22725
22725
  exports2.query = require_query();
22726
22726
  exports2.raw = bodyParser.raw;
@@ -22791,6 +22791,7 @@ __export(main_exports, {
22791
22791
  shouldSkipStartupRequirementsCheck: () => shouldSkipStartupRequirementsCheck
22792
22792
  });
22793
22793
  module.exports = __toCommonJS(main_exports);
22794
+ var http2 = __toESM(require("http"), 1);
22794
22795
  var nodePath = __toESM(require("path"), 1);
22795
22796
 
22796
22797
  // ../../packages/core/src/logger.ts
@@ -23149,6 +23150,13 @@ function persistNodeStartupTransport(storagePath, transport) {
23149
23150
  transport
23150
23151
  });
23151
23152
  }
23153
+ function persistNodeStartupJoin(storagePath, join13) {
23154
+ const startup = resolveNodeStartupMetadata(storagePath);
23155
+ persistNodeStartupMetadata(storagePath, {
23156
+ ...startup,
23157
+ join: join13
23158
+ });
23159
+ }
23152
23160
  function resolvePersistedDevTunnelId(storagePath, kind) {
23153
23161
  return readNodeMetadata(storagePath).devTunnelIds?.[kind]?.trim() || void 0;
23154
23162
  }
@@ -24013,19 +24021,19 @@ async function fetchWithTimeout(url, init, timeoutMs = DEFAULT_NODE_REQUEST_TIME
24013
24021
  cleanup();
24014
24022
  }
24015
24023
  }
24016
- async function fetchNodeWithFallback(node, path17, init, timeoutMs = DEFAULT_NODE_REQUEST_TIMEOUT_MS, trace) {
24024
+ async function fetchNodeWithFallback(node, path16, init, timeoutMs = DEFAULT_NODE_REQUEST_TIMEOUT_MS, trace) {
24017
24025
  let lastError;
24018
24026
  const endpoints = getNodeRequestEndpoints(node);
24019
24027
  for (const [index, endpoint] of endpoints.entries()) {
24020
24028
  const attempt = index + 1;
24021
- trace?.onAttempt?.({ attempt, endpoint, path: path17, timeoutMs, totalEndpoints: endpoints.length });
24029
+ trace?.onAttempt?.({ attempt, endpoint, path: path16, timeoutMs, totalEndpoints: endpoints.length });
24022
24030
  try {
24023
- const response = await fetchWithTimeout(`${endpoint}${path17}`, init, timeoutMs);
24024
- trace?.onResponse?.({ attempt, endpoint, path: path17, response, timeoutMs, totalEndpoints: endpoints.length });
24031
+ const response = await fetchWithTimeout(`${endpoint}${path16}`, init, timeoutMs);
24032
+ trace?.onResponse?.({ attempt, endpoint, path: path16, response, timeoutMs, totalEndpoints: endpoints.length });
24025
24033
  return { endpoint, response };
24026
24034
  } catch (error) {
24027
24035
  lastError = error;
24028
- trace?.onError?.({ attempt, endpoint, error, path: path17, timeoutMs, totalEndpoints: endpoints.length });
24036
+ trace?.onError?.({ attempt, endpoint, error, path: path16, timeoutMs, totalEndpoints: endpoints.length });
24029
24037
  }
24030
24038
  }
24031
24039
  throw lastError instanceof Error ? lastError : new Error("No reachable node endpoint");
@@ -25022,12 +25030,24 @@ function listWorkDirFolders(workDir) {
25022
25030
 
25023
25031
  // ../../packages/core/src/heartbeat.ts
25024
25032
  var MISSED_HEARTBEAT_THRESHOLD = 3;
25033
+ var DEFAULT_KEEPALIVE_INTERVAL_MS = 3e3;
25034
+ var HEARTBEAT_SUCCESS_LOG_INTERVAL_MS = 6e4;
25035
+ var HEARTBEAT_FAILURE_LOG_INTERVAL_MS = 1e4;
25025
25036
  function formatError(error) {
25026
25037
  return error instanceof Error ? error.message : String(error);
25027
25038
  }
25028
25039
  function truncateForLog(value, max = 240) {
25029
25040
  return !value || value.length <= max ? value : `${value.slice(0, max - 3)}...`;
25030
25041
  }
25042
+ function describeControlRequest(request) {
25043
+ return {
25044
+ requestId: request.requestId,
25045
+ kind: request.kind,
25046
+ taskId: request.taskId,
25047
+ path: request.path,
25048
+ enabled: request.enabled
25049
+ };
25050
+ }
25031
25051
  var HeartbeatMonitor = class {
25032
25052
  constructor(nodeRegistry, election, eventBus, config, logger) {
25033
25053
  this.nodeRegistry = nodeRegistry;
@@ -25080,6 +25100,8 @@ var HeartbeatMonitor = class {
25080
25100
  pendingControlResponses = /* @__PURE__ */ new Map();
25081
25101
  /** Follower-side callback for executing keepalive-delivered control requests. */
25082
25102
  controlRequestHandler;
25103
+ /** Throttle repetitive heartbeat / keepalive logs while preserving periodic visibility. */
25104
+ throttledLogs = /* @__PURE__ */ new Map();
25083
25105
  /** Set the callback used to query tasks assigned to a follower for pull-based dispatch. */
25084
25106
  setGetAssignedTasks(fn) {
25085
25107
  this.getAssignedTasks = fn;
@@ -25120,10 +25142,9 @@ var HeartbeatMonitor = class {
25120
25142
  const queued = this.queuedControlRequests.get(nodeId) ?? [];
25121
25143
  queued.push(fullRequest);
25122
25144
  this.queuedControlRequests.set(nodeId, queued);
25123
- this.log.info("queued control request for keepalive delivery", {
25145
+ this.log.info("queued keepalive control request", {
25124
25146
  nodeId,
25125
- requestId: fullRequest.requestId,
25126
- kind: fullRequest.kind
25147
+ ...describeControlRequest(fullRequest)
25127
25148
  });
25128
25149
  return new Promise((resolve10, reject) => {
25129
25150
  const timeoutId = setTimeout(() => {
@@ -25132,6 +25153,7 @@ var HeartbeatMonitor = class {
25132
25153
  }, timeoutMs);
25133
25154
  this.pendingControlResponses.set(fullRequest.requestId, {
25134
25155
  nodeId,
25156
+ kind: fullRequest.kind,
25135
25157
  resolve: resolve10,
25136
25158
  reject,
25137
25159
  timeoutId
@@ -25149,6 +25171,13 @@ var HeartbeatMonitor = class {
25149
25171
  }
25150
25172
  clearTimeout(pending.timeoutId);
25151
25173
  this.pendingControlResponses.delete(response.requestId);
25174
+ this.log.info("received keepalive control response", {
25175
+ requestId: response.requestId,
25176
+ nodeId: pending.nodeId,
25177
+ kind: pending.kind,
25178
+ ok: response.ok,
25179
+ statusCode: response.statusCode
25180
+ });
25152
25181
  pending.resolve(response);
25153
25182
  return true;
25154
25183
  }
@@ -25211,7 +25240,7 @@ var HeartbeatMonitor = class {
25211
25240
  body: JSON.stringify(request)
25212
25241
  }, void 0, {
25213
25242
  onAttempt: ({ attempt, endpoint: targetEndpoint, totalEndpoints, timeoutMs }) => {
25214
- this.log.info("sending heartbeat request", {
25243
+ this.log.debug("sending heartbeat request", {
25215
25244
  nodeId: node.id,
25216
25245
  endpoint: targetEndpoint,
25217
25246
  attempt,
@@ -25221,16 +25250,22 @@ var HeartbeatMonitor = class {
25221
25250
  });
25222
25251
  },
25223
25252
  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
- });
25253
+ this.logWithThrottle(
25254
+ "warn",
25255
+ `heartbeat-attempt-failure:${node.id}`,
25256
+ HEARTBEAT_FAILURE_LOG_INTERVAL_MS,
25257
+ "heartbeat request attempt failed",
25258
+ {
25259
+ nodeId: node.id,
25260
+ endpoint: targetEndpoint,
25261
+ attempt,
25262
+ totalEndpoints,
25263
+ error: formatError(error)
25264
+ }
25265
+ );
25231
25266
  },
25232
25267
  onResponse: ({ attempt, endpoint: targetEndpoint, response: heartbeatResponse, totalEndpoints }) => {
25233
- this.log.info("heartbeat response received", {
25268
+ this.log.debug("heartbeat response received", {
25234
25269
  nodeId: node.id,
25235
25270
  endpoint: targetEndpoint,
25236
25271
  attempt,
@@ -25255,13 +25290,19 @@ var HeartbeatMonitor = class {
25255
25290
  if (result.status !== node.status) {
25256
25291
  this.nodeRegistry.updateStatus(node.id, result.status);
25257
25292
  }
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
- });
25293
+ this.logWithThrottle(
25294
+ "info",
25295
+ `heartbeat-success:${node.id}`,
25296
+ HEARTBEAT_SUCCESS_LOG_INTERVAL_MS,
25297
+ "heartbeat response applied",
25298
+ {
25299
+ nodeId: node.id,
25300
+ endpoint,
25301
+ reportedStatus: result.status,
25302
+ load: result.load,
25303
+ workDirFolders: result.workDirFolders?.length ?? 0
25304
+ }
25305
+ );
25265
25306
  return;
25266
25307
  }
25267
25308
  const body = truncateForLog(await response.text().catch(() => void 0));
@@ -25401,6 +25442,15 @@ var HeartbeatMonitor = class {
25401
25442
  if (controlRequests.length > 0) {
25402
25443
  this.queuedControlRequests.delete(nodeId);
25403
25444
  }
25445
+ if (dispatchedTasks.length > 0 || followUpMessages.length > 0 || controlRequests.length > 0) {
25446
+ this.log.info("keepalive delivering queued work", {
25447
+ nodeId,
25448
+ dispatchedTaskCount: dispatchedTasks.length,
25449
+ followUpCount: followUpMessages.length,
25450
+ controlRequestCount: controlRequests.length,
25451
+ controlRequestKinds: controlRequests.map((request) => request.kind)
25452
+ });
25453
+ }
25404
25454
  const response = {
25405
25455
  leaderId: self.id,
25406
25456
  term: this.election.getCurrentTerm(),
@@ -25438,7 +25488,7 @@ var HeartbeatMonitor = class {
25438
25488
  previewOrigin: self.previewOrigin,
25439
25489
  workDirFolders: self.workDir ? listWorkDirFolders(self.workDir) : void 0
25440
25490
  };
25441
- this.log.info("sending keepalive request", {
25491
+ this.log.debug("sending keepalive request", {
25442
25492
  nodeId: self.id,
25443
25493
  leaderEndpoint,
25444
25494
  status: self.status,
@@ -25453,14 +25503,22 @@ var HeartbeatMonitor = class {
25453
25503
  }));
25454
25504
  if (response.ok) {
25455
25505
  const result = await response.json();
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
- });
25506
+ const hasQueuedWork = (result.dispatchedTasks?.length ?? 0) > 0 || (result.followUpMessages?.length ?? 0) > 0 || (result.controlRequests?.length ?? 0) > 0;
25507
+ this.logWithThrottle(
25508
+ "info",
25509
+ `keepalive-success:${leaderEndpoint}`,
25510
+ HEARTBEAT_SUCCESS_LOG_INTERVAL_MS,
25511
+ "keepalive response received",
25512
+ {
25513
+ leaderId: result.leaderId,
25514
+ term: result.term,
25515
+ nodeCount: result.clusterState.nodes.length,
25516
+ dispatchedTaskCount: result.dispatchedTasks?.length ?? 0,
25517
+ followUpCount: result.followUpMessages?.length ?? 0,
25518
+ controlRequestCount: result.controlRequests?.length ?? 0
25519
+ },
25520
+ hasQueuedWork
25521
+ );
25464
25522
  this.lastHeartbeatTime = Date.now();
25465
25523
  this.missedCount = 0;
25466
25524
  this.nodeRegistry.setLeader(result.leaderId, result.term);
@@ -25485,22 +25543,39 @@ var HeartbeatMonitor = class {
25485
25543
  }
25486
25544
  }
25487
25545
  if (result.controlRequests && result.controlRequests.length > 0) {
25546
+ this.log.info("processing keepalive control requests", {
25547
+ leaderEndpoint,
25548
+ controlRequestCount: result.controlRequests.length,
25549
+ controlRequestKinds: result.controlRequests.map((request2) => request2.kind)
25550
+ });
25488
25551
  await Promise.all(result.controlRequests.map(
25489
25552
  (request2) => this.processControlRequest(leaderEndpoint, request2)
25490
25553
  ));
25491
25554
  }
25492
25555
  } else {
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
- });
25556
+ this.logWithThrottle(
25557
+ "warn",
25558
+ `keepalive-failure:${leaderEndpoint}`,
25559
+ HEARTBEAT_FAILURE_LOG_INTERVAL_MS,
25560
+ "keepalive request returned non-ok response",
25561
+ {
25562
+ leaderEndpoint,
25563
+ statusCode: response.status,
25564
+ body: truncateForLog(await response.text().catch(() => void 0))
25565
+ }
25566
+ );
25498
25567
  }
25499
25568
  } catch (err) {
25500
- this.log.warn("keepalive request failed", {
25501
- leaderEndpoint,
25502
- error: formatError(err)
25503
- });
25569
+ this.logWithThrottle(
25570
+ "warn",
25571
+ `keepalive-failure:${leaderEndpoint}`,
25572
+ HEARTBEAT_FAILURE_LOG_INTERVAL_MS,
25573
+ "keepalive request failed",
25574
+ {
25575
+ leaderEndpoint,
25576
+ error: formatError(err)
25577
+ }
25578
+ );
25504
25579
  }
25505
25580
  }
25506
25581
  // ── Accessors ───────────────────────────────────────────────────────
@@ -25547,9 +25622,10 @@ var HeartbeatMonitor = class {
25547
25622
  this.startKeepalive();
25548
25623
  }
25549
25624
  startKeepalive() {
25625
+ const keepaliveInterval = Math.min(this.config.heartbeatInterval, DEFAULT_KEEPALIVE_INTERVAL_MS);
25550
25626
  this.keepaliveTimer = setInterval(() => {
25551
25627
  void this.sendKeepalive();
25552
- }, this.config.heartbeatInterval);
25628
+ }, keepaliveInterval);
25553
25629
  }
25554
25630
  resetFollowerTimer() {
25555
25631
  if (this.followerTimer !== null) {
@@ -25575,16 +25651,22 @@ var HeartbeatMonitor = class {
25575
25651
  const newCount = current + 1;
25576
25652
  this.followerMissedMap.set(node.id, newCount);
25577
25653
  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
- });
25654
+ this.logWithThrottle(
25655
+ "warn",
25656
+ `heartbeat-miss:${node.id}`,
25657
+ HEARTBEAT_FAILURE_LOG_INTERVAL_MS,
25658
+ "recorded heartbeat miss",
25659
+ {
25660
+ nodeId: node.id,
25661
+ misses: newCount,
25662
+ everReached,
25663
+ endpoint: details.endpoint,
25664
+ statusCode: details.statusCode,
25665
+ reason: details.reason,
25666
+ error: details.error,
25667
+ body: details.body
25668
+ }
25669
+ );
25588
25670
  if (newCount >= MISSED_HEARTBEAT_THRESHOLD) {
25589
25671
  const freshNode = this.nodeRegistry.getNode(node.id);
25590
25672
  if (freshNode) {
@@ -25634,6 +25716,10 @@ var HeartbeatMonitor = class {
25634
25716
  }
25635
25717
  }
25636
25718
  async processControlRequest(leaderEndpoint, request) {
25719
+ this.log.info("processing keepalive control request", {
25720
+ leaderEndpoint,
25721
+ ...describeControlRequest(request)
25722
+ });
25637
25723
  let response;
25638
25724
  if (!this.controlRequestHandler) {
25639
25725
  response = {
@@ -25668,6 +25754,12 @@ var HeartbeatMonitor = class {
25668
25754
  };
25669
25755
  }
25670
25756
  }
25757
+ this.log.info("completed keepalive control request", {
25758
+ leaderEndpoint,
25759
+ ...describeControlRequest(request),
25760
+ ok: response.ok,
25761
+ statusCode: response.statusCode
25762
+ });
25671
25763
  try {
25672
25764
  const res = await fetch(`${leaderEndpoint}/api/worker/control-response`, applyRequestAuthHeaders({
25673
25765
  method: "POST",
@@ -25691,6 +25783,21 @@ var HeartbeatMonitor = class {
25691
25783
  });
25692
25784
  }
25693
25785
  }
25786
+ logWithThrottle(level, key, intervalMs, message, data, force = false) {
25787
+ const now = Date.now();
25788
+ const existing = this.throttledLogs.get(key);
25789
+ if (existing && !force && now - existing.lastLoggedAt < intervalMs) {
25790
+ existing.suppressedCount += 1;
25791
+ return;
25792
+ }
25793
+ const mergedData = existing && existing.suppressedCount > 0 ? { ...data, suppressedCount: existing.suppressedCount } : data;
25794
+ this.throttledLogs.set(key, { lastLoggedAt: now, suppressedCount: 0 });
25795
+ if (level === "info") {
25796
+ this.log.info(message, mergedData);
25797
+ return;
25798
+ }
25799
+ this.log.warn(message, mergedData);
25800
+ }
25694
25801
  };
25695
25802
 
25696
25803
  // ../../packages/core/src/data-router.ts
@@ -25718,9 +25825,9 @@ var DataRouter = class {
25718
25825
  /**
25719
25826
  * Returns true if the request should be proxied to the leader.
25720
25827
  */
25721
- shouldProxy(method, path17) {
25828
+ shouldProxy(method, path16) {
25722
25829
  if (this.election.isLeader()) return false;
25723
- if (this.isExcludedPath(path17)) return false;
25830
+ if (this.isExcludedPath(path16)) return false;
25724
25831
  if (method.toUpperCase() === "GET") return false;
25725
25832
  return WRITE_METHODS.has(method.toUpperCase());
25726
25833
  }
@@ -25821,8 +25928,8 @@ var DataRouter = class {
25821
25928
  };
25822
25929
  }
25823
25930
  // ── Helpers ───────────────────────────────────────────────────────────
25824
- isExcludedPath(path17) {
25825
- return EXCLUDED_PATH_PREFIXES.some((prefix) => path17.startsWith(prefix)) || EXCLUDED_PATH_SUFFIXES.some((suffix) => path17.endsWith(suffix));
25931
+ isExcludedPath(path16) {
25932
+ return EXCLUDED_PATH_PREFIXES.some((prefix) => path16.startsWith(prefix)) || EXCLUDED_PATH_SUFFIXES.some((suffix) => path16.endsWith(suffix));
25826
25933
  }
25827
25934
  };
25828
25935
 
@@ -26836,22 +26943,34 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
26836
26943
  async joinCluster(seedUrl) {
26837
26944
  const log = this.logger.child("node/join-cluster");
26838
26945
  const tasks = this.taskEngine.listTasks().tasks;
26946
+ const self = this.nodeRegistry.getSelf();
26839
26947
  const joinBody = {
26840
- id: this.selfInfo.id,
26841
- endpoint: this.selfInfo.endpoint,
26842
- name: this.config.node.name,
26948
+ id: self.id,
26949
+ endpoint: self.endpoint,
26950
+ name: self.name,
26843
26951
  capabilities: [],
26952
+ transportType: self.transportType,
26953
+ workDir: self.workDir,
26954
+ workDirFolders: listWorkDirFolders(this.getWorkDir()),
26844
26955
  tasks
26845
26956
  };
26846
- if (this.selfInfo.devtunnelEndpoint) {
26847
- joinBody.devtunnelEndpoint = this.selfInfo.devtunnelEndpoint;
26957
+ if (self.devtunnelEndpoint) {
26958
+ joinBody.devtunnelEndpoint = self.devtunnelEndpoint;
26959
+ }
26960
+ if (self.dashboardOrigin) {
26961
+ joinBody.dashboardOrigin = self.dashboardOrigin;
26962
+ }
26963
+ if (self.previewOrigin) {
26964
+ joinBody.previewOrigin = self.previewOrigin;
26848
26965
  }
26849
26966
  log.info("sending cluster join request", {
26850
26967
  seedUrl,
26851
- nodeId: this.selfInfo.id,
26852
- endpoint: this.selfInfo.endpoint,
26968
+ nodeId: self.id,
26969
+ endpoint: self.endpoint,
26853
26970
  taskCount: tasks.length,
26854
- hasDevTunnel: !!this.selfInfo.devtunnelEndpoint
26971
+ hasDevTunnel: !!self.devtunnelEndpoint,
26972
+ hasDashboardOrigin: !!self.dashboardOrigin,
26973
+ hasPreviewOrigin: !!self.previewOrigin
26855
26974
  });
26856
26975
  let response;
26857
26976
  try {
@@ -26897,6 +27016,7 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
26897
27016
  nodeCount: data.nodes.length
26898
27017
  });
26899
27018
  this.applyClusterState(data.nodes, data.leaderId, data.term);
27019
+ persistNodeStartupJoin(this.config.storage.path, seedUrl);
26900
27020
  }
26901
27021
  async leaveCluster() {
26902
27022
  const log = this.logger.child("node/leave-cluster");
@@ -26949,6 +27069,7 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
26949
27069
  this.nodeRegistry.clearLeader();
26950
27070
  this.election.assumeLeadership();
26951
27071
  this.syncSelfInfoFromRegistry();
27072
+ persistNodeStartupJoin(this.config.storage.path, void 0);
26952
27073
  log.info("detached from leader and assumed solo leadership", {
26953
27074
  previousLeaderId: leader.id,
26954
27075
  nodeId: refreshedSelf.id,
@@ -27130,15 +27251,17 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
27130
27251
  this.selfInfo.status = current.status;
27131
27252
  }
27132
27253
  applyClusterState(nodes, leaderId, term) {
27133
- const remoteSelf = nodes.find((node) => node.id === this.selfInfo.id);
27254
+ const currentSelf = this.nodeRegistry.getSelf();
27255
+ const remoteSelf = nodes.find((node) => node.id === currentSelf.id);
27134
27256
  const nextSelf = {
27135
- ...this.selfInfo,
27257
+ ...currentSelf,
27136
27258
  ...remoteSelf ?? {},
27137
27259
  transportType: this.config.transport.type,
27138
- workDir: this.selfInfo.workDir,
27260
+ workDir: currentSelf.workDir,
27139
27261
  workDirFolders: listWorkDirFolders(this.getWorkDir()),
27140
- ...this.selfInfo.devtunnelEndpoint ? { devtunnelEndpoint: this.selfInfo.devtunnelEndpoint } : {},
27141
- ...this.selfInfo.previewOrigin ? { previewOrigin: this.selfInfo.previewOrigin } : {}
27262
+ ...currentSelf.devtunnelEndpoint ? { devtunnelEndpoint: currentSelf.devtunnelEndpoint } : {},
27263
+ ...currentSelf.dashboardOrigin ? { dashboardOrigin: currentSelf.dashboardOrigin } : {},
27264
+ ...currentSelf.previewOrigin ? { previewOrigin: currentSelf.previewOrigin } : {}
27142
27265
  };
27143
27266
  this.selfInfo = nextSelf;
27144
27267
  this.nodeRegistry.setSelf(nextSelf);
@@ -27782,8 +27905,8 @@ function getErrorMap() {
27782
27905
 
27783
27906
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
27784
27907
  var makeIssue = (params) => {
27785
- const { data, path: path17, errorMaps, issueData } = params;
27786
- const fullPath = [...path17, ...issueData.path || []];
27908
+ const { data, path: path16, errorMaps, issueData } = params;
27909
+ const fullPath = [...path16, ...issueData.path || []];
27787
27910
  const fullIssue = {
27788
27911
  ...issueData,
27789
27912
  path: fullPath
@@ -27899,11 +28022,11 @@ var errorUtil;
27899
28022
 
27900
28023
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
27901
28024
  var ParseInputLazyPath = class {
27902
- constructor(parent, value, path17, key) {
28025
+ constructor(parent, value, path16, key) {
27903
28026
  this._cachedPath = [];
27904
28027
  this.parent = parent;
27905
28028
  this.data = value;
27906
- this._path = path17;
28029
+ this._path = path16;
27907
28030
  this._key = key;
27908
28031
  }
27909
28032
  get path() {
@@ -31401,7 +31524,12 @@ var JoinClusterBody = external_exports.object({
31401
31524
  endpoint: external_exports.string().url(),
31402
31525
  name: external_exports.string().min(1),
31403
31526
  capabilities: external_exports.array(external_exports.string()).default([]),
31527
+ transportType: external_exports.string().optional(),
31528
+ workDir: external_exports.string().optional(),
31529
+ workDirFolders: external_exports.array(external_exports.string()).optional(),
31404
31530
  devtunnelEndpoint: external_exports.string().url().optional(),
31531
+ dashboardOrigin: external_exports.string().url().optional(),
31532
+ previewOrigin: external_exports.string().url().optional(),
31405
31533
  tasks: external_exports.array(JoinTaskSchema).default([])
31406
31534
  });
31407
31535
  var JoinClusterResponse = external_exports.object({
@@ -31564,9 +31692,9 @@ var BatchTaskIdsBody = external_exports.object({
31564
31692
  });
31565
31693
 
31566
31694
  // ../../packages/api/src/server.ts
31567
- var path15 = __toESM(require("path"), 1);
31568
- var fs15 = __toESM(require("fs"), 1);
31569
- var import_express7 = __toESM(require_express2(), 1);
31695
+ var path14 = __toESM(require("path"), 1);
31696
+ var fs14 = __toESM(require("fs"), 1);
31697
+ var import_express8 = __toESM(require_express2(), 1);
31570
31698
 
31571
31699
  // ../../packages/api/src/middleware/auth.ts
31572
31700
  var SKIP_AUTH_PATHS = ["/api/system/health"];
@@ -31646,7 +31774,7 @@ function createAuthMiddleware(config) {
31646
31774
  return;
31647
31775
  }
31648
31776
  if (config.validateBearerToken) {
31649
- if (isTrustedDashboardRequest(req, config)) {
31777
+ if (config.allowTrustedHostBypass !== false && isTrustedDashboardRequest(req, config)) {
31650
31778
  log.debug("skipping bearer auth for trusted dashboard request", {
31651
31779
  path: req.path,
31652
31780
  method: req.method,
@@ -31834,7 +31962,9 @@ function createClusterRoutes() {
31834
31962
  name: body.name,
31835
31963
  endpoint: body.endpoint,
31836
31964
  taskCount: body.tasks?.length ?? 0,
31837
- hasDevTunnel: !!body.devtunnelEndpoint
31965
+ hasDevTunnel: !!body.devtunnelEndpoint,
31966
+ hasDashboardOrigin: !!body.dashboardOrigin,
31967
+ hasPreviewOrigin: !!body.previewOrigin
31838
31968
  });
31839
31969
  const existingNodes = nodeRegistry.getAllNodes();
31840
31970
  let removedCount = 0;
@@ -31853,7 +31983,12 @@ function createClusterRoutes() {
31853
31983
  capabilities: body.capabilities ?? [],
31854
31984
  joinedAt: Date.now(),
31855
31985
  lastHeartbeat: Date.now(),
31856
- ...body.devtunnelEndpoint && { devtunnelEndpoint: body.devtunnelEndpoint }
31986
+ ...body.transportType && { transportType: body.transportType },
31987
+ ...body.workDir && { workDir: body.workDir },
31988
+ ...body.workDirFolders && { workDirFolders: body.workDirFolders },
31989
+ ...body.devtunnelEndpoint && { devtunnelEndpoint: body.devtunnelEndpoint },
31990
+ ...body.dashboardOrigin && { dashboardOrigin: body.dashboardOrigin },
31991
+ ...body.previewOrigin && { previewOrigin: body.previewOrigin }
31857
31992
  };
31858
31993
  nodeRegistry.addNode(node);
31859
31994
  taskEngine.importTasks(body.tasks ?? []);
@@ -31981,174 +32116,72 @@ function assertCanChangeNodeDevTunnel(taskEngine, nodeId) {
31981
32116
  );
31982
32117
  }
31983
32118
 
31984
- // ../../packages/api/src/worker-control.ts
31985
- var fs12 = __toESM(require("fs"), 1);
31986
- var path13 = __toESM(require("path"), 1);
31987
-
31988
- // ../../packages/api/src/preview/preview-server.ts
31989
- var crypto2 = __toESM(require("crypto"), 1);
31990
- var fs10 = __toESM(require("fs"), 1);
31991
- var path11 = __toESM(require("path"), 1);
31992
- var http = __toESM(require("http"), 1);
31993
- function resolvePreviewPath(rootPath, relativePath) {
31994
- const sanitizedPath = relativePath.replace(/\\/g, "/");
31995
- const resolvedPath = path11.resolve(rootPath, sanitizedPath);
31996
- const normalizedRoot = path11.resolve(rootPath);
31997
- if (!resolvedPath.startsWith(normalizedRoot + path11.sep) && resolvedPath !== normalizedRoot) {
31998
- throw new Error("Invalid preview path");
31999
- }
32000
- return {
32001
- absolutePath: resolvedPath,
32002
- normalizedPath: path11.relative(normalizedRoot, resolvedPath).split(path11.sep).join("/")
32003
- };
32004
- }
32005
- function resolvePreviewEntryPath(rootPath, entryPath) {
32006
- const { absolutePath, normalizedPath } = resolvePreviewPath(rootPath, entryPath ?? "index.html");
32007
- if (!fs10.existsSync(absolutePath) || !fs10.statSync(absolutePath).isFile()) {
32008
- throw new Error("Preview entry not found");
32009
- }
32010
- return normalizedPath;
32011
- }
32012
- function buildPreviewUrl(origin, session) {
32013
- const encodedEntryPath = session.entryPath.split("/").filter(Boolean).map((segment) => encodeURIComponent(segment)).join("/");
32014
- return `${origin.replace(/\/+$/, "")}/preview/${session.token}/${encodedEntryPath}`;
32015
- }
32016
- var DEFAULT_TTL_MS = 15 * 60 * 1e3;
32017
- var PreviewSessionManager = class {
32018
- sessions = /* @__PURE__ */ new Map();
32019
- create(options) {
32020
- const token = crypto2.randomBytes(32).toString("hex");
32021
- const entryPath = resolvePreviewEntryPath(options.rootPath, options.entryPath);
32022
- const session = {
32023
- token,
32024
- taskId: options.taskId,
32025
- rootPath: options.rootPath,
32026
- entryPath,
32027
- expiresAt: Date.now() + (options.ttlMs ?? DEFAULT_TTL_MS)
32028
- };
32029
- this.sessions.set(token, session);
32030
- return session;
32031
- }
32032
- get(token) {
32033
- const session = this.sessions.get(token);
32034
- if (!session) return null;
32035
- if (Date.now() > session.expiresAt) {
32036
- this.sessions.delete(token);
32037
- return null;
32119
+ // ../../packages/api/src/task-cancellation.ts
32120
+ var TERMINAL_STATUSES2 = /* @__PURE__ */ new Set(["completed", "failed", "cancelled", "archived"]);
32121
+ function cancelTaskOnCurrentNode(deps, taskId, options = {}) {
32122
+ const task = deps.taskEngine.getTask(taskId);
32123
+ if (!task) {
32124
+ if (options.missingOk) {
32125
+ return {
32126
+ task: null,
32127
+ cancelled: false,
32128
+ engineCancelRequested: false,
32129
+ missing: true,
32130
+ terminal: false
32131
+ };
32038
32132
  }
32039
- return session;
32133
+ throw new MeshyError("TASK_NOT_FOUND", `Task ${taskId} not found`, 404);
32040
32134
  }
32041
- cleanup() {
32042
- const now = Date.now();
32043
- for (const [token, session] of this.sessions) {
32044
- if (now > session.expiresAt) {
32045
- this.sessions.delete(token);
32046
- }
32135
+ if (TERMINAL_STATUSES2.has(task.status)) {
32136
+ if (options.terminalOk) {
32137
+ return {
32138
+ task,
32139
+ cancelled: false,
32140
+ engineCancelRequested: false,
32141
+ missing: false,
32142
+ terminal: true
32143
+ };
32047
32144
  }
32145
+ throw new MeshyError("VALIDATION_ERROR", `Task ${taskId} cannot be cancelled (status: ${task.status})`, 400);
32048
32146
  }
32049
- };
32050
- var MIME_MAP = {
32051
- ".html": "text/html",
32052
- ".htm": "text/html",
32053
- ".css": "text/css",
32054
- ".js": "text/javascript",
32055
- ".mjs": "text/javascript",
32056
- ".json": "application/json",
32057
- ".png": "image/png",
32058
- ".jpg": "image/jpeg",
32059
- ".jpeg": "image/jpeg",
32060
- ".gif": "image/gif",
32061
- ".svg": "image/svg+xml",
32062
- ".webp": "image/webp",
32063
- ".ico": "image/x-icon",
32064
- ".woff": "font/woff",
32065
- ".woff2": "font/woff2",
32066
- ".ttf": "font/ttf",
32067
- ".eot": "application/vnd.ms-fontobject",
32068
- ".pdf": "application/pdf"
32069
- };
32070
- function getMime(filePath) {
32071
- return MIME_MAP[path11.extname(filePath).toLowerCase()] ?? "application/octet-stream";
32072
- }
32073
- var PreviewServer = class {
32074
- server = null;
32075
- sessionManager;
32076
- constructor(sessionManager) {
32077
- this.sessionManager = sessionManager;
32078
- }
32079
- async start(port) {
32080
- return new Promise((resolve10, reject) => {
32081
- this.server = http.createServer((req, res) => this.handleRequest(req, res));
32082
- this.server.listen(port, () => {
32083
- const addr = this.server.address();
32084
- const actualPort = typeof addr === "object" && addr ? addr.port : port;
32085
- resolve10(actualPort);
32147
+ let engineCancelRequested = false;
32148
+ if (task.status === "running") {
32149
+ const engine = deps.engineRegistry.get(task.agent);
32150
+ if (!engine || typeof engine.cancelTask !== "function") {
32151
+ deps.logger.warn("engine not registered while cancelling running task", {
32152
+ taskId,
32153
+ agent: task.agent
32086
32154
  });
32087
- this.server.on("error", reject);
32088
- });
32089
- }
32090
- async stop() {
32091
- return new Promise((resolve10) => {
32092
- if (!this.server) {
32093
- resolve10();
32094
- return;
32155
+ } else {
32156
+ engineCancelRequested = engine.cancelTask(taskId);
32157
+ if (!engineCancelRequested) {
32158
+ deps.logger.warn("running task had no active engine process to cancel", {
32159
+ taskId,
32160
+ agent: task.agent
32161
+ });
32095
32162
  }
32096
- this.server.close(() => resolve10());
32097
- });
32098
- }
32099
- getPort() {
32100
- if (!this.server) return null;
32101
- const addr = this.server.address();
32102
- return typeof addr === "object" && addr ? addr.port : null;
32103
- }
32104
- handleRequest(req, res) {
32105
- if (req.method !== "GET") {
32106
- res.writeHead(405, { "Content-Type": "text/plain" });
32107
- res.end("Method not allowed");
32108
- return;
32109
- }
32110
- const url = new URL(req.url ?? "/", `http://localhost`);
32111
- const match = url.pathname.match(/^\/preview\/([a-f0-9]+)(?:\/(.*))?$/i);
32112
- const token = match?.[1];
32113
- if (!token) {
32114
- res.writeHead(404, { "Content-Type": "text/plain" });
32115
- res.end("Preview not found");
32116
- return;
32117
- }
32118
- const session = this.sessionManager.get(token);
32119
- if (!session) {
32120
- res.writeHead(403, { "Content-Type": "text/plain" });
32121
- res.end("Invalid or expired preview token");
32122
- return;
32123
32163
  }
32124
- const requestedPath = decodeURIComponent(match?.[2] ?? session.entryPath);
32125
- let resolved;
32126
- try {
32127
- resolved = resolvePreviewPath(session.rootPath, requestedPath).absolutePath;
32128
- } catch {
32129
- res.writeHead(400, { "Content-Type": "text/plain" });
32130
- res.end("Invalid path");
32131
- return;
32132
- }
32133
- if (!fs10.existsSync(resolved) || !fs10.statSync(resolved).isFile()) {
32134
- res.writeHead(404, { "Content-Type": "text/plain" });
32135
- res.end("File not found");
32136
- return;
32137
- }
32138
- const mime = getMime(resolved);
32139
- const content = fs10.readFileSync(resolved);
32140
- res.writeHead(200, {
32141
- "Content-Type": mime,
32142
- "Content-Length": content.length,
32143
- "Cache-Control": "no-cache"
32144
- });
32145
- res.end(content);
32146
32164
  }
32147
- };
32165
+ const cancelled = deps.taskEngine.cancelTask(taskId);
32166
+ if (!cancelled) {
32167
+ throw new MeshyError("VALIDATION_ERROR", `Task ${taskId} cannot be cancelled`, 400);
32168
+ }
32169
+ return {
32170
+ task,
32171
+ cancelled: true,
32172
+ engineCancelRequested,
32173
+ missing: false,
32174
+ terminal: false
32175
+ };
32176
+ }
32177
+
32178
+ // ../../packages/api/src/task-output-service.ts
32179
+ var fs12 = __toESM(require("fs"), 1);
32180
+ var path13 = __toESM(require("path"), 1);
32148
32181
 
32149
32182
  // ../../packages/api/src/output/helpers.ts
32150
- var fs11 = __toESM(require("fs"), 1);
32151
- var path12 = __toESM(require("path"), 1);
32183
+ var fs10 = __toESM(require("fs"), 1);
32184
+ var path11 = __toESM(require("path"), 1);
32152
32185
  var MAX_INLINE_SIZE = 512 * 1024;
32153
32186
  var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
32154
32187
  ".txt",
@@ -32225,7 +32258,7 @@ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
32225
32258
  ".ico",
32226
32259
  ".avif"
32227
32260
  ]);
32228
- var MIME_MAP2 = {
32261
+ var MIME_MAP = {
32229
32262
  ".png": "image/png",
32230
32263
  ".jpg": "image/jpeg",
32231
32264
  ".jpeg": "image/jpeg",
@@ -32258,18 +32291,18 @@ var MIME_MAP2 = {
32258
32291
  ".sh": "text/x-shellscript"
32259
32292
  };
32260
32293
  function mimeForExt(ext) {
32261
- return MIME_MAP2[ext] ?? "application/octet-stream";
32294
+ return MIME_MAP[ext] ?? "application/octet-stream";
32262
32295
  }
32263
32296
  function resolveOutputPath(root, relativePath) {
32264
- const resolved = path12.resolve(root, relativePath);
32265
- const normalizedRoot = path12.resolve(root);
32266
- if (!resolved.startsWith(normalizedRoot + path12.sep) && resolved !== normalizedRoot) {
32297
+ const resolved = path11.resolve(root, relativePath);
32298
+ const normalizedRoot = path11.resolve(root);
32299
+ if (!resolved.startsWith(normalizedRoot + path11.sep) && resolved !== normalizedRoot) {
32267
32300
  throw new Error("Path traversal detected");
32268
32301
  }
32269
32302
  return resolved;
32270
32303
  }
32271
32304
  function classifyFile(filePath) {
32272
- const ext = path12.extname(filePath).toLowerCase();
32305
+ const ext = path11.extname(filePath).toLowerCase();
32273
32306
  if (ext === ".json" || ext === ".jsonl" || ext === ".ndjson") {
32274
32307
  return { kind: "json", mimeType: "application/json" };
32275
32308
  }
@@ -32296,14 +32329,14 @@ function classifyFile(filePath) {
32296
32329
  }
32297
32330
  function listDirectory(root, relativePath) {
32298
32331
  const absPath = resolveOutputPath(root, relativePath);
32299
- if (!fs11.existsSync(absPath) || !fs11.statSync(absPath).isDirectory()) {
32332
+ if (!fs10.existsSync(absPath) || !fs10.statSync(absPath).isDirectory()) {
32300
32333
  return [];
32301
32334
  }
32302
- const entries = fs11.readdirSync(absPath, { withFileTypes: true });
32335
+ const entries = fs10.readdirSync(absPath, { withFileTypes: true });
32303
32336
  const result = [];
32304
32337
  for (const entry of entries) {
32305
32338
  if (entry.name.startsWith(".")) continue;
32306
- const entryRelPath = path12.join(relativePath || ".", entry.name).split(path12.sep).join("/");
32339
+ const entryRelPath = path11.join(relativePath || ".", entry.name).split(path11.sep).join("/");
32307
32340
  if (entry.isDirectory()) {
32308
32341
  result.push({
32309
32342
  path: entryRelPath,
@@ -32311,8 +32344,8 @@ function listDirectory(root, relativePath) {
32311
32344
  type: "directory"
32312
32345
  });
32313
32346
  } else if (entry.isFile()) {
32314
- const fullPath = path12.join(absPath, entry.name);
32315
- const stat = fs11.statSync(fullPath);
32347
+ const fullPath = path11.join(absPath, entry.name);
32348
+ const stat = fs10.statSync(fullPath);
32316
32349
  const { kind, mimeType } = classifyFile(entry.name);
32317
32350
  result.push({
32318
32351
  path: entryRelPath,
@@ -32332,11 +32365,11 @@ function listDirectory(root, relativePath) {
32332
32365
  }
32333
32366
  function detectHtmlEntries(root) {
32334
32367
  const entries = [];
32335
- if (fs11.existsSync(path12.join(root, "index.html"))) {
32368
+ if (fs10.existsSync(path11.join(root, "index.html"))) {
32336
32369
  entries.push({ path: "index.html", label: "index.html" });
32337
32370
  }
32338
32371
  try {
32339
- const topLevel = fs11.readdirSync(root, { withFileTypes: true });
32372
+ const topLevel = fs10.readdirSync(root, { withFileTypes: true });
32340
32373
  const htmlFiles = topLevel.filter(
32341
32374
  (e) => e.isFile() && e.name.endsWith(".html") && !e.name.startsWith(".")
32342
32375
  );
@@ -32347,8 +32380,8 @@ function detectHtmlEntries(root) {
32347
32380
  }
32348
32381
  const subdirs = topLevel.filter((e) => e.isDirectory() && !e.name.startsWith("."));
32349
32382
  for (const dir of subdirs) {
32350
- const subIndex = path12.join(root, dir.name, "index.html");
32351
- if (fs11.existsSync(subIndex)) {
32383
+ const subIndex = path11.join(root, dir.name, "index.html");
32384
+ if (fs10.existsSync(subIndex)) {
32352
32385
  entries.push({
32353
32386
  path: `${dir.name}/index.html`,
32354
32387
  label: `${dir.name}/index.html`
@@ -32360,11 +32393,11 @@ function detectHtmlEntries(root) {
32360
32393
  return entries;
32361
32394
  }
32362
32395
  function getOutputSummary(root) {
32363
- const rootName = path12.basename(root);
32396
+ const rootName = path11.basename(root);
32364
32397
  const htmlEntries = detectHtmlEntries(root);
32365
32398
  let fileCount;
32366
32399
  try {
32367
- const entries = fs11.readdirSync(root, { withFileTypes: true });
32400
+ const entries = fs10.readdirSync(root, { withFileTypes: true });
32368
32401
  fileCount = entries.filter((e) => !e.name.startsWith(".")).length;
32369
32402
  } catch {
32370
32403
  fileCount = void 0;
@@ -32380,14 +32413,14 @@ function getOutputSummary(root) {
32380
32413
  }
32381
32414
  function readFileContent(root, relativePath) {
32382
32415
  const absPath = resolveOutputPath(root, relativePath);
32383
- if (!fs11.existsSync(absPath) || !fs11.statSync(absPath).isFile()) {
32416
+ if (!fs10.existsSync(absPath) || !fs10.statSync(absPath).isFile()) {
32384
32417
  throw new Error("File not found");
32385
32418
  }
32386
- const stat = fs11.statSync(absPath);
32419
+ const stat = fs10.statSync(absPath);
32387
32420
  const { kind, mimeType } = classifyFile(absPath);
32388
32421
  if (kind === "image" || kind === "pdf" || kind === "binary") {
32389
32422
  const truncated2 = stat.size > MAX_INLINE_SIZE;
32390
- const buffer = truncated2 ? Buffer.alloc(0) : fs11.readFileSync(absPath);
32423
+ const buffer = truncated2 ? Buffer.alloc(0) : fs10.readFileSync(absPath);
32391
32424
  return {
32392
32425
  path: relativePath,
32393
32426
  kind,
@@ -32398,7 +32431,7 @@ function readFileContent(root, relativePath) {
32398
32431
  };
32399
32432
  }
32400
32433
  const truncated = stat.size > MAX_INLINE_SIZE;
32401
- const content = truncated ? fs11.readFileSync(absPath, "utf-8").slice(0, MAX_INLINE_SIZE) : fs11.readFileSync(absPath, "utf-8");
32434
+ const content = truncated ? fs10.readFileSync(absPath, "utf-8").slice(0, MAX_INLINE_SIZE) : fs10.readFileSync(absPath, "utf-8");
32402
32435
  return {
32403
32436
  path: relativePath,
32404
32437
  kind,
@@ -32458,62 +32491,264 @@ function getGitDiff(dirPath) {
32458
32491
  };
32459
32492
  }
32460
32493
 
32461
- // ../../packages/api/src/task-cancellation.ts
32462
- var TERMINAL_STATUSES2 = /* @__PURE__ */ new Set(["completed", "failed", "cancelled", "archived"]);
32463
- function cancelTaskOnCurrentNode(deps, taskId, options = {}) {
32464
- const task = deps.taskEngine.getTask(taskId);
32465
- if (!task) {
32466
- if (options.missingOk) {
32467
- return {
32468
- task: null,
32469
- cancelled: false,
32470
- engineCancelRequested: false,
32471
- missing: true,
32472
- terminal: false
32473
- };
32494
+ // ../../packages/api/src/preview/preview-server.ts
32495
+ var crypto2 = __toESM(require("crypto"), 1);
32496
+ var fs11 = __toESM(require("fs"), 1);
32497
+ var path12 = __toESM(require("path"), 1);
32498
+ var http = __toESM(require("http"), 1);
32499
+ function resolvePreviewPath(rootPath, relativePath) {
32500
+ const sanitizedPath = relativePath.replace(/\\/g, "/");
32501
+ const resolvedPath = path12.resolve(rootPath, sanitizedPath);
32502
+ const normalizedRoot = path12.resolve(rootPath);
32503
+ if (!resolvedPath.startsWith(normalizedRoot + path12.sep) && resolvedPath !== normalizedRoot) {
32504
+ throw new Error("Invalid preview path");
32505
+ }
32506
+ return {
32507
+ absolutePath: resolvedPath,
32508
+ normalizedPath: path12.relative(normalizedRoot, resolvedPath).split(path12.sep).join("/")
32509
+ };
32510
+ }
32511
+ function resolvePreviewEntryPath(rootPath, entryPath) {
32512
+ const { absolutePath, normalizedPath } = resolvePreviewPath(rootPath, entryPath ?? "index.html");
32513
+ if (!fs11.existsSync(absolutePath) || !fs11.statSync(absolutePath).isFile()) {
32514
+ throw new Error("Preview entry not found");
32515
+ }
32516
+ return normalizedPath;
32517
+ }
32518
+ function buildPreviewUrl(origin, session) {
32519
+ const encodedEntryPath = session.entryPath.split("/").filter(Boolean).map((segment) => encodeURIComponent(segment)).join("/");
32520
+ return `${origin.replace(/\/+$/, "")}/preview/${session.token}/${encodedEntryPath}`;
32521
+ }
32522
+ var DEFAULT_TTL_MS = 15 * 60 * 1e3;
32523
+ var PreviewSessionManager = class {
32524
+ sessions = /* @__PURE__ */ new Map();
32525
+ create(options) {
32526
+ const token = crypto2.randomBytes(32).toString("hex");
32527
+ const entryPath = resolvePreviewEntryPath(options.rootPath, options.entryPath);
32528
+ const session = {
32529
+ token,
32530
+ taskId: options.taskId,
32531
+ rootPath: options.rootPath,
32532
+ entryPath,
32533
+ expiresAt: Date.now() + (options.ttlMs ?? DEFAULT_TTL_MS)
32534
+ };
32535
+ this.sessions.set(token, session);
32536
+ return session;
32537
+ }
32538
+ get(token) {
32539
+ const session = this.sessions.get(token);
32540
+ if (!session) return null;
32541
+ if (Date.now() > session.expiresAt) {
32542
+ this.sessions.delete(token);
32543
+ return null;
32474
32544
  }
32545
+ return session;
32546
+ }
32547
+ cleanup() {
32548
+ const now = Date.now();
32549
+ for (const [token, session] of this.sessions) {
32550
+ if (now > session.expiresAt) {
32551
+ this.sessions.delete(token);
32552
+ }
32553
+ }
32554
+ }
32555
+ };
32556
+ var MIME_MAP2 = {
32557
+ ".html": "text/html",
32558
+ ".htm": "text/html",
32559
+ ".css": "text/css",
32560
+ ".js": "text/javascript",
32561
+ ".mjs": "text/javascript",
32562
+ ".json": "application/json",
32563
+ ".png": "image/png",
32564
+ ".jpg": "image/jpeg",
32565
+ ".jpeg": "image/jpeg",
32566
+ ".gif": "image/gif",
32567
+ ".svg": "image/svg+xml",
32568
+ ".webp": "image/webp",
32569
+ ".ico": "image/x-icon",
32570
+ ".woff": "font/woff",
32571
+ ".woff2": "font/woff2",
32572
+ ".ttf": "font/ttf",
32573
+ ".eot": "application/vnd.ms-fontobject",
32574
+ ".pdf": "application/pdf"
32575
+ };
32576
+ function getMime(filePath) {
32577
+ return MIME_MAP2[path12.extname(filePath).toLowerCase()] ?? "application/octet-stream";
32578
+ }
32579
+ function handlePreviewRequest(sessionManager, req, res) {
32580
+ const url = new URL(req.url ?? "/", "http://localhost");
32581
+ if (!url.pathname.startsWith("/preview/")) {
32582
+ return false;
32583
+ }
32584
+ if (req.method !== "GET") {
32585
+ res.writeHead(405, { "Content-Type": "text/plain" });
32586
+ res.end("Method not allowed");
32587
+ return true;
32588
+ }
32589
+ const match = url.pathname.match(/^\/preview\/([a-f0-9]+)(?:\/(.*))?$/i);
32590
+ const token = match?.[1];
32591
+ if (!token) {
32592
+ res.writeHead(404, { "Content-Type": "text/plain" });
32593
+ res.end("Preview not found");
32594
+ return true;
32595
+ }
32596
+ const session = sessionManager.get(token);
32597
+ if (!session) {
32598
+ res.writeHead(403, { "Content-Type": "text/plain" });
32599
+ res.end("Invalid or expired preview token");
32600
+ return true;
32601
+ }
32602
+ const requestedPath = decodeURIComponent(match?.[2] ?? session.entryPath);
32603
+ let resolved;
32604
+ try {
32605
+ resolved = resolvePreviewPath(session.rootPath, requestedPath).absolutePath;
32606
+ } catch {
32607
+ res.writeHead(400, { "Content-Type": "text/plain" });
32608
+ res.end("Invalid path");
32609
+ return true;
32610
+ }
32611
+ if (!fs11.existsSync(resolved) || !fs11.statSync(resolved).isFile()) {
32612
+ res.writeHead(404, { "Content-Type": "text/plain" });
32613
+ res.end("File not found");
32614
+ return true;
32615
+ }
32616
+ const mime = getMime(resolved);
32617
+ const content = fs11.readFileSync(resolved);
32618
+ res.writeHead(200, {
32619
+ "Content-Type": mime,
32620
+ "Content-Length": content.length,
32621
+ "Cache-Control": "no-cache"
32622
+ });
32623
+ res.end(content);
32624
+ return true;
32625
+ }
32626
+
32627
+ // ../../packages/api/src/task-output-service.ts
32628
+ var TASK_OUTPUT_ROUTE_PREFIX = "/api/tasks";
32629
+ function getTask(taskEngine, taskId) {
32630
+ const task = taskEngine.getTask(taskId);
32631
+ if (!task) {
32475
32632
  throw new MeshyError("TASK_NOT_FOUND", `Task ${taskId} not found`, 404);
32476
32633
  }
32477
- if (TERMINAL_STATUSES2.has(task.status)) {
32478
- if (options.terminalOk) {
32479
- return {
32480
- task,
32481
- cancelled: false,
32482
- engineCancelRequested: false,
32483
- missing: false,
32484
- terminal: true
32485
- };
32634
+ return task;
32635
+ }
32636
+ function getTaskOutputRoot(taskEngine, taskId) {
32637
+ const task = getTask(taskEngine, taskId);
32638
+ if (!task.effectiveProjectPath) {
32639
+ throw new MeshyError("VALIDATION_ERROR", "Task output not available", 400);
32640
+ }
32641
+ return task.effectiveProjectPath;
32642
+ }
32643
+ function buildTaskOutputDownloadUrl(taskId, filePath) {
32644
+ return `${TASK_OUTPUT_ROUTE_PREFIX}/${taskId}/output/download?path=${encodeURIComponent(filePath)}`;
32645
+ }
32646
+ function getLocalTaskOutputSummary(taskEngine, taskId) {
32647
+ const task = getTask(taskEngine, taskId);
32648
+ if (!task.effectiveProjectPath) {
32649
+ return {
32650
+ taskId: task.id,
32651
+ requestedProject: task.project,
32652
+ effectiveProjectPath: null,
32653
+ assignedTo: task.assignedTo,
32654
+ available: false,
32655
+ summary: null
32656
+ };
32657
+ }
32658
+ return {
32659
+ taskId: task.id,
32660
+ requestedProject: task.project,
32661
+ effectiveProjectPath: task.effectiveProjectPath,
32662
+ assignedTo: task.assignedTo,
32663
+ available: true,
32664
+ summary: getOutputSummary(task.effectiveProjectPath)
32665
+ };
32666
+ }
32667
+ function getLocalTaskOutputTree(taskEngine, taskId, currentPath) {
32668
+ const rootPath = getTaskOutputRoot(taskEngine, taskId);
32669
+ try {
32670
+ return {
32671
+ rootPath,
32672
+ currentPath,
32673
+ entries: listDirectory(rootPath, currentPath)
32674
+ };
32675
+ } catch (err) {
32676
+ if (err instanceof Error && err.message === "Path traversal detected") {
32677
+ throw new MeshyError("VALIDATION_ERROR", "Invalid directory path", 400);
32486
32678
  }
32487
- throw new MeshyError("VALIDATION_ERROR", `Task ${taskId} cannot be cancelled (status: ${task.status})`, 400);
32679
+ throw err;
32488
32680
  }
32489
- let engineCancelRequested = false;
32490
- if (task.status === "running") {
32491
- const engine = deps.engineRegistry.get(task.agent);
32492
- if (!engine || typeof engine.cancelTask !== "function") {
32493
- deps.logger.warn("engine not registered while cancelling running task", {
32494
- taskId,
32495
- agent: task.agent
32496
- });
32497
- } else {
32498
- engineCancelRequested = engine.cancelTask(taskId);
32499
- if (!engineCancelRequested) {
32500
- deps.logger.warn("running task had no active engine process to cancel", {
32501
- taskId,
32502
- agent: task.agent
32503
- });
32681
+ }
32682
+ function getLocalTaskOutputContent(taskEngine, taskId, filePath) {
32683
+ const rootPath = getTaskOutputRoot(taskEngine, taskId);
32684
+ try {
32685
+ return {
32686
+ ...readFileContent(rootPath, filePath),
32687
+ downloadUrl: buildTaskOutputDownloadUrl(taskId, filePath)
32688
+ };
32689
+ } catch (err) {
32690
+ if (err instanceof Error && err.message === "Path traversal detected") {
32691
+ throw new MeshyError("VALIDATION_ERROR", "Invalid file path", 400);
32692
+ }
32693
+ if (err instanceof Error && err.message === "File not found") {
32694
+ throw new MeshyError("TASK_NOT_FOUND", `File not found: ${filePath}`, 404);
32695
+ }
32696
+ throw err;
32697
+ }
32698
+ }
32699
+ function getLocalTaskOutputDownload(taskEngine, taskId, filePath) {
32700
+ const rootPath = getTaskOutputRoot(taskEngine, taskId);
32701
+ try {
32702
+ const absolutePath = resolveOutputPath(rootPath, filePath);
32703
+ if (!fs12.existsSync(absolutePath) || !fs12.statSync(absolutePath).isFile()) {
32704
+ throw new MeshyError("TASK_NOT_FOUND", `File not found: ${filePath}`, 404);
32705
+ }
32706
+ const { mimeType } = classifyFile(absolutePath);
32707
+ const fileName = path13.basename(absolutePath).replace(/"/g, "");
32708
+ return {
32709
+ content: fs12.readFileSync(absolutePath),
32710
+ headers: {
32711
+ "Content-Type": mimeType,
32712
+ "Content-Disposition": `inline; filename="${fileName}"`,
32713
+ "Cache-Control": "no-cache"
32504
32714
  }
32715
+ };
32716
+ } catch (err) {
32717
+ if (err instanceof MeshyError) {
32718
+ throw err;
32719
+ }
32720
+ if (err instanceof Error && err.message === "Path traversal detected") {
32721
+ throw new MeshyError("VALIDATION_ERROR", "Invalid file path", 400);
32505
32722
  }
32723
+ throw err;
32506
32724
  }
32507
- const cancelled = deps.taskEngine.cancelTask(taskId);
32508
- if (!cancelled) {
32509
- throw new MeshyError("VALIDATION_ERROR", `Task ${taskId} cannot be cancelled`, 400);
32725
+ }
32726
+ function getLocalTaskOutputDiff(taskEngine, taskId) {
32727
+ const rootPath = getTaskOutputRoot(taskEngine, taskId);
32728
+ return getGitDiff(rootPath);
32729
+ }
32730
+ async function createPreviewSessionPayload(deps, taskId, entryPath) {
32731
+ const previewManager = deps.previewSessionManager;
32732
+ if (!previewManager) {
32733
+ throw new MeshyError("VALIDATION_ERROR", "Preview not available on this node", 400);
32734
+ }
32735
+ if (!deps.previewPort) {
32736
+ throw new MeshyError("VALIDATION_ERROR", "Preview server not running", 400);
32737
+ }
32738
+ const rootPath = getTaskOutputRoot(deps.taskEngine, taskId);
32739
+ const session = previewManager.create({
32740
+ taskId,
32741
+ rootPath,
32742
+ entryPath
32743
+ });
32744
+ const origin = deps.ensurePreviewOrigin ? await deps.ensurePreviewOrigin() ?? deps.previewOrigin : deps.previewOrigin;
32745
+ if (!origin) {
32746
+ throw new MeshyError("VALIDATION_ERROR", "Preview origin not available", 502);
32510
32747
  }
32511
32748
  return {
32512
- task,
32513
- cancelled: true,
32514
- engineCancelRequested,
32515
- missing: false,
32516
- terminal: false
32749
+ previewUrl: buildPreviewUrl(origin, session),
32750
+ expiresAt: session.expiresAt,
32751
+ entryPath: session.entryPath
32517
32752
  };
32518
32753
  }
32519
32754
 
@@ -32555,46 +32790,17 @@ function errorResponse(requestId, err) {
32555
32790
  }
32556
32791
  });
32557
32792
  }
32558
- function getTask(taskEngine, taskId) {
32559
- const task = taskEngine.getTask(taskId);
32560
- if (!task) {
32561
- throw new MeshyError("TASK_NOT_FOUND", `Task ${taskId} not found`, 404);
32562
- }
32563
- return task;
32564
- }
32565
- function getTaskOutputRoot(taskEngine, taskId) {
32566
- const task = getTask(taskEngine, taskId);
32567
- if (!task.effectiveProjectPath) {
32568
- throw new MeshyError("VALIDATION_ERROR", "Task output not available", 400);
32569
- }
32570
- return task.effectiveProjectPath;
32571
- }
32572
- async function createPreviewSessionPayload(deps, taskId, entryPath) {
32573
- const previewManager = deps.previewSessionManager;
32574
- if (!previewManager) {
32575
- throw new MeshyError("VALIDATION_ERROR", "Preview not available on this node", 400);
32576
- }
32577
- if (!deps.previewPort) {
32578
- throw new MeshyError("VALIDATION_ERROR", "Preview server not running", 400);
32579
- }
32580
- const rootPath = getTaskOutputRoot(deps.taskEngine, taskId);
32581
- const session = previewManager.create({
32582
- taskId,
32583
- rootPath,
32584
- entryPath
32585
- });
32586
- const origin = deps.ensurePreviewOrigin ? await deps.ensurePreviewOrigin() ?? deps.previewOrigin : deps.previewOrigin;
32587
- if (!origin) {
32588
- throw new MeshyError("VALIDATION_ERROR", "Preview origin not available", 502);
32589
- }
32590
- return {
32591
- previewUrl: buildPreviewUrl(origin, session),
32592
- expiresAt: session.expiresAt,
32593
- entryPath: session.entryPath
32594
- };
32595
- }
32596
32793
  async function executeWorkerControlRequest(deps, request) {
32794
+ const log = deps.logger.child("worker-control");
32795
+ log.info("received worker control request", {
32796
+ requestId: request.requestId,
32797
+ kind: request.kind,
32798
+ taskId: request.taskId,
32799
+ path: request.path,
32800
+ enabled: request.enabled
32801
+ });
32597
32802
  try {
32803
+ let response;
32598
32804
  switch (request.kind) {
32599
32805
  case "devtunnel": {
32600
32806
  assertCanChangeNodeDevTunnel(deps.taskEngine, deps.nodeRegistry.getSelf().id);
@@ -32603,22 +32809,24 @@ async function executeWorkerControlRequest(deps, request) {
32603
32809
  throw new MeshyError("VALIDATION_ERROR", "DevTunnel control not available", 501);
32604
32810
  }
32605
32811
  const devtunnelEndpoint = await deps.enableDevTunnel();
32606
- return jsonResponse(request.requestId, 200, {
32812
+ response = jsonResponse(request.requestId, 200, {
32607
32813
  ok: true,
32608
32814
  enabled: true,
32609
32815
  devtunnelEndpoint,
32610
32816
  dashboardOrigin: deps.nodeRegistry.getSelf().dashboardOrigin
32611
32817
  });
32818
+ break;
32612
32819
  }
32613
32820
  if (!deps.disableDevTunnel) {
32614
32821
  throw new MeshyError("VALIDATION_ERROR", "DevTunnel control not available", 501);
32615
32822
  }
32616
32823
  await deps.disableDevTunnel();
32617
- return jsonResponse(request.requestId, 200, {
32824
+ response = jsonResponse(request.requestId, 200, {
32618
32825
  ok: true,
32619
32826
  enabled: false,
32620
32827
  dashboardOrigin: deps.nodeRegistry.getSelf().dashboardOrigin
32621
32828
  });
32829
+ break;
32622
32830
  }
32623
32831
  case "task-cancel": {
32624
32832
  const taskId = request.taskId ?? "";
@@ -32630,7 +32838,7 @@ async function executeWorkerControlRequest(deps, request) {
32630
32838
  missingOk: true,
32631
32839
  terminalOk: true
32632
32840
  });
32633
- return jsonResponse(request.requestId, 200, {
32841
+ response = jsonResponse(request.requestId, 200, {
32634
32842
  ok: true,
32635
32843
  taskId,
32636
32844
  cancelled: result.cancelled,
@@ -32638,97 +32846,77 @@ async function executeWorkerControlRequest(deps, request) {
32638
32846
  missing: result.missing,
32639
32847
  terminal: result.terminal
32640
32848
  });
32849
+ break;
32641
32850
  }
32642
32851
  case "task-output-summary": {
32643
- const task = getTask(deps.taskEngine, request.taskId ?? "");
32644
- if (!task.effectiveProjectPath) {
32645
- return jsonResponse(request.requestId, 200, {
32646
- taskId: task.id,
32647
- requestedProject: task.project,
32648
- effectiveProjectPath: null,
32649
- assignedTo: task.assignedTo,
32650
- available: false,
32651
- summary: null
32652
- });
32653
- }
32654
- return jsonResponse(request.requestId, 200, {
32655
- taskId: task.id,
32656
- requestedProject: task.project,
32657
- effectiveProjectPath: task.effectiveProjectPath,
32658
- assignedTo: task.assignedTo,
32659
- available: true,
32660
- summary: getOutputSummary(task.effectiveProjectPath)
32661
- });
32852
+ response = jsonResponse(
32853
+ request.requestId,
32854
+ 200,
32855
+ getLocalTaskOutputSummary(deps.taskEngine, request.taskId ?? "")
32856
+ );
32857
+ break;
32662
32858
  }
32663
32859
  case "task-output-tree": {
32664
- const rootPath = getTaskOutputRoot(deps.taskEngine, request.taskId ?? "");
32665
- try {
32666
- return jsonResponse(request.requestId, 200, {
32667
- rootPath,
32668
- currentPath: request.path ?? ".",
32669
- entries: listDirectory(rootPath, request.path ?? ".")
32670
- });
32671
- } catch (err) {
32672
- if (err instanceof Error && err.message === "Path traversal detected") {
32673
- throw new MeshyError("VALIDATION_ERROR", "Invalid directory path", 400);
32674
- }
32675
- throw err;
32676
- }
32860
+ response = jsonResponse(
32861
+ request.requestId,
32862
+ 200,
32863
+ getLocalTaskOutputTree(deps.taskEngine, request.taskId ?? "", request.path ?? ".")
32864
+ );
32865
+ break;
32677
32866
  }
32678
32867
  case "task-output-content": {
32679
- const rootPath = getTaskOutputRoot(deps.taskEngine, request.taskId ?? "");
32680
- try {
32681
- const filePath = request.path ?? "";
32682
- return jsonResponse(request.requestId, 200, {
32683
- ...readFileContent(rootPath, filePath),
32684
- downloadUrl: `/api/tasks/${request.taskId}/output/download?path=${encodeURIComponent(filePath)}`
32685
- });
32686
- } catch (err) {
32687
- if (err instanceof Error && err.message === "Path traversal detected") {
32688
- throw new MeshyError("VALIDATION_ERROR", "Invalid file path", 400);
32689
- }
32690
- if (err instanceof Error && err.message === "File not found") {
32691
- throw new MeshyError("TASK_NOT_FOUND", `File not found: ${request.path}`, 404);
32692
- }
32693
- throw err;
32694
- }
32868
+ response = jsonResponse(
32869
+ request.requestId,
32870
+ 200,
32871
+ getLocalTaskOutputContent(deps.taskEngine, request.taskId ?? "", request.path ?? "")
32872
+ );
32873
+ break;
32695
32874
  }
32696
32875
  case "task-output-download": {
32697
- const rootPath = getTaskOutputRoot(deps.taskEngine, request.taskId ?? "");
32698
- try {
32699
- const absolutePath = resolveOutputPath(rootPath, request.path ?? "");
32700
- if (!fs12.existsSync(absolutePath) || !fs12.statSync(absolutePath).isFile()) {
32701
- throw new MeshyError("TASK_NOT_FOUND", `File not found: ${request.path}`, 404);
32702
- }
32703
- const { mimeType } = classifyFile(absolutePath);
32704
- const fileName = path13.basename(absolutePath).replace(/"/g, "");
32705
- return binaryResponse(request.requestId, 200, fs12.readFileSync(absolutePath), {
32706
- "Content-Type": mimeType,
32707
- "Content-Disposition": `inline; filename="${fileName}"`,
32708
- "Cache-Control": "no-cache"
32709
- });
32710
- } catch (err) {
32711
- if (err instanceof MeshyError) throw err;
32712
- if (err instanceof Error && err.message === "Path traversal detected") {
32713
- throw new MeshyError("VALIDATION_ERROR", "Invalid file path", 400);
32714
- }
32715
- throw err;
32716
- }
32876
+ const download = getLocalTaskOutputDownload(deps.taskEngine, request.taskId ?? "", request.path ?? "");
32877
+ response = binaryResponse(request.requestId, 200, download.content, download.headers);
32878
+ break;
32717
32879
  }
32718
32880
  case "task-output-diff": {
32719
- const rootPath = getTaskOutputRoot(deps.taskEngine, request.taskId ?? "");
32720
- return jsonResponse(request.requestId, 200, getGitDiff(rootPath));
32881
+ response = jsonResponse(
32882
+ request.requestId,
32883
+ 200,
32884
+ getLocalTaskOutputDiff(deps.taskEngine, request.taskId ?? "")
32885
+ );
32886
+ break;
32721
32887
  }
32722
32888
  case "task-preview-session": {
32723
- return jsonResponse(
32889
+ response = jsonResponse(
32724
32890
  request.requestId,
32725
32891
  200,
32726
32892
  await createPreviewSessionPayload(deps, request.taskId ?? "", request.path)
32727
32893
  );
32894
+ break;
32728
32895
  }
32729
32896
  }
32897
+ log.info("completed worker control request", {
32898
+ requestId: request.requestId,
32899
+ kind: request.kind,
32900
+ taskId: request.taskId,
32901
+ path: request.path,
32902
+ enabled: request.enabled,
32903
+ ok: response.ok,
32904
+ statusCode: response.statusCode
32905
+ });
32906
+ return response;
32730
32907
  } catch (err) {
32731
- return errorResponse(request.requestId, err);
32908
+ const response = errorResponse(request.requestId, err);
32909
+ log.warn("worker control request failed", {
32910
+ requestId: request.requestId,
32911
+ kind: request.kind,
32912
+ taskId: request.taskId,
32913
+ path: request.path,
32914
+ enabled: request.enabled,
32915
+ ok: response.ok,
32916
+ statusCode: response.statusCode,
32917
+ error: err instanceof Error ? err.message : String(err)
32918
+ });
32919
+ return response;
32732
32920
  }
32733
32921
  }
32734
32922
  function sendWorkerControlResponse(res, response) {
@@ -32927,9 +33115,7 @@ function createNodeRoutes() {
32927
33115
  }
32928
33116
 
32929
33117
  // ../../packages/api/src/routes/tasks.ts
32930
- var fs14 = __toESM(require("fs"), 1);
32931
- var path14 = __toESM(require("path"), 1);
32932
- var import_express3 = __toESM(require_express2(), 1);
33118
+ var import_express4 = __toESM(require_express2(), 1);
32933
33119
 
32934
33120
  // ../../packages/api/src/task-route-utils.ts
32935
33121
  var fs13 = __toESM(require("fs"), 1);
@@ -33038,11 +33224,190 @@ function startLocalTaskFollowUp(deps, task, content, assignedTo, metadata) {
33038
33224
  }
33039
33225
  }
33040
33226
 
33227
+ // ../../packages/api/src/routes/task-output.ts
33228
+ var import_express3 = __toESM(require_express2(), 1);
33229
+ function asyncHandler3(fn) {
33230
+ return (req, res, next) => fn(req, res, next).catch(next);
33231
+ }
33232
+ async function maybeHandleRemoteTaskOutputRequest(req, res, taskId, subPath, init, fallbackRequest) {
33233
+ const { taskEngine, nodeRegistry, heartbeat, logger: rootLogger } = req.app.locals.deps;
33234
+ const log = rootLogger.child("tasks/output");
33235
+ const task = taskEngine.getTask(taskId);
33236
+ if (!task) {
33237
+ throw new MeshyError("TASK_NOT_FOUND", `Task ${taskId} not found`, 404);
33238
+ }
33239
+ const selfId = nodeRegistry.getSelf()?.id;
33240
+ const needsProxy = !!(task.assignedTo && task.assignedTo !== selfId);
33241
+ if (!needsProxy) {
33242
+ return false;
33243
+ }
33244
+ const assignedNodeId = task.assignedTo;
33245
+ if (!assignedNodeId) {
33246
+ return false;
33247
+ }
33248
+ const node = nodeRegistry.getNode(assignedNodeId);
33249
+ if (!node) {
33250
+ throw new MeshyError("NODE_NOT_FOUND", `Assigned node ${assignedNodeId} not found`, 404);
33251
+ }
33252
+ if (!node.previewOrigin) {
33253
+ if (fallbackRequest && heartbeat?.requestWorkerControl) {
33254
+ log.warn("task output server origin missing, falling back to keepalive control", {
33255
+ taskId,
33256
+ assignedTo: assignedNodeId,
33257
+ kind: fallbackRequest.kind
33258
+ });
33259
+ const controlResponse = await heartbeat.requestWorkerControl(assignedNodeId, fallbackRequest);
33260
+ sendWorkerControlResponse(res, controlResponse);
33261
+ return true;
33262
+ }
33263
+ throw new MeshyError("NODE_OFFLINE", "Task output API is not available on the assigned worker", 502);
33264
+ }
33265
+ const qs = new URL(req.originalUrl ?? req.url, "http://localhost").search;
33266
+ const proxyPath = `/api/tasks/${taskId}/output${subPath}${qs}`;
33267
+ try {
33268
+ const { endpoint, response: proxyRes } = await fetchNodeWithFallback(
33269
+ { endpoint: node.previewOrigin },
33270
+ proxyPath,
33271
+ init
33272
+ );
33273
+ log.debug("proxying task output request to worker output server", {
33274
+ taskId,
33275
+ assignedTo: assignedNodeId,
33276
+ proxyPath,
33277
+ outputOrigin: endpoint
33278
+ });
33279
+ await sendProxyResponse(res, proxyRes);
33280
+ return true;
33281
+ } catch (err) {
33282
+ if (fallbackRequest && heartbeat?.requestWorkerControl) {
33283
+ log.warn("output server proxy failed, falling back to keepalive control", {
33284
+ taskId,
33285
+ assignedTo: assignedNodeId,
33286
+ kind: fallbackRequest.kind,
33287
+ error: err instanceof Error ? err.message : String(err)
33288
+ });
33289
+ const controlResponse = await heartbeat.requestWorkerControl(assignedNodeId, fallbackRequest);
33290
+ sendWorkerControlResponse(res, controlResponse);
33291
+ return true;
33292
+ }
33293
+ log.warn("output server proxy error", {
33294
+ taskId,
33295
+ assignedTo: assignedNodeId,
33296
+ error: err instanceof Error ? err.message : String(err)
33297
+ });
33298
+ throw new MeshyError("NODE_OFFLINE", "Cannot reach worker for task output", 502);
33299
+ }
33300
+ }
33301
+ function createTaskOutputRoutes(options = {}) {
33302
+ const router = (0, import_express3.Router)();
33303
+ const allowRemoteProxy = options.allowRemoteProxy ?? true;
33304
+ router.get("/:id/output", asyncHandler3(async (req, res) => {
33305
+ const taskId = req.params.id;
33306
+ if (allowRemoteProxy) {
33307
+ const handled = await maybeHandleRemoteTaskOutputRequest(req, res, taskId, "", void 0, {
33308
+ kind: "task-output-summary",
33309
+ taskId
33310
+ });
33311
+ if (handled) {
33312
+ return;
33313
+ }
33314
+ }
33315
+ const { taskEngine } = req.app.locals.deps;
33316
+ res.json(getLocalTaskOutputSummary(taskEngine, taskId));
33317
+ }));
33318
+ router.get("/:id/output/tree", asyncHandler3(async (req, res) => {
33319
+ const taskId = req.params.id;
33320
+ const query = TaskOutputTreeQuery.parse(req.query);
33321
+ if (allowRemoteProxy) {
33322
+ const handled = await maybeHandleRemoteTaskOutputRequest(req, res, taskId, "/tree", void 0, {
33323
+ kind: "task-output-tree",
33324
+ taskId,
33325
+ path: query.path
33326
+ });
33327
+ if (handled) {
33328
+ return;
33329
+ }
33330
+ }
33331
+ const { taskEngine } = req.app.locals.deps;
33332
+ res.json(getLocalTaskOutputTree(taskEngine, taskId, query.path));
33333
+ }));
33334
+ router.get("/:id/output/content", asyncHandler3(async (req, res) => {
33335
+ const taskId = req.params.id;
33336
+ const query = TaskOutputContentQuery.parse(req.query);
33337
+ if (allowRemoteProxy) {
33338
+ const handled = await maybeHandleRemoteTaskOutputRequest(req, res, taskId, "/content", void 0, {
33339
+ kind: "task-output-content",
33340
+ taskId,
33341
+ path: query.path
33342
+ });
33343
+ if (handled) {
33344
+ return;
33345
+ }
33346
+ }
33347
+ const { taskEngine } = req.app.locals.deps;
33348
+ res.json(getLocalTaskOutputContent(taskEngine, taskId, query.path));
33349
+ }));
33350
+ router.get("/:id/output/download", asyncHandler3(async (req, res) => {
33351
+ const taskId = req.params.id;
33352
+ const query = TaskOutputDownloadQuery.parse(req.query);
33353
+ if (allowRemoteProxy) {
33354
+ const handled = await maybeHandleRemoteTaskOutputRequest(req, res, taskId, "/download", void 0, {
33355
+ kind: "task-output-download",
33356
+ taskId,
33357
+ path: query.path
33358
+ });
33359
+ if (handled) {
33360
+ return;
33361
+ }
33362
+ }
33363
+ const { taskEngine } = req.app.locals.deps;
33364
+ const download = getLocalTaskOutputDownload(taskEngine, taskId, query.path);
33365
+ for (const [key, value] of Object.entries(download.headers)) {
33366
+ res.setHeader(key, value);
33367
+ }
33368
+ res.send(download.content);
33369
+ }));
33370
+ router.get("/:id/output/diff", asyncHandler3(async (req, res) => {
33371
+ const taskId = req.params.id;
33372
+ if (allowRemoteProxy) {
33373
+ const handled = await maybeHandleRemoteTaskOutputRequest(req, res, taskId, "/diff", void 0, {
33374
+ kind: "task-output-diff",
33375
+ taskId
33376
+ });
33377
+ if (handled) {
33378
+ return;
33379
+ }
33380
+ }
33381
+ const { taskEngine } = req.app.locals.deps;
33382
+ res.json(getLocalTaskOutputDiff(taskEngine, taskId));
33383
+ }));
33384
+ router.post("/:id/output/preview-sessions", asyncHandler3(async (req, res) => {
33385
+ const taskId = req.params.id;
33386
+ const body = TaskPreviewSessionBody.parse(req.body ?? {});
33387
+ if (allowRemoteProxy) {
33388
+ const handled = await maybeHandleRemoteTaskOutputRequest(req, res, taskId, "/preview-sessions", {
33389
+ method: "POST",
33390
+ headers: { "Content-Type": "application/json" },
33391
+ body: JSON.stringify(body)
33392
+ }, {
33393
+ kind: "task-preview-session",
33394
+ taskId,
33395
+ path: body.path
33396
+ });
33397
+ if (handled) {
33398
+ return;
33399
+ }
33400
+ }
33401
+ res.json(await createPreviewSessionPayload(req.app.locals.deps, taskId, body.path));
33402
+ }));
33403
+ return router;
33404
+ }
33405
+
33041
33406
  // ../../packages/api/src/routes/tasks.ts
33042
33407
  var TERMINAL_STATUSES3 = /* @__PURE__ */ new Set(["completed", "failed", "cancelled", "archived"]);
33043
33408
  var ARCHIVABLE_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled", "archived"]);
33044
33409
  var ACTIVE_STATUSES = /* @__PURE__ */ new Set(["pending", "assigned", "running"]);
33045
- function asyncHandler3(fn) {
33410
+ function asyncHandler4(fn) {
33046
33411
  return (req, res, next) => fn(req, res, next).catch(next);
33047
33412
  }
33048
33413
  function withAssignedNodeMetadata(task, nodeRegistry) {
@@ -33057,8 +33422,8 @@ function withAssignedNodeMetadata(task, nodeRegistry) {
33057
33422
  };
33058
33423
  }
33059
33424
  function createTaskRoutes() {
33060
- const router = (0, import_express3.Router)();
33061
- router.post("/", asyncHandler3(async (req, res) => {
33425
+ const router = (0, import_express4.Router)();
33426
+ router.post("/", asyncHandler4(async (req, res) => {
33062
33427
  const { taskEngine, nodeRegistry } = req.app.locals.deps;
33063
33428
  const body = CreateTaskBody.parse(req.body);
33064
33429
  const task = taskEngine.createTask({
@@ -33077,7 +33442,7 @@ function createTaskRoutes() {
33077
33442
  }
33078
33443
  res.status(201).json(withAssignedNodeMetadata(task, nodeRegistry));
33079
33444
  }));
33080
- router.get("/", asyncHandler3(async (req, res) => {
33445
+ router.get("/", asyncHandler4(async (req, res) => {
33081
33446
  const { taskEngine, nodeRegistry } = req.app.locals.deps;
33082
33447
  const query = TaskListQuery.parse(req.query);
33083
33448
  const filter = {};
@@ -33092,7 +33457,7 @@ function createTaskRoutes() {
33092
33457
  total: result.total
33093
33458
  });
33094
33459
  }));
33095
- router.post("/batch/delete", asyncHandler3(async (req, res) => {
33460
+ router.post("/batch/delete", asyncHandler4(async (req, res) => {
33096
33461
  const { taskEngine } = req.app.locals.deps;
33097
33462
  const { ids } = BatchTaskIdsBody.parse(req.body);
33098
33463
  const results = ids.map((id) => {
@@ -33105,7 +33470,7 @@ function createTaskRoutes() {
33105
33470
  });
33106
33471
  res.json({ results });
33107
33472
  }));
33108
- router.post("/batch/archive", asyncHandler3(async (req, res) => {
33473
+ router.post("/batch/archive", asyncHandler4(async (req, res) => {
33109
33474
  const { taskEngine } = req.app.locals.deps;
33110
33475
  const { ids } = BatchTaskIdsBody.parse(req.body);
33111
33476
  const results = ids.map((id) => {
@@ -33123,7 +33488,7 @@ function createTaskRoutes() {
33123
33488
  });
33124
33489
  res.json({ results });
33125
33490
  }));
33126
- router.get("/:id", asyncHandler3(async (req, res) => {
33491
+ router.get("/:id", asyncHandler4(async (req, res) => {
33127
33492
  const { taskEngine, nodeRegistry } = req.app.locals.deps;
33128
33493
  const task = taskEngine.getTask(req.params.id);
33129
33494
  if (!task) {
@@ -33131,7 +33496,7 @@ function createTaskRoutes() {
33131
33496
  }
33132
33497
  res.json(withAssignedNodeMetadata(task, nodeRegistry));
33133
33498
  }));
33134
- router.patch("/:id", asyncHandler3(async (req, res) => {
33499
+ router.patch("/:id", asyncHandler4(async (req, res) => {
33135
33500
  const { taskEngine, nodeRegistry, logger: rootLogger } = req.app.locals.deps;
33136
33501
  const log = rootLogger.child("tasks/patch");
33137
33502
  const updates = UpdateTaskBody.parse(req.body);
@@ -33170,7 +33535,7 @@ function createTaskRoutes() {
33170
33535
  }
33171
33536
  res.json(withAssignedNodeMetadata(task, nodeRegistry));
33172
33537
  }));
33173
- router.delete("/:id", asyncHandler3(async (req, res) => {
33538
+ router.delete("/:id", asyncHandler4(async (req, res) => {
33174
33539
  const { taskEngine } = req.app.locals.deps;
33175
33540
  const result = taskEngine.deleteTask(req.params.id);
33176
33541
  if (!result) {
@@ -33178,7 +33543,7 @@ function createTaskRoutes() {
33178
33543
  }
33179
33544
  res.json({ ok: true });
33180
33545
  }));
33181
- router.post("/:id/cancel", asyncHandler3(async (req, res) => {
33546
+ router.post("/:id/cancel", asyncHandler4(async (req, res) => {
33182
33547
  const { taskEngine, nodeRegistry, engineRegistry, heartbeat, logger: rootLogger } = req.app.locals.deps;
33183
33548
  const log = rootLogger.child("tasks/cancel");
33184
33549
  const task = taskEngine.getTask(req.params.id);
@@ -33215,18 +33580,18 @@ function createTaskRoutes() {
33215
33580
  }, task.id);
33216
33581
  res.json({ ok: true });
33217
33582
  }));
33218
- router.post("/:id/assign", asyncHandler3(async (req, res) => {
33583
+ router.post("/:id/assign", asyncHandler4(async (req, res) => {
33219
33584
  const { taskEngine, nodeRegistry } = req.app.locals.deps;
33220
33585
  const body = AssignTaskBody.parse(req.body);
33221
33586
  const task = taskEngine.assignTask(req.params.id, body.nodeId);
33222
33587
  res.json(withAssignedNodeMetadata(task, nodeRegistry));
33223
33588
  }));
33224
- router.post("/:id/retry", asyncHandler3(async (req, res) => {
33589
+ router.post("/:id/retry", asyncHandler4(async (req, res) => {
33225
33590
  const { taskEngine, nodeRegistry } = req.app.locals.deps;
33226
33591
  const task = taskEngine.retryTask(req.params.id);
33227
33592
  res.json(withAssignedNodeMetadata(task, nodeRegistry));
33228
33593
  }));
33229
- router.get("/:id/logs", asyncHandler3(async (req, res) => {
33594
+ router.get("/:id/logs", asyncHandler4(async (req, res) => {
33230
33595
  const { engineRegistry, taskEngine, nodeRegistry, logger: rootLogger } = req.app.locals.deps;
33231
33596
  const log = rootLogger.child("tasks/logs");
33232
33597
  const query = TaskLogsQuery.parse(req.query);
@@ -33293,7 +33658,7 @@ function createTaskRoutes() {
33293
33658
  });
33294
33659
  res.json(local);
33295
33660
  }));
33296
- router.post("/:id/message", asyncHandler3(async (req, res) => {
33661
+ router.post("/:id/message", asyncHandler4(async (req, res) => {
33297
33662
  const { taskEngine, engineRegistry, nodeRegistry, heartbeat, logger: rootLogger } = req.app.locals.deps;
33298
33663
  const log = rootLogger.child("tasks/message");
33299
33664
  const body = SendMessageBody.parse(req.body);
@@ -33377,281 +33742,24 @@ function createTaskRoutes() {
33377
33742
  }, task, body.content, task.assignedTo);
33378
33743
  res.json({ ok: true });
33379
33744
  }));
33380
- async function resolveTaskOutputOrProxy(req, res, taskId, subPath, init, fallbackRequest) {
33381
- const { taskEngine, nodeRegistry, heartbeat, logger: rootLogger } = req.app.locals.deps;
33382
- const log = rootLogger.child("tasks/output");
33383
- const task = taskEngine.getTask(taskId);
33384
- if (!task) {
33385
- throw new MeshyError("TASK_NOT_FOUND", `Task ${taskId} not found`, 404);
33386
- }
33387
- const effectivePath = task.effectiveProjectPath;
33388
- if (!effectivePath) {
33389
- throw new MeshyError("VALIDATION_ERROR", "Task output not available", 400);
33390
- }
33391
- const selfId = nodeRegistry.getSelf()?.id;
33392
- const needsProxy = !!(task.assignedTo && task.assignedTo !== selfId);
33393
- if (needsProxy) {
33394
- const node = nodeRegistry.getNode(task.assignedTo);
33395
- if (!node) {
33396
- throw new MeshyError("NODE_NOT_FOUND", `Assigned node ${task.assignedTo} not found`, 404);
33397
- }
33398
- const canPushToNode = heartbeat?.canPushToNode?.(task.assignedTo) ?? true;
33399
- if (!canPushToNode && fallbackRequest && heartbeat?.requestWorkerControl) {
33400
- log.debug("skipping direct output proxy because worker is keepalive-only", {
33401
- taskId,
33402
- assignedTo: task.assignedTo,
33403
- kind: fallbackRequest.kind
33404
- });
33405
- const controlResponse = await heartbeat.requestWorkerControl(task.assignedTo, fallbackRequest);
33406
- sendWorkerControlResponse(res, controlResponse);
33407
- return null;
33408
- }
33409
- const qs = new URL(req.url, "http://localhost").search;
33410
- const proxyPath = `/api/tasks/${taskId}/output${subPath}${qs}`;
33411
- try {
33412
- const { endpoint, response: proxyRes } = await fetchNodeWithFallback(node, proxyPath, init);
33413
- const proxyUrl = `${endpoint}${proxyPath}`;
33414
- log.debug("proxying output request to worker", { taskId, proxyUrl });
33415
- await sendProxyResponse(res, proxyRes);
33416
- return null;
33417
- } catch (err) {
33418
- if (fallbackRequest && heartbeat?.requestWorkerControl) {
33419
- log.warn("direct output proxy failed, falling back to keepalive control", {
33420
- taskId,
33421
- assignedTo: task.assignedTo,
33422
- kind: fallbackRequest.kind,
33423
- error: err instanceof Error ? err.message : String(err)
33424
- });
33425
- try {
33426
- const controlResponse = await heartbeat.requestWorkerControl(task.assignedTo, fallbackRequest);
33427
- sendWorkerControlResponse(res, controlResponse);
33428
- return null;
33429
- } catch (fallbackErr) {
33430
- log.warn("keepalive output fallback failed", {
33431
- taskId,
33432
- assignedTo: task.assignedTo,
33433
- kind: fallbackRequest.kind,
33434
- error: fallbackErr instanceof Error ? fallbackErr.message : String(fallbackErr)
33435
- });
33436
- }
33437
- }
33438
- log.warn("output proxy error", { error: err instanceof Error ? err.message : String(err) });
33439
- throw new MeshyError("NODE_OFFLINE", "Cannot reach worker for task output", 502);
33440
- }
33441
- }
33442
- return effectivePath;
33443
- }
33444
- router.get("/:id/output", asyncHandler3(async (req, res) => {
33445
- const { taskEngine } = req.app.locals.deps;
33446
- const taskId = req.params.id;
33447
- const task = taskEngine.getTask(taskId);
33448
- if (!task) {
33449
- throw new MeshyError("TASK_NOT_FOUND", `Task ${taskId} not found`, 404);
33450
- }
33451
- const effectivePath = task.effectiveProjectPath;
33452
- if (!effectivePath) {
33453
- res.json({
33454
- taskId,
33455
- requestedProject: task.project,
33456
- effectiveProjectPath: null,
33457
- assignedTo: task.assignedTo,
33458
- available: false,
33459
- summary: null
33460
- });
33461
- return;
33462
- }
33463
- const root = await resolveTaskOutputOrProxy(req, res, taskId, "", void 0, {
33464
- kind: "task-output-summary",
33465
- taskId
33466
- });
33467
- if (root === null) return;
33468
- const summary = getOutputSummary(root);
33469
- res.json({
33470
- taskId,
33471
- requestedProject: task.project,
33472
- effectiveProjectPath: effectivePath,
33473
- assignedTo: task.assignedTo,
33474
- available: true,
33475
- summary
33476
- });
33477
- }));
33478
- router.get("/:id/output/tree", asyncHandler3(async (req, res) => {
33479
- const taskId = req.params.id;
33480
- const query = TaskOutputTreeQuery.parse(req.query);
33481
- const root = await resolveTaskOutputOrProxy(req, res, taskId, "/tree", void 0, {
33482
- kind: "task-output-tree",
33483
- taskId,
33484
- path: query.path
33485
- });
33486
- if (root === null) return;
33487
- try {
33488
- const entries = listDirectory(root, query.path);
33489
- res.json({
33490
- rootPath: root,
33491
- currentPath: query.path,
33492
- entries
33493
- });
33494
- } catch (err) {
33495
- if (err instanceof Error && err.message === "Path traversal detected") {
33496
- throw new MeshyError("VALIDATION_ERROR", "Invalid directory path", 400);
33497
- }
33498
- throw err;
33499
- }
33500
- }));
33501
- router.get("/:id/output/content", asyncHandler3(async (req, res) => {
33502
- const taskId = req.params.id;
33503
- const query = TaskOutputContentQuery.parse(req.query);
33504
- const root = await resolveTaskOutputOrProxy(req, res, taskId, "/content", void 0, {
33505
- kind: "task-output-content",
33506
- taskId,
33507
- path: query.path
33508
- });
33509
- if (root === null) return;
33510
- try {
33511
- const content = readFileContent(root, query.path);
33512
- res.json({
33513
- ...content,
33514
- downloadUrl: `/api/tasks/${taskId}/output/download?path=${encodeURIComponent(query.path)}`
33515
- });
33516
- } catch (err) {
33517
- if (err instanceof Error && err.message === "Path traversal detected") {
33518
- throw new MeshyError("VALIDATION_ERROR", "Invalid file path", 400);
33519
- }
33520
- if (err instanceof Error && err.message === "File not found") {
33521
- throw new MeshyError("TASK_NOT_FOUND", `File not found: ${query.path}`, 404);
33522
- }
33523
- throw err;
33524
- }
33525
- }));
33526
- router.get("/:id/output/download", asyncHandler3(async (req, res) => {
33527
- const taskId = req.params.id;
33528
- const query = TaskOutputDownloadQuery.parse(req.query);
33529
- const root = await resolveTaskOutputOrProxy(req, res, taskId, "/download", void 0, {
33530
- kind: "task-output-download",
33531
- taskId,
33532
- path: query.path
33533
- });
33534
- if (root === null) return;
33535
- try {
33536
- const absolutePath = resolveOutputPath(root, query.path);
33537
- if (!fs14.existsSync(absolutePath) || !fs14.statSync(absolutePath).isFile()) {
33538
- throw new MeshyError("TASK_NOT_FOUND", `File not found: ${query.path}`, 404);
33539
- }
33540
- const { mimeType } = classifyFile(absolutePath);
33541
- const fileName = path14.basename(absolutePath).replace(/"/g, "");
33542
- const content = fs14.readFileSync(absolutePath);
33543
- res.setHeader("Content-Type", mimeType);
33544
- res.setHeader("Content-Disposition", `inline; filename="${fileName}"`);
33545
- res.setHeader("Cache-Control", "no-cache");
33546
- res.send(content);
33547
- } catch (err) {
33548
- if (err instanceof MeshyError) throw err;
33549
- if (err instanceof Error && err.message === "Path traversal detected") {
33550
- throw new MeshyError("VALIDATION_ERROR", "Invalid file path", 400);
33551
- }
33552
- throw err;
33553
- }
33554
- }));
33555
- router.get("/:id/output/diff", asyncHandler3(async (req, res) => {
33556
- const taskId = req.params.id;
33557
- const root = await resolveTaskOutputOrProxy(req, res, taskId, "/diff", void 0, {
33558
- kind: "task-output-diff",
33559
- taskId
33560
- });
33561
- if (root === null) return;
33562
- const diff = getGitDiff(root);
33563
- res.json(diff);
33564
- }));
33565
- router.post("/:id/output/preview-sessions", asyncHandler3(async (req, res) => {
33566
- const { taskEngine, nodeRegistry, heartbeat, logger: rootLogger } = req.app.locals.deps;
33567
- const log = rootLogger.child("tasks/preview");
33568
- const taskId = req.params.id;
33569
- const body = TaskPreviewSessionBody.parse(req.body ?? {});
33570
- const task = taskEngine.getTask(taskId);
33571
- if (!task) {
33572
- throw new MeshyError("TASK_NOT_FOUND", `Task ${taskId} not found`, 404);
33573
- }
33574
- const effectivePath = task.effectiveProjectPath;
33575
- if (!effectivePath) {
33576
- throw new MeshyError("VALIDATION_ERROR", "Task output not available", 400);
33577
- }
33578
- const selfId = nodeRegistry.getSelf()?.id;
33579
- const needsProxy = !!(task.assignedTo && task.assignedTo !== selfId);
33580
- if (needsProxy) {
33581
- const node = nodeRegistry.getNode(task.assignedTo);
33582
- if (!node) {
33583
- throw new MeshyError("NODE_NOT_FOUND", `Assigned node ${task.assignedTo} not found`, 404);
33584
- }
33585
- const canPushToNode = heartbeat?.canPushToNode?.(task.assignedTo) ?? true;
33586
- if (!canPushToNode && heartbeat?.requestWorkerControl) {
33587
- log.debug("skipping direct preview proxy because worker is keepalive-only", {
33588
- taskId,
33589
- assignedTo: task.assignedTo
33590
- });
33591
- const controlResponse = await heartbeat.requestWorkerControl(task.assignedTo, {
33592
- kind: "task-preview-session",
33593
- taskId,
33594
- path: body.path
33595
- });
33596
- sendWorkerControlResponse(res, controlResponse);
33597
- return;
33598
- }
33599
- try {
33600
- const { endpoint, response: proxyRes } = await fetchNodeWithFallback(node, "/api/worker/preview-session", {
33601
- method: "POST",
33602
- headers: { "Content-Type": "application/json" },
33603
- body: JSON.stringify({ taskId, path: body.path })
33604
- });
33605
- const workerEndpoint = endpoint;
33606
- log.debug("proxying preview session request to worker", { taskId, workerEndpoint });
33607
- await sendProxyResponse(res, proxyRes);
33608
- return;
33609
- } catch (err) {
33610
- if (heartbeat?.requestWorkerControl) {
33611
- log.warn("direct preview proxy failed, falling back to keepalive control", {
33612
- taskId,
33613
- assignedTo: task.assignedTo,
33614
- error: err instanceof Error ? err.message : String(err)
33615
- });
33616
- try {
33617
- const controlResponse = await heartbeat.requestWorkerControl(task.assignedTo, {
33618
- kind: "task-preview-session",
33619
- taskId,
33620
- path: body.path
33621
- });
33622
- sendWorkerControlResponse(res, controlResponse);
33623
- return;
33624
- } catch (fallbackErr) {
33625
- log.warn("keepalive preview fallback failed", {
33626
- taskId,
33627
- assignedTo: task.assignedTo,
33628
- error: fallbackErr instanceof Error ? fallbackErr.message : String(fallbackErr)
33629
- });
33630
- }
33631
- }
33632
- log.warn("preview session proxy error", { error: err instanceof Error ? err.message : String(err) });
33633
- throw new MeshyError("NODE_OFFLINE", "Cannot reach worker for preview session", 502);
33634
- }
33635
- }
33636
- res.json(await createPreviewSessionPayload(req.app.locals.deps, taskId, body.path));
33637
- }));
33745
+ router.use(createTaskOutputRoutes());
33638
33746
  return router;
33639
33747
  }
33640
33748
 
33641
33749
  // ../../packages/api/src/routes/worker.ts
33642
- var import_express4 = __toESM(require_express2(), 1);
33750
+ var import_express5 = __toESM(require_express2(), 1);
33643
33751
  var WorkerMessageBody = external_exports.object({
33644
33752
  taskId: external_exports.string().min(1)
33645
33753
  }).and(SendMessageBody);
33646
33754
  var WorkerTaskBody = external_exports.object({
33647
33755
  taskId: external_exports.string().min(1)
33648
33756
  });
33649
- function asyncHandler4(fn) {
33757
+ function asyncHandler5(fn) {
33650
33758
  return (req, res, next) => fn(req, res, next).catch(next);
33651
33759
  }
33652
33760
  function createWorkerRoutes() {
33653
- const router = (0, import_express4.Router)();
33654
- router.post("/execute", asyncHandler4(async (req, res) => {
33761
+ const router = (0, import_express5.Router)();
33762
+ router.post("/execute", asyncHandler5(async (req, res) => {
33655
33763
  const { taskEngine, engineRegistry, nodeRegistry, eventBus, logger: rootLogger, workDir } = req.app.locals.deps;
33656
33764
  const log = rootLogger.child("worker/execute");
33657
33765
  const task = req.body;
@@ -33724,7 +33832,7 @@ function createWorkerRoutes() {
33724
33832
  }
33725
33833
  }
33726
33834
  }));
33727
- router.post("/message", asyncHandler4(async (req, res) => {
33835
+ router.post("/message", asyncHandler5(async (req, res) => {
33728
33836
  const { engineRegistry, taskEngine, nodeRegistry, eventBus, logger: rootLogger } = req.app.locals.deps;
33729
33837
  const log = rootLogger.child("worker/message");
33730
33838
  const body = WorkerMessageBody.parse(req.body);
@@ -33767,7 +33875,7 @@ function createWorkerRoutes() {
33767
33875
  }
33768
33876
  res.json({ ok: true });
33769
33877
  }));
33770
- router.post("/cancel", asyncHandler4(async (req, res) => {
33878
+ router.post("/cancel", asyncHandler5(async (req, res) => {
33771
33879
  const { taskEngine, engineRegistry, logger: rootLogger } = req.app.locals.deps;
33772
33880
  const log = rootLogger.child("worker/cancel");
33773
33881
  const body = WorkerTaskBody.parse(req.body);
@@ -33787,7 +33895,7 @@ function createWorkerRoutes() {
33787
33895
  terminal: result.terminal
33788
33896
  });
33789
33897
  }));
33790
- router.post("/output", asyncHandler4(async (req, res) => {
33898
+ router.post("/output", asyncHandler5(async (req, res) => {
33791
33899
  const { eventBus, engineRegistry, taskEngine, logger: rootLogger } = req.app.locals.deps;
33792
33900
  const log = rootLogger.child("worker/output");
33793
33901
  const { taskId, event } = req.body;
@@ -33802,34 +33910,34 @@ function createWorkerRoutes() {
33802
33910
  }
33803
33911
  res.json({ ok: true });
33804
33912
  }));
33805
- router.post("/heartbeat", asyncHandler4(async (req, res) => {
33913
+ router.post("/heartbeat", asyncHandler5(async (req, res) => {
33806
33914
  const { heartbeat, logger: rootLogger } = req.app.locals.deps;
33807
33915
  const log = rootLogger.child("worker/heartbeat");
33808
33916
  const body = req.body;
33809
- log.info("received worker heartbeat API call", {
33917
+ log.debug("received worker heartbeat API call", {
33810
33918
  leaderId: body.leaderId,
33811
33919
  term: body.term,
33812
33920
  nodeCount: body.clusterState?.nodes?.length ?? 0
33813
33921
  });
33814
33922
  const response = heartbeat.handleHeartbeat(body);
33815
- log.info("completed worker heartbeat API call", {
33923
+ log.debug("completed worker heartbeat API call", {
33816
33924
  nodeId: response.nodeId,
33817
33925
  status: response.status,
33818
33926
  load: response.load
33819
33927
  });
33820
33928
  res.json(response);
33821
33929
  }));
33822
- router.post("/keepalive", asyncHandler4(async (req, res) => {
33930
+ router.post("/keepalive", asyncHandler5(async (req, res) => {
33823
33931
  const { heartbeat, logger: rootLogger } = req.app.locals.deps;
33824
33932
  const log = rootLogger.child("worker/keepalive");
33825
33933
  const body = req.body;
33826
- log.info("received worker keepalive API call", {
33934
+ log.debug("received worker keepalive API call", {
33827
33935
  nodeId: body.nodeId,
33828
33936
  status: body.status,
33829
33937
  endpoint: body.endpoint
33830
33938
  });
33831
33939
  const response = heartbeat.handleKeepalive(body);
33832
- log.info("completed worker keepalive API call", {
33940
+ log.debug("completed worker keepalive API call", {
33833
33941
  leaderId: response.leaderId,
33834
33942
  term: response.term,
33835
33943
  nodeCount: response.clusterState.nodes.length,
@@ -33839,17 +33947,17 @@ function createWorkerRoutes() {
33839
33947
  });
33840
33948
  res.json(response);
33841
33949
  }));
33842
- router.post("/vote", asyncHandler4(async (req, res) => {
33950
+ router.post("/vote", asyncHandler5(async (req, res) => {
33843
33951
  const { election } = req.app.locals.deps;
33844
33952
  const response = election.handleVoteRequest(req.body);
33845
33953
  res.json(response);
33846
33954
  }));
33847
- router.post("/announce", asyncHandler4(async (req, res) => {
33955
+ router.post("/announce", asyncHandler5(async (req, res) => {
33848
33956
  const { election } = req.app.locals.deps;
33849
33957
  election.handleLeaderAnnounce(req.body);
33850
33958
  res.json({ ok: true });
33851
33959
  }));
33852
- router.post("/preview-session", asyncHandler4(async (req, res) => {
33960
+ router.post("/preview-session", asyncHandler5(async (req, res) => {
33853
33961
  const { logger: rootLogger } = req.app.locals.deps;
33854
33962
  const log = rootLogger.child("worker/preview-session");
33855
33963
  const body = TaskPreviewSessionBody.extend({
@@ -33859,7 +33967,7 @@ function createWorkerRoutes() {
33859
33967
  log.info("created preview session", { taskId: body.taskId, entryPath: payload.entryPath });
33860
33968
  res.json(payload);
33861
33969
  }));
33862
- router.post("/control-response", asyncHandler4(async (req, res) => {
33970
+ router.post("/control-response", asyncHandler5(async (req, res) => {
33863
33971
  const { heartbeat, logger: rootLogger } = req.app.locals.deps;
33864
33972
  const log = rootLogger.child("worker/control-response");
33865
33973
  const body = req.body;
@@ -33879,13 +33987,13 @@ function createWorkerRoutes() {
33879
33987
  }
33880
33988
 
33881
33989
  // ../../packages/api/src/routes/system.ts
33882
- var import_express5 = __toESM(require_express2(), 1);
33883
- function asyncHandler5(fn) {
33990
+ var import_express6 = __toESM(require_express2(), 1);
33991
+ function asyncHandler6(fn) {
33884
33992
  return (req, res, next) => fn(req, res, next).catch(next);
33885
33993
  }
33886
33994
  function createSystemRoutes() {
33887
- const router = (0, import_express5.Router)();
33888
- router.get("/health", asyncHandler5(async (req, res) => {
33995
+ const router = (0, import_express6.Router)();
33996
+ router.get("/health", asyncHandler6(async (req, res) => {
33889
33997
  const { logger: rootLogger } = req.app.locals.deps;
33890
33998
  rootLogger.child("system/health").info("received system health API call", {
33891
33999
  method: req.method,
@@ -33894,7 +34002,7 @@ function createSystemRoutes() {
33894
34002
  });
33895
34003
  res.json({ status: "ok", timestamp: Date.now() });
33896
34004
  }));
33897
- router.get("/info", asyncHandler5(async (req, res) => {
34005
+ router.get("/info", asyncHandler6(async (req, res) => {
33898
34006
  const { nodeRegistry, getTransportType, config, dashboardOrigin } = req.app.locals.deps;
33899
34007
  const self = nodeRegistry.getSelf();
33900
34008
  res.json({
@@ -33910,7 +34018,7 @@ function createSystemRoutes() {
33910
34018
  }
33911
34019
  });
33912
34020
  }));
33913
- router.post("/transport", asyncHandler5(async (req, res) => {
34021
+ router.post("/transport", asyncHandler6(async (req, res) => {
33914
34022
  const { switchTransport } = req.app.locals.deps;
33915
34023
  if (!switchTransport) {
33916
34024
  res.status(501).json({ error: "Transport switching not available" });
@@ -33924,7 +34032,7 @@ function createSystemRoutes() {
33924
34032
  const newEndpoint = await switchTransport(type);
33925
34033
  res.json({ ok: true, transportType: type, endpoint: newEndpoint });
33926
34034
  }));
33927
- router.post("/devtunnel", asyncHandler5(async (req, res) => {
34035
+ router.post("/devtunnel", asyncHandler6(async (req, res) => {
33928
34036
  const { enableDevTunnel, disableDevTunnel, nodeRegistry, taskEngine } = req.app.locals.deps;
33929
34037
  if (!enableDevTunnel || !disableDevTunnel) {
33930
34038
  res.status(501).json({ error: "DevTunnel control not available" });
@@ -33953,7 +34061,7 @@ function createSystemRoutes() {
33953
34061
  });
33954
34062
  }
33955
34063
  }));
33956
- router.get("/metrics", asyncHandler5(async (req, res) => {
34064
+ router.get("/metrics", asyncHandler6(async (req, res) => {
33957
34065
  const { taskEngine } = req.app.locals.deps;
33958
34066
  const metrics = taskEngine.getMetrics();
33959
34067
  res.json(metrics);
@@ -33962,7 +34070,7 @@ function createSystemRoutes() {
33962
34070
  }
33963
34071
 
33964
34072
  // ../../packages/api/src/routes/events.ts
33965
- var import_express6 = __toESM(require_express2(), 1);
34073
+ var import_express7 = __toESM(require_express2(), 1);
33966
34074
  var HEARTBEAT_INTERVAL_MS = 15e3;
33967
34075
  var CATEGORY_MAP = {
33968
34076
  tasks: "task.",
@@ -33997,7 +34105,7 @@ function shouldIncludeEvent(eventName, categories) {
33997
34105
  });
33998
34106
  }
33999
34107
  function createEventRoutes() {
34000
- const router = (0, import_express6.Router)();
34108
+ const router = (0, import_express7.Router)();
34001
34109
  router.get("/", (req, res) => {
34002
34110
  const { eventBus } = req.app.locals.deps;
34003
34111
  const categories = parseFilter(req.query.filter);
@@ -34048,8 +34156,8 @@ var JSON_BODY_LIMIT_LARGE = "25mb";
34048
34156
  function resolveRuntimeBaseDir() {
34049
34157
  const entryPath = process.argv[1];
34050
34158
  if (typeof entryPath === "string" && entryPath.length > 0) {
34051
- const resolved = fs15.realpathSync(path15.resolve(entryPath));
34052
- return path15.dirname(resolved);
34159
+ const resolved = fs14.realpathSync(path14.resolve(entryPath));
34160
+ return path14.dirname(resolved);
34053
34161
  }
34054
34162
  return process.cwd();
34055
34163
  }
@@ -34057,25 +34165,25 @@ function resolveStaticDir(baseDir) {
34057
34165
  const envStaticDir = process.env.MESHY_STATIC_DIR;
34058
34166
  const candidateDirs = [
34059
34167
  envStaticDir,
34060
- path15.resolve(baseDir, "dashboard"),
34061
- path15.resolve(baseDir, "../dashboard"),
34062
- path15.resolve(baseDir, "../../dashboard/dist"),
34063
- path15.resolve(baseDir, "../../../packages/dashboard/dist"),
34064
- path15.resolve(baseDir, "../public"),
34065
- path15.resolve(baseDir, "../../packages/api/public"),
34066
- path15.resolve(baseDir, "../../../packages/api/public"),
34067
- path15.resolve(process.cwd(), "packages/dashboard/dist"),
34068
- path15.resolve(process.cwd(), "packages/api/public")
34168
+ path14.resolve(baseDir, "dashboard"),
34169
+ path14.resolve(baseDir, "../dashboard"),
34170
+ path14.resolve(baseDir, "../../dashboard/dist"),
34171
+ path14.resolve(baseDir, "../../../packages/dashboard/dist"),
34172
+ path14.resolve(baseDir, "../public"),
34173
+ path14.resolve(baseDir, "../../packages/api/public"),
34174
+ path14.resolve(baseDir, "../../../packages/api/public"),
34175
+ path14.resolve(process.cwd(), "packages/dashboard/dist"),
34176
+ path14.resolve(process.cwd(), "packages/api/public")
34069
34177
  ].filter((value) => typeof value === "string" && value.length > 0);
34070
34178
  for (const candidate of candidateDirs) {
34071
- if (fs15.existsSync(candidate)) {
34179
+ if (fs14.existsSync(candidate)) {
34072
34180
  return candidate;
34073
34181
  }
34074
34182
  }
34075
34183
  return null;
34076
34184
  }
34077
34185
  function createServer2(deps) {
34078
- const app = (0, import_express7.default)();
34186
+ const app = (0, import_express8.default)();
34079
34187
  app.locals.deps = deps;
34080
34188
  if (typeof deps.heartbeat.setControlRequestHandler === "function") {
34081
34189
  deps.heartbeat.setControlRequestHandler((request) => executeWorkerControlRequest(deps, request));
@@ -34099,7 +34207,7 @@ function createServer2(deps) {
34099
34207
  const runtimeBaseDir = resolveRuntimeBaseDir();
34100
34208
  const staticDir = resolveStaticDir(runtimeBaseDir);
34101
34209
  if (staticDir) {
34102
- const staticMiddleware = import_express7.default.static(staticDir);
34210
+ const staticMiddleware = import_express8.default.static(staticDir);
34103
34211
  app.use((req, res, next) => {
34104
34212
  if (isApiRequest(req)) {
34105
34213
  next();
@@ -34112,10 +34220,10 @@ function createServer2(deps) {
34112
34220
  staticMiddleware(req, res, next);
34113
34221
  });
34114
34222
  }
34115
- app.use(import_express7.default.json({ limit: JSON_BODY_LIMIT }));
34223
+ app.use(import_express8.default.json({ limit: JSON_BODY_LIMIT }));
34116
34224
  app.use(createAuthMiddleware(authConfig));
34117
34225
  app.use(createRoutingMiddleware(deps.dataRouter));
34118
- const largeBodyParser = import_express7.default.json({ limit: JSON_BODY_LIMIT_LARGE });
34226
+ const largeBodyParser = import_express8.default.json({ limit: JSON_BODY_LIMIT_LARGE });
34119
34227
  app.use("/api/cluster", createClusterRoutes());
34120
34228
  app.use("/api/nodes", createNodeRoutes());
34121
34229
  app.use("/api/tasks", largeBodyParser, createTaskRoutes());
@@ -34123,8 +34231,8 @@ function createServer2(deps) {
34123
34231
  app.use("/api/system", createSystemRoutes());
34124
34232
  app.use("/api/events", createEventRoutes());
34125
34233
  if (staticDir) {
34126
- const indexPath = path15.join(staticDir, "index.html");
34127
- if (fs15.existsSync(indexPath)) {
34234
+ const indexPath = path14.join(staticDir, "index.html");
34235
+ if (fs14.existsSync(indexPath)) {
34128
34236
  app.get("*", (req, res, next) => {
34129
34237
  if (isApiRequest(req)) {
34130
34238
  next();
@@ -34142,6 +34250,34 @@ function createServer2(deps) {
34142
34250
  return app;
34143
34251
  }
34144
34252
 
34253
+ // ../../packages/api/src/output-server.ts
34254
+ var import_express9 = __toESM(require_express2(), 1);
34255
+ var JSON_BODY_LIMIT_LARGE2 = "25mb";
34256
+ function createOutputServer(deps) {
34257
+ if (!deps.previewSessionManager) {
34258
+ throw new Error("Preview session manager is required for the output server");
34259
+ }
34260
+ const app = (0, import_express9.default)();
34261
+ app.locals.deps = deps;
34262
+ app.use((req, res, next) => {
34263
+ if (handlePreviewRequest(deps.previewSessionManager, req, res)) {
34264
+ return;
34265
+ }
34266
+ next();
34267
+ });
34268
+ const authConfig = {
34269
+ apiKey: deps.config.apiKey,
34270
+ validateBearerToken: deps.config.validateBearerToken,
34271
+ allowTrustedHostBypass: false
34272
+ };
34273
+ const largeBodyParser = import_express9.default.json({ limit: JSON_BODY_LIMIT_LARGE2 });
34274
+ app.use("/api/tasks", largeBodyParser, createAuthMiddleware(authConfig), createTaskOutputRoutes({
34275
+ allowRemoteProxy: false
34276
+ }));
34277
+ app.use(createErrorMiddleware());
34278
+ return app;
34279
+ }
34280
+
34145
34281
  // ../../packages/transport/src/direct.ts
34146
34282
  var import_node_os = require("os");
34147
34283
  var import_node_http = require("http");
@@ -34452,8 +34588,8 @@ function createTransport(config) {
34452
34588
  }
34453
34589
 
34454
34590
  // src/startup.ts
34455
- var fs16 = __toESM(require("fs"), 1);
34456
- var path16 = __toESM(require("path"), 1);
34591
+ var fs15 = __toESM(require("fs"), 1);
34592
+ var path15 = __toESM(require("path"), 1);
34457
34593
  var readline = __toESM(require("readline/promises"), 1);
34458
34594
  var import_node_child_process6 = require("child_process");
34459
34595
  function getDefaultNodeName() {
@@ -34467,7 +34603,7 @@ function createDefaultConfig(storagePath = resolveDefaultStoragePath(), nodeName
34467
34603
  return {
34468
34604
  node: { name: nodeName, port: DEFAULT_NODE_PORT },
34469
34605
  transport: { type: "direct" },
34470
- cluster: { seeds: [], heartbeatInterval: 12e3, electionTimeout: 36e3, apiKey: "" },
34606
+ cluster: { seeds: [], heartbeatInterval: 3e3, electionTimeout: 36e3, apiKey: "" },
34471
34607
  storage: { path: storagePath }
34472
34608
  };
34473
34609
  }
@@ -34517,19 +34653,19 @@ function createDefaultCommandRunner(platform) {
34517
34653
  };
34518
34654
  }
34519
34655
  function getNodeMetadataPath2(storagePath) {
34520
- return path16.join(storagePath, "metadata.json");
34656
+ return path15.join(storagePath, "metadata.json");
34521
34657
  }
34522
34658
  function readStartupMetadataFile(storagePath) {
34523
34659
  try {
34524
- const raw = JSON.parse(fs16.readFileSync(getNodeMetadataPath2(storagePath), "utf-8"));
34660
+ const raw = JSON.parse(fs15.readFileSync(getNodeMetadataPath2(storagePath), "utf-8"));
34525
34661
  return typeof raw === "object" && raw !== null ? raw : {};
34526
34662
  } catch {
34527
34663
  return {};
34528
34664
  }
34529
34665
  }
34530
34666
  function writeStartupMetadataFile(storagePath, metadata) {
34531
- fs16.mkdirSync(storagePath, { recursive: true });
34532
- fs16.writeFileSync(getNodeMetadataPath2(storagePath), JSON.stringify(metadata, null, 2) + "\n", "utf-8");
34667
+ fs15.mkdirSync(storagePath, { recursive: true });
34668
+ fs15.writeFileSync(getNodeMetadataPath2(storagePath), JSON.stringify(metadata, null, 2) + "\n", "utf-8");
34533
34669
  }
34534
34670
  function formatLocalDate(now) {
34535
34671
  const year = now.getFullYear();
@@ -34774,9 +34910,9 @@ function parseArgs(argv) {
34774
34910
  }
34775
34911
  return result;
34776
34912
  }
34777
- function loadConfigFile(path17) {
34913
+ function loadConfigFile(path16) {
34778
34914
  try {
34779
- const raw = fs16.readFileSync(path17, "utf-8");
34915
+ const raw = fs15.readFileSync(path16, "utf-8");
34780
34916
  return JSON.parse(raw);
34781
34917
  } catch {
34782
34918
  return {};
@@ -35025,14 +35161,35 @@ async function main() {
35025
35161
  });
35026
35162
  await meshyNode.start();
35027
35163
  const previewSessionManager = new PreviewSessionManager();
35028
- const previewServer = new PreviewServer(previewSessionManager);
35029
35164
  const previewPort = config.node.port + 1;
35030
- const actualPreviewPort = await previewServer.start(previewPort);
35165
+ let actualPreviewPort = previewPort;
35031
35166
  let dashboardTransport = null;
35032
35167
  let dashboardOrigin;
35033
35168
  let previewTransport = null;
35034
35169
  let previewOrigin;
35170
+ let outputServer = null;
35035
35171
  let deps;
35172
+ async function listen(app2, port) {
35173
+ return new Promise((resolve10, reject) => {
35174
+ const server2 = http2.createServer(app2);
35175
+ server2.listen(port, () => resolve10(server2));
35176
+ server2.on("error", reject);
35177
+ });
35178
+ }
35179
+ async function closeServer(server2) {
35180
+ if (!server2) {
35181
+ return;
35182
+ }
35183
+ await new Promise((resolve10, reject) => {
35184
+ server2.close((err) => {
35185
+ if (err) {
35186
+ reject(err);
35187
+ return;
35188
+ }
35189
+ resolve10();
35190
+ });
35191
+ });
35192
+ }
35036
35193
  function createDashboardTransportConfig() {
35037
35194
  return {
35038
35195
  type: "devtunnel",
@@ -35155,6 +35312,10 @@ async function main() {
35155
35312
  const nextOrigin = await nextTransport.getEndpoint();
35156
35313
  previewTransport = nextTransport;
35157
35314
  setAdvertisedPreviewOrigin(nextOrigin);
35315
+ meshyNode.getLogger().info("started output preview tunnel", {
35316
+ previewOrigin: nextOrigin,
35317
+ previewPort: actualPreviewPort
35318
+ });
35158
35319
  if (previousTransport) {
35159
35320
  await previousTransport.stop().catch(() => void 0);
35160
35321
  }
@@ -35233,6 +35394,11 @@ async function main() {
35233
35394
  deps.previewPort = actualPreviewPort;
35234
35395
  deps.dashboardOrigin = dashboardOrigin;
35235
35396
  deps.previewOrigin = previewOrigin;
35397
+ const outputApp = createOutputServer(deps);
35398
+ outputServer = await listen(outputApp, previewPort);
35399
+ const outputAddress = outputServer.address();
35400
+ actualPreviewPort = typeof outputAddress === "object" && outputAddress ? outputAddress.port : previewPort;
35401
+ deps.previewPort = actualPreviewPort;
35236
35402
  meshyNode.getLogger().info("configured node auth mode", {
35237
35403
  authEnabled: authMetadata.enabled,
35238
35404
  allowSameTenant: authMetadata.allowSameTenant,
@@ -35240,6 +35406,7 @@ async function main() {
35240
35406
  mainTransportType: meshyNode.getTransportType(),
35241
35407
  sidecarEnabled: meshyNode.isDevTunnelEnabled()
35242
35408
  });
35409
+ await restartPreviewTransport(createPreviewTransportConfig());
35243
35410
  await syncDashboardTransport("startup");
35244
35411
  const previewHealthTimer = setInterval(() => {
35245
35412
  void (async () => {
@@ -35252,6 +35419,7 @@ async function main() {
35252
35419
  meshyNode.getLogger().warn("preview transport became unhealthy and was cleared", {
35253
35420
  previewPort: actualPreviewPort
35254
35421
  });
35422
+ await restartPreviewTransport(createPreviewTransportConfig());
35255
35423
  })();
35256
35424
  }, config.cluster.heartbeatInterval);
35257
35425
  const dashboardHealthTimer = setInterval(() => {
@@ -35298,9 +35466,9 @@ async function main() {
35298
35466
  if (previewTransport) {
35299
35467
  await previewTransport.stop();
35300
35468
  }
35301
- await previewServer.stop();
35469
+ await closeServer(outputServer);
35302
35470
  await meshyNode.stop();
35303
- server.close();
35471
+ await closeServer(server);
35304
35472
  console.log("Goodbye!");
35305
35473
  process.exit(0);
35306
35474
  } catch (err) {