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/README.md +1 -1
- package/dashboard/assets/{DashboardPage-D5VZZBFL.js → DashboardPage-CspTw10d.js} +20 -20
- package/dashboard/assets/{DiffTab-DHa2twrY.js → DiffTab-DBsjdYWn.js} +4 -4
- package/dashboard/assets/FilesTab-Bi9oHsVg.js +34 -0
- package/dashboard/assets/PreviewTab-DUCCQm-Z.js +16 -0
- package/dashboard/assets/{folder-0eOoupgZ.js → folder-BemVlz-Z.js} +1 -1
- package/dashboard/assets/index-COGcvWLp.css +1 -0
- package/dashboard/assets/{index-CRdTxsjS.js → index-qpJbLw0n.js} +10 -10
- package/dashboard/index.html +2 -2
- package/main.cjs +1105 -937
- package/package.json +1 -1
- package/dashboard/assets/FilesTab-DI35HxWK.js +0 -11
- package/dashboard/assets/PreviewTab-CAEInFgg.js +0 -6
- package/dashboard/assets/index-Bx5CT0VB.css +0 -1
package/main.cjs
CHANGED
|
@@ -1460,8 +1460,8 @@ var require_node = __commonJS({
|
|
|
1460
1460
|
}
|
|
1461
1461
|
break;
|
|
1462
1462
|
case "FILE":
|
|
1463
|
-
var
|
|
1464
|
-
stream2 = new
|
|
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(
|
|
14255
|
-
if (!
|
|
14254
|
+
function lookup(path16) {
|
|
14255
|
+
if (!path16 || typeof path16 !== "string") {
|
|
14256
14256
|
return false;
|
|
14257
14257
|
}
|
|
14258
|
-
var extension2 = extname3("x." +
|
|
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(
|
|
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 (
|
|
17791
|
-
while (m = MATCHING_GROUP_REGEXP.exec(
|
|
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
|
|
17799
|
+
return path16;
|
|
17800
17800
|
}
|
|
17801
|
-
if (Array.isArray(
|
|
17802
|
-
|
|
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(
|
|
17805
|
+
return new RegExp(path16.join("|"), flags);
|
|
17806
17806
|
}
|
|
17807
|
-
if (typeof
|
|
17807
|
+
if (typeof path16 !== "string") {
|
|
17808
17808
|
throw new TypeError("path must be a string, array of strings, or regular expression");
|
|
17809
17809
|
}
|
|
17810
|
-
|
|
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 +=
|
|
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(
|
|
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
|
-
|
|
17869
|
+
path16 += strict ? "" : path16[path16.length - 1] === "/" ? "?" : "/?";
|
|
17870
17870
|
if (end) {
|
|
17871
|
-
|
|
17872
|
-
} else if (
|
|
17873
|
-
|
|
17871
|
+
path16 += "$";
|
|
17872
|
+
} else if (path16[path16.length - 1] !== "/") {
|
|
17873
|
+
path16 += lookahead ? "(?=/|$)" : "(?:/|$)";
|
|
17874
17874
|
}
|
|
17875
|
-
return new RegExp("^" +
|
|
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(
|
|
17888
|
+
function Layer(path16, options, fn) {
|
|
17889
17889
|
if (!(this instanceof Layer)) {
|
|
17890
|
-
return new Layer(
|
|
17890
|
+
return new Layer(path16, options, fn);
|
|
17891
17891
|
}
|
|
17892
|
-
debug("new %o",
|
|
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(
|
|
17899
|
-
this.regexp.fast_star =
|
|
17900
|
-
this.regexp.fast_slash =
|
|
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(
|
|
17924
|
+
Layer.prototype.match = function match(path16) {
|
|
17925
17925
|
var match2;
|
|
17926
|
-
if (
|
|
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(
|
|
17934
|
-
this.path =
|
|
17933
|
+
this.params = { "0": decode_param(path16) };
|
|
17934
|
+
this.path = path16;
|
|
17935
17935
|
return true;
|
|
17936
17936
|
}
|
|
17937
|
-
match2 = this.regexp.exec(
|
|
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
|
|
17979
|
+
var http3 = require("http");
|
|
17980
17980
|
module2.exports = getCurrentNodeMethods() || getBasicNodeMethods();
|
|
17981
17981
|
function getCurrentNodeMethods() {
|
|
17982
|
-
return
|
|
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(
|
|
18031
|
-
this.path =
|
|
18030
|
+
function Route(path16) {
|
|
18031
|
+
this.path = path16;
|
|
18032
18032
|
this.stack = [];
|
|
18033
|
-
debug("new %o",
|
|
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
|
|
18247
|
-
if (
|
|
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,
|
|
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,
|
|
18293
|
+
trim_prefix(layer, layerError, layerPath, path16);
|
|
18294
18294
|
}
|
|
18295
18295
|
sync = 0;
|
|
18296
18296
|
});
|
|
18297
18297
|
}
|
|
18298
|
-
function trim_prefix(layer, layerError, layerPath,
|
|
18298
|
+
function trim_prefix(layer, layerError, layerPath, path16) {
|
|
18299
18299
|
if (layerPath.length !== 0) {
|
|
18300
|
-
if (layerPath !==
|
|
18300
|
+
if (layerPath !== path16.slice(0, layerPath.length)) {
|
|
18301
18301
|
next(layerError);
|
|
18302
18302
|
return;
|
|
18303
18303
|
}
|
|
18304
|
-
var c =
|
|
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
|
|
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
|
-
|
|
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",
|
|
18403
|
-
var layer = new Layer(
|
|
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(
|
|
18414
|
-
var route2 = new Route(
|
|
18415
|
-
var layer = new Layer(
|
|
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(
|
|
18426
|
-
var route = this.route(
|
|
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,
|
|
18462
|
+
function matchLayer(layer, path16) {
|
|
18463
18463
|
try {
|
|
18464
|
-
return layer.match(
|
|
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
|
|
18583
|
-
var
|
|
18584
|
-
var dirname3 =
|
|
18585
|
-
var
|
|
18586
|
-
var extname3 =
|
|
18587
|
-
var join13 =
|
|
18588
|
-
var resolve10 =
|
|
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
|
|
18617
|
+
var path17;
|
|
18618
18618
|
var roots = [].concat(this.root);
|
|
18619
18619
|
debug('lookup "%s"', name);
|
|
18620
|
-
for (var i = 0; i < roots.length && !
|
|
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 =
|
|
18625
|
-
|
|
18624
|
+
var file = basename3(loc);
|
|
18625
|
+
path17 = this.resolve(dir, file);
|
|
18626
18626
|
}
|
|
18627
|
-
return
|
|
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
|
|
18636
|
-
var stat = tryStat(
|
|
18635
|
+
var path17 = join13(dir, file);
|
|
18636
|
+
var stat = tryStat(path17);
|
|
18637
18637
|
if (stat && stat.isFile()) {
|
|
18638
|
-
return
|
|
18638
|
+
return path17;
|
|
18639
18639
|
}
|
|
18640
|
-
|
|
18641
|
-
stat = tryStat(
|
|
18640
|
+
path17 = join13(dir, basename3(file, ext), "index" + ext);
|
|
18641
|
+
stat = tryStat(path17);
|
|
18642
18642
|
if (stat && stat.isFile()) {
|
|
18643
|
-
return
|
|
18643
|
+
return path17;
|
|
18644
18644
|
}
|
|
18645
18645
|
};
|
|
18646
|
-
function tryStat(
|
|
18647
|
-
debug('stat "%s"',
|
|
18646
|
+
function tryStat(path17) {
|
|
18647
|
+
debug('stat "%s"', path17);
|
|
18648
18648
|
try {
|
|
18649
|
-
return
|
|
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
|
|
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 =
|
|
18758
|
+
var name = basename3(filename);
|
|
18759
18759
|
var isQuotedString = TEXT_REGEXP.test(name);
|
|
18760
|
-
var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name) :
|
|
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
|
|
19006
|
-
var
|
|
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 =
|
|
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(
|
|
19036
|
-
var ext =
|
|
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
|
|
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
|
|
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 =
|
|
19276
|
-
var join13 =
|
|
19277
|
-
var normalize =
|
|
19278
|
-
var resolve10 =
|
|
19279
|
-
var sep3 =
|
|
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,
|
|
19286
|
-
return new SendStream(req,
|
|
19285
|
+
function send(req, path17, options) {
|
|
19286
|
+
return new SendStream(req, path17, options);
|
|
19287
19287
|
}
|
|
19288
|
-
function SendStream(req,
|
|
19288
|
+
function SendStream(req, path17, options) {
|
|
19289
19289
|
Stream.call(this);
|
|
19290
19290
|
var opts = options || {};
|
|
19291
19291
|
this.options = opts;
|
|
19292
|
-
this.path =
|
|
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(
|
|
19339
|
-
this._root = resolve10(String(
|
|
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(
|
|
19452
|
+
SendStream.prototype.redirect = function redirect(path17) {
|
|
19453
19453
|
var res = this.res;
|
|
19454
19454
|
if (hasListeners(this, "directory")) {
|
|
19455
|
-
this.emit("directory", res,
|
|
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
|
|
19476
|
-
if (
|
|
19475
|
+
var path17 = decode(this.path);
|
|
19476
|
+
if (path17 === -1) {
|
|
19477
19477
|
this.error(400);
|
|
19478
19478
|
return res;
|
|
19479
19479
|
}
|
|
19480
|
-
if (~
|
|
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 (
|
|
19487
|
-
|
|
19486
|
+
if (path17) {
|
|
19487
|
+
path17 = normalize("." + sep3 + path17);
|
|
19488
19488
|
}
|
|
19489
|
-
if (UP_PATH_REGEXP.test(
|
|
19490
|
-
debug('malicious path "%s"',
|
|
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 =
|
|
19495
|
-
|
|
19494
|
+
parts = path17.split(sep3);
|
|
19495
|
+
path17 = normalize(join13(root, path17));
|
|
19496
19496
|
} else {
|
|
19497
|
-
if (UP_PATH_REGEXP.test(
|
|
19498
|
-
debug('malicious path "%s"',
|
|
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(
|
|
19503
|
-
|
|
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,
|
|
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(
|
|
19524
|
+
this.sendIndex(path17);
|
|
19525
19525
|
return res;
|
|
19526
19526
|
}
|
|
19527
|
-
this.sendFile(
|
|
19527
|
+
this.sendFile(path17);
|
|
19528
19528
|
return res;
|
|
19529
19529
|
};
|
|
19530
|
-
SendStream.prototype.send = function send2(
|
|
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"',
|
|
19543
|
-
this.setHeader(
|
|
19544
|
-
this.type(
|
|
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(
|
|
19593
|
+
this.stream(path17, opts);
|
|
19594
19594
|
};
|
|
19595
|
-
SendStream.prototype.sendFile = function sendFile(
|
|
19595
|
+
SendStream.prototype.sendFile = function sendFile(path17) {
|
|
19596
19596
|
var i = 0;
|
|
19597
19597
|
var self = this;
|
|
19598
|
-
debug('stat "%s"',
|
|
19599
|
-
|
|
19600
|
-
if (err && err.code === "ENOENT" && !extname3(
|
|
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(
|
|
19605
|
-
self.emit("file",
|
|
19606
|
-
self.send(
|
|
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 =
|
|
19612
|
+
var p = path17 + "." + self._extensions[i++];
|
|
19613
19613
|
debug('stat "%s"', p);
|
|
19614
|
-
|
|
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(
|
|
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(
|
|
19630
|
+
var p = join13(path17, self._index[i]);
|
|
19631
19631
|
debug('stat "%s"', p);
|
|
19632
|
-
|
|
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(
|
|
19641
|
+
SendStream.prototype.stream = function stream(path17, options) {
|
|
19642
19642
|
var self = this;
|
|
19643
19643
|
var res = this.res;
|
|
19644
|
-
var stream2 =
|
|
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(
|
|
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(
|
|
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(
|
|
19671
|
+
SendStream.prototype.setHeader = function setHeader(path17, stat) {
|
|
19672
19672
|
var res = this.res;
|
|
19673
|
-
this.emit("headers", res,
|
|
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(
|
|
19732
|
+
function decode(path17) {
|
|
19733
19733
|
try {
|
|
19734
|
-
return decodeURIComponent(
|
|
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(
|
|
20645
|
-
if ("/" ===
|
|
20646
|
-
if (":" ===
|
|
20647
|
-
if ("\\\\" ===
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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(
|
|
20877
|
+
return router.use(path16, fn2);
|
|
20878
20878
|
}
|
|
20879
|
-
debug(".use app under %s",
|
|
20880
|
-
fn2.mountpath =
|
|
20879
|
+
debug(".use app under %s", path16);
|
|
20880
|
+
fn2.mountpath = path16;
|
|
20881
20881
|
fn2.parent = this;
|
|
20882
|
-
router.use(
|
|
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(
|
|
20894
|
+
app.route = function route(path16) {
|
|
20895
20895
|
this.lazyrouter();
|
|
20896
|
-
return this._router.route(
|
|
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
|
|
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(
|
|
20963
|
+
app[method] = function(path16) {
|
|
20964
20964
|
if (method === "get" && arguments.length === 1) {
|
|
20965
|
-
return this.set(
|
|
20965
|
+
return this.set(path16);
|
|
20966
20966
|
}
|
|
20967
20967
|
this.lazyrouter();
|
|
20968
|
-
var route = this._router.route(
|
|
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(
|
|
20973
|
+
app.all = function all(path16) {
|
|
20974
20974
|
this.lazyrouter();
|
|
20975
|
-
var route = this._router.route(
|
|
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 =
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
22054
|
+
var http3 = require("http");
|
|
22055
22055
|
var isAbsolute2 = require_utils2().isAbsolute;
|
|
22056
22056
|
var onFinished = require_on_finished();
|
|
22057
|
-
var
|
|
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 =
|
|
22066
|
+
var extname3 = path16.extname;
|
|
22067
22067
|
var mime = send.mime;
|
|
22068
|
-
var resolve10 =
|
|
22068
|
+
var resolve10 = path16.resolve;
|
|
22069
22069
|
var vary = require_vary();
|
|
22070
|
-
var res = Object.create(
|
|
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(
|
|
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 (!
|
|
22251
|
+
if (!path17) {
|
|
22252
22252
|
throw new TypeError("path argument is required to res.sendFile");
|
|
22253
22253
|
}
|
|
22254
|
-
if (typeof
|
|
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(
|
|
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(
|
|
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(
|
|
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,
|
|
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(
|
|
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 ||
|
|
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(
|
|
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
|
|
22629
|
-
if (
|
|
22630
|
-
|
|
22628
|
+
var path16 = parseUrl(req).pathname;
|
|
22629
|
+
if (path16 === "/" && originalUrl.pathname.substr(-1) !== "/") {
|
|
22630
|
+
path16 = "";
|
|
22631
22631
|
}
|
|
22632
|
-
var stream = send(req,
|
|
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
|
|
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 =
|
|
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,
|
|
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:
|
|
24029
|
+
trace?.onAttempt?.({ attempt, endpoint, path: path16, timeoutMs, totalEndpoints: endpoints.length });
|
|
24022
24030
|
try {
|
|
24023
|
-
const response = await fetchWithTimeout(`${endpoint}${
|
|
24024
|
-
trace?.onResponse?.({ attempt, endpoint, path:
|
|
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:
|
|
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
|
|
25145
|
+
this.log.info("queued keepalive control request", {
|
|
25124
25146
|
nodeId,
|
|
25125
|
-
|
|
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.
|
|
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.
|
|
25225
|
-
|
|
25226
|
-
|
|
25227
|
-
|
|
25228
|
-
|
|
25229
|
-
|
|
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.
|
|
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.
|
|
25259
|
-
|
|
25260
|
-
|
|
25261
|
-
|
|
25262
|
-
|
|
25263
|
-
|
|
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.
|
|
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
|
-
|
|
25457
|
-
|
|
25458
|
-
|
|
25459
|
-
|
|
25460
|
-
|
|
25461
|
-
|
|
25462
|
-
|
|
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.
|
|
25494
|
-
|
|
25495
|
-
|
|
25496
|
-
|
|
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.
|
|
25501
|
-
|
|
25502
|
-
|
|
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
|
-
},
|
|
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.
|
|
25579
|
-
|
|
25580
|
-
|
|
25581
|
-
|
|
25582
|
-
|
|
25583
|
-
|
|
25584
|
-
|
|
25585
|
-
|
|
25586
|
-
|
|
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,
|
|
25828
|
+
shouldProxy(method, path16) {
|
|
25722
25829
|
if (this.election.isLeader()) return false;
|
|
25723
|
-
if (this.isExcludedPath(
|
|
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(
|
|
25825
|
-
return EXCLUDED_PATH_PREFIXES.some((prefix) =>
|
|
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:
|
|
26841
|
-
endpoint:
|
|
26842
|
-
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 (
|
|
26847
|
-
joinBody.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:
|
|
26852
|
-
endpoint:
|
|
26968
|
+
nodeId: self.id,
|
|
26969
|
+
endpoint: self.endpoint,
|
|
26853
26970
|
taskCount: tasks.length,
|
|
26854
|
-
hasDevTunnel: !!
|
|
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
|
|
27254
|
+
const currentSelf = this.nodeRegistry.getSelf();
|
|
27255
|
+
const remoteSelf = nodes.find((node) => node.id === currentSelf.id);
|
|
27134
27256
|
const nextSelf = {
|
|
27135
|
-
...
|
|
27257
|
+
...currentSelf,
|
|
27136
27258
|
...remoteSelf ?? {},
|
|
27137
27259
|
transportType: this.config.transport.type,
|
|
27138
|
-
workDir:
|
|
27260
|
+
workDir: currentSelf.workDir,
|
|
27139
27261
|
workDirFolders: listWorkDirFolders(this.getWorkDir()),
|
|
27140
|
-
...
|
|
27141
|
-
...
|
|
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:
|
|
27786
|
-
const fullPath = [...
|
|
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,
|
|
28025
|
+
constructor(parent, value, path16, key) {
|
|
27903
28026
|
this._cachedPath = [];
|
|
27904
28027
|
this.parent = parent;
|
|
27905
28028
|
this.data = value;
|
|
27906
|
-
this._path =
|
|
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
|
|
31568
|
-
var
|
|
31569
|
-
var
|
|
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.
|
|
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/
|
|
31985
|
-
var
|
|
31986
|
-
|
|
31987
|
-
|
|
31988
|
-
|
|
31989
|
-
|
|
31990
|
-
|
|
31991
|
-
|
|
31992
|
-
|
|
31993
|
-
|
|
31994
|
-
|
|
31995
|
-
|
|
31996
|
-
|
|
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
|
-
|
|
32133
|
+
throw new MeshyError("TASK_NOT_FOUND", `Task ${taskId} not found`, 404);
|
|
32040
32134
|
}
|
|
32041
|
-
|
|
32042
|
-
|
|
32043
|
-
|
|
32044
|
-
|
|
32045
|
-
|
|
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
|
-
|
|
32051
|
-
|
|
32052
|
-
|
|
32053
|
-
|
|
32054
|
-
|
|
32055
|
-
|
|
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
|
-
|
|
32088
|
-
|
|
32089
|
-
|
|
32090
|
-
|
|
32091
|
-
|
|
32092
|
-
|
|
32093
|
-
|
|
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
|
|
32151
|
-
var
|
|
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
|
|
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
|
|
32294
|
+
return MIME_MAP[ext] ?? "application/octet-stream";
|
|
32262
32295
|
}
|
|
32263
32296
|
function resolveOutputPath(root, relativePath) {
|
|
32264
|
-
const resolved =
|
|
32265
|
-
const normalizedRoot =
|
|
32266
|
-
if (!resolved.startsWith(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 =
|
|
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 (!
|
|
32332
|
+
if (!fs10.existsSync(absPath) || !fs10.statSync(absPath).isDirectory()) {
|
|
32300
32333
|
return [];
|
|
32301
32334
|
}
|
|
32302
|
-
const entries =
|
|
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 =
|
|
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 =
|
|
32315
|
-
const stat =
|
|
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 (
|
|
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 =
|
|
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 =
|
|
32351
|
-
if (
|
|
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 =
|
|
32396
|
+
const rootName = path11.basename(root);
|
|
32364
32397
|
const htmlEntries = detectHtmlEntries(root);
|
|
32365
32398
|
let fileCount;
|
|
32366
32399
|
try {
|
|
32367
|
-
const entries =
|
|
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 (!
|
|
32416
|
+
if (!fs10.existsSync(absPath) || !fs10.statSync(absPath).isFile()) {
|
|
32384
32417
|
throw new Error("File not found");
|
|
32385
32418
|
}
|
|
32386
|
-
const stat =
|
|
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) :
|
|
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 ?
|
|
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/
|
|
32462
|
-
var
|
|
32463
|
-
|
|
32464
|
-
|
|
32465
|
-
|
|
32466
|
-
|
|
32467
|
-
|
|
32468
|
-
|
|
32469
|
-
|
|
32470
|
-
|
|
32471
|
-
|
|
32472
|
-
|
|
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
|
-
|
|
32478
|
-
|
|
32479
|
-
|
|
32480
|
-
|
|
32481
|
-
|
|
32482
|
-
|
|
32483
|
-
|
|
32484
|
-
|
|
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
|
|
32679
|
+
throw err;
|
|
32488
32680
|
}
|
|
32489
|
-
|
|
32490
|
-
|
|
32491
|
-
|
|
32492
|
-
|
|
32493
|
-
|
|
32494
|
-
|
|
32495
|
-
|
|
32496
|
-
|
|
32497
|
-
|
|
32498
|
-
|
|
32499
|
-
|
|
32500
|
-
|
|
32501
|
-
|
|
32502
|
-
|
|
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
|
-
|
|
32508
|
-
|
|
32509
|
-
|
|
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
|
-
|
|
32513
|
-
|
|
32514
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
32644
|
-
|
|
32645
|
-
|
|
32646
|
-
|
|
32647
|
-
|
|
32648
|
-
|
|
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
|
-
|
|
32665
|
-
|
|
32666
|
-
|
|
32667
|
-
|
|
32668
|
-
|
|
32669
|
-
|
|
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
|
-
|
|
32680
|
-
|
|
32681
|
-
|
|
32682
|
-
|
|
32683
|
-
|
|
32684
|
-
|
|
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
|
|
32698
|
-
|
|
32699
|
-
|
|
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
|
-
|
|
32720
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
|
33061
|
-
router.post("/",
|
|
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("/",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
|
33654
|
-
router.post("/execute",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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.
|
|
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.
|
|
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",
|
|
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.
|
|
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.
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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
|
|
33883
|
-
function
|
|
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,
|
|
33888
|
-
router.get("/health",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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
|
|
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,
|
|
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 =
|
|
34052
|
-
return
|
|
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
|
-
|
|
34061
|
-
|
|
34062
|
-
|
|
34063
|
-
|
|
34064
|
-
|
|
34065
|
-
|
|
34066
|
-
|
|
34067
|
-
|
|
34068
|
-
|
|
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 (
|
|
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,
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
34127
|
-
if (
|
|
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
|
|
34456
|
-
var
|
|
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:
|
|
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
|
|
34656
|
+
return path15.join(storagePath, "metadata.json");
|
|
34521
34657
|
}
|
|
34522
34658
|
function readStartupMetadataFile(storagePath) {
|
|
34523
34659
|
try {
|
|
34524
|
-
const raw = JSON.parse(
|
|
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
|
-
|
|
34532
|
-
|
|
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(
|
|
34913
|
+
function loadConfigFile(path16) {
|
|
34778
34914
|
try {
|
|
34779
|
-
const raw =
|
|
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
|
-
|
|
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
|
|
35469
|
+
await closeServer(outputServer);
|
|
35302
35470
|
await meshyNode.stop();
|
|
35303
|
-
server
|
|
35471
|
+
await closeServer(server);
|
|
35304
35472
|
console.log("Goodbye!");
|
|
35305
35473
|
process.exit(0);
|
|
35306
35474
|
} catch (err) {
|