@zltquant/zlt-mcp 0.6.1-beta.2 → 0.6.1-beta.4
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/package.json +1 -1
- package/zlt-mcp-proxy.bundle.cjs +1255 -1543
package/zlt-mcp-proxy.bundle.cjs
CHANGED
|
@@ -1147,8 +1147,8 @@ var require_command = __commonJS({
|
|
|
1147
1147
|
"../../node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/command.js"(exports2) {
|
|
1148
1148
|
var EventEmitter = require("node:events").EventEmitter;
|
|
1149
1149
|
var childProcess = require("node:child_process");
|
|
1150
|
-
var
|
|
1151
|
-
var
|
|
1150
|
+
var path16 = require("node:path");
|
|
1151
|
+
var fs15 = require("node:fs");
|
|
1152
1152
|
var process4 = require("node:process");
|
|
1153
1153
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
1154
1154
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -2129,7 +2129,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2129
2129
|
* @param {string} subcommandName
|
|
2130
2130
|
*/
|
|
2131
2131
|
_checkForMissingExecutable(executableFile, executableDir, subcommandName) {
|
|
2132
|
-
if (
|
|
2132
|
+
if (fs15.existsSync(executableFile)) return;
|
|
2133
2133
|
const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
|
|
2134
2134
|
const executableMissing = `'${executableFile}' does not exist
|
|
2135
2135
|
- if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
@@ -2147,11 +2147,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2147
2147
|
let launchWithNode = false;
|
|
2148
2148
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
2149
2149
|
function findFile(baseDir, baseName) {
|
|
2150
|
-
const localBin =
|
|
2151
|
-
if (
|
|
2152
|
-
if (sourceExt.includes(
|
|
2150
|
+
const localBin = path16.resolve(baseDir, baseName);
|
|
2151
|
+
if (fs15.existsSync(localBin)) return localBin;
|
|
2152
|
+
if (sourceExt.includes(path16.extname(baseName))) return void 0;
|
|
2153
2153
|
const foundExt = sourceExt.find(
|
|
2154
|
-
(ext) =>
|
|
2154
|
+
(ext) => fs15.existsSync(`${localBin}${ext}`)
|
|
2155
2155
|
);
|
|
2156
2156
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
2157
2157
|
return void 0;
|
|
@@ -2163,21 +2163,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2163
2163
|
if (this._scriptPath) {
|
|
2164
2164
|
let resolvedScriptPath;
|
|
2165
2165
|
try {
|
|
2166
|
-
resolvedScriptPath =
|
|
2166
|
+
resolvedScriptPath = fs15.realpathSync(this._scriptPath);
|
|
2167
2167
|
} catch {
|
|
2168
2168
|
resolvedScriptPath = this._scriptPath;
|
|
2169
2169
|
}
|
|
2170
|
-
executableDir =
|
|
2171
|
-
|
|
2170
|
+
executableDir = path16.resolve(
|
|
2171
|
+
path16.dirname(resolvedScriptPath),
|
|
2172
2172
|
executableDir
|
|
2173
2173
|
);
|
|
2174
2174
|
}
|
|
2175
2175
|
if (executableDir) {
|
|
2176
2176
|
let localFile = findFile(executableDir, executableFile);
|
|
2177
2177
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
2178
|
-
const legacyName =
|
|
2178
|
+
const legacyName = path16.basename(
|
|
2179
2179
|
this._scriptPath,
|
|
2180
|
-
|
|
2180
|
+
path16.extname(this._scriptPath)
|
|
2181
2181
|
);
|
|
2182
2182
|
if (legacyName !== this._name) {
|
|
2183
2183
|
localFile = findFile(
|
|
@@ -2188,7 +2188,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2188
2188
|
}
|
|
2189
2189
|
executableFile = localFile || executableFile;
|
|
2190
2190
|
}
|
|
2191
|
-
launchWithNode = sourceExt.includes(
|
|
2191
|
+
launchWithNode = sourceExt.includes(path16.extname(executableFile));
|
|
2192
2192
|
let proc;
|
|
2193
2193
|
if (process4.platform !== "win32") {
|
|
2194
2194
|
if (launchWithNode) {
|
|
@@ -3035,7 +3035,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3035
3035
|
* @return {Command}
|
|
3036
3036
|
*/
|
|
3037
3037
|
nameFromFilename(filename) {
|
|
3038
|
-
this._name =
|
|
3038
|
+
this._name = path16.basename(filename, path16.extname(filename));
|
|
3039
3039
|
return this;
|
|
3040
3040
|
}
|
|
3041
3041
|
/**
|
|
@@ -3049,9 +3049,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3049
3049
|
* @param {string} [path]
|
|
3050
3050
|
* @return {(string|null|Command)}
|
|
3051
3051
|
*/
|
|
3052
|
-
executableDir(
|
|
3053
|
-
if (
|
|
3054
|
-
this._executableDir =
|
|
3052
|
+
executableDir(path17) {
|
|
3053
|
+
if (path17 === void 0) return this._executableDir;
|
|
3054
|
+
this._executableDir = path17;
|
|
3055
3055
|
return this;
|
|
3056
3056
|
}
|
|
3057
3057
|
/**
|
|
@@ -3700,11 +3700,11 @@ var require_codegen = __commonJS({
|
|
|
3700
3700
|
const rhs = this.rhs === void 0 ? "" : ` = ${this.rhs}`;
|
|
3701
3701
|
return `${varKind} ${this.name}${rhs};` + _n;
|
|
3702
3702
|
}
|
|
3703
|
-
optimizeNames(names,
|
|
3703
|
+
optimizeNames(names, constants2) {
|
|
3704
3704
|
if (!names[this.name.str])
|
|
3705
3705
|
return;
|
|
3706
3706
|
if (this.rhs)
|
|
3707
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
3707
|
+
this.rhs = optimizeExpr(this.rhs, names, constants2);
|
|
3708
3708
|
return this;
|
|
3709
3709
|
}
|
|
3710
3710
|
get names() {
|
|
@@ -3721,10 +3721,10 @@ var require_codegen = __commonJS({
|
|
|
3721
3721
|
render({ _n }) {
|
|
3722
3722
|
return `${this.lhs} = ${this.rhs};` + _n;
|
|
3723
3723
|
}
|
|
3724
|
-
optimizeNames(names,
|
|
3724
|
+
optimizeNames(names, constants2) {
|
|
3725
3725
|
if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
|
|
3726
3726
|
return;
|
|
3727
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
3727
|
+
this.rhs = optimizeExpr(this.rhs, names, constants2);
|
|
3728
3728
|
return this;
|
|
3729
3729
|
}
|
|
3730
3730
|
get names() {
|
|
@@ -3785,8 +3785,8 @@ var require_codegen = __commonJS({
|
|
|
3785
3785
|
optimizeNodes() {
|
|
3786
3786
|
return `${this.code}` ? this : void 0;
|
|
3787
3787
|
}
|
|
3788
|
-
optimizeNames(names,
|
|
3789
|
-
this.code = optimizeExpr(this.code, names,
|
|
3788
|
+
optimizeNames(names, constants2) {
|
|
3789
|
+
this.code = optimizeExpr(this.code, names, constants2);
|
|
3790
3790
|
return this;
|
|
3791
3791
|
}
|
|
3792
3792
|
get names() {
|
|
@@ -3815,12 +3815,12 @@ var require_codegen = __commonJS({
|
|
|
3815
3815
|
}
|
|
3816
3816
|
return nodes.length > 0 ? this : void 0;
|
|
3817
3817
|
}
|
|
3818
|
-
optimizeNames(names,
|
|
3818
|
+
optimizeNames(names, constants2) {
|
|
3819
3819
|
const { nodes } = this;
|
|
3820
3820
|
let i = nodes.length;
|
|
3821
3821
|
while (i--) {
|
|
3822
3822
|
const n = nodes[i];
|
|
3823
|
-
if (n.optimizeNames(names,
|
|
3823
|
+
if (n.optimizeNames(names, constants2))
|
|
3824
3824
|
continue;
|
|
3825
3825
|
subtractNames(names, n.names);
|
|
3826
3826
|
nodes.splice(i, 1);
|
|
@@ -3873,12 +3873,12 @@ var require_codegen = __commonJS({
|
|
|
3873
3873
|
return void 0;
|
|
3874
3874
|
return this;
|
|
3875
3875
|
}
|
|
3876
|
-
optimizeNames(names,
|
|
3876
|
+
optimizeNames(names, constants2) {
|
|
3877
3877
|
var _a;
|
|
3878
|
-
this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names,
|
|
3879
|
-
if (!(super.optimizeNames(names,
|
|
3878
|
+
this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants2);
|
|
3879
|
+
if (!(super.optimizeNames(names, constants2) || this.else))
|
|
3880
3880
|
return;
|
|
3881
|
-
this.condition = optimizeExpr(this.condition, names,
|
|
3881
|
+
this.condition = optimizeExpr(this.condition, names, constants2);
|
|
3882
3882
|
return this;
|
|
3883
3883
|
}
|
|
3884
3884
|
get names() {
|
|
@@ -3901,10 +3901,10 @@ var require_codegen = __commonJS({
|
|
|
3901
3901
|
render(opts) {
|
|
3902
3902
|
return `for(${this.iteration})` + super.render(opts);
|
|
3903
3903
|
}
|
|
3904
|
-
optimizeNames(names,
|
|
3905
|
-
if (!super.optimizeNames(names,
|
|
3904
|
+
optimizeNames(names, constants2) {
|
|
3905
|
+
if (!super.optimizeNames(names, constants2))
|
|
3906
3906
|
return;
|
|
3907
|
-
this.iteration = optimizeExpr(this.iteration, names,
|
|
3907
|
+
this.iteration = optimizeExpr(this.iteration, names, constants2);
|
|
3908
3908
|
return this;
|
|
3909
3909
|
}
|
|
3910
3910
|
get names() {
|
|
@@ -3940,10 +3940,10 @@ var require_codegen = __commonJS({
|
|
|
3940
3940
|
render(opts) {
|
|
3941
3941
|
return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
|
|
3942
3942
|
}
|
|
3943
|
-
optimizeNames(names,
|
|
3944
|
-
if (!super.optimizeNames(names,
|
|
3943
|
+
optimizeNames(names, constants2) {
|
|
3944
|
+
if (!super.optimizeNames(names, constants2))
|
|
3945
3945
|
return;
|
|
3946
|
-
this.iterable = optimizeExpr(this.iterable, names,
|
|
3946
|
+
this.iterable = optimizeExpr(this.iterable, names, constants2);
|
|
3947
3947
|
return this;
|
|
3948
3948
|
}
|
|
3949
3949
|
get names() {
|
|
@@ -3985,11 +3985,11 @@ var require_codegen = __commonJS({
|
|
|
3985
3985
|
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNodes();
|
|
3986
3986
|
return this;
|
|
3987
3987
|
}
|
|
3988
|
-
optimizeNames(names,
|
|
3988
|
+
optimizeNames(names, constants2) {
|
|
3989
3989
|
var _a, _b;
|
|
3990
|
-
super.optimizeNames(names,
|
|
3991
|
-
(_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names,
|
|
3992
|
-
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names,
|
|
3990
|
+
super.optimizeNames(names, constants2);
|
|
3991
|
+
(_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants2);
|
|
3992
|
+
(_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants2);
|
|
3993
3993
|
return this;
|
|
3994
3994
|
}
|
|
3995
3995
|
get names() {
|
|
@@ -4290,7 +4290,7 @@ var require_codegen = __commonJS({
|
|
|
4290
4290
|
function addExprNames(names, from) {
|
|
4291
4291
|
return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
|
|
4292
4292
|
}
|
|
4293
|
-
function optimizeExpr(expr, names,
|
|
4293
|
+
function optimizeExpr(expr, names, constants2) {
|
|
4294
4294
|
if (expr instanceof code_1.Name)
|
|
4295
4295
|
return replaceName(expr);
|
|
4296
4296
|
if (!canOptimize(expr))
|
|
@@ -4305,14 +4305,14 @@ var require_codegen = __commonJS({
|
|
|
4305
4305
|
return items;
|
|
4306
4306
|
}, []));
|
|
4307
4307
|
function replaceName(n) {
|
|
4308
|
-
const c =
|
|
4308
|
+
const c = constants2[n.str];
|
|
4309
4309
|
if (c === void 0 || names[n.str] !== 1)
|
|
4310
4310
|
return n;
|
|
4311
4311
|
delete names[n.str];
|
|
4312
4312
|
return c;
|
|
4313
4313
|
}
|
|
4314
4314
|
function canOptimize(e) {
|
|
4315
|
-
return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 &&
|
|
4315
|
+
return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants2[c.str] !== void 0);
|
|
4316
4316
|
}
|
|
4317
4317
|
}
|
|
4318
4318
|
function subtractNames(names, from) {
|
|
@@ -6274,7 +6274,7 @@ var require_compile = __commonJS({
|
|
|
6274
6274
|
const schOrFunc = root.refs[ref];
|
|
6275
6275
|
if (schOrFunc)
|
|
6276
6276
|
return schOrFunc;
|
|
6277
|
-
let _sch =
|
|
6277
|
+
let _sch = resolve8.call(this, root, ref);
|
|
6278
6278
|
if (_sch === void 0) {
|
|
6279
6279
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
6280
6280
|
const { schemaId } = this.opts;
|
|
@@ -6301,7 +6301,7 @@ var require_compile = __commonJS({
|
|
|
6301
6301
|
function sameSchemaEnv(s1, s2) {
|
|
6302
6302
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
6303
6303
|
}
|
|
6304
|
-
function
|
|
6304
|
+
function resolve8(root, ref) {
|
|
6305
6305
|
let sch;
|
|
6306
6306
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
6307
6307
|
ref = sch;
|
|
@@ -6516,8 +6516,8 @@ var require_utils = __commonJS({
|
|
|
6516
6516
|
}
|
|
6517
6517
|
return ind;
|
|
6518
6518
|
}
|
|
6519
|
-
function removeDotSegments(
|
|
6520
|
-
let input =
|
|
6519
|
+
function removeDotSegments(path16) {
|
|
6520
|
+
let input = path16;
|
|
6521
6521
|
const output = [];
|
|
6522
6522
|
let nextSlash = -1;
|
|
6523
6523
|
let len = 0;
|
|
@@ -6716,8 +6716,8 @@ var require_schemes = __commonJS({
|
|
|
6716
6716
|
wsComponent.secure = void 0;
|
|
6717
6717
|
}
|
|
6718
6718
|
if (wsComponent.resourceName) {
|
|
6719
|
-
const [
|
|
6720
|
-
wsComponent.path =
|
|
6719
|
+
const [path16, query] = wsComponent.resourceName.split("?");
|
|
6720
|
+
wsComponent.path = path16 && path16 !== "/" ? path16 : void 0;
|
|
6721
6721
|
wsComponent.query = query;
|
|
6722
6722
|
wsComponent.resourceName = void 0;
|
|
6723
6723
|
}
|
|
@@ -6876,7 +6876,7 @@ var require_fast_uri = __commonJS({
|
|
|
6876
6876
|
}
|
|
6877
6877
|
return uri;
|
|
6878
6878
|
}
|
|
6879
|
-
function
|
|
6879
|
+
function resolve8(baseURI, relativeURI, options) {
|
|
6880
6880
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
6881
6881
|
const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
6882
6882
|
schemelessOptions.skipEscape = true;
|
|
@@ -7103,7 +7103,7 @@ var require_fast_uri = __commonJS({
|
|
|
7103
7103
|
var fastUri = {
|
|
7104
7104
|
SCHEMES,
|
|
7105
7105
|
normalize: normalize2,
|
|
7106
|
-
resolve:
|
|
7106
|
+
resolve: resolve8,
|
|
7107
7107
|
resolveComponent,
|
|
7108
7108
|
equal,
|
|
7109
7109
|
serialize,
|
|
@@ -10079,12 +10079,12 @@ var require_dist = __commonJS({
|
|
|
10079
10079
|
throw new Error(`Unknown format "${name}"`);
|
|
10080
10080
|
return f;
|
|
10081
10081
|
};
|
|
10082
|
-
function addFormats(ajv, list,
|
|
10082
|
+
function addFormats(ajv, list, fs15, exportName) {
|
|
10083
10083
|
var _a;
|
|
10084
10084
|
var _b;
|
|
10085
10085
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
10086
10086
|
for (const f of list)
|
|
10087
|
-
ajv.addFormat(f,
|
|
10087
|
+
ajv.addFormat(f, fs15[f]);
|
|
10088
10088
|
}
|
|
10089
10089
|
module2.exports = exports2 = formatsPlugin;
|
|
10090
10090
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -10097,8 +10097,8 @@ var require_windows = __commonJS({
|
|
|
10097
10097
|
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.js"(exports2, module2) {
|
|
10098
10098
|
module2.exports = isexe;
|
|
10099
10099
|
isexe.sync = sync;
|
|
10100
|
-
var
|
|
10101
|
-
function checkPathExt(
|
|
10100
|
+
var fs15 = require("fs");
|
|
10101
|
+
function checkPathExt(path16, options) {
|
|
10102
10102
|
var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
|
|
10103
10103
|
if (!pathext) {
|
|
10104
10104
|
return true;
|
|
@@ -10109,25 +10109,25 @@ var require_windows = __commonJS({
|
|
|
10109
10109
|
}
|
|
10110
10110
|
for (var i = 0; i < pathext.length; i++) {
|
|
10111
10111
|
var p = pathext[i].toLowerCase();
|
|
10112
|
-
if (p &&
|
|
10112
|
+
if (p && path16.substr(-p.length).toLowerCase() === p) {
|
|
10113
10113
|
return true;
|
|
10114
10114
|
}
|
|
10115
10115
|
}
|
|
10116
10116
|
return false;
|
|
10117
10117
|
}
|
|
10118
|
-
function checkStat(stat,
|
|
10118
|
+
function checkStat(stat, path16, options) {
|
|
10119
10119
|
if (!stat.isSymbolicLink() && !stat.isFile()) {
|
|
10120
10120
|
return false;
|
|
10121
10121
|
}
|
|
10122
|
-
return checkPathExt(
|
|
10122
|
+
return checkPathExt(path16, options);
|
|
10123
10123
|
}
|
|
10124
|
-
function isexe(
|
|
10125
|
-
|
|
10126
|
-
cb(er, er ? false : checkStat(stat,
|
|
10124
|
+
function isexe(path16, options, cb) {
|
|
10125
|
+
fs15.stat(path16, function(er, stat) {
|
|
10126
|
+
cb(er, er ? false : checkStat(stat, path16, options));
|
|
10127
10127
|
});
|
|
10128
10128
|
}
|
|
10129
|
-
function sync(
|
|
10130
|
-
return checkStat(
|
|
10129
|
+
function sync(path16, options) {
|
|
10130
|
+
return checkStat(fs15.statSync(path16), path16, options);
|
|
10131
10131
|
}
|
|
10132
10132
|
}
|
|
10133
10133
|
});
|
|
@@ -10137,14 +10137,14 @@ var require_mode = __commonJS({
|
|
|
10137
10137
|
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.js"(exports2, module2) {
|
|
10138
10138
|
module2.exports = isexe;
|
|
10139
10139
|
isexe.sync = sync;
|
|
10140
|
-
var
|
|
10141
|
-
function isexe(
|
|
10142
|
-
|
|
10140
|
+
var fs15 = require("fs");
|
|
10141
|
+
function isexe(path16, options, cb) {
|
|
10142
|
+
fs15.stat(path16, function(er, stat) {
|
|
10143
10143
|
cb(er, er ? false : checkStat(stat, options));
|
|
10144
10144
|
});
|
|
10145
10145
|
}
|
|
10146
|
-
function sync(
|
|
10147
|
-
return checkStat(
|
|
10146
|
+
function sync(path16, options) {
|
|
10147
|
+
return checkStat(fs15.statSync(path16), options);
|
|
10148
10148
|
}
|
|
10149
10149
|
function checkStat(stat, options) {
|
|
10150
10150
|
return stat.isFile() && checkMode(stat, options);
|
|
@@ -10168,7 +10168,7 @@ var require_mode = __commonJS({
|
|
|
10168
10168
|
// ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js
|
|
10169
10169
|
var require_isexe = __commonJS({
|
|
10170
10170
|
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js"(exports2, module2) {
|
|
10171
|
-
var
|
|
10171
|
+
var fs15 = require("fs");
|
|
10172
10172
|
var core;
|
|
10173
10173
|
if (process.platform === "win32" || global.TESTING_WINDOWS) {
|
|
10174
10174
|
core = require_windows();
|
|
@@ -10177,7 +10177,7 @@ var require_isexe = __commonJS({
|
|
|
10177
10177
|
}
|
|
10178
10178
|
module2.exports = isexe;
|
|
10179
10179
|
isexe.sync = sync;
|
|
10180
|
-
function isexe(
|
|
10180
|
+
function isexe(path16, options, cb) {
|
|
10181
10181
|
if (typeof options === "function") {
|
|
10182
10182
|
cb = options;
|
|
10183
10183
|
options = {};
|
|
@@ -10186,17 +10186,17 @@ var require_isexe = __commonJS({
|
|
|
10186
10186
|
if (typeof Promise !== "function") {
|
|
10187
10187
|
throw new TypeError("callback not provided");
|
|
10188
10188
|
}
|
|
10189
|
-
return new Promise(function(
|
|
10190
|
-
isexe(
|
|
10189
|
+
return new Promise(function(resolve8, reject) {
|
|
10190
|
+
isexe(path16, options || {}, function(er, is) {
|
|
10191
10191
|
if (er) {
|
|
10192
10192
|
reject(er);
|
|
10193
10193
|
} else {
|
|
10194
|
-
|
|
10194
|
+
resolve8(is);
|
|
10195
10195
|
}
|
|
10196
10196
|
});
|
|
10197
10197
|
});
|
|
10198
10198
|
}
|
|
10199
|
-
core(
|
|
10199
|
+
core(path16, options || {}, function(er, is) {
|
|
10200
10200
|
if (er) {
|
|
10201
10201
|
if (er.code === "EACCES" || options && options.ignoreErrors) {
|
|
10202
10202
|
er = null;
|
|
@@ -10206,9 +10206,9 @@ var require_isexe = __commonJS({
|
|
|
10206
10206
|
cb(er, is);
|
|
10207
10207
|
});
|
|
10208
10208
|
}
|
|
10209
|
-
function sync(
|
|
10209
|
+
function sync(path16, options) {
|
|
10210
10210
|
try {
|
|
10211
|
-
return core.sync(
|
|
10211
|
+
return core.sync(path16, options || {});
|
|
10212
10212
|
} catch (er) {
|
|
10213
10213
|
if (options && options.ignoreErrors || er.code === "EACCES") {
|
|
10214
10214
|
return false;
|
|
@@ -10224,7 +10224,7 @@ var require_isexe = __commonJS({
|
|
|
10224
10224
|
var require_which = __commonJS({
|
|
10225
10225
|
"../../node_modules/.pnpm/which@2.0.2/node_modules/which/which.js"(exports2, module2) {
|
|
10226
10226
|
var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
|
|
10227
|
-
var
|
|
10227
|
+
var path16 = require("path");
|
|
10228
10228
|
var COLON = isWindows ? ";" : ":";
|
|
10229
10229
|
var isexe = require_isexe();
|
|
10230
10230
|
var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
|
|
@@ -10257,27 +10257,27 @@ var require_which = __commonJS({
|
|
|
10257
10257
|
opt = {};
|
|
10258
10258
|
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
10259
10259
|
const found = [];
|
|
10260
|
-
const step = (i) => new Promise((
|
|
10260
|
+
const step = (i) => new Promise((resolve8, reject) => {
|
|
10261
10261
|
if (i === pathEnv.length)
|
|
10262
|
-
return opt.all && found.length ?
|
|
10262
|
+
return opt.all && found.length ? resolve8(found) : reject(getNotFoundError(cmd));
|
|
10263
10263
|
const ppRaw = pathEnv[i];
|
|
10264
10264
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
10265
|
-
const pCmd =
|
|
10265
|
+
const pCmd = path16.join(pathPart, cmd);
|
|
10266
10266
|
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
10267
|
-
|
|
10267
|
+
resolve8(subStep(p, i, 0));
|
|
10268
10268
|
});
|
|
10269
|
-
const subStep = (p, i, ii) => new Promise((
|
|
10269
|
+
const subStep = (p, i, ii) => new Promise((resolve8, reject) => {
|
|
10270
10270
|
if (ii === pathExt.length)
|
|
10271
|
-
return
|
|
10271
|
+
return resolve8(step(i + 1));
|
|
10272
10272
|
const ext = pathExt[ii];
|
|
10273
10273
|
isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
|
|
10274
10274
|
if (!er && is) {
|
|
10275
10275
|
if (opt.all)
|
|
10276
10276
|
found.push(p + ext);
|
|
10277
10277
|
else
|
|
10278
|
-
return
|
|
10278
|
+
return resolve8(p + ext);
|
|
10279
10279
|
}
|
|
10280
|
-
return
|
|
10280
|
+
return resolve8(subStep(p, i, ii + 1));
|
|
10281
10281
|
});
|
|
10282
10282
|
});
|
|
10283
10283
|
return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
|
|
@@ -10289,7 +10289,7 @@ var require_which = __commonJS({
|
|
|
10289
10289
|
for (let i = 0; i < pathEnv.length; i++) {
|
|
10290
10290
|
const ppRaw = pathEnv[i];
|
|
10291
10291
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
10292
|
-
const pCmd =
|
|
10292
|
+
const pCmd = path16.join(pathPart, cmd);
|
|
10293
10293
|
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
10294
10294
|
for (let j = 0; j < pathExt.length; j++) {
|
|
10295
10295
|
const cur = p + pathExt[j];
|
|
@@ -10337,7 +10337,7 @@ var require_path_key = __commonJS({
|
|
|
10337
10337
|
var require_resolveCommand = __commonJS({
|
|
10338
10338
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js"(exports2, module2) {
|
|
10339
10339
|
"use strict";
|
|
10340
|
-
var
|
|
10340
|
+
var path16 = require("path");
|
|
10341
10341
|
var which = require_which();
|
|
10342
10342
|
var getPathKey = require_path_key();
|
|
10343
10343
|
function resolveCommandAttempt(parsed, withoutPathExt) {
|
|
@@ -10355,7 +10355,7 @@ var require_resolveCommand = __commonJS({
|
|
|
10355
10355
|
try {
|
|
10356
10356
|
resolved = which.sync(parsed.command, {
|
|
10357
10357
|
path: env[getPathKey({ env })],
|
|
10358
|
-
pathExt: withoutPathExt ?
|
|
10358
|
+
pathExt: withoutPathExt ? path16.delimiter : void 0
|
|
10359
10359
|
});
|
|
10360
10360
|
} catch (e) {
|
|
10361
10361
|
} finally {
|
|
@@ -10364,7 +10364,7 @@ var require_resolveCommand = __commonJS({
|
|
|
10364
10364
|
}
|
|
10365
10365
|
}
|
|
10366
10366
|
if (resolved) {
|
|
10367
|
-
resolved =
|
|
10367
|
+
resolved = path16.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
|
|
10368
10368
|
}
|
|
10369
10369
|
return resolved;
|
|
10370
10370
|
}
|
|
@@ -10418,8 +10418,8 @@ var require_shebang_command = __commonJS({
|
|
|
10418
10418
|
if (!match) {
|
|
10419
10419
|
return null;
|
|
10420
10420
|
}
|
|
10421
|
-
const [
|
|
10422
|
-
const binary =
|
|
10421
|
+
const [path16, argument] = match[0].replace(/#! ?/, "").split(" ");
|
|
10422
|
+
const binary = path16.split("/").pop();
|
|
10423
10423
|
if (binary === "env") {
|
|
10424
10424
|
return argument;
|
|
10425
10425
|
}
|
|
@@ -10432,16 +10432,16 @@ var require_shebang_command = __commonJS({
|
|
|
10432
10432
|
var require_readShebang = __commonJS({
|
|
10433
10433
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js"(exports2, module2) {
|
|
10434
10434
|
"use strict";
|
|
10435
|
-
var
|
|
10435
|
+
var fs15 = require("fs");
|
|
10436
10436
|
var shebangCommand = require_shebang_command();
|
|
10437
10437
|
function readShebang(command) {
|
|
10438
10438
|
const size = 150;
|
|
10439
10439
|
const buffer = Buffer.alloc(size);
|
|
10440
10440
|
let fd;
|
|
10441
10441
|
try {
|
|
10442
|
-
fd =
|
|
10443
|
-
|
|
10444
|
-
|
|
10442
|
+
fd = fs15.openSync(command, "r");
|
|
10443
|
+
fs15.readSync(fd, buffer, 0, size, 0);
|
|
10444
|
+
fs15.closeSync(fd);
|
|
10445
10445
|
} catch (e) {
|
|
10446
10446
|
}
|
|
10447
10447
|
return shebangCommand(buffer.toString());
|
|
@@ -10454,7 +10454,7 @@ var require_readShebang = __commonJS({
|
|
|
10454
10454
|
var require_parse = __commonJS({
|
|
10455
10455
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js"(exports2, module2) {
|
|
10456
10456
|
"use strict";
|
|
10457
|
-
var
|
|
10457
|
+
var path16 = require("path");
|
|
10458
10458
|
var resolveCommand = require_resolveCommand();
|
|
10459
10459
|
var escape2 = require_escape();
|
|
10460
10460
|
var readShebang = require_readShebang();
|
|
@@ -10479,7 +10479,7 @@ var require_parse = __commonJS({
|
|
|
10479
10479
|
const needsShell = !isExecutableRegExp.test(commandFile);
|
|
10480
10480
|
if (parsed.options.forceShell || needsShell) {
|
|
10481
10481
|
const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
|
|
10482
|
-
parsed.command =
|
|
10482
|
+
parsed.command = path16.normalize(parsed.command);
|
|
10483
10483
|
parsed.command = escape2.command(parsed.command);
|
|
10484
10484
|
parsed.args = parsed.args.map((arg) => escape2.argument(arg, needsDoubleEscapeMetaChars));
|
|
10485
10485
|
const shellCommand = [parsed.command].concat(parsed.args).join(" ");
|
|
@@ -10569,7 +10569,7 @@ var require_cross_spawn = __commonJS({
|
|
|
10569
10569
|
var cp = require("child_process");
|
|
10570
10570
|
var parse3 = require_parse();
|
|
10571
10571
|
var enoent = require_enoent();
|
|
10572
|
-
function
|
|
10572
|
+
function spawn4(command, args, options) {
|
|
10573
10573
|
const parsed = parse3(command, args, options);
|
|
10574
10574
|
const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
|
|
10575
10575
|
enoent.hookChildProcess(spawned, parsed);
|
|
@@ -10581,8 +10581,8 @@ var require_cross_spawn = __commonJS({
|
|
|
10581
10581
|
result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
|
|
10582
10582
|
return result;
|
|
10583
10583
|
}
|
|
10584
|
-
module2.exports =
|
|
10585
|
-
module2.exports.spawn =
|
|
10584
|
+
module2.exports = spawn4;
|
|
10585
|
+
module2.exports.spawn = spawn4;
|
|
10586
10586
|
module2.exports.sync = spawnSync3;
|
|
10587
10587
|
module2.exports._parse = parse3;
|
|
10588
10588
|
module2.exports._enoent = enoent;
|
|
@@ -10607,15 +10607,12 @@ var {
|
|
|
10607
10607
|
} = import_index.default;
|
|
10608
10608
|
|
|
10609
10609
|
// src/index.ts
|
|
10610
|
-
var
|
|
10611
|
-
var
|
|
10610
|
+
var fs14 = __toESM(require("node:fs"), 1);
|
|
10611
|
+
var path15 = __toESM(require("node:path"), 1);
|
|
10612
10612
|
|
|
10613
10613
|
// src/cli.ts
|
|
10614
10614
|
var fs9 = __toESM(require("fs"), 1);
|
|
10615
|
-
var os4 = __toESM(require("os"), 1);
|
|
10616
10615
|
var path9 = __toESM(require("path"), 1);
|
|
10617
|
-
var import_crypto4 = require("crypto");
|
|
10618
|
-
var import_child_process4 = require("child_process");
|
|
10619
10616
|
|
|
10620
10617
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/core.js
|
|
10621
10618
|
var NEVER = Object.freeze({
|
|
@@ -10812,10 +10809,10 @@ function assignProp(target, prop, value) {
|
|
|
10812
10809
|
configurable: true
|
|
10813
10810
|
});
|
|
10814
10811
|
}
|
|
10815
|
-
function getElementAtPath(obj,
|
|
10816
|
-
if (!
|
|
10812
|
+
function getElementAtPath(obj, path16) {
|
|
10813
|
+
if (!path16)
|
|
10817
10814
|
return obj;
|
|
10818
|
-
return
|
|
10815
|
+
return path16.reduce((acc, key) => acc?.[key], obj);
|
|
10819
10816
|
}
|
|
10820
10817
|
function promiseAllObject(promisesObj) {
|
|
10821
10818
|
const keys = Object.keys(promisesObj);
|
|
@@ -11135,11 +11132,11 @@ function aborted(x, startIndex = 0) {
|
|
|
11135
11132
|
}
|
|
11136
11133
|
return false;
|
|
11137
11134
|
}
|
|
11138
|
-
function prefixIssues(
|
|
11135
|
+
function prefixIssues(path16, issues) {
|
|
11139
11136
|
return issues.map((iss) => {
|
|
11140
11137
|
var _a;
|
|
11141
11138
|
(_a = iss).path ?? (_a.path = []);
|
|
11142
|
-
iss.path.unshift(
|
|
11139
|
+
iss.path.unshift(path16);
|
|
11143
11140
|
return iss;
|
|
11144
11141
|
});
|
|
11145
11142
|
}
|
|
@@ -16457,7 +16454,7 @@ var Protocol = class {
|
|
|
16457
16454
|
return;
|
|
16458
16455
|
}
|
|
16459
16456
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
16460
|
-
await new Promise((
|
|
16457
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
16461
16458
|
options?.signal?.throwIfAborted();
|
|
16462
16459
|
}
|
|
16463
16460
|
} catch (error2) {
|
|
@@ -16474,7 +16471,7 @@ var Protocol = class {
|
|
|
16474
16471
|
*/
|
|
16475
16472
|
request(request, resultSchema, options) {
|
|
16476
16473
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
16477
|
-
return new Promise((
|
|
16474
|
+
return new Promise((resolve8, reject) => {
|
|
16478
16475
|
const earlyReject = (error2) => {
|
|
16479
16476
|
reject(error2);
|
|
16480
16477
|
};
|
|
@@ -16552,7 +16549,7 @@ var Protocol = class {
|
|
|
16552
16549
|
if (!parseResult.success) {
|
|
16553
16550
|
reject(parseResult.error);
|
|
16554
16551
|
} else {
|
|
16555
|
-
|
|
16552
|
+
resolve8(parseResult.data);
|
|
16556
16553
|
}
|
|
16557
16554
|
} catch (error2) {
|
|
16558
16555
|
reject(error2);
|
|
@@ -16813,12 +16810,12 @@ var Protocol = class {
|
|
|
16813
16810
|
}
|
|
16814
16811
|
} catch {
|
|
16815
16812
|
}
|
|
16816
|
-
return new Promise((
|
|
16813
|
+
return new Promise((resolve8, reject) => {
|
|
16817
16814
|
if (signal.aborted) {
|
|
16818
16815
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
16819
16816
|
return;
|
|
16820
16817
|
}
|
|
16821
|
-
const timeoutId = setTimeout(
|
|
16818
|
+
const timeoutId = setTimeout(resolve8, interval);
|
|
16822
16819
|
signal.addEventListener("abort", () => {
|
|
16823
16820
|
clearTimeout(timeoutId);
|
|
16824
16821
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -17769,7 +17766,7 @@ var StdioClientTransport = class {
|
|
|
17769
17766
|
if (this._process) {
|
|
17770
17767
|
throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");
|
|
17771
17768
|
}
|
|
17772
|
-
return new Promise((
|
|
17769
|
+
return new Promise((resolve8, reject) => {
|
|
17773
17770
|
this._process = (0, import_cross_spawn.default)(this._serverParams.command, this._serverParams.args ?? [], {
|
|
17774
17771
|
// merge default env with server env because mcp server needs some env vars
|
|
17775
17772
|
env: {
|
|
@@ -17786,7 +17783,7 @@ var StdioClientTransport = class {
|
|
|
17786
17783
|
this.onerror?.(error2);
|
|
17787
17784
|
});
|
|
17788
17785
|
this._process.on("spawn", () => {
|
|
17789
|
-
|
|
17786
|
+
resolve8();
|
|
17790
17787
|
});
|
|
17791
17788
|
this._process.on("close", (_code) => {
|
|
17792
17789
|
this._process = void 0;
|
|
@@ -17845,22 +17842,22 @@ var StdioClientTransport = class {
|
|
|
17845
17842
|
if (this._process) {
|
|
17846
17843
|
const processToClose = this._process;
|
|
17847
17844
|
this._process = void 0;
|
|
17848
|
-
const closePromise = new Promise((
|
|
17845
|
+
const closePromise = new Promise((resolve8) => {
|
|
17849
17846
|
processToClose.once("close", () => {
|
|
17850
|
-
|
|
17847
|
+
resolve8();
|
|
17851
17848
|
});
|
|
17852
17849
|
});
|
|
17853
17850
|
try {
|
|
17854
17851
|
processToClose.stdin?.end();
|
|
17855
17852
|
} catch {
|
|
17856
17853
|
}
|
|
17857
|
-
await Promise.race([closePromise, new Promise((
|
|
17854
|
+
await Promise.race([closePromise, new Promise((resolve8) => setTimeout(resolve8, 2e3).unref())]);
|
|
17858
17855
|
if (processToClose.exitCode === null) {
|
|
17859
17856
|
try {
|
|
17860
17857
|
processToClose.kill("SIGTERM");
|
|
17861
17858
|
} catch {
|
|
17862
17859
|
}
|
|
17863
|
-
await Promise.race([closePromise, new Promise((
|
|
17860
|
+
await Promise.race([closePromise, new Promise((resolve8) => setTimeout(resolve8, 2e3).unref())]);
|
|
17864
17861
|
}
|
|
17865
17862
|
if (processToClose.exitCode === null) {
|
|
17866
17863
|
try {
|
|
@@ -17872,205 +17869,579 @@ var StdioClientTransport = class {
|
|
|
17872
17869
|
this._readBuffer.clear();
|
|
17873
17870
|
}
|
|
17874
17871
|
send(message) {
|
|
17875
|
-
return new Promise((
|
|
17872
|
+
return new Promise((resolve8) => {
|
|
17876
17873
|
if (!this._process?.stdin) {
|
|
17877
17874
|
throw new Error("Not connected");
|
|
17878
17875
|
}
|
|
17879
17876
|
const json = serializeMessage(message);
|
|
17880
17877
|
if (this._process.stdin.write(json)) {
|
|
17881
|
-
|
|
17878
|
+
resolve8();
|
|
17882
17879
|
} else {
|
|
17883
|
-
this._process.stdin.once("drain",
|
|
17880
|
+
this._process.stdin.once("drain", resolve8);
|
|
17884
17881
|
}
|
|
17885
17882
|
});
|
|
17886
17883
|
}
|
|
17887
17884
|
};
|
|
17888
17885
|
|
|
17889
|
-
// ../zlt-runtime-core/dist/
|
|
17890
|
-
var
|
|
17891
|
-
var
|
|
17892
|
-
var
|
|
17893
|
-
var
|
|
17894
|
-
var
|
|
17895
|
-
|
|
17896
|
-
|
|
17897
|
-
|
|
17898
|
-
|
|
17899
|
-
|
|
17900
|
-
|
|
17901
|
-
|
|
17902
|
-
|
|
17903
|
-
|
|
17904
|
-
|
|
17905
|
-
var ZLTAF_CONFIG_FILE_DEFAULT = "application-local.properties";
|
|
17906
|
-
var OFFICIAL_MIRROR_ROOTS = {
|
|
17907
|
-
public: "https://zlt-data-house.oss-cn-wuhan-lr.aliyuncs.com/zltkj.site/down/v1/up/Zlt.Std.Official",
|
|
17908
|
-
internal: "http://192.168.1.243:9000/zlt-data-house/zltkj.site/down/v1/up/Zlt.Std.Official"
|
|
17909
|
-
};
|
|
17910
|
-
var OFFICIAL_INSTALLERS = {
|
|
17911
|
-
public: {
|
|
17912
|
-
// 2026-08-31 抬到 2026.08.31.3,接替 2026.06.18.11 —— 运维已把件传上公网 OSS。
|
|
17913
|
-
// 摘要不必重下:公网与内网是同一份字节,HEAD 实测 Content-Length 168,548,568
|
|
17914
|
-
// 与 ETag(OSS 侧即 MD5)C404C12F…33DA 两边完全一致,所以沿用内网那份已核过的
|
|
17915
|
-
// SHA256=5BE939F0…5B19。
|
|
17916
|
-
// 卡在 2026.06.18.11 的代价是实打实的:它低于我们自己发布的
|
|
17917
|
-
// zlt_quant_version_index.json 里的 Client.min = 2026.08.12.3,于是一台 full
|
|
17918
|
-
// 装机撞上闸门只会得到 blockedByPlugin,被告知「请先升级 ZLT Quant 插件」——
|
|
17919
|
-
// 而插件已经是最新的那一版,闸门永远消不掉。
|
|
17920
|
-
// 本条与 internal.full 这次同版本,那是因为公网刚补齐,不是两张表从此必然同步。
|
|
17921
|
-
// **本版没有装机验证**,与 internal.full 同一句话。
|
|
17922
|
-
full: {
|
|
17923
|
-
artifact: "zlt_client",
|
|
17924
|
-
version: "2026.08.31.3",
|
|
17925
|
-
sha256: "5BE939F069E69C05F37017FBB06FF76DE4DBCBD4CBCAF1322479255A5CE55B19"
|
|
17926
|
-
},
|
|
17927
|
-
// 2026-08-15 抬到 2026.08.14.5:公网 OSS 与内网镜像是同一份字节(ETag 113b3cff…、
|
|
17928
|
-
// 75,075,160 字节两边一致),本机下载实测 SHA256=9D40AE9A…D551,与 2026-08-14 覆盖
|
|
17929
|
-
// 安装时校验过的摘要一致,两条独立路径互证。这一版是投研模块下限(≥2026.08.11.2)
|
|
17930
|
-
// 之上的第一个已发布 mini:低于它,投研模块 upgrade/check 直接以「客户端版本过低」
|
|
17931
|
-
// 拒绝,且该下限只在模块服务端。version 取安装包自身 FileVersion 的点分四段(不是
|
|
17932
|
-
// 构建目录名的紧凑形 20260814.5):升级判定拿它和 InstallInfo.xml 的
|
|
17933
|
-
// InstallAppReleaseVer 比,写成紧凑形会让「有可用更新」永远消不掉。
|
|
17934
|
-
// 2026-08-31 抬到 2026.08.31.4,接替 2026.08.14.5。判据与 full 同一条:HEAD 实测
|
|
17935
|
-
// Content-Length 79,605,832 与 ETag 7A53D1EE…1375 公网内网一致,摘要沿用内网已核过的
|
|
17936
|
-
// SHA256=115A3EED…83CE。
|
|
17937
|
-
// 这一槽位是市场版的首装路径 —— VSCode 只装 mini(runtime-profile.mjs 的
|
|
17938
|
-
// VSCODE_INSTALL_TYPE),full 槽位只在已装 full 的机器上参与升级判定。
|
|
17939
|
-
// **本版没有装机验证**:本机停在 2026.08.28.7,08-30 对 .7 做的那轮活体复核
|
|
17940
|
-
// (三进程起得来、ZLTHQHost 管道在、两轮 check:npm-live 全绿)不适用于本版。
|
|
17941
|
-
mini: {
|
|
17942
|
-
artifact: "zlt_plugin",
|
|
17943
|
-
version: "2026.08.31.4",
|
|
17944
|
-
sha256: "115A3EEDC07211F6FBE56696573F668AE8315E351B017FECB0F6136AAAD983CE"
|
|
17945
|
-
}
|
|
17946
|
-
},
|
|
17947
|
-
internal: {
|
|
17948
|
-
// 2026-08-31 抬到 2026.08.31.3(1.0.2 RC 用件),接替 2026.08.28.8。内网镜像下载
|
|
17949
|
-
// 核验:168,548,568 字节,SHA256=5BE939F0…5B19,安装包 FileVersion 自报
|
|
17950
|
-
// 2026.08.31.3(版本取它,不取文件名)。它仍高于 Client.min = 2026.08.12.3,
|
|
17951
|
-
// 所以内测通道上一台 full 装机不会以 blockedByPlugin 收场。
|
|
17952
|
-
// 公网 OSS 上这一版 404(2026-08-31 实测 HEAD),public.full 不动。
|
|
17953
|
-
full: {
|
|
17954
|
-
artifact: "zlt_client",
|
|
17955
|
-
version: "2026.08.31.3",
|
|
17956
|
-
sha256: "5BE939F069E69C05F37017FBB06FF76DE4DBCBD4CBCAF1322479255A5CE55B19"
|
|
17957
|
-
},
|
|
17958
|
-
// 2026-08-31 抬到 2026.08.31.4(1.0.2 RC 用件),接替 2026.08.28.7。下载核验:
|
|
17959
|
-
// 79,605,832 字节,SHA256=115A3EED…83CE,FileVersion 自报 2026.08.31.4。
|
|
17960
|
-
//
|
|
17961
|
-
// **本条两件都只核到字节与版本,没有装机验证。** 本机停在 2026.08.28.7
|
|
17962
|
-
// (InstallInfo.xml 的 InstallAppReleaseVer 实读如此),所以 08-30 对 .7 做的那轮
|
|
17963
|
-
// 活体复核(三进程起得来、ZLTHQHost 管道在、两轮 check:npm-live 全绿)**不适用于
|
|
17964
|
-
// 这两版**,别把它顺移过来当证据。RC 装机后要重新确认两件事:ZLTHome 起得来、
|
|
17965
|
-
// 且 InstallAppReleaseVer 回读等于本条点分四段(对不上会让「有可用更新」永远消不掉)。
|
|
17966
|
-
//
|
|
17967
|
-
// 这条 08-28 起的历史仍然有效,记着是因为它解释了为什么这批件在密集换版:
|
|
17968
|
-
// 2026.08.28.3 现场装过并 ZLTHome 启动即崩(TTaskFunc 持栈上 lambda 的悬垂引用,
|
|
17969
|
-
// 100% 复现,ZLTHQHost 管道从未存活);同版起把 zltaf 从投研模块的子模块集里去掉,
|
|
17970
|
-
// 修的是首装必炸的另一条权限死路 —— 安装器与模块各发一份 zltaf,模块解压要覆盖
|
|
17971
|
-
// 安装器以管理员身份写下的文件,而 ZLTBackService 跑在登录账户的 UAC 过滤令牌上,
|
|
17972
|
-
// 卷根 ACL 缺 Authenticated Users:(M) 时覆盖必被拒,2 毫秒失败在第一个文件上。
|
|
17973
|
-
// 见 docs/reports/2026-08-28-zltaf-submodule-extract-access-denied.md。
|
|
17974
|
-
// 这些版本都没进过本表,不要读成本槽位的版本序列(上一个 pin 是 2026.08.28.7)。
|
|
17975
|
-
//
|
|
17976
|
-
// 公网 OSS 上这一版同样 404,所以 public.mini 仍停在 2026.08.14.5 —— 两张表不同版本,
|
|
17977
|
-
// 这正是按镜像分表的理由。
|
|
17978
|
-
mini: {
|
|
17979
|
-
artifact: "zlt_plugin",
|
|
17980
|
-
version: "2026.08.31.4",
|
|
17981
|
-
sha256: "115A3EEDC07211F6FBE56696573F668AE8315E351B017FECB0F6136AAAD983CE"
|
|
17886
|
+
// ../zlt-runtime-core/dist/zltaf-ipc.js
|
|
17887
|
+
var import_node_crypto = require("node:crypto");
|
|
17888
|
+
var fs = __toESM(require("node:fs"), 1);
|
|
17889
|
+
var net = __toESM(require("node:net"), 1);
|
|
17890
|
+
var os = __toESM(require("node:os"), 1);
|
|
17891
|
+
var path = __toESM(require("node:path"), 1);
|
|
17892
|
+
|
|
17893
|
+
// ../zlt-runtime-core/dist/packet-encoding.js
|
|
17894
|
+
function decodePacketBody(body) {
|
|
17895
|
+
try {
|
|
17896
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(body);
|
|
17897
|
+
} catch {
|
|
17898
|
+
try {
|
|
17899
|
+
return new TextDecoder("gbk").decode(body);
|
|
17900
|
+
} catch {
|
|
17901
|
+
return body.toString("utf8");
|
|
17982
17902
|
}
|
|
17983
17903
|
}
|
|
17984
|
-
};
|
|
17985
|
-
function resolveInstallerMirror() {
|
|
17986
|
-
return false ? "internal" : "public";
|
|
17987
|
-
}
|
|
17988
|
-
function officialInstallerUrl(slot, mirror = "public") {
|
|
17989
|
-
const spec = OFFICIAL_INSTALLERS[mirror][slot];
|
|
17990
|
-
return `${OFFICIAL_MIRROR_ROOTS[mirror]}/pkg/${spec.artifact}_${spec.version}.exe`;
|
|
17991
17904
|
}
|
|
17992
|
-
|
|
17993
|
-
|
|
17905
|
+
|
|
17906
|
+
// ../zlt-runtime-core/dist/zltaf-ipc.js
|
|
17907
|
+
function urlEncode(value) {
|
|
17908
|
+
let result = "";
|
|
17909
|
+
for (const code of Buffer.from(value, "utf8")) {
|
|
17910
|
+
const char = String.fromCharCode(code);
|
|
17911
|
+
if (code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || char === "-" || char === "_" || char === "." || char === "~") {
|
|
17912
|
+
result += char;
|
|
17913
|
+
} else if (char === " ") {
|
|
17914
|
+
result += "+";
|
|
17915
|
+
} else {
|
|
17916
|
+
result += `%${code.toString(16).toUpperCase().padStart(2, "0")}`;
|
|
17917
|
+
}
|
|
17918
|
+
}
|
|
17919
|
+
return result;
|
|
17994
17920
|
}
|
|
17995
|
-
|
|
17996
|
-
|
|
17997
|
-
|
|
17998
|
-
|
|
17999
|
-
|
|
18000
|
-
|
|
18001
|
-
|
|
18002
|
-
|
|
18003
|
-
|
|
18004
|
-
|
|
18005
|
-
|
|
18006
|
-
|
|
18007
|
-
|
|
18008
|
-
|
|
18009
|
-
|
|
18010
|
-
|
|
18011
|
-
},
|
|
18012
|
-
envMode: "OFFICIAL",
|
|
18013
|
-
backserviceDownload: {
|
|
18014
|
-
OFFICIAL: {
|
|
18015
|
-
full: officialInstallerUrl("full"),
|
|
18016
|
-
mini: officialInstallerUrl("mini")
|
|
18017
|
-
},
|
|
18018
|
-
REL: {
|
|
18019
|
-
full: "",
|
|
18020
|
-
mini: ""
|
|
18021
|
-
},
|
|
18022
|
-
DEBUG: {
|
|
18023
|
-
full: DEBUG_ASSISTANT_INSTALLER_URL,
|
|
18024
|
-
mini: DEBUG_ASSISTANT_INSTALLER_URL
|
|
17921
|
+
function urlDecode(value) {
|
|
17922
|
+
const bytes = [];
|
|
17923
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
17924
|
+
const char = value[index];
|
|
17925
|
+
if (char === "+") {
|
|
17926
|
+
bytes.push(32);
|
|
17927
|
+
} else if (char === "%" && index + 2 < value.length) {
|
|
17928
|
+
const code = Number.parseInt(value.substring(index + 1, index + 3), 16);
|
|
17929
|
+
if (!Number.isNaN(code)) {
|
|
17930
|
+
bytes.push(code);
|
|
17931
|
+
index += 2;
|
|
17932
|
+
} else {
|
|
17933
|
+
bytes.push(char.charCodeAt(0));
|
|
17934
|
+
}
|
|
17935
|
+
} else {
|
|
17936
|
+
bytes.push(...Buffer.from(char, "utf8"));
|
|
18025
17937
|
}
|
|
18026
|
-
}
|
|
18027
|
-
|
|
18028
|
-
|
|
18029
|
-
|
|
18030
|
-
|
|
18031
|
-
|
|
18032
|
-
|
|
18033
|
-
|
|
18034
|
-
|
|
18035
|
-
|
|
18036
|
-
|
|
18037
|
-
|
|
18038
|
-
|
|
18039
|
-
|
|
18040
|
-
|
|
17938
|
+
}
|
|
17939
|
+
return Buffer.from(bytes).toString("utf8");
|
|
17940
|
+
}
|
|
17941
|
+
var ZltafHttpPacket = class {
|
|
17942
|
+
httpVersion = "HTTP/1.1";
|
|
17943
|
+
statusCode = 200;
|
|
17944
|
+
statusMessage = "OK";
|
|
17945
|
+
content = "";
|
|
17946
|
+
contentLength = 0;
|
|
17947
|
+
uri = "";
|
|
17948
|
+
method = "";
|
|
17949
|
+
headers = /* @__PURE__ */ new Map();
|
|
17950
|
+
params = /* @__PURE__ */ new Map();
|
|
17951
|
+
xErr = /* @__PURE__ */ new Map();
|
|
17952
|
+
xOption = /* @__PURE__ */ new Map();
|
|
17953
|
+
headerLength = 0;
|
|
17954
|
+
isBodyComplete = false;
|
|
17955
|
+
remainingBodyLength = 0;
|
|
17956
|
+
generatePacket() {
|
|
17957
|
+
let packet = `POST ${this.uri} ${this.httpVersion}\r
|
|
17958
|
+
`;
|
|
17959
|
+
for (const [key, value] of this.headers)
|
|
17960
|
+
packet += `${key}:${urlEncode(value)}\r
|
|
17961
|
+
`;
|
|
17962
|
+
if (this.xErr.size > 0) {
|
|
17963
|
+
packet += "X-Err:";
|
|
17964
|
+
for (const [key, value] of this.xErr)
|
|
17965
|
+
packet += `${key}=${urlEncode(value)},`;
|
|
17966
|
+
packet += "\r\n";
|
|
18041
17967
|
}
|
|
18042
|
-
|
|
18043
|
-
|
|
18044
|
-
|
|
18045
|
-
|
|
18046
|
-
|
|
18047
|
-
full: OFFICIAL_INSTALLERS.public.full.version,
|
|
18048
|
-
mini: OFFICIAL_INSTALLERS.public.mini.version
|
|
18049
|
-
},
|
|
18050
|
-
REL: { full: "", mini: "" },
|
|
18051
|
-
DEBUG: {
|
|
18052
|
-
full: "20260714.4",
|
|
18053
|
-
mini: "20260714.4"
|
|
17968
|
+
if (this.xOption.size > 0) {
|
|
17969
|
+
packet += "X-Option:";
|
|
17970
|
+
for (const [key, value] of this.xOption)
|
|
17971
|
+
packet += `${key}=${urlEncode(value)},`;
|
|
17972
|
+
packet += "\r\n";
|
|
18054
17973
|
}
|
|
18055
|
-
|
|
18056
|
-
|
|
18057
|
-
|
|
18058
|
-
|
|
18059
|
-
|
|
18060
|
-
|
|
18061
|
-
|
|
18062
|
-
|
|
18063
|
-
|
|
18064
|
-
|
|
18065
|
-
|
|
18066
|
-
|
|
18067
|
-
|
|
18068
|
-
|
|
18069
|
-
|
|
18070
|
-
|
|
18071
|
-
|
|
18072
|
-
|
|
18073
|
-
|
|
17974
|
+
packet += `Content-Length:${Buffer.byteLength(this.content, "utf8")}\r
|
|
17975
|
+
\r
|
|
17976
|
+
`;
|
|
17977
|
+
return packet + this.content;
|
|
17978
|
+
}
|
|
17979
|
+
parsePacket(data) {
|
|
17980
|
+
const raw = data.toString("binary");
|
|
17981
|
+
const headerEnd = raw.indexOf("\r\n\r\n");
|
|
17982
|
+
if (headerEnd === -1)
|
|
17983
|
+
return false;
|
|
17984
|
+
this.headerLength = headerEnd + 4;
|
|
17985
|
+
const lines = raw.substring(0, headerEnd).split("\r\n");
|
|
17986
|
+
if (lines.length === 0)
|
|
17987
|
+
return false;
|
|
17988
|
+
const firstLine = lines[0];
|
|
17989
|
+
if (firstLine.startsWith("HTTP/")) {
|
|
17990
|
+
const match = firstLine.match(/^(\S+)\s+(\d+)\s+(.*)$/);
|
|
17991
|
+
if (match) {
|
|
17992
|
+
this.httpVersion = match[1];
|
|
17993
|
+
this.statusCode = Number.parseInt(match[2], 10);
|
|
17994
|
+
this.statusMessage = match[3] || "";
|
|
17995
|
+
}
|
|
17996
|
+
} else {
|
|
17997
|
+
const match = firstLine.match(/^(\S+)\s+(\S+)/);
|
|
17998
|
+
if (match) {
|
|
17999
|
+
this.method = match[1];
|
|
18000
|
+
this.uri = match[2];
|
|
18001
|
+
const queryIndex = this.uri.indexOf("?");
|
|
18002
|
+
if (queryIndex !== -1) {
|
|
18003
|
+
for (const param of this.uri.substring(queryIndex + 1).split("&")) {
|
|
18004
|
+
const equalIndex = param.indexOf("=");
|
|
18005
|
+
if (equalIndex !== -1) {
|
|
18006
|
+
this.params.set(param.substring(0, equalIndex), urlDecode(param.substring(equalIndex + 1)));
|
|
18007
|
+
}
|
|
18008
|
+
}
|
|
18009
|
+
}
|
|
18010
|
+
}
|
|
18011
|
+
}
|
|
18012
|
+
this.headers.clear();
|
|
18013
|
+
for (const line of lines.slice(1)) {
|
|
18014
|
+
const colonIndex = line.indexOf(":");
|
|
18015
|
+
if (colonIndex !== -1) {
|
|
18016
|
+
this.headers.set(line.substring(0, colonIndex), urlDecode(line.substring(colonIndex + 1)));
|
|
18017
|
+
}
|
|
18018
|
+
}
|
|
18019
|
+
const xErrValue = this.headers.get("X-Err");
|
|
18020
|
+
if (xErrValue)
|
|
18021
|
+
this.parseCommaSeparatedHeader(this.xErr, xErrValue);
|
|
18022
|
+
const xOptionValue = this.headers.get("X-Option");
|
|
18023
|
+
if (xOptionValue)
|
|
18024
|
+
this.parseCommaSeparatedHeader(this.xOption, xOptionValue);
|
|
18025
|
+
const contentLengthValue = this.headers.get("Content-Length");
|
|
18026
|
+
this.contentLength = contentLengthValue ? Number.parseInt(contentLengthValue, 10) : 0;
|
|
18027
|
+
const totalLength = this.headerLength + this.contentLength;
|
|
18028
|
+
if (data.length < totalLength) {
|
|
18029
|
+
this.isBodyComplete = false;
|
|
18030
|
+
this.remainingBodyLength = totalLength - data.length;
|
|
18031
|
+
return false;
|
|
18032
|
+
}
|
|
18033
|
+
this.isBodyComplete = true;
|
|
18034
|
+
this.remainingBodyLength = 0;
|
|
18035
|
+
this.content = this.contentLength > 0 ? decodePacketBody(data.subarray(this.headerLength, totalLength)) : "";
|
|
18036
|
+
return true;
|
|
18037
|
+
}
|
|
18038
|
+
getTotalLength() {
|
|
18039
|
+
return this.headerLength + this.contentLength;
|
|
18040
|
+
}
|
|
18041
|
+
isBodyCompletePacket() {
|
|
18042
|
+
return this.isBodyComplete;
|
|
18043
|
+
}
|
|
18044
|
+
getRemainingBodyLength() {
|
|
18045
|
+
return this.remainingBodyLength;
|
|
18046
|
+
}
|
|
18047
|
+
parseCommaSeparatedHeader(target, value) {
|
|
18048
|
+
target.clear();
|
|
18049
|
+
for (const pair of value.split(",")) {
|
|
18050
|
+
const equalIndex = pair.indexOf("=");
|
|
18051
|
+
if (equalIndex !== -1) {
|
|
18052
|
+
const key = pair.substring(0, equalIndex);
|
|
18053
|
+
if (key)
|
|
18054
|
+
target.set(key, urlDecode(pair.substring(equalIndex + 1)));
|
|
18055
|
+
}
|
|
18056
|
+
}
|
|
18057
|
+
}
|
|
18058
|
+
};
|
|
18059
|
+
var LOG_FILE = path.join(os.tmpdir(), "zlt-mcp-proxy.log");
|
|
18060
|
+
var pendingLogLines = [];
|
|
18061
|
+
var logWriteInFlight = false;
|
|
18062
|
+
function log(tag, message) {
|
|
18063
|
+
if (process.env.ZLT_IPC_DEBUG_LOG !== "1")
|
|
18064
|
+
return;
|
|
18065
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().substring(11, 23);
|
|
18066
|
+
pendingLogLines.push(`[${timestamp}][zltmcp][${tag}] ${message}
|
|
18067
|
+
`);
|
|
18068
|
+
flushLogQueue();
|
|
18069
|
+
}
|
|
18070
|
+
function flushLogQueue() {
|
|
18071
|
+
if (logWriteInFlight || pendingLogLines.length === 0)
|
|
18072
|
+
return;
|
|
18073
|
+
logWriteInFlight = true;
|
|
18074
|
+
const batch = pendingLogLines.splice(0).join("");
|
|
18075
|
+
try {
|
|
18076
|
+
fs.appendFile(LOG_FILE, batch, "utf8", () => {
|
|
18077
|
+
logWriteInFlight = false;
|
|
18078
|
+
flushLogQueue();
|
|
18079
|
+
});
|
|
18080
|
+
} catch {
|
|
18081
|
+
logWriteInFlight = false;
|
|
18082
|
+
}
|
|
18083
|
+
}
|
|
18084
|
+
function getZltafIpcLogFilePath() {
|
|
18085
|
+
return LOG_FILE;
|
|
18086
|
+
}
|
|
18087
|
+
var ZltafIpcClient = class {
|
|
18088
|
+
mainSocket = null;
|
|
18089
|
+
workSocket = null;
|
|
18090
|
+
buffer = Buffer.alloc(0);
|
|
18091
|
+
seqCounter = 0;
|
|
18092
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
18093
|
+
connected = false;
|
|
18094
|
+
onDisconnect = null;
|
|
18095
|
+
isConnected() {
|
|
18096
|
+
return this.connected;
|
|
18097
|
+
}
|
|
18098
|
+
async connect(pipePath, timeout = 5e3) {
|
|
18099
|
+
log("CONNECT", `\u5F00\u59CB\u8FDE\u63A5\u4E3B\u7BA1\u9053: ${pipePath}`);
|
|
18100
|
+
const uuid2 = (0, import_node_crypto.randomUUID)();
|
|
18101
|
+
const handshake = new ZltafHttpPacket();
|
|
18102
|
+
handshake.uri = `/ipcHandshake/pipName?ipcUUID=${uuid2}&supportFullDuplex=0`;
|
|
18103
|
+
handshake.content = "{}";
|
|
18104
|
+
log("HANDSHAKE", `\u53D1\u9001\u63E1\u624B\u8BF7\u6C42, uuid=${uuid2}`);
|
|
18105
|
+
const response = await this.connectAndSend(pipePath, handshake.generatePacket(), timeout);
|
|
18106
|
+
if (!response) {
|
|
18107
|
+
log("HANDSHAKE", "\u63E1\u624B\u5931\u8D25: \u672A\u6536\u5230\u54CD\u5E94");
|
|
18108
|
+
throw new Error("Handshake failed: no response from main pipe");
|
|
18109
|
+
}
|
|
18110
|
+
log("HANDSHAKE", `\u63E1\u624B\u6210\u529F, statusCode=${response.statusCode}`);
|
|
18111
|
+
const workPipeName = pipePath.replace(/[^\\/]+$/, uuid2);
|
|
18112
|
+
log("CONNECT", `\u8FDE\u63A5\u5DE5\u4F5C\u7BA1\u9053: ${workPipeName}`);
|
|
18113
|
+
await this.connectWorkPipe(workPipeName, timeout);
|
|
18114
|
+
this.connected = true;
|
|
18115
|
+
log("CONNECT", "IPC \u8FDE\u63A5\u5EFA\u7ACB\u5B8C\u6210");
|
|
18116
|
+
}
|
|
18117
|
+
invoke(uri, params, body = "{}", timeout = 5e3, customHeaders = []) {
|
|
18118
|
+
return new Promise((resolve8, reject) => {
|
|
18119
|
+
if (!this.workSocket || !this.connected) {
|
|
18120
|
+
log("INVOKE", `\u8C03\u7528\u5931\u8D25: \u672A\u8FDE\u63A5 (hasSocket=${Boolean(this.workSocket)}, connected=${this.connected})`);
|
|
18121
|
+
reject(new Error("Not connected"));
|
|
18122
|
+
return;
|
|
18123
|
+
}
|
|
18124
|
+
const seq = String(++this.seqCounter);
|
|
18125
|
+
const paramString = Object.entries(params).filter(([, value]) => value !== void 0 && value !== "").map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join("&");
|
|
18126
|
+
const baseUri = uri.startsWith("/") ? uri.substring(1) : uri;
|
|
18127
|
+
const fullUri = paramString ? `${baseUri}?${paramString}` : baseUri;
|
|
18128
|
+
const request = new ZltafHttpPacket();
|
|
18129
|
+
request.uri = fullUri;
|
|
18130
|
+
request.headers.set("Content-SEQ", seq);
|
|
18131
|
+
request.headers.set("Msg-Type", "2");
|
|
18132
|
+
for (const header of customHeaders) {
|
|
18133
|
+
const colon = header.indexOf(":");
|
|
18134
|
+
if (colon > 0)
|
|
18135
|
+
request.headers.set(header.substring(0, colon), header.substring(colon + 1));
|
|
18136
|
+
}
|
|
18137
|
+
request.content = body;
|
|
18138
|
+
const bodyPreview = body.length > 200 ? `${body.substring(0, 200)}...` : body;
|
|
18139
|
+
log("REQ", `seq=${seq} uri=${fullUri} body=${bodyPreview} timeout=${timeout}`);
|
|
18140
|
+
const timer = setTimeout(() => {
|
|
18141
|
+
this.pendingRequests.delete(seq);
|
|
18142
|
+
log("REQ", `seq=${seq} \u8D85\u65F6 (timeout=${timeout}ms)`);
|
|
18143
|
+
reject(new Error(`RPC timeout for ${uri} (seq=${seq})`));
|
|
18144
|
+
}, timeout);
|
|
18145
|
+
this.pendingRequests.set(seq, { resolve: resolve8, reject, timer });
|
|
18146
|
+
this.workSocket.write(request.generatePacket());
|
|
18147
|
+
});
|
|
18148
|
+
}
|
|
18149
|
+
async disconnect() {
|
|
18150
|
+
this.connected = false;
|
|
18151
|
+
if (this.workSocket) {
|
|
18152
|
+
this.workSocket.destroy();
|
|
18153
|
+
this.workSocket = null;
|
|
18154
|
+
}
|
|
18155
|
+
if (this.mainSocket) {
|
|
18156
|
+
this.mainSocket.destroy();
|
|
18157
|
+
this.mainSocket = null;
|
|
18158
|
+
}
|
|
18159
|
+
for (const [, pending] of this.pendingRequests) {
|
|
18160
|
+
clearTimeout(pending.timer);
|
|
18161
|
+
pending.reject(new Error("Disconnected"));
|
|
18162
|
+
}
|
|
18163
|
+
this.pendingRequests.clear();
|
|
18164
|
+
log("DISCONNECT", "\u4E3B\u52A8\u65AD\u5F00\u8FDE\u63A5");
|
|
18165
|
+
}
|
|
18166
|
+
connectWorkPipe(pipeName, timeout) {
|
|
18167
|
+
return new Promise((resolve8, reject) => {
|
|
18168
|
+
const timer = setTimeout(() => reject(new Error(`Work pipe connect timeout: ${pipeName}`)), timeout);
|
|
18169
|
+
this.workSocket = net.connect(pipeName, () => {
|
|
18170
|
+
clearTimeout(timer);
|
|
18171
|
+
resolve8();
|
|
18172
|
+
});
|
|
18173
|
+
this.workSocket.on("error", (error2) => {
|
|
18174
|
+
clearTimeout(timer);
|
|
18175
|
+
reject(error2);
|
|
18176
|
+
});
|
|
18177
|
+
this.workSocket.on("data", (data) => this.onData(data));
|
|
18178
|
+
this.workSocket.on("end", () => this.handleServerDisconnect("end"));
|
|
18179
|
+
this.workSocket.on("close", () => this.handleServerDisconnect("close"));
|
|
18180
|
+
});
|
|
18181
|
+
}
|
|
18182
|
+
handleServerDisconnect(event) {
|
|
18183
|
+
if (!this.connected)
|
|
18184
|
+
return;
|
|
18185
|
+
this.connected = false;
|
|
18186
|
+
log("DISCONNECT", `IPC \u670D\u52A1\u7AEF\u65AD\u5F00\u8FDE\u63A5 (event=${event}), pending=${this.pendingRequests.size}`);
|
|
18187
|
+
for (const [seq, pending] of this.pendingRequests) {
|
|
18188
|
+
clearTimeout(pending.timer);
|
|
18189
|
+
pending.reject(new Error("IPC server disconnected"));
|
|
18190
|
+
log("DISCONNECT", `\u6E05\u7406 pending \u8BF7\u6C42: seq=${seq}`);
|
|
18191
|
+
}
|
|
18192
|
+
this.pendingRequests.clear();
|
|
18193
|
+
this.onDisconnect?.();
|
|
18194
|
+
}
|
|
18195
|
+
connectAndSend(pipePath, data, timeout) {
|
|
18196
|
+
return new Promise((resolve8, reject) => {
|
|
18197
|
+
const timer = setTimeout(() => {
|
|
18198
|
+
if (this.mainSocket) {
|
|
18199
|
+
this.mainSocket.destroy();
|
|
18200
|
+
this.mainSocket = null;
|
|
18201
|
+
}
|
|
18202
|
+
resolve8(null);
|
|
18203
|
+
}, timeout);
|
|
18204
|
+
let responseBuffer = Buffer.alloc(0);
|
|
18205
|
+
this.mainSocket = net.connect(pipePath, () => this.mainSocket.write(data));
|
|
18206
|
+
this.mainSocket.on("data", (chunk) => {
|
|
18207
|
+
responseBuffer = Buffer.concat([responseBuffer, chunk]);
|
|
18208
|
+
const packet = new ZltafHttpPacket();
|
|
18209
|
+
if (packet.parsePacket(responseBuffer)) {
|
|
18210
|
+
clearTimeout(timer);
|
|
18211
|
+
this.mainSocket.destroy();
|
|
18212
|
+
this.mainSocket = null;
|
|
18213
|
+
resolve8(packet);
|
|
18214
|
+
}
|
|
18215
|
+
});
|
|
18216
|
+
this.mainSocket.on("error", (error2) => {
|
|
18217
|
+
clearTimeout(timer);
|
|
18218
|
+
reject(error2);
|
|
18219
|
+
});
|
|
18220
|
+
});
|
|
18221
|
+
}
|
|
18222
|
+
onData(data) {
|
|
18223
|
+
this.buffer = Buffer.concat([this.buffer, data]);
|
|
18224
|
+
while (this.buffer.length > 0) {
|
|
18225
|
+
const packet = new ZltafHttpPacket();
|
|
18226
|
+
if (!packet.parsePacket(this.buffer))
|
|
18227
|
+
break;
|
|
18228
|
+
this.buffer = this.buffer.subarray(packet.getTotalLength());
|
|
18229
|
+
const seq = packet.headers.get("Content-SEQ");
|
|
18230
|
+
if (seq) {
|
|
18231
|
+
const pending = this.pendingRequests.get(seq);
|
|
18232
|
+
if (pending) {
|
|
18233
|
+
clearTimeout(pending.timer);
|
|
18234
|
+
this.pendingRequests.delete(seq);
|
|
18235
|
+
const preview = packet.content.length > 300 ? `${packet.content.substring(0, 300)}... (${packet.contentLength} bytes)` : packet.content;
|
|
18236
|
+
log("RESP", `seq=${seq} status=${packet.statusCode} content=${preview}`);
|
|
18237
|
+
pending.resolve(packet);
|
|
18238
|
+
} else {
|
|
18239
|
+
log("RESP", `seq=${seq} status=${packet.statusCode} (\u65E0\u5339\u914D\u8BF7\u6C42\uFF0C\u4E22\u5F03)`);
|
|
18240
|
+
}
|
|
18241
|
+
} else {
|
|
18242
|
+
log("PUSH", `status=${packet.statusCode} content=${packet.content.substring(0, 200)}`);
|
|
18243
|
+
}
|
|
18244
|
+
}
|
|
18245
|
+
}
|
|
18246
|
+
};
|
|
18247
|
+
|
|
18248
|
+
// src/config.ts
|
|
18249
|
+
var config_exports = {};
|
|
18250
|
+
__export(config_exports, {
|
|
18251
|
+
discoverPipePath: () => discoverPipePath,
|
|
18252
|
+
loadConfig: () => loadConfig,
|
|
18253
|
+
matchingPipeNames: () => matchingPipeNames2,
|
|
18254
|
+
resolveDefaultConfigPath: () => resolveDefaultConfigPath,
|
|
18255
|
+
resolveDefaultRuntimeConfigPath: () => resolveDefaultRuntimeConfigPath
|
|
18256
|
+
});
|
|
18257
|
+
var fs8 = __toESM(require("fs"), 1);
|
|
18258
|
+
var path8 = __toESM(require("path"), 1);
|
|
18259
|
+
|
|
18260
|
+
// ../zlt-runtime-core/dist/config.js
|
|
18261
|
+
var fs2 = __toESM(require("fs"), 1);
|
|
18262
|
+
var EXDATA_SERVICE_INDEX = 2;
|
|
18263
|
+
var FACTOR_SERVICE_INDEX = 3;
|
|
18264
|
+
var SDK_SERVICE_INDEX = 6;
|
|
18265
|
+
var TY_MODULE_INDEX = 1;
|
|
18266
|
+
var CLIENT_PLUGIN_MODULE_INDEX = 4;
|
|
18267
|
+
var DEFAULT_BACKTEST_SERVICE_INDICES = [
|
|
18268
|
+
EXDATA_SERVICE_INDEX,
|
|
18269
|
+
FACTOR_SERVICE_INDEX,
|
|
18270
|
+
SDK_SERVICE_INDEX
|
|
18271
|
+
];
|
|
18272
|
+
var DEFAULT_STARTUP_CHECK_INDICES = [SDK_SERVICE_INDEX];
|
|
18273
|
+
var DEFAULT_BACKTEST_MODULE_INDICES = [TY_MODULE_INDEX];
|
|
18274
|
+
var DEBUG_ASSISTANT_INSTALLER_URL = "https://beta.zltquant.com/download/setup-ZLTStudio-Dbg-mini-20260714.4.exe";
|
|
18275
|
+
var PUBLIC_PYTHON_SDK_INDEX_URL = "https://pypip.zltquant.com/";
|
|
18276
|
+
var ZLTAF_CONFIG_FILE_DEFAULT = "application-local.properties";
|
|
18277
|
+
var OFFICIAL_MIRROR_ROOTS = {
|
|
18278
|
+
public: "https://zlt-data-house.oss-cn-wuhan-lr.aliyuncs.com/zltkj.site/down/v1/up/Zlt.Std.Official",
|
|
18279
|
+
internal: "http://192.168.1.243:9000/zlt-data-house/zltkj.site/down/v1/up/Zlt.Std.Official"
|
|
18280
|
+
};
|
|
18281
|
+
var OFFICIAL_INSTALLERS = {
|
|
18282
|
+
public: {
|
|
18283
|
+
// 2026-08-31 抬到 2026.08.31.3,接替 2026.06.18.11 —— 运维已把件传上公网 OSS。
|
|
18284
|
+
// 摘要不必重下:公网与内网是同一份字节,HEAD 实测 Content-Length 168,548,568
|
|
18285
|
+
// 与 ETag(OSS 侧即 MD5)C404C12F…33DA 两边完全一致,所以沿用内网那份已核过的
|
|
18286
|
+
// SHA256=5BE939F0…5B19。
|
|
18287
|
+
// 卡在 2026.06.18.11 的代价是实打实的:它低于我们自己发布的
|
|
18288
|
+
// zlt_quant_version_index.json 里的 Client.min = 2026.08.12.3,于是一台 full
|
|
18289
|
+
// 装机撞上闸门只会得到 blockedByPlugin,被告知「请先升级 ZLT Quant 插件」——
|
|
18290
|
+
// 而插件已经是最新的那一版,闸门永远消不掉。
|
|
18291
|
+
// 本条与 internal.full 这次同版本,那是因为公网刚补齐,不是两张表从此必然同步。
|
|
18292
|
+
// **本版没有装机验证**,与 internal.full 同一句话。
|
|
18293
|
+
full: {
|
|
18294
|
+
artifact: "zlt_client",
|
|
18295
|
+
version: "2026.08.31.3",
|
|
18296
|
+
sha256: "5BE939F069E69C05F37017FBB06FF76DE4DBCBD4CBCAF1322479255A5CE55B19"
|
|
18297
|
+
},
|
|
18298
|
+
// 2026-08-15 抬到 2026.08.14.5:公网 OSS 与内网镜像是同一份字节(ETag 113b3cff…、
|
|
18299
|
+
// 75,075,160 字节两边一致),本机下载实测 SHA256=9D40AE9A…D551,与 2026-08-14 覆盖
|
|
18300
|
+
// 安装时校验过的摘要一致,两条独立路径互证。这一版是投研模块下限(≥2026.08.11.2)
|
|
18301
|
+
// 之上的第一个已发布 mini:低于它,投研模块 upgrade/check 直接以「客户端版本过低」
|
|
18302
|
+
// 拒绝,且该下限只在模块服务端。version 取安装包自身 FileVersion 的点分四段(不是
|
|
18303
|
+
// 构建目录名的紧凑形 20260814.5):升级判定拿它和 InstallInfo.xml 的
|
|
18304
|
+
// InstallAppReleaseVer 比,写成紧凑形会让「有可用更新」永远消不掉。
|
|
18305
|
+
// 2026-08-31 抬到 2026.08.31.4,接替 2026.08.14.5。判据与 full 同一条:HEAD 实测
|
|
18306
|
+
// Content-Length 79,605,832 与 ETag 7A53D1EE…1375 公网内网一致,摘要沿用内网已核过的
|
|
18307
|
+
// SHA256=115A3EED…83CE。
|
|
18308
|
+
// 这一槽位是市场版的首装路径 —— VSCode 只装 mini(runtime-profile.mjs 的
|
|
18309
|
+
// VSCODE_INSTALL_TYPE),full 槽位只在已装 full 的机器上参与升级判定。
|
|
18310
|
+
// **本版没有装机验证**:本机停在 2026.08.28.7,08-30 对 .7 做的那轮活体复核
|
|
18311
|
+
// (三进程起得来、ZLTHQHost 管道在、两轮 check:npm-live 全绿)不适用于本版。
|
|
18312
|
+
mini: {
|
|
18313
|
+
artifact: "zlt_plugin",
|
|
18314
|
+
version: "2026.08.31.4",
|
|
18315
|
+
sha256: "115A3EEDC07211F6FBE56696573F668AE8315E351B017FECB0F6136AAAD983CE"
|
|
18316
|
+
}
|
|
18317
|
+
},
|
|
18318
|
+
internal: {
|
|
18319
|
+
// 2026-08-31 抬到 2026.08.31.3(1.0.2 RC 用件),接替 2026.08.28.8。内网镜像下载
|
|
18320
|
+
// 核验:168,548,568 字节,SHA256=5BE939F0…5B19,安装包 FileVersion 自报
|
|
18321
|
+
// 2026.08.31.3(版本取它,不取文件名)。它仍高于 Client.min = 2026.08.12.3,
|
|
18322
|
+
// 所以内测通道上一台 full 装机不会以 blockedByPlugin 收场。
|
|
18323
|
+
// 公网 OSS 上这一版 404(2026-08-31 实测 HEAD),public.full 不动。
|
|
18324
|
+
full: {
|
|
18325
|
+
artifact: "zlt_client",
|
|
18326
|
+
version: "2026.08.31.3",
|
|
18327
|
+
sha256: "5BE939F069E69C05F37017FBB06FF76DE4DBCBD4CBCAF1322479255A5CE55B19"
|
|
18328
|
+
},
|
|
18329
|
+
// 2026-08-31 抬到 2026.08.31.4(1.0.2 RC 用件),接替 2026.08.28.7。下载核验:
|
|
18330
|
+
// 79,605,832 字节,SHA256=115A3EED…83CE,FileVersion 自报 2026.08.31.4。
|
|
18331
|
+
//
|
|
18332
|
+
// **本条两件都只核到字节与版本,没有装机验证。** 本机停在 2026.08.28.7
|
|
18333
|
+
// (InstallInfo.xml 的 InstallAppReleaseVer 实读如此),所以 08-30 对 .7 做的那轮
|
|
18334
|
+
// 活体复核(三进程起得来、ZLTHQHost 管道在、两轮 check:npm-live 全绿)**不适用于
|
|
18335
|
+
// 这两版**,别把它顺移过来当证据。RC 装机后要重新确认两件事:ZLTHome 起得来、
|
|
18336
|
+
// 且 InstallAppReleaseVer 回读等于本条点分四段(对不上会让「有可用更新」永远消不掉)。
|
|
18337
|
+
//
|
|
18338
|
+
// 这条 08-28 起的历史仍然有效,记着是因为它解释了为什么这批件在密集换版:
|
|
18339
|
+
// 2026.08.28.3 现场装过并 ZLTHome 启动即崩(TTaskFunc 持栈上 lambda 的悬垂引用,
|
|
18340
|
+
// 100% 复现,ZLTHQHost 管道从未存活);同版起把 zltaf 从投研模块的子模块集里去掉,
|
|
18341
|
+
// 修的是首装必炸的另一条权限死路 —— 安装器与模块各发一份 zltaf,模块解压要覆盖
|
|
18342
|
+
// 安装器以管理员身份写下的文件,而 ZLTBackService 跑在登录账户的 UAC 过滤令牌上,
|
|
18343
|
+
// 卷根 ACL 缺 Authenticated Users:(M) 时覆盖必被拒,2 毫秒失败在第一个文件上。
|
|
18344
|
+
// 见 docs/reports/2026-08-28-zltaf-submodule-extract-access-denied.md。
|
|
18345
|
+
// 这些版本都没进过本表,不要读成本槽位的版本序列(上一个 pin 是 2026.08.28.7)。
|
|
18346
|
+
//
|
|
18347
|
+
// 公网 OSS 上这一版同样 404,所以 public.mini 仍停在 2026.08.14.5 —— 两张表不同版本,
|
|
18348
|
+
// 这正是按镜像分表的理由。
|
|
18349
|
+
mini: {
|
|
18350
|
+
artifact: "zlt_plugin",
|
|
18351
|
+
version: "2026.08.31.4",
|
|
18352
|
+
sha256: "115A3EEDC07211F6FBE56696573F668AE8315E351B017FECB0F6136AAAD983CE"
|
|
18353
|
+
}
|
|
18354
|
+
}
|
|
18355
|
+
};
|
|
18356
|
+
function resolveInstallerMirror() {
|
|
18357
|
+
return false ? "internal" : "public";
|
|
18358
|
+
}
|
|
18359
|
+
function officialInstallerUrl(slot, mirror = "public") {
|
|
18360
|
+
const spec = OFFICIAL_INSTALLERS[mirror][slot];
|
|
18361
|
+
return `${OFFICIAL_MIRROR_ROOTS[mirror]}/pkg/${spec.artifact}_${spec.version}.exe`;
|
|
18362
|
+
}
|
|
18363
|
+
function officialVersionIndexUrl(mirror = "public") {
|
|
18364
|
+
return `${OFFICIAL_MIRROR_ROOTS[mirror]}/VscodeMarketPlugin/zlt_quant_version_index.json`;
|
|
18365
|
+
}
|
|
18366
|
+
var INTERNAL_PYTHON_SDK_INDEX_URL = "https://192.168.1.32:9100/pypi/simple/";
|
|
18367
|
+
var INTERNAL_PYTHON_SDK_TRUSTED_HOST = "192.168.1.32";
|
|
18368
|
+
var PYTHON_SDK_PACKAGES = ["zltquant", "zltsdk-plugin"];
|
|
18369
|
+
var PUBLIC_PYTHON_SDK_PACKAGES = [...PYTHON_SDK_PACKAGES];
|
|
18370
|
+
var INTERNAL_PYTHON_SDK_PACKAGES = [...PYTHON_SDK_PACKAGES];
|
|
18371
|
+
var PROD_PYTHON_SDK_PACKAGES = [...PYTHON_SDK_PACKAGES];
|
|
18372
|
+
var DEV_PYTHON_SDK_PACKAGES = [...PYTHON_SDK_PACKAGES];
|
|
18373
|
+
var PYTHON_SDK_ABI_TAG = "cp310";
|
|
18374
|
+
var PYTHON_PIP_WHEEL_URL = "https://repo.huaweicloud.com/repository/pypi/packages/5d/95/6b5cb3461ea5673ba0995989746db58eb18b91b54dbf331e72f569540946/pip-26.1.2-py3-none-any.whl";
|
|
18375
|
+
var PYTHON_PIP_WHEEL_SHA256 = "382FF9F685EE3BC25864F820AA50505825F10F5458FFFF07E30A6D96E5715CAB";
|
|
18376
|
+
var PYTHON_RUNTIME_INDEX_URL = "https://repo.huaweicloud.com/repository/pypi/simple/";
|
|
18377
|
+
var defaultAssistantRuntimeConfig = {
|
|
18378
|
+
registryKeys: {
|
|
18379
|
+
OFFICIAL: "Zlt.Std.Official_is1",
|
|
18380
|
+
REL: "Zlt.Std.Rel_is1",
|
|
18381
|
+
DEBUG: "Zlt.Std.Dbg_is1"
|
|
18382
|
+
},
|
|
18383
|
+
envMode: "OFFICIAL",
|
|
18384
|
+
backserviceDownload: {
|
|
18385
|
+
OFFICIAL: {
|
|
18386
|
+
full: officialInstallerUrl("full"),
|
|
18387
|
+
mini: officialInstallerUrl("mini")
|
|
18388
|
+
},
|
|
18389
|
+
REL: {
|
|
18390
|
+
full: "",
|
|
18391
|
+
mini: ""
|
|
18392
|
+
},
|
|
18393
|
+
DEBUG: {
|
|
18394
|
+
full: DEBUG_ASSISTANT_INSTALLER_URL,
|
|
18395
|
+
mini: DEBUG_ASSISTANT_INSTALLER_URL
|
|
18396
|
+
}
|
|
18397
|
+
},
|
|
18398
|
+
// Exact artifact digests. A URL update requires a matching digest update in the
|
|
18399
|
+
// same reviewed change; downloadRuntimeInstaller fails closed when it is absent.
|
|
18400
|
+
// OFFICIAL 的取值来自 OFFICIAL_INSTALLERS.public —— URL/版本/摘要三者同源,只有那一处可改。
|
|
18401
|
+
// 这里恒取公网表:模块级默认必须公网可达(runtime.test.ts 的 LAN 守卫钉的就是它),
|
|
18402
|
+
// 内网镜像那档由 applyEnvOverrides 按镜像轴整行换掉。
|
|
18403
|
+
backserviceDownloadSha256: {
|
|
18404
|
+
OFFICIAL: {
|
|
18405
|
+
full: OFFICIAL_INSTALLERS.public.full.sha256,
|
|
18406
|
+
mini: OFFICIAL_INSTALLERS.public.mini.sha256
|
|
18407
|
+
},
|
|
18408
|
+
REL: { full: "", mini: "" },
|
|
18409
|
+
DEBUG: {
|
|
18410
|
+
full: "05C57A5D212684A801665774E9F0813EFC1AA4762D1540EC353BB41173712B07",
|
|
18411
|
+
mini: "05C57A5D212684A801665774E9F0813EFC1AA4762D1540EC353BB41173712B07"
|
|
18412
|
+
}
|
|
18413
|
+
},
|
|
18414
|
+
// 本体升级判定拿它当「我们能立刻交付的版本下限」。OFFICIAL 与 URL 同源自
|
|
18415
|
+
// OFFICIAL_INSTALLERS,结构上不可能只改 URL 不改这里。
|
|
18416
|
+
backserviceDownloadVersion: {
|
|
18417
|
+
OFFICIAL: {
|
|
18418
|
+
full: OFFICIAL_INSTALLERS.public.full.version,
|
|
18419
|
+
mini: OFFICIAL_INSTALLERS.public.mini.version
|
|
18420
|
+
},
|
|
18421
|
+
REL: { full: "", mini: "" },
|
|
18422
|
+
DEBUG: {
|
|
18423
|
+
full: "20260714.4",
|
|
18424
|
+
mini: "20260714.4"
|
|
18425
|
+
}
|
|
18426
|
+
},
|
|
18427
|
+
// 我们自己发布的版本索引:versions[] 按**本插件**的发布序列给出各组件的 min/max,
|
|
18428
|
+
// 形状沿用李扬的 zlt_version_index.json,方便日后合并。
|
|
18429
|
+
//
|
|
18430
|
+
// 为什么不复用李扬那份:它的 versions[] 编号是 claw 插件的版本序列,与我们合并后的
|
|
18431
|
+
// 1.0.x 撞车 —— 远程 1.0.1 条目写的是 claw 1.0.1 的门槛(ClientPlugin.min = 2026.06.05.1),
|
|
18432
|
+
// 按我们的 VSIX 1.0.1 去区间匹配就会读到一个与我们无关、且明显偏低的下限。
|
|
18433
|
+
//
|
|
18434
|
+
// REL/DEBUG 没有对应发布面,留空即跳过远程判定。地址不可达或文件不存在同样 fail-open,
|
|
18435
|
+
// 所以这条链路默认是关的,直到有人把文件传上去 —— 见 deploy/README.md。
|
|
18436
|
+
// 与安装包同源自 OFFICIAL_MIRROR_ROOTS:内测构建把安装包指到内网时,这条也必须跟着走,
|
|
18437
|
+
// 否则一个 -internal 产物会拿公网索引判闸门 —— 而索引取不到时闸门是 fail-open。
|
|
18438
|
+
baseRequirementUrl: {
|
|
18439
|
+
OFFICIAL: officialVersionIndexUrl("public"),
|
|
18440
|
+
REL: "",
|
|
18441
|
+
DEBUG: ""
|
|
18442
|
+
},
|
|
18443
|
+
// 用来做区间匹配的插件版本。VSCode 侧由 loadVscodeRuntimeConfig 填当前 VSIX 版本;
|
|
18444
|
+
// 没有插件版本概念的消费者(zlt-mcp-proxy)留空,留空即整条远程判定跳过。
|
|
18074
18445
|
baseRequirementPluginVersion: "",
|
|
18075
18446
|
baseRequirementTimeout: 5e3,
|
|
18076
18447
|
pythonSdkIndex: {
|
|
@@ -18129,7 +18500,7 @@ var defaultAssistantRuntimeConfig = {
|
|
|
18129
18500
|
function loadAssistantRuntimeConfig(configPath) {
|
|
18130
18501
|
if (!configPath)
|
|
18131
18502
|
return applyEnvOverrides(defaultAssistantRuntimeConfig);
|
|
18132
|
-
const raw = JSON.parse(
|
|
18503
|
+
const raw = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
|
|
18133
18504
|
if (!raw.assistant)
|
|
18134
18505
|
return applyEnvOverrides(defaultAssistantRuntimeConfig);
|
|
18135
18506
|
const assistant = raw.assistant;
|
|
@@ -18418,7 +18789,7 @@ function buildPowerShellRegistryArgs() {
|
|
|
18418
18789
|
return ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", READ_REGISTRY_VALUE_SCRIPT];
|
|
18419
18790
|
}
|
|
18420
18791
|
function readRegistryValueWithPowerShell(registryKey, valueName) {
|
|
18421
|
-
return new Promise((
|
|
18792
|
+
return new Promise((resolve8, reject) => {
|
|
18422
18793
|
(0, import_child_process.execFile)(POWERSHELL_EXE, buildPowerShellRegistryArgs(), {
|
|
18423
18794
|
encoding: "utf-8",
|
|
18424
18795
|
env: buildPowerShellRegistryEnvironment(registryKey, valueName),
|
|
@@ -18427,7 +18798,7 @@ function readRegistryValueWithPowerShell(registryKey, valueName) {
|
|
|
18427
18798
|
if (error2)
|
|
18428
18799
|
reject(error2);
|
|
18429
18800
|
else
|
|
18430
|
-
|
|
18801
|
+
resolve8(stdout.trim());
|
|
18431
18802
|
});
|
|
18432
18803
|
});
|
|
18433
18804
|
}
|
|
@@ -18453,8 +18824,8 @@ async function readAssistantRegistryStringValue(config2, valueName, _suppressStd
|
|
|
18453
18824
|
}
|
|
18454
18825
|
|
|
18455
18826
|
// ../zlt-runtime-core/dist/pipe.js
|
|
18456
|
-
var
|
|
18457
|
-
var
|
|
18827
|
+
var fs3 = __toESM(require("fs"), 1);
|
|
18828
|
+
var path2 = __toESM(require("path"), 1);
|
|
18458
18829
|
function matchingPipeNames(entries, prefix) {
|
|
18459
18830
|
const searchPrefix = `${prefix}_`;
|
|
18460
18831
|
const exactResults = [];
|
|
@@ -18475,13 +18846,13 @@ function selectUnambiguousPipeName(entries, prefix) {
|
|
|
18475
18846
|
function enumeratePipeNames(prefix) {
|
|
18476
18847
|
try {
|
|
18477
18848
|
if (process.platform === "win32") {
|
|
18478
|
-
return matchingPipeNames(
|
|
18849
|
+
return matchingPipeNames(fs3.readdirSync("\\\\.\\pipe\\"), prefix);
|
|
18479
18850
|
}
|
|
18480
18851
|
const socketResults = [];
|
|
18481
|
-
for (const name of matchingPipeNames(
|
|
18482
|
-
const fullPath =
|
|
18852
|
+
for (const name of matchingPipeNames(fs3.readdirSync("/tmp"), prefix)) {
|
|
18853
|
+
const fullPath = path2.join("/tmp", name);
|
|
18483
18854
|
try {
|
|
18484
|
-
if (!
|
|
18855
|
+
if (!fs3.statSync(fullPath).isSocket())
|
|
18485
18856
|
continue;
|
|
18486
18857
|
socketResults.push(name);
|
|
18487
18858
|
} catch {
|
|
@@ -18504,26 +18875,26 @@ function toPipeEndpoint(pipeName) {
|
|
|
18504
18875
|
}
|
|
18505
18876
|
function pipeEndpointExists(pipePath) {
|
|
18506
18877
|
try {
|
|
18507
|
-
return
|
|
18878
|
+
return fs3.existsSync(pipePath);
|
|
18508
18879
|
} catch {
|
|
18509
18880
|
return false;
|
|
18510
18881
|
}
|
|
18511
18882
|
}
|
|
18512
18883
|
function readZltHostPipeName(clientRootDir) {
|
|
18513
|
-
let configPath =
|
|
18514
|
-
if (!
|
|
18515
|
-
configPath =
|
|
18884
|
+
let configPath = path2.join(clientRootDir, "zlthost.json");
|
|
18885
|
+
if (!fs3.existsSync(configPath)) {
|
|
18886
|
+
configPath = path2.join(clientRootDir, "zltHost", "zlthost.json");
|
|
18516
18887
|
}
|
|
18517
|
-
if (!
|
|
18888
|
+
if (!fs3.existsSync(configPath))
|
|
18518
18889
|
return null;
|
|
18519
|
-
const parsed = JSON.parse(
|
|
18890
|
+
const parsed = JSON.parse(fs3.readFileSync(configPath, "utf-8"));
|
|
18520
18891
|
return parsed.pipName || null;
|
|
18521
18892
|
}
|
|
18522
18893
|
function readZltPipeSuffix(clientRootDir) {
|
|
18523
|
-
const zltFile =
|
|
18524
|
-
if (!
|
|
18894
|
+
const zltFile = path2.join(clientRootDir, "Temporary", "zlt");
|
|
18895
|
+
if (!fs3.existsSync(zltFile))
|
|
18525
18896
|
return null;
|
|
18526
|
-
return
|
|
18897
|
+
return fs3.readFileSync(zltFile, "utf-8").trim() || null;
|
|
18527
18898
|
}
|
|
18528
18899
|
function resolveInstallPipeName(clientRootDir, pipeName) {
|
|
18529
18900
|
const suffix = readZltPipeSuffix(clientRootDir);
|
|
@@ -18562,33 +18933,18 @@ function pipeExists(clientRootDir, explicitPipeName) {
|
|
|
18562
18933
|
}
|
|
18563
18934
|
|
|
18564
18935
|
// ../zlt-runtime-core/dist/runtime.js
|
|
18565
|
-
var
|
|
18566
|
-
var
|
|
18567
|
-
var
|
|
18936
|
+
var fs6 = __toESM(require("fs"), 1);
|
|
18937
|
+
var os2 = __toESM(require("os"), 1);
|
|
18938
|
+
var path6 = __toESM(require("path"), 1);
|
|
18568
18939
|
var http = __toESM(require("http"), 1);
|
|
18569
18940
|
var https = __toESM(require("https"), 1);
|
|
18570
18941
|
var import_crypto3 = require("crypto");
|
|
18571
18942
|
var import_child_process3 = require("child_process");
|
|
18572
18943
|
|
|
18573
18944
|
// ../zlt-runtime-core/dist/assistant-ipc.js
|
|
18574
|
-
var
|
|
18575
|
-
var
|
|
18945
|
+
var net2 = __toESM(require("net"), 1);
|
|
18946
|
+
var path3 = __toESM(require("path"), 1);
|
|
18576
18947
|
var import_crypto = require("crypto");
|
|
18577
|
-
|
|
18578
|
-
// ../zlt-runtime-core/dist/packet-encoding.js
|
|
18579
|
-
function decodePacketBody(body) {
|
|
18580
|
-
try {
|
|
18581
|
-
return new TextDecoder("utf-8", { fatal: true }).decode(body);
|
|
18582
|
-
} catch {
|
|
18583
|
-
try {
|
|
18584
|
-
return new TextDecoder("gbk").decode(body);
|
|
18585
|
-
} catch {
|
|
18586
|
-
return body.toString("utf8");
|
|
18587
|
-
}
|
|
18588
|
-
}
|
|
18589
|
-
}
|
|
18590
|
-
|
|
18591
|
-
// ../zlt-runtime-core/dist/assistant-ipc.js
|
|
18592
18948
|
var ASSISTANT_CONNECT_MAX_ATTEMPTS = 3;
|
|
18593
18949
|
var ASSISTANT_CONNECT_RETRY_DELAY_MS = 1e3;
|
|
18594
18950
|
var AssistantMasterIpcClient = class {
|
|
@@ -18843,8 +19199,8 @@ var AssistantMasterIpcClient = class {
|
|
|
18843
19199
|
this.buffer = Buffer.alloc(0);
|
|
18844
19200
|
}
|
|
18845
19201
|
connectMainPipe(pipePath, timeout) {
|
|
18846
|
-
return new Promise((
|
|
18847
|
-
const socket =
|
|
19202
|
+
return new Promise((resolve8, reject) => {
|
|
19203
|
+
const socket = net2.connect(pipePath);
|
|
18848
19204
|
const timer = setTimeout(() => {
|
|
18849
19205
|
socket.destroy();
|
|
18850
19206
|
reject(new Error(`Assistant master pipe connect timeout: ${pipePath}`));
|
|
@@ -18852,7 +19208,7 @@ var AssistantMasterIpcClient = class {
|
|
|
18852
19208
|
socket.once("connect", () => {
|
|
18853
19209
|
clearTimeout(timer);
|
|
18854
19210
|
this.mainSocket = socket;
|
|
18855
|
-
|
|
19211
|
+
resolve8();
|
|
18856
19212
|
});
|
|
18857
19213
|
socket.once("error", (error2) => {
|
|
18858
19214
|
clearTimeout(timer);
|
|
@@ -18861,7 +19217,7 @@ var AssistantMasterIpcClient = class {
|
|
|
18861
19217
|
});
|
|
18862
19218
|
}
|
|
18863
19219
|
sendHandshake(timeout) {
|
|
18864
|
-
return new Promise((
|
|
19220
|
+
return new Promise((resolve8, reject) => {
|
|
18865
19221
|
if (!this.mainSocket) {
|
|
18866
19222
|
reject(new Error("Assistant master pipe is not connected"));
|
|
18867
19223
|
return;
|
|
@@ -18890,7 +19246,7 @@ var AssistantMasterIpcClient = class {
|
|
|
18890
19246
|
reject(new Error(`Assistant master pipe handshake failed: ${buffer.slice(0, 200)}`));
|
|
18891
19247
|
return;
|
|
18892
19248
|
}
|
|
18893
|
-
|
|
19249
|
+
resolve8();
|
|
18894
19250
|
};
|
|
18895
19251
|
this.mainSocket.on("data", onData);
|
|
18896
19252
|
this.mainSocket.on("error", onError);
|
|
@@ -18906,8 +19262,8 @@ var AssistantMasterIpcClient = class {
|
|
|
18906
19262
|
});
|
|
18907
19263
|
}
|
|
18908
19264
|
connectBusinessPipe(pipePath, timeout) {
|
|
18909
|
-
return new Promise((
|
|
18910
|
-
const socket =
|
|
19265
|
+
return new Promise((resolve8, reject) => {
|
|
19266
|
+
const socket = net2.connect(pipePath);
|
|
18911
19267
|
const timer = setTimeout(() => {
|
|
18912
19268
|
socket.destroy();
|
|
18913
19269
|
reject(new Error(`Assistant business pipe connect timeout: ${pipePath}`));
|
|
@@ -18917,7 +19273,7 @@ var AssistantMasterIpcClient = class {
|
|
|
18917
19273
|
this.businessSocket = socket;
|
|
18918
19274
|
socket.on("data", (chunk) => this.onBusinessData(chunk));
|
|
18919
19275
|
socket.on("close", () => this.rejectAll(new Error("Assistant business pipe closed")));
|
|
18920
|
-
|
|
19276
|
+
resolve8();
|
|
18921
19277
|
});
|
|
18922
19278
|
socket.once("error", (error2) => {
|
|
18923
19279
|
clearTimeout(timer);
|
|
@@ -18926,7 +19282,7 @@ var AssistantMasterIpcClient = class {
|
|
|
18926
19282
|
});
|
|
18927
19283
|
}
|
|
18928
19284
|
sendRequest(moduleName, funcName, data, timeout) {
|
|
18929
|
-
return new Promise((
|
|
19285
|
+
return new Promise((resolve8, reject) => {
|
|
18930
19286
|
if (!this.businessSocket || !this.connected) {
|
|
18931
19287
|
reject(new Error("Assistant business pipe is not connected"));
|
|
18932
19288
|
return;
|
|
@@ -18949,7 +19305,7 @@ var AssistantMasterIpcClient = class {
|
|
|
18949
19305
|
this.pending.delete(seq);
|
|
18950
19306
|
reject(new Error(`Assistant IPC request timeout: ${moduleName}/${funcName}`));
|
|
18951
19307
|
}, timeout);
|
|
18952
|
-
this.pending.set(seq, { resolve:
|
|
19308
|
+
this.pending.set(seq, { resolve: resolve8, reject, timer });
|
|
18953
19309
|
this.businessSocket.write(request);
|
|
18954
19310
|
});
|
|
18955
19311
|
}
|
|
@@ -19091,7 +19447,7 @@ var AssistantMasterIpcClient = class {
|
|
|
19091
19447
|
const response = await this.callUpgradeApi("upgrade/status", moduleIndex, config2);
|
|
19092
19448
|
const progress = parseModuleInstallProgress(response);
|
|
19093
19449
|
lastProgress = progress;
|
|
19094
|
-
onProgress?.(
|
|
19450
|
+
onProgress?.(formatModuleInstallProgress("\u6295\u7814\u6A21\u5757\u5305\u4E0B\u8F7D\u72B6\u6001", moduleIndex, progress));
|
|
19095
19451
|
if (isModuleInstallFailed(progress)) {
|
|
19096
19452
|
throw new Error(formatModuleInstallError("\u6295\u7814\u6A21\u5757\u5305\u5B89\u88C5\u5931\u8D25", moduleIndex, progress));
|
|
19097
19453
|
}
|
|
@@ -19113,7 +19469,7 @@ var AssistantMasterIpcClient = class {
|
|
|
19113
19469
|
const response = await this.callUpgradeApi("upgrade/status", moduleIndex, config2);
|
|
19114
19470
|
const progress = parseModuleInstallProgress(response);
|
|
19115
19471
|
lastProgress = progress;
|
|
19116
|
-
onProgress?.(
|
|
19472
|
+
onProgress?.(formatModuleInstallProgress("\u6295\u7814\u6A21\u5757\u5305\u8986\u76D6\u5B89\u88C5\u72B6\u6001", moduleIndex, progress));
|
|
19117
19473
|
if (isModuleInstallFailed(progress)) {
|
|
19118
19474
|
throw new Error(formatModuleInstallError("\u6295\u7814\u6A21\u5757\u5305\u8986\u76D6\u5B89\u88C5\u5931\u8D25", moduleIndex, progress));
|
|
19119
19475
|
}
|
|
@@ -19166,18 +19522,18 @@ async function waitForPipe(workRoot, pipePrefix, timeout) {
|
|
|
19166
19522
|
throw new Error(`\u7B49\u5F85 ${pipePrefix} \u7BA1\u9053\u8D85\u65F6`);
|
|
19167
19523
|
}
|
|
19168
19524
|
async function readZltContent(workRoot, temporaryZltFile) {
|
|
19169
|
-
const
|
|
19170
|
-
const
|
|
19171
|
-
const zltFile =
|
|
19172
|
-
return
|
|
19525
|
+
const fs15 = await import("fs");
|
|
19526
|
+
const path16 = await import("path");
|
|
19527
|
+
const zltFile = path16.join(workRoot, temporaryZltFile || "Temporary/zlt");
|
|
19528
|
+
return fs15.existsSync(zltFile) ? fs15.readFileSync(zltFile, "utf-8").trim() : "";
|
|
19173
19529
|
}
|
|
19174
19530
|
async function pipeExists2(pipeName) {
|
|
19175
|
-
const
|
|
19531
|
+
const fs15 = await import("fs");
|
|
19176
19532
|
try {
|
|
19177
19533
|
if (process.platform === "win32") {
|
|
19178
|
-
return
|
|
19534
|
+
return fs15.readdirSync("\\\\.\\pipe\\").includes(pipeName);
|
|
19179
19535
|
}
|
|
19180
|
-
return
|
|
19536
|
+
return fs15.existsSync(`/tmp/${pipeName}`);
|
|
19181
19537
|
} catch {
|
|
19182
19538
|
return false;
|
|
19183
19539
|
}
|
|
@@ -19223,13 +19579,19 @@ function getAssistantRequestBody(data) {
|
|
|
19223
19579
|
}
|
|
19224
19580
|
function parseModuleInstallProgress(response) {
|
|
19225
19581
|
const data = isRecord(response) ? isRecord(response.data) ? response.data : isRecord(response.Data) ? response.Data : response : {};
|
|
19582
|
+
const note = data.note ?? data.Note;
|
|
19226
19583
|
return {
|
|
19227
19584
|
status: Number(data.status ?? data.Status ?? 0),
|
|
19228
19585
|
process: Number(data.process ?? data.Process ?? 0),
|
|
19229
19586
|
phase: Number(data.phase ?? data.Phase ?? 0),
|
|
19587
|
+
note: typeof note === "string" ? note.trim() || void 0 : void 0,
|
|
19230
19588
|
response
|
|
19231
19589
|
};
|
|
19232
19590
|
}
|
|
19591
|
+
function formatModuleInstallProgress(message, moduleIndex, progress) {
|
|
19592
|
+
const step = progress.note ? `, \u5F53\u524D\u6B65\u9AA4=${progress.note}` : "";
|
|
19593
|
+
return `${message}: moduleIndex=${moduleIndex}, status=${progress.status}, phase=${progress.phase}, process=${progress.process}${step}, \u5F53\u524D\u6B65\u9AA4\u8FDB\u5EA6=${progress.process}%`;
|
|
19594
|
+
}
|
|
19233
19595
|
function assertSuccessfulUpgradeResponse(optName, moduleIndex, response) {
|
|
19234
19596
|
if (!isRecord(response) || response.success !== false)
|
|
19235
19597
|
return;
|
|
@@ -19261,7 +19623,7 @@ function isUpgradeBusyError(message) {
|
|
|
19261
19623
|
}
|
|
19262
19624
|
function isRecoverableTyCodeCoverFailure(message, workRoot) {
|
|
19263
19625
|
const normalizedMessage = message.replaceAll("/", "\\").toLowerCase();
|
|
19264
|
-
const managedCodePath =
|
|
19626
|
+
const managedCodePath = path3.join(workRoot, "vscode", "Code.exe").toLowerCase();
|
|
19265
19627
|
return normalizedMessage.includes("\u521B\u5EFA\u89E3\u538B\u76EE\u6807\u6587\u4EF6") && normalizedMessage.includes(managedCodePath) && normalizedMessage.includes("\u5931\u8D25");
|
|
19266
19628
|
}
|
|
19267
19629
|
function isClientCoverBoundaryError(message) {
|
|
@@ -19299,17 +19661,17 @@ function formatModuleInstallError(message, moduleIndex, progress) {
|
|
|
19299
19661
|
return `${message}: moduleIndex=${moduleIndex}, status=${progress.status}, phase=${progress.phase}, process=${progress.process}, response=${JSON.stringify(progress.response)}`;
|
|
19300
19662
|
}
|
|
19301
19663
|
function sleep(ms) {
|
|
19302
|
-
return new Promise((
|
|
19664
|
+
return new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
19303
19665
|
}
|
|
19304
19666
|
|
|
19305
19667
|
// ../zlt-runtime-core/dist/runtime-lifecycle.js
|
|
19306
|
-
var
|
|
19307
|
-
var
|
|
19668
|
+
var fs4 = __toESM(require("fs"), 1);
|
|
19669
|
+
var path4 = __toESM(require("path"), 1);
|
|
19308
19670
|
var import_crypto2 = require("crypto");
|
|
19309
19671
|
var import_child_process2 = require("child_process");
|
|
19310
19672
|
var LOCK_WAIT_MS = 1e4;
|
|
19311
19673
|
var LOCK_RETRY_MS = 100;
|
|
19312
|
-
var STATE_RELATIVE_PATH =
|
|
19674
|
+
var STATE_RELATIVE_PATH = path4.join("Temporary", "zlt-mcp-runtime");
|
|
19313
19675
|
async function acquireRuntimeLease(workRoot, role, options = {}) {
|
|
19314
19676
|
const deps = options.deps ?? defaultRuntimeLifecycleDeps;
|
|
19315
19677
|
return withLifecycleLock(workRoot, deps, async (stateDir) => {
|
|
@@ -19334,7 +19696,7 @@ async function acquireRuntimeLease(workRoot, role, options = {}) {
|
|
|
19334
19696
|
}
|
|
19335
19697
|
}
|
|
19336
19698
|
const handle = {
|
|
19337
|
-
workRoot:
|
|
19699
|
+
workRoot: path4.resolve(workRoot),
|
|
19338
19700
|
token: deps.randomToken(),
|
|
19339
19701
|
holder: deps.currentProcess(),
|
|
19340
19702
|
role
|
|
@@ -19389,7 +19751,7 @@ async function releaseRuntimeLease(handle, options = {}) {
|
|
|
19389
19751
|
return withLifecycleLock(handle.workRoot, deps, async (stateDir) => {
|
|
19390
19752
|
const record3 = readJson(leasePath(stateDir, handle.token));
|
|
19391
19753
|
if (record3 && sameIdentity(record3.holder, handle.holder)) {
|
|
19392
|
-
|
|
19754
|
+
fs4.rmSync(leasePath(stateDir, handle.token), { force: true });
|
|
19393
19755
|
}
|
|
19394
19756
|
const recordedOwner = readJson(ownerPath(stateDir));
|
|
19395
19757
|
const store = readAndPruneStore(stateDir, deps);
|
|
@@ -19403,19 +19765,19 @@ async function releaseRuntimeLease(handle, options = {}) {
|
|
|
19403
19765
|
}
|
|
19404
19766
|
const current = deps.inspectProcess(store.owner.process.pid);
|
|
19405
19767
|
if (!current || !sameIdentity(current, store.owner.process)) {
|
|
19406
|
-
|
|
19768
|
+
fs4.rmSync(ownerPath(stateDir), { force: true });
|
|
19407
19769
|
return { stopped: false, reason: "owner-mismatch" };
|
|
19408
19770
|
}
|
|
19409
19771
|
assertOwnedZltafIdentity(handle.workRoot, current);
|
|
19410
19772
|
deps.terminateProcess(current);
|
|
19411
|
-
|
|
19773
|
+
fs4.rmSync(ownerPath(stateDir), { force: true });
|
|
19412
19774
|
return { stopped: true, reason: "stopped" };
|
|
19413
19775
|
});
|
|
19414
19776
|
}
|
|
19415
19777
|
function inspectRuntimeProcess(pid) {
|
|
19416
19778
|
if (process.platform !== "win32" || !Number.isInteger(pid) || pid <= 0)
|
|
19417
19779
|
return null;
|
|
19418
|
-
const powershell =
|
|
19780
|
+
const powershell = path4.join(process.env.SystemRoot || "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
|
|
19419
19781
|
const command = [
|
|
19420
19782
|
'$p = Get-CimInstance Win32_Process -Filter "ProcessId=$env:ZLT_RUNTIME_PID" -ErrorAction SilentlyContinue',
|
|
19421
19783
|
"if ($p) { [pscustomobject]@{ pid=[int]$p.ProcessId; executablePath=[string]$p.ExecutablePath; creationTime=$p.CreationDate.ToUniversalTime().ToString('o') } | ConvertTo-Json -Compress }"
|
|
@@ -19444,7 +19806,7 @@ var defaultRuntimeLifecycleDeps = {
|
|
|
19444
19806
|
},
|
|
19445
19807
|
inspectProcess: inspectRuntimeProcess,
|
|
19446
19808
|
terminateProcess: (identity) => {
|
|
19447
|
-
const powershell =
|
|
19809
|
+
const powershell = path4.join(process.env.SystemRoot || "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
|
|
19448
19810
|
const command = [
|
|
19449
19811
|
'$p = Get-CimInstance Win32_Process -Filter "ProcessId=$env:ZLT_RUNTIME_PID" -ErrorAction SilentlyContinue',
|
|
19450
19812
|
"if (-not $p) { exit 3 }",
|
|
@@ -19471,12 +19833,12 @@ var defaultRuntimeLifecycleDeps = {
|
|
|
19471
19833
|
},
|
|
19472
19834
|
randomToken: import_crypto2.randomUUID,
|
|
19473
19835
|
now: Date.now,
|
|
19474
|
-
sleep: (ms) => new Promise((
|
|
19836
|
+
sleep: (ms) => new Promise((resolve8) => setTimeout(resolve8, ms))
|
|
19475
19837
|
};
|
|
19476
19838
|
async function withLifecycleLock(workRoot, deps, action) {
|
|
19477
19839
|
const stateDir = stateDirectory(workRoot);
|
|
19478
|
-
|
|
19479
|
-
const lockPath =
|
|
19840
|
+
fs4.mkdirSync(path4.join(stateDir, "leases"), { recursive: true });
|
|
19841
|
+
const lockPath = path4.join(stateDir, "lifecycle.lock");
|
|
19480
19842
|
const lock = {
|
|
19481
19843
|
token: deps.randomToken(),
|
|
19482
19844
|
holder: deps.currentProcess(),
|
|
@@ -19485,11 +19847,11 @@ async function withLifecycleLock(workRoot, deps, action) {
|
|
|
19485
19847
|
const deadline = deps.now() + LOCK_WAIT_MS;
|
|
19486
19848
|
while (true) {
|
|
19487
19849
|
try {
|
|
19488
|
-
const descriptor =
|
|
19850
|
+
const descriptor = fs4.openSync(lockPath, "wx");
|
|
19489
19851
|
try {
|
|
19490
|
-
|
|
19852
|
+
fs4.writeFileSync(descriptor, JSON.stringify(lock), "utf8");
|
|
19491
19853
|
} finally {
|
|
19492
|
-
|
|
19854
|
+
fs4.closeSync(descriptor);
|
|
19493
19855
|
}
|
|
19494
19856
|
break;
|
|
19495
19857
|
} catch (error2) {
|
|
@@ -19517,9 +19879,9 @@ async function withLifecycleLock(workRoot, deps, action) {
|
|
|
19517
19879
|
}
|
|
19518
19880
|
function readLifecycleLock(lockPath) {
|
|
19519
19881
|
try {
|
|
19520
|
-
const before =
|
|
19521
|
-
const raw =
|
|
19522
|
-
const after =
|
|
19882
|
+
const before = fs4.statSync(lockPath);
|
|
19883
|
+
const raw = fs4.readFileSync(lockPath);
|
|
19884
|
+
const after = fs4.statSync(lockPath);
|
|
19523
19885
|
if (before.mtimeMs !== after.mtimeMs || before.size !== after.size)
|
|
19524
19886
|
return null;
|
|
19525
19887
|
return {
|
|
@@ -19549,14 +19911,14 @@ function sameLifecycleLockIdentity(left, right) {
|
|
|
19549
19911
|
function restoreMovedLifecycleLock(movedPath, lockPath) {
|
|
19550
19912
|
let restored = false;
|
|
19551
19913
|
try {
|
|
19552
|
-
|
|
19914
|
+
fs4.linkSync(movedPath, lockPath);
|
|
19553
19915
|
restored = true;
|
|
19554
19916
|
} catch (error2) {
|
|
19555
19917
|
if (error2.code === "EEXIST") {
|
|
19556
19918
|
restored = true;
|
|
19557
19919
|
} else {
|
|
19558
19920
|
try {
|
|
19559
|
-
|
|
19921
|
+
fs4.copyFileSync(movedPath, lockPath, fs4.constants.COPYFILE_EXCL);
|
|
19560
19922
|
restored = true;
|
|
19561
19923
|
} catch (restoreError) {
|
|
19562
19924
|
if (restoreError.code === "EEXIST")
|
|
@@ -19565,12 +19927,12 @@ function restoreMovedLifecycleLock(movedPath, lockPath) {
|
|
|
19565
19927
|
}
|
|
19566
19928
|
}
|
|
19567
19929
|
if (restored)
|
|
19568
|
-
|
|
19930
|
+
fs4.rmSync(movedPath, { force: true });
|
|
19569
19931
|
}
|
|
19570
19932
|
function retireLifecycleLockIfUnchanged(lockPath, expected) {
|
|
19571
19933
|
const movedPath = `${lockPath}.${process.pid}.${(0, import_crypto2.randomUUID)()}.retired`;
|
|
19572
19934
|
try {
|
|
19573
|
-
|
|
19935
|
+
fs4.renameSync(lockPath, movedPath);
|
|
19574
19936
|
} catch (error2) {
|
|
19575
19937
|
if (error2.code === "ENOENT")
|
|
19576
19938
|
return false;
|
|
@@ -19581,20 +19943,20 @@ function retireLifecycleLockIfUnchanged(lockPath, expected) {
|
|
|
19581
19943
|
restoreMovedLifecycleLock(movedPath, lockPath);
|
|
19582
19944
|
return false;
|
|
19583
19945
|
}
|
|
19584
|
-
|
|
19946
|
+
fs4.rmSync(movedPath, { force: true });
|
|
19585
19947
|
return true;
|
|
19586
19948
|
}
|
|
19587
19949
|
function readAndPruneStore(stateDir, deps) {
|
|
19588
|
-
const leasesDir =
|
|
19950
|
+
const leasesDir = path4.join(stateDir, "leases");
|
|
19589
19951
|
const leases = [];
|
|
19590
|
-
for (const entry of
|
|
19952
|
+
for (const entry of fs4.readdirSync(leasesDir, { withFileTypes: true })) {
|
|
19591
19953
|
if (!entry.isFile() || !entry.name.endsWith(".json"))
|
|
19592
19954
|
continue;
|
|
19593
|
-
const filePath =
|
|
19955
|
+
const filePath = path4.join(leasesDir, entry.name);
|
|
19594
19956
|
const record3 = readJson(filePath);
|
|
19595
19957
|
const current = record3 ? deps.inspectProcess(record3.holder.pid) : null;
|
|
19596
19958
|
if (!record3 || !current || !sameIdentity(current, record3.holder)) {
|
|
19597
|
-
|
|
19959
|
+
fs4.rmSync(filePath, { force: true });
|
|
19598
19960
|
continue;
|
|
19599
19961
|
}
|
|
19600
19962
|
leases.push(record3);
|
|
@@ -19603,7 +19965,7 @@ function readAndPruneStore(stateDir, deps) {
|
|
|
19603
19965
|
if (owner) {
|
|
19604
19966
|
const current = deps.inspectProcess(owner.process.pid);
|
|
19605
19967
|
if (!current || !sameIdentity(current, owner.process)) {
|
|
19606
|
-
|
|
19968
|
+
fs4.rmSync(ownerPath(stateDir), { force: true });
|
|
19607
19969
|
owner = null;
|
|
19608
19970
|
}
|
|
19609
19971
|
}
|
|
@@ -19639,24 +20001,24 @@ function normalizeLegacyActiveJobs(value) {
|
|
|
19639
20001
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.trunc(value) : 0;
|
|
19640
20002
|
}
|
|
19641
20003
|
function stateDirectory(workRoot) {
|
|
19642
|
-
const resolvedRoot =
|
|
19643
|
-
const stateDir =
|
|
19644
|
-
const prefix = `${resolvedRoot}${
|
|
20004
|
+
const resolvedRoot = path4.resolve(workRoot);
|
|
20005
|
+
const stateDir = path4.resolve(resolvedRoot, STATE_RELATIVE_PATH);
|
|
20006
|
+
const prefix = `${resolvedRoot}${path4.sep}`.toLowerCase();
|
|
19645
20007
|
if (!stateDir.toLowerCase().startsWith(prefix))
|
|
19646
20008
|
throw new Error(`runtime lifecycle path \u8D8A\u754C: ${stateDir}`);
|
|
19647
20009
|
return stateDir;
|
|
19648
20010
|
}
|
|
19649
20011
|
function assertOwnedZltafIdentity(workRoot, identity) {
|
|
19650
|
-
const expected =
|
|
19651
|
-
if (
|
|
20012
|
+
const expected = path4.resolve(workRoot, "zltaf", "zltaf.exe");
|
|
20013
|
+
if (path4.resolve(identity.executablePath).toLowerCase() !== expected.toLowerCase()) {
|
|
19652
20014
|
throw new Error(`\u62D2\u7EDD\u7BA1\u7406\u975E\u76EE\u6807 ZLTAF \u8FDB\u7A0B: ${identity.executablePath}`);
|
|
19653
20015
|
}
|
|
19654
20016
|
}
|
|
19655
20017
|
function sameIdentity(left, right) {
|
|
19656
|
-
return left.pid === right.pid &&
|
|
20018
|
+
return left.pid === right.pid && path4.resolve(left.executablePath).toLowerCase() === path4.resolve(right.executablePath).toLowerCase() && left.creationTime === right.creationTime;
|
|
19657
20019
|
}
|
|
19658
20020
|
function ownerPath(stateDir) {
|
|
19659
|
-
return
|
|
20021
|
+
return path4.join(stateDir, "owner.json");
|
|
19660
20022
|
}
|
|
19661
20023
|
function writeRuntimeOwnerRecord(stateDir, owner) {
|
|
19662
20024
|
writeJson(ownerPath(stateDir), {
|
|
@@ -19667,24 +20029,24 @@ function writeRuntimeOwnerRecord(stateDir, owner) {
|
|
|
19667
20029
|
function leasePath(stateDir, token) {
|
|
19668
20030
|
if (!/^[A-Za-z0-9-]+$/.test(token))
|
|
19669
20031
|
throw new Error(`\u975E\u6CD5 runtime lease token: ${token}`);
|
|
19670
|
-
return
|
|
20032
|
+
return path4.join(stateDir, "leases", `${token}.json`);
|
|
19671
20033
|
}
|
|
19672
20034
|
function readJson(filePath) {
|
|
19673
20035
|
try {
|
|
19674
|
-
return JSON.parse(
|
|
20036
|
+
return JSON.parse(fs4.readFileSync(filePath, "utf8"));
|
|
19675
20037
|
} catch {
|
|
19676
20038
|
return null;
|
|
19677
20039
|
}
|
|
19678
20040
|
}
|
|
19679
20041
|
function writeJson(filePath, value) {
|
|
19680
20042
|
const temporary = `${filePath}.${process.pid}.${(0, import_crypto2.randomUUID)()}.tmp`;
|
|
19681
|
-
|
|
19682
|
-
|
|
20043
|
+
fs4.writeFileSync(temporary, JSON.stringify(value), "utf8");
|
|
20044
|
+
fs4.renameSync(temporary, filePath);
|
|
19683
20045
|
}
|
|
19684
20046
|
|
|
19685
20047
|
// ../zlt-runtime-core/dist/assistant-base-upgrade.js
|
|
19686
|
-
var
|
|
19687
|
-
var
|
|
20048
|
+
var fs5 = __toESM(require("fs"), 1);
|
|
20049
|
+
var path5 = __toESM(require("path"), 1);
|
|
19688
20050
|
|
|
19689
20051
|
// ../zlt-runtime-core/dist/version-gates.js
|
|
19690
20052
|
function versionGatesDisabled() {
|
|
@@ -19698,7 +20060,7 @@ var requirementCache = /* @__PURE__ */ new Map();
|
|
|
19698
20060
|
var requirementInFlight = /* @__PURE__ */ new Map();
|
|
19699
20061
|
function readInstalledAssistantBaseVersion(workRoot) {
|
|
19700
20062
|
try {
|
|
19701
|
-
const content =
|
|
20063
|
+
const content = fs5.readFileSync(path5.join(workRoot, INSTALL_INFO_FILE), "utf-8");
|
|
19702
20064
|
const matched = content.match(/<InstallAppReleaseVer>(.*?)<\/InstallAppReleaseVer>/i);
|
|
19703
20065
|
const version2 = matched?.[1]?.trim();
|
|
19704
20066
|
return version2 ? version2 : null;
|
|
@@ -19838,12 +20200,12 @@ var MANAGED_PROCESS_EXIT_INTERVAL_MS = 200;
|
|
|
19838
20200
|
var MANAGED_PROCESS_RESPAWN_RETRY_ROUNDS = 3;
|
|
19839
20201
|
function getDefaultInstallPath() {
|
|
19840
20202
|
if (process.platform === "win32") {
|
|
19841
|
-
return
|
|
20203
|
+
return fs6.existsSync("D:\\") ? "D:\\ZLTClient" : "C:\\ZLTClient";
|
|
19842
20204
|
}
|
|
19843
|
-
return
|
|
20205
|
+
return path6.join(os2.homedir(), "ZLTClient");
|
|
19844
20206
|
}
|
|
19845
20207
|
function validateWorkRootComplete(workRoot, _config) {
|
|
19846
|
-
if (!
|
|
20208
|
+
if (!fs6.existsSync(workRoot)) {
|
|
19847
20209
|
return { complete: false, reason: `\u5DE5\u7A0B\u8DEF\u5F84\u4E0D\u5B58\u5728: ${workRoot}` };
|
|
19848
20210
|
}
|
|
19849
20211
|
const requiredPaths = [
|
|
@@ -19851,17 +20213,17 @@ function validateWorkRootComplete(workRoot, _config) {
|
|
|
19851
20213
|
{ label: "ZLTAF \u914D\u7F6E", filePath: getZltafConfigPath(workRoot) }
|
|
19852
20214
|
];
|
|
19853
20215
|
for (const item of requiredPaths) {
|
|
19854
|
-
if (!
|
|
20216
|
+
if (!fs6.existsSync(item.filePath)) {
|
|
19855
20217
|
return { complete: false, reason: `\u7F3A\u5C11${item.label}: ${item.filePath}` };
|
|
19856
20218
|
}
|
|
19857
20219
|
}
|
|
19858
20220
|
return { complete: true };
|
|
19859
20221
|
}
|
|
19860
20222
|
function validateAssistantBaseComplete(workRoot, config2) {
|
|
19861
|
-
if (!
|
|
20223
|
+
if (!fs6.existsSync(workRoot))
|
|
19862
20224
|
return { complete: false, reason: `\u5DE5\u7A0B\u8DEF\u5F84\u4E0D\u5B58\u5728: ${workRoot}` };
|
|
19863
|
-
const hostPath =
|
|
19864
|
-
return
|
|
20225
|
+
const hostPath = path6.join(workRoot, config2.hostPath);
|
|
20226
|
+
return fs6.existsSync(hostPath) ? { complete: true } : { complete: false, reason: `\u7F3A\u5C11\u667A\u80FD\u7BA1\u5BB6\u7A0B\u5E8F: ${hostPath}` };
|
|
19865
20227
|
}
|
|
19866
20228
|
function validateDependencyWorkRootComplete(workRoot, config2) {
|
|
19867
20229
|
const launchReady = validateRuntimeLaunchReady(workRoot, config2);
|
|
@@ -19878,21 +20240,21 @@ function validateRuntimeLaunchReady(workRoot, config2) {
|
|
|
19878
20240
|
{ label: "MinGit \u7A0B\u5E8F", filePath: getGitExePath(workRoot) }
|
|
19879
20241
|
];
|
|
19880
20242
|
for (const item of requiredPaths) {
|
|
19881
|
-
if (!
|
|
20243
|
+
if (!fs6.existsSync(item.filePath)) {
|
|
19882
20244
|
return { complete: false, reason: `\u7F3A\u5C11${item.label}: ${item.filePath}` };
|
|
19883
20245
|
}
|
|
19884
20246
|
}
|
|
19885
20247
|
return { complete: true };
|
|
19886
20248
|
}
|
|
19887
20249
|
function ensureUsersProjectsDirectory(workRoot) {
|
|
19888
|
-
const projectsDir =
|
|
19889
|
-
if (
|
|
19890
|
-
if (!
|
|
20250
|
+
const projectsDir = path6.join(workRoot, "Users", "projects");
|
|
20251
|
+
if (fs6.existsSync(projectsDir)) {
|
|
20252
|
+
if (!fs6.statSync(projectsDir).isDirectory()) {
|
|
19891
20253
|
throw new Error(`Users\\projects \u8DEF\u5F84\u5DF2\u5B58\u5728\u4F46\u4E0D\u662F\u76EE\u5F55: ${projectsDir}`);
|
|
19892
20254
|
}
|
|
19893
20255
|
return projectsDir;
|
|
19894
20256
|
}
|
|
19895
|
-
|
|
20257
|
+
fs6.mkdirSync(projectsDir, { recursive: true });
|
|
19896
20258
|
return projectsDir;
|
|
19897
20259
|
}
|
|
19898
20260
|
async function readRegistryInstallLocation(config2) {
|
|
@@ -19931,7 +20293,7 @@ async function resolveRuntimeRoot(config2, options = {}) {
|
|
|
19931
20293
|
const workRoot = candidate?.trim();
|
|
19932
20294
|
if (!workRoot)
|
|
19933
20295
|
continue;
|
|
19934
|
-
const key =
|
|
20296
|
+
const key = path6.resolve(workRoot).toLowerCase();
|
|
19935
20297
|
if (seen.has(key))
|
|
19936
20298
|
continue;
|
|
19937
20299
|
seen.add(key);
|
|
@@ -19974,7 +20336,7 @@ async function runDoctor(config2, options = {}) {
|
|
|
19974
20336
|
}
|
|
19975
20337
|
const assistant = workRoot ? validateWorkRootComplete(workRoot, config2) : { complete: false, reason: "\u672A\u53D1\u73B0\u53EF\u7528 InstallLocation" };
|
|
19976
20338
|
const dependency = workRoot ? validateDependencyWorkRootComplete(workRoot, config2) : { complete: false, reason: "\u672A\u53D1\u73B0\u53EF\u7528 InstallLocation" };
|
|
19977
|
-
const zltFile = workRoot ?
|
|
20339
|
+
const zltFile = workRoot ? path6.join(workRoot, config2.temporaryZltFile) : void 0;
|
|
19978
20340
|
let pipePath;
|
|
19979
20341
|
let ipcReachable = false;
|
|
19980
20342
|
const explicitPipeName = process.env.ZLT_PIPE_NAME?.trim();
|
|
@@ -20016,20 +20378,20 @@ async function runDoctor(config2, options = {}) {
|
|
|
20016
20378
|
}
|
|
20017
20379
|
function startZltafRuntime(workRoot, config2) {
|
|
20018
20380
|
const zltafPath = getZltafExePath(workRoot);
|
|
20019
|
-
if (!
|
|
20381
|
+
if (!fs6.existsSync(zltafPath)) {
|
|
20020
20382
|
throw new Error(`ZLTAF \u7A0B\u5E8F\u4E0D\u5B58\u5728: ${zltafPath}`);
|
|
20021
20383
|
}
|
|
20022
20384
|
const configPath = resolveZltafLaunchConfigPath(workRoot, config2);
|
|
20023
|
-
if (!
|
|
20385
|
+
if (!fs6.existsSync(configPath)) {
|
|
20024
20386
|
throw new Error(`ZLTAF \u914D\u7F6E\u4E0D\u5B58\u5728: ${configPath}`);
|
|
20025
20387
|
}
|
|
20026
|
-
const tmpDir =
|
|
20027
|
-
|
|
20388
|
+
const tmpDir = path6.join(workRoot, "zltaf", "tmp");
|
|
20389
|
+
fs6.mkdirSync(tmpDir, { recursive: true });
|
|
20028
20390
|
const child = (0, import_child_process3.spawn)(zltafPath, [
|
|
20029
20391
|
`-Dconfig.path=${configPath}`,
|
|
20030
20392
|
`-Djava.io.tmpdir=${tmpDir}`
|
|
20031
20393
|
], {
|
|
20032
|
-
cwd:
|
|
20394
|
+
cwd: path6.dirname(zltafPath),
|
|
20033
20395
|
detached: true,
|
|
20034
20396
|
stdio: "ignore",
|
|
20035
20397
|
windowsHide: true
|
|
@@ -20090,15 +20452,15 @@ async function ensureAssistantHostRunning(workRoot, config2, onProgress, options
|
|
|
20090
20452
|
if (zltContent && masterPipeExists(zltContent))
|
|
20091
20453
|
return zltContent;
|
|
20092
20454
|
}
|
|
20093
|
-
throw new Error(`\u7B49\u5F85\u667A\u80FD\u7BA1\u5BB6 IPC \u914D\u7F6E\u8D85\u65F6\uFF08\u540E\u7F00\u6587\u4EF6\u6216\u4E3B\u7BA1\u9053\u672A\u5C31\u7EEA\uFF09: ${
|
|
20455
|
+
throw new Error(`\u7B49\u5F85\u667A\u80FD\u7BA1\u5BB6 IPC \u914D\u7F6E\u8D85\u65F6\uFF08\u540E\u7F00\u6587\u4EF6\u6216\u4E3B\u7BA1\u9053\u672A\u5C31\u7EEA\uFF09: ${path6.join(workRoot, config2.temporaryZltFile)}`);
|
|
20094
20456
|
}
|
|
20095
|
-
var ASSISTANT_UPGRADE_FINISH_LOCK =
|
|
20457
|
+
var ASSISTANT_UPGRADE_FINISH_LOCK = path6.join("Temporary", "upgradeFinsh.lock");
|
|
20096
20458
|
function launchAssistantHost(workRoot, config2, onProgress) {
|
|
20097
|
-
const hostPath =
|
|
20459
|
+
const hostPath = path6.join(workRoot, config2.hostPath);
|
|
20098
20460
|
onProgress?.("\u542F\u52A8\u667A\u80FD\u7BA1\u5BB6");
|
|
20099
20461
|
const { ELECTRON_RUN_AS_NODE: _dropped, ...env } = process.env;
|
|
20100
20462
|
const child = (0, import_child_process3.spawn)(hostPath, ["startwithplugin", "selfstart"], {
|
|
20101
|
-
cwd:
|
|
20463
|
+
cwd: path6.dirname(hostPath),
|
|
20102
20464
|
detached: true,
|
|
20103
20465
|
stdio: "ignore",
|
|
20104
20466
|
windowsHide: true,
|
|
@@ -20115,7 +20477,7 @@ async function locateInstalledRuntime(config2) {
|
|
|
20115
20477
|
return workRoot;
|
|
20116
20478
|
}
|
|
20117
20479
|
async function waitForUpgradedAssistantClient(workRoot, config2, onProgress, versionBefore) {
|
|
20118
|
-
const finishLockPath =
|
|
20480
|
+
const finishLockPath = path6.join(workRoot, ASSISTANT_UPGRADE_FINISH_LOCK);
|
|
20119
20481
|
const finishStartedAt = Date.now();
|
|
20120
20482
|
const versionRaised = () => {
|
|
20121
20483
|
if (!versionBefore)
|
|
@@ -20123,7 +20485,7 @@ async function waitForUpgradedAssistantClient(workRoot, config2, onProgress, ver
|
|
|
20123
20485
|
const current = readInstalledAssistantBaseVersion(workRoot);
|
|
20124
20486
|
return Boolean(current) && compareAssistantVersions(current, versionBefore) > 0;
|
|
20125
20487
|
};
|
|
20126
|
-
while (!
|
|
20488
|
+
while (!fs6.existsSync(finishLockPath)) {
|
|
20127
20489
|
if (versionRaised()) {
|
|
20128
20490
|
onProgress?.("\u5BA2\u6237\u7AEF\u7248\u672C\u53F7\u5DF2\u88AB\u8986\u76D6\u62AC\u9AD8\uFF0C\u89C6\u4E3A Client \u8986\u76D6\u5B8C\u6210\uFF08\u672A\u51FA\u73B0 upgradeFinsh.lock\uFF09");
|
|
20129
20491
|
break;
|
|
@@ -20185,9 +20547,9 @@ async function installRuntime(options) {
|
|
|
20185
20547
|
}
|
|
20186
20548
|
const installDir = options.installDir || getDefaultInstallPath();
|
|
20187
20549
|
const installerPath = options.installerPath || await downloadRuntimeInstaller(options.config, options.onProgress, options.installType || "full");
|
|
20188
|
-
|
|
20189
|
-
const installerLogPath =
|
|
20190
|
-
|
|
20550
|
+
fs6.mkdirSync(installDir, { recursive: true });
|
|
20551
|
+
const installerLogPath = path6.join(installDir, "Temporary", "logs", "install.log");
|
|
20552
|
+
fs6.mkdirSync(path6.dirname(installerLogPath), { recursive: true });
|
|
20191
20553
|
options.onProgress?.(`\u6267\u884C\u5B89\u88C5\u7A0B\u5E8F: ${installerPath}`);
|
|
20192
20554
|
const exitCode = await executeInstallerProcess(installerPath, installDir, installerLogPath);
|
|
20193
20555
|
options.onProgress?.(`\u5B89\u88C5\u8FDB\u7A0B\u9000\u51FA\u7801: ${exitCode}`);
|
|
@@ -20271,7 +20633,7 @@ async function installMissingBacktestModules(workRoot, config2, onProgress, opti
|
|
|
20271
20633
|
if (moduleIndex !== CLIENT_PLUGIN_MODULE_INDEX && moduleIndex !== TY_MODULE_INDEX)
|
|
20272
20634
|
return;
|
|
20273
20635
|
if (moduleIndex === CLIENT_PLUGIN_MODULE_INDEX) {
|
|
20274
|
-
|
|
20636
|
+
fs6.rmSync(path6.join(workRoot, ASSISTANT_UPGRADE_FINISH_LOCK), { force: true });
|
|
20275
20637
|
}
|
|
20276
20638
|
await quiesceTyModuleProcesses(workRoot, onProgress, (selected) => {
|
|
20277
20639
|
stoppedPayloadProcesses = [...stoppedPayloadProcesses, ...selected];
|
|
@@ -20286,7 +20648,7 @@ async function installMissingBacktestModules(workRoot, config2, onProgress, opti
|
|
|
20286
20648
|
const upgradedZltContent = await waitForUpgradedAssistantClient(workRoot, config2, onProgress, baseVersionBeforeCover ?? void 0);
|
|
20287
20649
|
onProgress?.("\u667A\u80FD\u7BA1\u5BB6 Client \u5347\u7EA7\u540E IPC \u5DF2\u6062\u590D");
|
|
20288
20650
|
await installBacktestModules(workRoot, upgradedZltContent, config2, onProgress, installHooks);
|
|
20289
|
-
|
|
20651
|
+
fs6.rmSync(path6.join(workRoot, ASSISTANT_UPGRADE_FINISH_LOCK), { force: true });
|
|
20290
20652
|
}
|
|
20291
20653
|
} catch (error2) {
|
|
20292
20654
|
if (runtimeStopped || stoppedPayloadProcesses.length > 0) {
|
|
@@ -20359,30 +20721,30 @@ function prepareRuntimeToolchain(workRoot, onProgress) {
|
|
|
20359
20721
|
}
|
|
20360
20722
|
function ensurePythonToolchain(workRoot) {
|
|
20361
20723
|
const targetPython = getPythonExePath(workRoot);
|
|
20362
|
-
if (!
|
|
20724
|
+
if (!fs6.existsSync(targetPython)) {
|
|
20363
20725
|
throw new Error(`\u6295\u7814\u6A21\u5757\u5C1A\u672A\u4E0B\u53D1 Python \u8FD0\u884C\u65F6: ${targetPython}\u3002\u8BF7\u5728\u667A\u80FD\u7BA1\u5BB6\u4E2D\u5B89\u88C5\u6216\u4FEE\u590D\u6295\u7814\u6A21\u5757\u540E\u91CD\u8BD5\u3002`);
|
|
20364
20726
|
}
|
|
20365
|
-
const abiDll =
|
|
20366
|
-
if (!
|
|
20727
|
+
const abiDll = path6.join(path6.dirname(targetPython), `python${PYTHON_SDK_ABI_TAG.replace(/^cp/, "")}.dll`);
|
|
20728
|
+
if (!fs6.existsSync(abiDll)) {
|
|
20367
20729
|
throw new Error(`\u6295\u7814\u6A21\u5757\u4E0B\u53D1\u7684 Python \u4E0E zltsdk-plugin \u7684 ${PYTHON_SDK_ABI_TAG} wheel ABI \u4E0D\u5339\u914D\uFF1A\u672A\u627E\u5230 ${abiDll}\u3002\u8BF7\u5728\u667A\u80FD\u7BA1\u5BB6\u4E2D\u91CD\u65B0\u5B89\u88C5\u6295\u7814\u6A21\u5757\u3002`);
|
|
20368
20730
|
}
|
|
20369
20731
|
return targetPython;
|
|
20370
20732
|
}
|
|
20371
20733
|
function toolchainDownloadCacheDir() {
|
|
20372
|
-
return
|
|
20734
|
+
return path6.join(os2.tmpdir(), "zlt-runtime-toolchains");
|
|
20373
20735
|
}
|
|
20374
20736
|
async function ensureVerifiedToolchainAsset(options) {
|
|
20375
20737
|
const { label, url, sha256, destination, timeoutMs, onProgress } = options;
|
|
20376
20738
|
if (!url || !sha256) {
|
|
20377
20739
|
throw new Error(`${label} \u672A\u914D\u7F6E\u56FA\u5B9A URL/SHA256`);
|
|
20378
20740
|
}
|
|
20379
|
-
if (
|
|
20741
|
+
if (fs6.existsSync(destination)) {
|
|
20380
20742
|
try {
|
|
20381
20743
|
assertFileSha256(destination, sha256);
|
|
20382
20744
|
onProgress?.(`\u590D\u7528\u5DF2\u6821\u9A8C ${label}: ${destination}`);
|
|
20383
20745
|
return;
|
|
20384
20746
|
} catch {
|
|
20385
|
-
|
|
20747
|
+
fs6.rmSync(destination, { force: true });
|
|
20386
20748
|
}
|
|
20387
20749
|
}
|
|
20388
20750
|
onProgress?.(`\u4E0B\u8F7D ${label}: ${url}`);
|
|
@@ -20391,8 +20753,8 @@ async function ensureVerifiedToolchainAsset(options) {
|
|
|
20391
20753
|
onProgress?.(`${label} SHA256 \u6821\u9A8C\u901A\u8FC7: ${sha256}`);
|
|
20392
20754
|
}
|
|
20393
20755
|
async function ensureManagedPipWheel(workRoot, config2, onProgress) {
|
|
20394
|
-
const destination =
|
|
20395
|
-
|
|
20756
|
+
const destination = path6.join(toolchainDownloadCacheDir(), "pip-26.1.2-py3-none-any.whl");
|
|
20757
|
+
fs6.mkdirSync(path6.dirname(destination), { recursive: true });
|
|
20396
20758
|
await ensureVerifiedToolchainAsset({
|
|
20397
20759
|
label: "pip 26.1.2 wheel",
|
|
20398
20760
|
url: config2.pythonPipWheelUrl,
|
|
@@ -20404,7 +20766,7 @@ async function ensureManagedPipWheel(workRoot, config2, onProgress) {
|
|
|
20404
20766
|
return destination;
|
|
20405
20767
|
}
|
|
20406
20768
|
function assertFileSha256(filePath, expectedSha256) {
|
|
20407
|
-
const actual = (0, import_crypto3.createHash)("sha256").update(
|
|
20769
|
+
const actual = (0, import_crypto3.createHash)("sha256").update(fs6.readFileSync(filePath)).digest("hex").toUpperCase();
|
|
20408
20770
|
const expected = expectedSha256.trim().toUpperCase();
|
|
20409
20771
|
if (actual !== expected) {
|
|
20410
20772
|
throw new Error(`SHA256 \u6821\u9A8C\u5931\u8D25: ${filePath}, actual=${actual}, expected=${expected}`);
|
|
@@ -20413,27 +20775,27 @@ function assertFileSha256(filePath, expectedSha256) {
|
|
|
20413
20775
|
async function quiesceTyModuleProcesses(workRoot, onProgress, onWillStop) {
|
|
20414
20776
|
if (process.platform !== "win32")
|
|
20415
20777
|
return [];
|
|
20416
|
-
const managedCodePath =
|
|
20417
|
-
const jsserviceRoot = `${
|
|
20418
|
-
const managedGitRoot =
|
|
20778
|
+
const managedCodePath = path6.resolve(workRoot, "vscode", "Code.exe");
|
|
20779
|
+
const jsserviceRoot = `${path6.resolve(workRoot, "jsservice")}${path6.sep}`.toLowerCase();
|
|
20780
|
+
const managedGitRoot = path6.resolve(workRoot, "mingit");
|
|
20419
20781
|
assertPathInside(workRoot, managedGitRoot);
|
|
20420
20782
|
const executablePaths = [
|
|
20421
|
-
|
|
20422
|
-
|
|
20423
|
-
|
|
20424
|
-
|
|
20783
|
+
path6.join(workRoot, "zltaf", "zltaf.exe"),
|
|
20784
|
+
path6.join(workRoot, "python", "python.exe"),
|
|
20785
|
+
path6.join(workRoot, "mingit", "cmd", "git.exe"),
|
|
20786
|
+
path6.join(workRoot, "zltHost", "ZltDcmClient.exe"),
|
|
20425
20787
|
managedCodePath
|
|
20426
20788
|
].map((candidate) => {
|
|
20427
|
-
const resolved =
|
|
20789
|
+
const resolved = path6.resolve(candidate);
|
|
20428
20790
|
assertPathInside(workRoot, resolved);
|
|
20429
20791
|
return resolved;
|
|
20430
20792
|
});
|
|
20431
|
-
const installedExecutablePaths = executablePaths.filter((candidate) =>
|
|
20432
|
-
const installedExecutableRoots =
|
|
20793
|
+
const installedExecutablePaths = executablePaths.filter((candidate) => fs6.existsSync(candidate));
|
|
20794
|
+
const installedExecutableRoots = fs6.existsSync(managedGitRoot) ? [`${managedGitRoot}${path6.sep}`] : [];
|
|
20433
20795
|
if (installedExecutablePaths.length === 0 && installedExecutableRoots.length === 0)
|
|
20434
20796
|
return [];
|
|
20435
20797
|
const selectTyPayloadProcesses = () => listManagedRuntimeProcesses(installedExecutablePaths, installedExecutableRoots).filter((item) => {
|
|
20436
|
-
if (
|
|
20798
|
+
if (path6.resolve(item.executablePath).toLowerCase() !== managedCodePath.toLowerCase())
|
|
20437
20799
|
return true;
|
|
20438
20800
|
const commandLine = item.commandLine.replaceAll("/", "\\").toLowerCase();
|
|
20439
20801
|
return commandLine.includes(jsserviceRoot) && commandLine.includes("--ms-enable-electron-run-as-node");
|
|
@@ -20491,16 +20853,16 @@ async function stopManagedRuntimeProcesses(workRoot, config2, onProgress, messag
|
|
|
20491
20853
|
if (process.platform !== "win32")
|
|
20492
20854
|
return [];
|
|
20493
20855
|
const executablePaths = [
|
|
20494
|
-
|
|
20495
|
-
|
|
20496
|
-
|
|
20497
|
-
|
|
20856
|
+
path6.join(workRoot, config2.hostPath),
|
|
20857
|
+
path6.join(workRoot, config2.backservicePath),
|
|
20858
|
+
path6.join(workRoot, "zltHost", "zlthost.exe"),
|
|
20859
|
+
path6.join(workRoot, "zltaf", "zltaf.exe")
|
|
20498
20860
|
].map((candidate) => {
|
|
20499
|
-
const resolved =
|
|
20861
|
+
const resolved = path6.resolve(candidate);
|
|
20500
20862
|
assertPathInside(workRoot, resolved);
|
|
20501
20863
|
return resolved;
|
|
20502
20864
|
});
|
|
20503
|
-
const installedExecutablePaths = executablePaths.filter((candidate) =>
|
|
20865
|
+
const installedExecutablePaths = executablePaths.filter((candidate) => fs6.existsSync(candidate));
|
|
20504
20866
|
if (installedExecutablePaths.length === 0)
|
|
20505
20867
|
return [];
|
|
20506
20868
|
const running = listManagedRuntimeProcesses(installedExecutablePaths);
|
|
@@ -20513,9 +20875,9 @@ async function stopManagedRuntimeProcesses(workRoot, config2, onProgress, messag
|
|
|
20513
20875
|
throw new Error(`${messages.failed}: ${formatManagedProcessList(remaining)}\u3002\u8BF7\u5173\u95ED\u667A\u91CF\u901A\u76F8\u5173\u4EFB\u52A1\u540E\u91CD\u8BD5\u5B89\u88C5\u3002`);
|
|
20514
20876
|
}
|
|
20515
20877
|
}
|
|
20516
|
-
const zltMarker =
|
|
20878
|
+
const zltMarker = path6.resolve(workRoot, config2.temporaryZltFile || "Temporary/zlt");
|
|
20517
20879
|
assertPathInside(workRoot, zltMarker);
|
|
20518
|
-
|
|
20880
|
+
fs6.rmSync(zltMarker, { force: true });
|
|
20519
20881
|
if (running.length > 0)
|
|
20520
20882
|
onProgress?.(messages.stopped);
|
|
20521
20883
|
return running;
|
|
@@ -20585,7 +20947,7 @@ ${result.stderr || ""}`);
|
|
|
20585
20947
|
return [];
|
|
20586
20948
|
return [{
|
|
20587
20949
|
pid,
|
|
20588
|
-
name: typeof item.Name === "string" ? item.Name :
|
|
20950
|
+
name: typeof item.Name === "string" ? item.Name : path6.basename(item.ExecutablePath),
|
|
20589
20951
|
executablePath: item.ExecutablePath,
|
|
20590
20952
|
commandLine: typeof item.CommandLine === "string" ? item.CommandLine : ""
|
|
20591
20953
|
}];
|
|
@@ -20593,14 +20955,14 @@ ${result.stderr || ""}`);
|
|
|
20593
20955
|
}
|
|
20594
20956
|
function windowsSystemToolPath(relativePath) {
|
|
20595
20957
|
const systemRoot = process.env.SystemRoot || process.env.WINDIR;
|
|
20596
|
-
if (!systemRoot || !
|
|
20958
|
+
if (!systemRoot || !path6.isAbsolute(systemRoot)) {
|
|
20597
20959
|
throw new Error("\u65E0\u6CD5\u5B89\u5168\u5B9A\u4F4D Windows \u7CFB\u7EDF\u5DE5\u5177: SystemRoot \u672A\u8BBE\u7F6E");
|
|
20598
20960
|
}
|
|
20599
|
-
return
|
|
20961
|
+
return path6.join(systemRoot, "System32", ...relativePath.split("/"));
|
|
20600
20962
|
}
|
|
20601
20963
|
function ensureGitToolchain(workRoot) {
|
|
20602
20964
|
const targetGit = getGitExePath(workRoot);
|
|
20603
|
-
if (!
|
|
20965
|
+
if (!fs6.existsSync(targetGit)) {
|
|
20604
20966
|
throw new Error(`\u6295\u7814\u6A21\u5757\u5C1A\u672A\u4E0B\u53D1 MinGit \u5DE5\u5177\u94FE: ${targetGit}\u3002\u8BF7\u5728\u667A\u80FD\u7BA1\u5BB6\u4E2D\u5B89\u88C5\u6216\u4FEE\u590D\u6295\u7814\u6A21\u5757\u540E\u91CD\u8BD5\u3002`);
|
|
20605
20967
|
}
|
|
20606
20968
|
return targetGit;
|
|
@@ -20610,7 +20972,7 @@ function validatePythonSdkComplete(workRoot, config2) {
|
|
|
20610
20972
|
if (packages.length === 0)
|
|
20611
20973
|
return { complete: true };
|
|
20612
20974
|
const pythonPath = getPythonExePath(workRoot);
|
|
20613
|
-
if (!
|
|
20975
|
+
if (!fs6.existsSync(pythonPath)) {
|
|
20614
20976
|
return { complete: false, reason: `\u7F3A\u5C11Python \u7A0B\u5E8F: ${pythonPath}` };
|
|
20615
20977
|
}
|
|
20616
20978
|
if (areBundledSitePackagesPresent(workRoot, packages)) {
|
|
@@ -20658,7 +21020,7 @@ async function installPythonSdk(workRoot, config2, onProgress) {
|
|
|
20658
21020
|
return;
|
|
20659
21021
|
}
|
|
20660
21022
|
const pythonPath = getPythonExePath(workRoot);
|
|
20661
|
-
if (!
|
|
21023
|
+
if (!fs6.existsSync(pythonPath)) {
|
|
20662
21024
|
throw new Error(`\u65E0\u6CD5\u5B89\u88C5 Python SDK\uFF0C\u7F3A\u5C11 Python \u7A0B\u5E8F: ${pythonPath}`);
|
|
20663
21025
|
}
|
|
20664
21026
|
const packages = normalizePythonSdkPackages(config2);
|
|
@@ -20751,16 +21113,16 @@ function buildManagedPipEnvironment(runtimeIndexUrl, baseEnvironment = process.e
|
|
|
20751
21113
|
async function downloadRuntimeInstaller(config2, onProgress, installType = "full") {
|
|
20752
21114
|
const url = resolveAssistantDownloadUrl(config2, installType);
|
|
20753
21115
|
const sha256 = resolveAssistantDownloadSha256(config2, installType);
|
|
20754
|
-
const filename =
|
|
20755
|
-
const dir =
|
|
20756
|
-
const destination =
|
|
20757
|
-
|
|
21116
|
+
const filename = path6.basename(new URL(url).pathname) || "zlt-runtime-installer.exe";
|
|
21117
|
+
const dir = path6.join(os2.tmpdir(), config2.downloadTempDir);
|
|
21118
|
+
const destination = path6.join(dir, filename);
|
|
21119
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
20758
21120
|
onProgress?.(`\u4E0B\u8F7D\u5B89\u88C5\u5305: ${url}`);
|
|
20759
21121
|
await downloadFile(url, destination);
|
|
20760
21122
|
try {
|
|
20761
21123
|
assertFileSha256(destination, sha256);
|
|
20762
21124
|
} catch (error2) {
|
|
20763
|
-
|
|
21125
|
+
fs6.rmSync(destination, { force: true });
|
|
20764
21126
|
throw error2;
|
|
20765
21127
|
}
|
|
20766
21128
|
onProgress?.(`\u5B89\u88C5\u5305 SHA256 \u6821\u9A8C\u901A\u8FC7: ${sha256}`);
|
|
@@ -20788,7 +21150,7 @@ function describeInstallerExitCode(exitCode) {
|
|
|
20788
21150
|
}
|
|
20789
21151
|
}
|
|
20790
21152
|
function executeInstallerProcess(installerPath, installDir, logPath) {
|
|
20791
|
-
return new Promise((
|
|
21153
|
+
return new Promise((resolve8, reject) => {
|
|
20792
21154
|
const child = (0, import_child_process3.spawn)(installerPath, [
|
|
20793
21155
|
"/VERYSILENT",
|
|
20794
21156
|
"/SUPPRESSMSGBOXES",
|
|
@@ -20810,14 +21172,14 @@ function executeInstallerProcess(installerPath, installDir, logPath) {
|
|
|
20810
21172
|
} else if (code === null) {
|
|
20811
21173
|
reject(new Error("\u5B89\u88C5\u7A0B\u5E8F\u6267\u884C\u5931\u8D25\uFF0C\u672A\u8FD4\u56DE\u9000\u51FA\u7801"));
|
|
20812
21174
|
} else {
|
|
20813
|
-
|
|
21175
|
+
resolve8(code);
|
|
20814
21176
|
}
|
|
20815
21177
|
});
|
|
20816
21178
|
child.on("error", (error2) => reject(new Error(`\u5B89\u88C5\u7A0B\u5E8F\u542F\u52A8\u5931\u8D25: ${error2.message}`)));
|
|
20817
21179
|
});
|
|
20818
21180
|
}
|
|
20819
21181
|
function runPythonSdkInstall(pythonPath, args, timeoutMs, bootstrapPipWheelPath, environment = process.env) {
|
|
20820
|
-
return new Promise((
|
|
21182
|
+
return new Promise((resolve8, reject) => {
|
|
20821
21183
|
const commandArgs = bootstrapPipWheelPath ? buildPipBootstrapCommand(args, bootstrapPipWheelPath) : args;
|
|
20822
21184
|
const child = (0, import_child_process3.spawn)(pythonPath, commandArgs, {
|
|
20823
21185
|
env: environment,
|
|
@@ -20838,7 +21200,7 @@ function runPythonSdkInstall(pythonPath, args, timeoutMs, bootstrapPipWheelPath,
|
|
|
20838
21200
|
child.on("close", (code) => {
|
|
20839
21201
|
clearTimeout(timer);
|
|
20840
21202
|
if (code === 0) {
|
|
20841
|
-
|
|
21203
|
+
resolve8();
|
|
20842
21204
|
} else {
|
|
20843
21205
|
reject(new Error(`Python SDK \u5B89\u88C5\u5931\u8D25\uFF0C\u9000\u51FA\u7801: ${code ?? "unknown"}, output=${truncateOutput(output)}`));
|
|
20844
21206
|
}
|
|
@@ -20896,14 +21258,14 @@ function downloadFile(url, destination, redirectCount = 0, timeoutMs = 0, initia
|
|
|
20896
21258
|
if (redirectCount > 5) {
|
|
20897
21259
|
return Promise.reject(new Error(`\u4E0B\u8F7D\u91CD\u5B9A\u5411\u8FC7\u591A: ${url}`));
|
|
20898
21260
|
}
|
|
20899
|
-
|
|
21261
|
+
fs6.mkdirSync(path6.dirname(destination), { recursive: true });
|
|
20900
21262
|
const partialPath = `${destination}.${process.pid}.${(0, import_crypto3.randomUUID)()}.part`;
|
|
20901
|
-
return new Promise((
|
|
21263
|
+
return new Promise((resolve8, reject) => {
|
|
20902
21264
|
let settled = false;
|
|
20903
21265
|
let file;
|
|
20904
21266
|
const cleanupPartial = () => {
|
|
20905
21267
|
file?.destroy();
|
|
20906
|
-
|
|
21268
|
+
fs6.rmSync(partialPath, { force: true });
|
|
20907
21269
|
};
|
|
20908
21270
|
const fail2 = (error2) => {
|
|
20909
21271
|
if (settled)
|
|
@@ -20916,10 +21278,10 @@ function downloadFile(url, destination, redirectCount = 0, timeoutMs = 0, initia
|
|
|
20916
21278
|
if (settled)
|
|
20917
21279
|
return;
|
|
20918
21280
|
try {
|
|
20919
|
-
|
|
20920
|
-
|
|
21281
|
+
fs6.rmSync(destination, { force: true });
|
|
21282
|
+
fs6.renameSync(partialPath, destination);
|
|
20921
21283
|
settled = true;
|
|
20922
|
-
|
|
21284
|
+
resolve8();
|
|
20923
21285
|
} catch (error2) {
|
|
20924
21286
|
fail2(error2);
|
|
20925
21287
|
}
|
|
@@ -20944,7 +21306,7 @@ function downloadFile(url, destination, redirectCount = 0, timeoutMs = 0, initia
|
|
|
20944
21306
|
if (settled)
|
|
20945
21307
|
return;
|
|
20946
21308
|
settled = true;
|
|
20947
|
-
|
|
21309
|
+
resolve8();
|
|
20948
21310
|
}, fail2);
|
|
20949
21311
|
return;
|
|
20950
21312
|
}
|
|
@@ -20953,7 +21315,7 @@ function downloadFile(url, destination, redirectCount = 0, timeoutMs = 0, initia
|
|
|
20953
21315
|
fail2(new Error(`\u4E0B\u8F7D\u5931\u8D25: HTTP ${statusCode}`));
|
|
20954
21316
|
return;
|
|
20955
21317
|
}
|
|
20956
|
-
file =
|
|
21318
|
+
file = fs6.createWriteStream(partialPath, { flags: "wx" });
|
|
20957
21319
|
response.on("aborted", () => fail2(new Error(`\u4E0B\u8F7D\u54CD\u5E94\u4E2D\u65AD: ${url}`)));
|
|
20958
21320
|
response.on("error", fail2);
|
|
20959
21321
|
response.on("close", () => {
|
|
@@ -20979,637 +21341,280 @@ function downloadFile(url, destination, redirectCount = 0, timeoutMs = 0, initia
|
|
|
20979
21341
|
});
|
|
20980
21342
|
}
|
|
20981
21343
|
function delay(ms) {
|
|
20982
|
-
return new Promise((
|
|
21344
|
+
return new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
20983
21345
|
}
|
|
20984
21346
|
function getZltafExePath(workRoot) {
|
|
20985
|
-
return
|
|
21347
|
+
return path6.join(workRoot, "zltaf", "zltaf.exe");
|
|
20986
21348
|
}
|
|
20987
21349
|
function getZltafConfigPath(workRoot) {
|
|
20988
|
-
return
|
|
21350
|
+
return path6.join(workRoot, "zltaf", "application-local.properties");
|
|
20989
21351
|
}
|
|
20990
21352
|
function resolveZltafLaunchConfigPath(workRoot, config2) {
|
|
20991
21353
|
if (config2.zltafConfigFile === ZLTAF_CONFIG_FILE_DEFAULT) {
|
|
20992
21354
|
return getZltafConfigPath(workRoot);
|
|
20993
21355
|
}
|
|
20994
|
-
const preferred =
|
|
20995
|
-
if (
|
|
20996
|
-
return preferred;
|
|
20997
|
-
}
|
|
20998
|
-
const base = getZltafConfigPath(workRoot);
|
|
20999
|
-
process.stderr.write(`[zlt-runtime] ZLTAF \u914D\u7F6E ${config2.zltafConfigFile} \u4E0D\u5B58\u5728\uFF0C\u56DE\u9000\u5230 ${path5.basename(base)}
|
|
21000
|
-
`);
|
|
21001
|
-
return base;
|
|
21002
|
-
}
|
|
21003
|
-
function getPythonExePath(workRoot) {
|
|
21004
|
-
return path5.join(workRoot, "python", "python.exe");
|
|
21005
|
-
}
|
|
21006
|
-
function getGitExePath(workRoot) {
|
|
21007
|
-
return path5.join(workRoot, "mingit", "cmd", "git.exe");
|
|
21008
|
-
}
|
|
21009
|
-
function areBacktestModuleRuntimeFilesPresent(workRoot) {
|
|
21010
|
-
return fs5.existsSync(getZltafExePath(workRoot)) && fs5.existsSync(getZltafConfigPath(workRoot));
|
|
21011
|
-
}
|
|
21012
|
-
function assertPathInside(root, targetPath) {
|
|
21013
|
-
const resolvedRoot = path5.resolve(root);
|
|
21014
|
-
const resolvedTarget = path5.resolve(targetPath);
|
|
21015
|
-
const relative2 = path5.relative(resolvedRoot, resolvedTarget);
|
|
21016
|
-
if (relative2.startsWith("..") || path5.isAbsolute(relative2)) {
|
|
21017
|
-
throw new Error(`\u62D2\u7EDD\u5199\u5165\u5B89\u88C5\u76EE\u5F55\u5916\u8DEF\u5F84: ${resolvedTarget}`);
|
|
21018
|
-
}
|
|
21019
|
-
}
|
|
21020
|
-
function normalizePythonSdkPackages(config2) {
|
|
21021
|
-
return config2.pythonSdkPackages.map((item) => item.trim()).filter(Boolean);
|
|
21022
|
-
}
|
|
21023
|
-
function normalizePythonRuntimePackages(config2) {
|
|
21024
|
-
return config2.pythonRuntimePackages.map((item) => item.trim()).filter(Boolean);
|
|
21025
|
-
}
|
|
21026
|
-
function normalizeRequiredPythonPackages(config2) {
|
|
21027
|
-
return [...normalizePythonRuntimePackages(config2), ...normalizePythonSdkPackages(config2)];
|
|
21028
|
-
}
|
|
21029
|
-
function areBundledSitePackagesPresent(workRoot, packages) {
|
|
21030
|
-
if (packages.some(hasPythonVersionSpecifier))
|
|
21031
|
-
return false;
|
|
21032
|
-
const sitePackages = path5.join(workRoot, "python", "Lib", "site-packages");
|
|
21033
|
-
if (!fs5.existsSync(sitePackages))
|
|
21034
|
-
return false;
|
|
21035
|
-
let entries = [];
|
|
21036
|
-
try {
|
|
21037
|
-
entries = fs5.readdirSync(sitePackages).map((entry) => entry.toLowerCase());
|
|
21038
|
-
} catch {
|
|
21039
|
-
return false;
|
|
21040
|
-
}
|
|
21041
|
-
return packages.every((packageName) => {
|
|
21042
|
-
const requirementName = getPythonRequirementName(packageName);
|
|
21043
|
-
const normalized = normalizePythonPackageName(requirementName);
|
|
21044
|
-
const importName = pythonDistributionImportName(packageName);
|
|
21045
|
-
const candidateFiles = [
|
|
21046
|
-
path5.join(sitePackages, requirementName, "__init__.py"),
|
|
21047
|
-
path5.join(sitePackages, `${requirementName}.py`),
|
|
21048
|
-
path5.join(sitePackages, importName, "__init__.py"),
|
|
21049
|
-
path5.join(sitePackages, `${importName}.py`)
|
|
21050
|
-
];
|
|
21051
|
-
return candidateFiles.some((candidate) => fs5.existsSync(candidate)) || entries.some((entry) => entry.startsWith(`${normalized}-`) && (entry.endsWith(".dist-info") || entry.endsWith(".egg-info")));
|
|
21052
|
-
});
|
|
21053
|
-
}
|
|
21054
|
-
function hasPythonVersionSpecifier(packageSpec) {
|
|
21055
|
-
return /[<>=!~]/.test(packageSpec);
|
|
21056
|
-
}
|
|
21057
|
-
function getPythonRequirementName(packageSpec) {
|
|
21058
|
-
const match = packageSpec.trim().match(/^([A-Za-z0-9_.-]+)/);
|
|
21059
|
-
return match?.[1] || packageSpec.trim();
|
|
21060
|
-
}
|
|
21061
|
-
function pythonDistributionImportName(packageSpec) {
|
|
21062
|
-
const name = normalizePythonPackageName(getPythonRequirementName(packageSpec));
|
|
21063
|
-
if (name === "zltsdk_plugin")
|
|
21064
|
-
return "zltsdk";
|
|
21065
|
-
return name;
|
|
21066
|
-
}
|
|
21067
|
-
function normalizePythonPackageName(packageName) {
|
|
21068
|
-
return packageName.toLowerCase().replace(/[-_.]+/g, "_");
|
|
21069
|
-
}
|
|
21070
|
-
function truncateOutput(output) {
|
|
21071
|
-
const normalized = output.replace(/\s+/g, " ").trim();
|
|
21072
|
-
return normalized.length > 2e3 ? `${normalized.slice(0, 2e3)}...` : normalized;
|
|
21073
|
-
}
|
|
21074
|
-
async function waitForZltafPipe(workRoot, config2, options) {
|
|
21075
|
-
const startedAt = Date.now();
|
|
21076
|
-
let started = false;
|
|
21077
|
-
let startedPid;
|
|
21078
|
-
while (Date.now() - startedAt <= config2.zltafPipeWait) {
|
|
21079
|
-
if (pipeExists(workRoot, "ZLTAF"))
|
|
21080
|
-
return startedPid;
|
|
21081
|
-
if (options.startIfMissing && !started) {
|
|
21082
|
-
startedPid = startZltafRuntime(workRoot, config2);
|
|
21083
|
-
started = true;
|
|
21084
|
-
await delay(config2.serviceStartupWait);
|
|
21085
|
-
continue;
|
|
21086
|
-
}
|
|
21087
|
-
await delay(500);
|
|
21088
|
-
}
|
|
21089
|
-
throw new Error(`\u7B49\u5F85 ZLTAF \u7BA1\u9053\u8D85\u65F6: ${discoverPipePath(workRoot, "ZLTAF")}`);
|
|
21090
|
-
}
|
|
21091
|
-
|
|
21092
|
-
// ../zlt-runtime-core/dist/auth.js
|
|
21093
|
-
var fs6 = __toESM(require("fs"), 1);
|
|
21094
|
-
var os2 = __toESM(require("os"), 1);
|
|
21095
|
-
var path6 = __toESM(require("path"), 1);
|
|
21096
|
-
var DEFAULT_ZLTQUANT_API_BASE = "https://api.zltquant.com";
|
|
21097
|
-
function resolveZltQuantHome(env = process.env) {
|
|
21098
|
-
const configuredHome = env.ZLTQUANT_HOME?.trim();
|
|
21099
|
-
if (configuredHome)
|
|
21100
|
-
return expandHome(configuredHome);
|
|
21101
|
-
return path6.join(os2.homedir(), ".zltquant");
|
|
21102
|
-
}
|
|
21103
|
-
function resolveCredentialsPath(env = process.env) {
|
|
21104
|
-
const configuredPath = env.ZLTQUANT_CREDENTIALS?.trim();
|
|
21105
|
-
if (configuredPath)
|
|
21106
|
-
return expandHome(configuredPath);
|
|
21107
|
-
return path6.join(resolveZltQuantHome(env), "credentials.json");
|
|
21108
|
-
}
|
|
21109
|
-
function readCredentials(env = process.env) {
|
|
21110
|
-
const credentialsPath = resolveCredentialsPath(env);
|
|
21111
|
-
if (!fs6.existsSync(credentialsPath))
|
|
21112
|
-
return null;
|
|
21113
|
-
const parsed = JSON.parse(fs6.readFileSync(credentialsPath, "utf-8"));
|
|
21114
|
-
const apiKey = typeof parsed.apiKey === "string" ? parsed.apiKey.trim() : "";
|
|
21115
|
-
if (!apiKey)
|
|
21116
|
-
return null;
|
|
21117
|
-
return {
|
|
21118
|
-
apiKey,
|
|
21119
|
-
apiBase: typeof parsed.apiBase === "string" && parsed.apiBase.trim() ? parsed.apiBase.trim() : DEFAULT_ZLTQUANT_API_BASE,
|
|
21120
|
-
source: typeof parsed.source === "string" && parsed.source.trim() ? parsed.source.trim() : "file",
|
|
21121
|
-
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : ""
|
|
21122
|
-
};
|
|
21123
|
-
}
|
|
21124
|
-
function writeCredentialsFromEnv(env = process.env) {
|
|
21125
|
-
const apiKey = env.ZLTQUANT_API_KEY?.trim();
|
|
21126
|
-
if (!apiKey) {
|
|
21127
|
-
return getAuthStatus(env);
|
|
21128
|
-
}
|
|
21129
|
-
writeCredentials({
|
|
21130
|
-
apiKey,
|
|
21131
|
-
apiBase: env.ZLTQUANT_API_BASE,
|
|
21132
|
-
source: "trae-mcp"
|
|
21133
|
-
}, env);
|
|
21134
|
-
return getAuthStatus(env);
|
|
21135
|
-
}
|
|
21136
|
-
function writeCredentials(input, env = process.env) {
|
|
21137
|
-
const apiKey = input.apiKey.trim();
|
|
21138
|
-
const source = input.source.trim();
|
|
21139
|
-
if (!apiKey)
|
|
21140
|
-
throw new Error("ZLTQuant API key is required");
|
|
21141
|
-
if (!source)
|
|
21142
|
-
throw new Error("ZLTQuant credential source is required");
|
|
21143
|
-
if (env.ZLTQUANT_CREDENTIALS?.trim() && tryReadCredentials(env)) {
|
|
21144
|
-
return getAuthStatus(env);
|
|
21145
|
-
}
|
|
21146
|
-
const credentialsPath = resolveCredentialsPath(env);
|
|
21147
|
-
const credentials = {
|
|
21148
|
-
apiKey,
|
|
21149
|
-
apiBase: input.apiBase?.trim() || DEFAULT_ZLTQUANT_API_BASE,
|
|
21150
|
-
source,
|
|
21151
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
21152
|
-
};
|
|
21153
|
-
fs6.mkdirSync(path6.dirname(credentialsPath), { recursive: true });
|
|
21154
|
-
const tempPath = `${credentialsPath}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`;
|
|
21155
|
-
try {
|
|
21156
|
-
fs6.writeFileSync(tempPath, `${JSON.stringify(credentials, null, 2)}
|
|
21157
|
-
`, { encoding: "utf-8", mode: 384 });
|
|
21158
|
-
chmodOwnerOnly(tempPath);
|
|
21159
|
-
fs6.renameSync(tempPath, credentialsPath);
|
|
21160
|
-
chmodOwnerOnly(credentialsPath);
|
|
21161
|
-
} finally {
|
|
21162
|
-
fs6.rmSync(tempPath, { force: true });
|
|
21163
|
-
}
|
|
21164
|
-
return fileAuthStatus(credentialsPath, resolveZltQuantHome(env), credentials);
|
|
21165
|
-
}
|
|
21166
|
-
function getAuthStatus(env = process.env) {
|
|
21167
|
-
const credentialsPath = resolveCredentialsPath(env);
|
|
21168
|
-
const zltquantHome = resolveZltQuantHome(env);
|
|
21169
|
-
const credentials = readCredentials(env);
|
|
21170
|
-
if (env.ZLTQUANT_CREDENTIALS?.trim() && credentials) {
|
|
21171
|
-
return {
|
|
21172
|
-
configured: true,
|
|
21173
|
-
source: "file",
|
|
21174
|
-
credentialsPath,
|
|
21175
|
-
zltquantHome,
|
|
21176
|
-
apiKeyMask: maskApiKey(credentials.apiKey),
|
|
21177
|
-
apiBase: credentials.apiBase,
|
|
21178
|
-
updatedAt: credentials.updatedAt
|
|
21179
|
-
};
|
|
21180
|
-
}
|
|
21181
|
-
const envKey = env.ZLTQUANT_API_KEY?.trim();
|
|
21182
|
-
if (envKey) {
|
|
21183
|
-
return {
|
|
21184
|
-
configured: true,
|
|
21185
|
-
source: "env",
|
|
21186
|
-
credentialsPath,
|
|
21187
|
-
zltquantHome,
|
|
21188
|
-
apiKeyMask: maskApiKey(envKey),
|
|
21189
|
-
apiBase: env.ZLTQUANT_API_BASE?.trim() || DEFAULT_ZLTQUANT_API_BASE,
|
|
21190
|
-
updatedAt: ""
|
|
21191
|
-
};
|
|
21192
|
-
}
|
|
21193
|
-
if (credentials) {
|
|
21194
|
-
return {
|
|
21195
|
-
configured: true,
|
|
21196
|
-
source: "file",
|
|
21197
|
-
credentialsPath,
|
|
21198
|
-
zltquantHome,
|
|
21199
|
-
apiKeyMask: maskApiKey(credentials.apiKey),
|
|
21200
|
-
apiBase: credentials.apiBase,
|
|
21201
|
-
updatedAt: credentials.updatedAt
|
|
21202
|
-
};
|
|
21356
|
+
const preferred = path6.join(workRoot, "zltaf", config2.zltafConfigFile);
|
|
21357
|
+
if (fs6.existsSync(preferred)) {
|
|
21358
|
+
return preferred;
|
|
21203
21359
|
}
|
|
21204
|
-
|
|
21205
|
-
|
|
21206
|
-
|
|
21207
|
-
|
|
21208
|
-
zltquantHome,
|
|
21209
|
-
apiKeyMask: "",
|
|
21210
|
-
apiBase: env.ZLTQUANT_API_BASE?.trim() || DEFAULT_ZLTQUANT_API_BASE,
|
|
21211
|
-
updatedAt: ""
|
|
21212
|
-
};
|
|
21360
|
+
const base = getZltafConfigPath(workRoot);
|
|
21361
|
+
process.stderr.write(`[zlt-runtime] ZLTAF \u914D\u7F6E ${config2.zltafConfigFile} \u4E0D\u5B58\u5728\uFF0C\u56DE\u9000\u5230 ${path6.basename(base)}
|
|
21362
|
+
`);
|
|
21363
|
+
return base;
|
|
21213
21364
|
}
|
|
21214
|
-
function
|
|
21215
|
-
|
|
21216
|
-
if (!trimmed)
|
|
21217
|
-
return "";
|
|
21218
|
-
if (trimmed.length <= 8)
|
|
21219
|
-
return `****${trimmed.slice(-2)}`;
|
|
21220
|
-
return `${trimmed.slice(0, 4)}...${trimmed.slice(-4)}`;
|
|
21365
|
+
function getPythonExePath(workRoot) {
|
|
21366
|
+
return path6.join(workRoot, "python", "python.exe");
|
|
21221
21367
|
}
|
|
21222
|
-
function
|
|
21223
|
-
|
|
21224
|
-
return os2.homedir();
|
|
21225
|
-
if (input.startsWith("~/") || input.startsWith("~\\")) {
|
|
21226
|
-
return path6.join(os2.homedir(), input.slice(2));
|
|
21227
|
-
}
|
|
21228
|
-
return path6.resolve(input);
|
|
21368
|
+
function getGitExePath(workRoot) {
|
|
21369
|
+
return path6.join(workRoot, "mingit", "cmd", "git.exe");
|
|
21229
21370
|
}
|
|
21230
|
-
function
|
|
21231
|
-
|
|
21232
|
-
|
|
21233
|
-
|
|
21234
|
-
|
|
21371
|
+
function areBacktestModuleRuntimeFilesPresent(workRoot) {
|
|
21372
|
+
return fs6.existsSync(getZltafExePath(workRoot)) && fs6.existsSync(getZltafConfigPath(workRoot));
|
|
21373
|
+
}
|
|
21374
|
+
function assertPathInside(root, targetPath) {
|
|
21375
|
+
const resolvedRoot = path6.resolve(root);
|
|
21376
|
+
const resolvedTarget = path6.resolve(targetPath);
|
|
21377
|
+
const relative2 = path6.relative(resolvedRoot, resolvedTarget);
|
|
21378
|
+
if (relative2.startsWith("..") || path6.isAbsolute(relative2)) {
|
|
21379
|
+
throw new Error(`\u62D2\u7EDD\u5199\u5165\u5B89\u88C5\u76EE\u5F55\u5916\u8DEF\u5F84: ${resolvedTarget}`);
|
|
21235
21380
|
}
|
|
21236
21381
|
}
|
|
21237
|
-
function
|
|
21382
|
+
function normalizePythonSdkPackages(config2) {
|
|
21383
|
+
return config2.pythonSdkPackages.map((item) => item.trim()).filter(Boolean);
|
|
21384
|
+
}
|
|
21385
|
+
function normalizePythonRuntimePackages(config2) {
|
|
21386
|
+
return config2.pythonRuntimePackages.map((item) => item.trim()).filter(Boolean);
|
|
21387
|
+
}
|
|
21388
|
+
function normalizeRequiredPythonPackages(config2) {
|
|
21389
|
+
return [...normalizePythonRuntimePackages(config2), ...normalizePythonSdkPackages(config2)];
|
|
21390
|
+
}
|
|
21391
|
+
function areBundledSitePackagesPresent(workRoot, packages) {
|
|
21392
|
+
if (packages.some(hasPythonVersionSpecifier))
|
|
21393
|
+
return false;
|
|
21394
|
+
const sitePackages = path6.join(workRoot, "python", "Lib", "site-packages");
|
|
21395
|
+
if (!fs6.existsSync(sitePackages))
|
|
21396
|
+
return false;
|
|
21397
|
+
let entries = [];
|
|
21238
21398
|
try {
|
|
21239
|
-
fs6.
|
|
21399
|
+
entries = fs6.readdirSync(sitePackages).map((entry) => entry.toLowerCase());
|
|
21240
21400
|
} catch {
|
|
21401
|
+
return false;
|
|
21241
21402
|
}
|
|
21403
|
+
return packages.every((packageName) => {
|
|
21404
|
+
const requirementName = getPythonRequirementName(packageName);
|
|
21405
|
+
const normalized = normalizePythonPackageName(requirementName);
|
|
21406
|
+
const importName = pythonDistributionImportName(packageName);
|
|
21407
|
+
const candidateFiles = [
|
|
21408
|
+
path6.join(sitePackages, requirementName, "__init__.py"),
|
|
21409
|
+
path6.join(sitePackages, `${requirementName}.py`),
|
|
21410
|
+
path6.join(sitePackages, importName, "__init__.py"),
|
|
21411
|
+
path6.join(sitePackages, `${importName}.py`)
|
|
21412
|
+
];
|
|
21413
|
+
return candidateFiles.some((candidate) => fs6.existsSync(candidate)) || entries.some((entry) => entry.startsWith(`${normalized}-`) && (entry.endsWith(".dist-info") || entry.endsWith(".egg-info")));
|
|
21414
|
+
});
|
|
21242
21415
|
}
|
|
21243
|
-
function
|
|
21244
|
-
return
|
|
21245
|
-
configured: true,
|
|
21246
|
-
source: "file",
|
|
21247
|
-
credentialsPath,
|
|
21248
|
-
zltquantHome,
|
|
21249
|
-
apiKeyMask: maskApiKey(credentials.apiKey),
|
|
21250
|
-
apiBase: credentials.apiBase,
|
|
21251
|
-
updatedAt: credentials.updatedAt
|
|
21252
|
-
};
|
|
21416
|
+
function hasPythonVersionSpecifier(packageSpec) {
|
|
21417
|
+
return /[<>=!~]/.test(packageSpec);
|
|
21253
21418
|
}
|
|
21254
|
-
|
|
21255
|
-
|
|
21256
|
-
|
|
21257
|
-
var fs7 = __toESM(require("node:fs"), 1);
|
|
21258
|
-
var net2 = __toESM(require("node:net"), 1);
|
|
21259
|
-
var os3 = __toESM(require("node:os"), 1);
|
|
21260
|
-
var path7 = __toESM(require("node:path"), 1);
|
|
21261
|
-
function urlEncode(value) {
|
|
21262
|
-
let result = "";
|
|
21263
|
-
for (const code of Buffer.from(value, "utf8")) {
|
|
21264
|
-
const char = String.fromCharCode(code);
|
|
21265
|
-
if (code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || char === "-" || char === "_" || char === "." || char === "~") {
|
|
21266
|
-
result += char;
|
|
21267
|
-
} else if (char === " ") {
|
|
21268
|
-
result += "+";
|
|
21269
|
-
} else {
|
|
21270
|
-
result += `%${code.toString(16).toUpperCase().padStart(2, "0")}`;
|
|
21271
|
-
}
|
|
21272
|
-
}
|
|
21273
|
-
return result;
|
|
21419
|
+
function getPythonRequirementName(packageSpec) {
|
|
21420
|
+
const match = packageSpec.trim().match(/^([A-Za-z0-9_.-]+)/);
|
|
21421
|
+
return match?.[1] || packageSpec.trim();
|
|
21274
21422
|
}
|
|
21275
|
-
function
|
|
21276
|
-
const
|
|
21277
|
-
|
|
21278
|
-
|
|
21279
|
-
|
|
21280
|
-
bytes.push(32);
|
|
21281
|
-
} else if (char === "%" && index + 2 < value.length) {
|
|
21282
|
-
const code = Number.parseInt(value.substring(index + 1, index + 3), 16);
|
|
21283
|
-
if (!Number.isNaN(code)) {
|
|
21284
|
-
bytes.push(code);
|
|
21285
|
-
index += 2;
|
|
21286
|
-
} else {
|
|
21287
|
-
bytes.push(char.charCodeAt(0));
|
|
21288
|
-
}
|
|
21289
|
-
} else {
|
|
21290
|
-
bytes.push(...Buffer.from(char, "utf8"));
|
|
21291
|
-
}
|
|
21292
|
-
}
|
|
21293
|
-
return Buffer.from(bytes).toString("utf8");
|
|
21423
|
+
function pythonDistributionImportName(packageSpec) {
|
|
21424
|
+
const name = normalizePythonPackageName(getPythonRequirementName(packageSpec));
|
|
21425
|
+
if (name === "zltsdk_plugin")
|
|
21426
|
+
return "zltsdk";
|
|
21427
|
+
return name;
|
|
21294
21428
|
}
|
|
21295
|
-
|
|
21296
|
-
|
|
21297
|
-
|
|
21298
|
-
|
|
21299
|
-
|
|
21300
|
-
|
|
21301
|
-
|
|
21302
|
-
|
|
21303
|
-
|
|
21304
|
-
|
|
21305
|
-
|
|
21306
|
-
|
|
21307
|
-
|
|
21308
|
-
|
|
21309
|
-
|
|
21310
|
-
|
|
21311
|
-
|
|
21312
|
-
|
|
21313
|
-
|
|
21314
|
-
packet += `${key}:${urlEncode(value)}\r
|
|
21315
|
-
`;
|
|
21316
|
-
if (this.xErr.size > 0) {
|
|
21317
|
-
packet += "X-Err:";
|
|
21318
|
-
for (const [key, value] of this.xErr)
|
|
21319
|
-
packet += `${key}=${urlEncode(value)},`;
|
|
21320
|
-
packet += "\r\n";
|
|
21321
|
-
}
|
|
21322
|
-
if (this.xOption.size > 0) {
|
|
21323
|
-
packet += "X-Option:";
|
|
21324
|
-
for (const [key, value] of this.xOption)
|
|
21325
|
-
packet += `${key}=${urlEncode(value)},`;
|
|
21326
|
-
packet += "\r\n";
|
|
21327
|
-
}
|
|
21328
|
-
packet += `Content-Length:${Buffer.byteLength(this.content, "utf8")}\r
|
|
21329
|
-
\r
|
|
21330
|
-
`;
|
|
21331
|
-
return packet + this.content;
|
|
21332
|
-
}
|
|
21333
|
-
parsePacket(data) {
|
|
21334
|
-
const raw = data.toString("binary");
|
|
21335
|
-
const headerEnd = raw.indexOf("\r\n\r\n");
|
|
21336
|
-
if (headerEnd === -1)
|
|
21337
|
-
return false;
|
|
21338
|
-
this.headerLength = headerEnd + 4;
|
|
21339
|
-
const lines = raw.substring(0, headerEnd).split("\r\n");
|
|
21340
|
-
if (lines.length === 0)
|
|
21341
|
-
return false;
|
|
21342
|
-
const firstLine = lines[0];
|
|
21343
|
-
if (firstLine.startsWith("HTTP/")) {
|
|
21344
|
-
const match = firstLine.match(/^(\S+)\s+(\d+)\s+(.*)$/);
|
|
21345
|
-
if (match) {
|
|
21346
|
-
this.httpVersion = match[1];
|
|
21347
|
-
this.statusCode = Number.parseInt(match[2], 10);
|
|
21348
|
-
this.statusMessage = match[3] || "";
|
|
21349
|
-
}
|
|
21350
|
-
} else {
|
|
21351
|
-
const match = firstLine.match(/^(\S+)\s+(\S+)/);
|
|
21352
|
-
if (match) {
|
|
21353
|
-
this.method = match[1];
|
|
21354
|
-
this.uri = match[2];
|
|
21355
|
-
const queryIndex = this.uri.indexOf("?");
|
|
21356
|
-
if (queryIndex !== -1) {
|
|
21357
|
-
for (const param of this.uri.substring(queryIndex + 1).split("&")) {
|
|
21358
|
-
const equalIndex = param.indexOf("=");
|
|
21359
|
-
if (equalIndex !== -1) {
|
|
21360
|
-
this.params.set(param.substring(0, equalIndex), urlDecode(param.substring(equalIndex + 1)));
|
|
21361
|
-
}
|
|
21362
|
-
}
|
|
21363
|
-
}
|
|
21364
|
-
}
|
|
21365
|
-
}
|
|
21366
|
-
this.headers.clear();
|
|
21367
|
-
for (const line of lines.slice(1)) {
|
|
21368
|
-
const colonIndex = line.indexOf(":");
|
|
21369
|
-
if (colonIndex !== -1) {
|
|
21370
|
-
this.headers.set(line.substring(0, colonIndex), urlDecode(line.substring(colonIndex + 1)));
|
|
21371
|
-
}
|
|
21372
|
-
}
|
|
21373
|
-
const xErrValue = this.headers.get("X-Err");
|
|
21374
|
-
if (xErrValue)
|
|
21375
|
-
this.parseCommaSeparatedHeader(this.xErr, xErrValue);
|
|
21376
|
-
const xOptionValue = this.headers.get("X-Option");
|
|
21377
|
-
if (xOptionValue)
|
|
21378
|
-
this.parseCommaSeparatedHeader(this.xOption, xOptionValue);
|
|
21379
|
-
const contentLengthValue = this.headers.get("Content-Length");
|
|
21380
|
-
this.contentLength = contentLengthValue ? Number.parseInt(contentLengthValue, 10) : 0;
|
|
21381
|
-
const totalLength = this.headerLength + this.contentLength;
|
|
21382
|
-
if (data.length < totalLength) {
|
|
21383
|
-
this.isBodyComplete = false;
|
|
21384
|
-
this.remainingBodyLength = totalLength - data.length;
|
|
21385
|
-
return false;
|
|
21386
|
-
}
|
|
21387
|
-
this.isBodyComplete = true;
|
|
21388
|
-
this.remainingBodyLength = 0;
|
|
21389
|
-
this.content = this.contentLength > 0 ? decodePacketBody(data.subarray(this.headerLength, totalLength)) : "";
|
|
21390
|
-
return true;
|
|
21391
|
-
}
|
|
21392
|
-
getTotalLength() {
|
|
21393
|
-
return this.headerLength + this.contentLength;
|
|
21394
|
-
}
|
|
21395
|
-
isBodyCompletePacket() {
|
|
21396
|
-
return this.isBodyComplete;
|
|
21397
|
-
}
|
|
21398
|
-
getRemainingBodyLength() {
|
|
21399
|
-
return this.remainingBodyLength;
|
|
21400
|
-
}
|
|
21401
|
-
parseCommaSeparatedHeader(target, value) {
|
|
21402
|
-
target.clear();
|
|
21403
|
-
for (const pair of value.split(",")) {
|
|
21404
|
-
const equalIndex = pair.indexOf("=");
|
|
21405
|
-
if (equalIndex !== -1) {
|
|
21406
|
-
const key = pair.substring(0, equalIndex);
|
|
21407
|
-
if (key)
|
|
21408
|
-
target.set(key, urlDecode(pair.substring(equalIndex + 1)));
|
|
21409
|
-
}
|
|
21429
|
+
function normalizePythonPackageName(packageName) {
|
|
21430
|
+
return packageName.toLowerCase().replace(/[-_.]+/g, "_");
|
|
21431
|
+
}
|
|
21432
|
+
function truncateOutput(output) {
|
|
21433
|
+
const normalized = output.replace(/\s+/g, " ").trim();
|
|
21434
|
+
return normalized.length > 2e3 ? `${normalized.slice(0, 2e3)}...` : normalized;
|
|
21435
|
+
}
|
|
21436
|
+
async function waitForZltafPipe(workRoot, config2, options) {
|
|
21437
|
+
const startedAt = Date.now();
|
|
21438
|
+
let started = false;
|
|
21439
|
+
let startedPid;
|
|
21440
|
+
while (Date.now() - startedAt <= config2.zltafPipeWait) {
|
|
21441
|
+
if (pipeExists(workRoot, "ZLTAF"))
|
|
21442
|
+
return startedPid;
|
|
21443
|
+
if (options.startIfMissing && !started) {
|
|
21444
|
+
startedPid = startZltafRuntime(workRoot, config2);
|
|
21445
|
+
started = true;
|
|
21446
|
+
await delay(config2.serviceStartupWait);
|
|
21447
|
+
continue;
|
|
21410
21448
|
}
|
|
21449
|
+
await delay(500);
|
|
21411
21450
|
}
|
|
21412
|
-
};
|
|
21413
|
-
var LOG_FILE = path7.join(os3.tmpdir(), "zlt-mcp-proxy.log");
|
|
21414
|
-
var pendingLogLines = [];
|
|
21415
|
-
var logWriteInFlight = false;
|
|
21416
|
-
function log(tag, message) {
|
|
21417
|
-
if (process.env.ZLT_IPC_DEBUG_LOG !== "1")
|
|
21418
|
-
return;
|
|
21419
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString().substring(11, 23);
|
|
21420
|
-
pendingLogLines.push(`[${timestamp}][zltmcp][${tag}] ${message}
|
|
21421
|
-
`);
|
|
21422
|
-
flushLogQueue();
|
|
21451
|
+
throw new Error(`\u7B49\u5F85 ZLTAF \u7BA1\u9053\u8D85\u65F6: ${discoverPipePath(workRoot, "ZLTAF")}`);
|
|
21423
21452
|
}
|
|
21424
|
-
|
|
21425
|
-
|
|
21426
|
-
|
|
21427
|
-
|
|
21428
|
-
|
|
21429
|
-
|
|
21430
|
-
|
|
21431
|
-
|
|
21432
|
-
|
|
21433
|
-
|
|
21434
|
-
|
|
21435
|
-
logWriteInFlight = false;
|
|
21436
|
-
}
|
|
21453
|
+
|
|
21454
|
+
// ../zlt-runtime-core/dist/auth.js
|
|
21455
|
+
var fs7 = __toESM(require("fs"), 1);
|
|
21456
|
+
var os3 = __toESM(require("os"), 1);
|
|
21457
|
+
var path7 = __toESM(require("path"), 1);
|
|
21458
|
+
var DEFAULT_ZLTQUANT_API_BASE = "https://api.zltquant.com";
|
|
21459
|
+
function resolveZltQuantHome(env = process.env) {
|
|
21460
|
+
const configuredHome = env.ZLTQUANT_HOME?.trim();
|
|
21461
|
+
if (configuredHome)
|
|
21462
|
+
return expandHome(configuredHome);
|
|
21463
|
+
return path7.join(os3.homedir(), ".zltquant");
|
|
21437
21464
|
}
|
|
21438
|
-
function
|
|
21439
|
-
|
|
21465
|
+
function resolveCredentialsPath(env = process.env) {
|
|
21466
|
+
const configuredPath = env.ZLTQUANT_CREDENTIALS?.trim();
|
|
21467
|
+
if (configuredPath)
|
|
21468
|
+
return expandHome(configuredPath);
|
|
21469
|
+
return path7.join(resolveZltQuantHome(env), "credentials.json");
|
|
21440
21470
|
}
|
|
21441
|
-
|
|
21442
|
-
|
|
21443
|
-
|
|
21444
|
-
|
|
21445
|
-
|
|
21446
|
-
|
|
21447
|
-
|
|
21448
|
-
|
|
21449
|
-
|
|
21450
|
-
|
|
21471
|
+
function readCredentials(env = process.env) {
|
|
21472
|
+
const credentialsPath = resolveCredentialsPath(env);
|
|
21473
|
+
if (!fs7.existsSync(credentialsPath))
|
|
21474
|
+
return null;
|
|
21475
|
+
const parsed = JSON.parse(fs7.readFileSync(credentialsPath, "utf-8"));
|
|
21476
|
+
const apiKey = typeof parsed.apiKey === "string" ? parsed.apiKey.trim() : "";
|
|
21477
|
+
if (!apiKey)
|
|
21478
|
+
return null;
|
|
21479
|
+
return {
|
|
21480
|
+
apiKey,
|
|
21481
|
+
apiBase: typeof parsed.apiBase === "string" && parsed.apiBase.trim() ? parsed.apiBase.trim() : DEFAULT_ZLTQUANT_API_BASE,
|
|
21482
|
+
source: typeof parsed.source === "string" && parsed.source.trim() ? parsed.source.trim() : "file",
|
|
21483
|
+
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : ""
|
|
21484
|
+
};
|
|
21485
|
+
}
|
|
21486
|
+
function writeCredentialsFromEnv(env = process.env) {
|
|
21487
|
+
const apiKey = env.ZLTQUANT_API_KEY?.trim();
|
|
21488
|
+
if (!apiKey) {
|
|
21489
|
+
return getAuthStatus(env);
|
|
21451
21490
|
}
|
|
21452
|
-
|
|
21453
|
-
|
|
21454
|
-
|
|
21455
|
-
|
|
21456
|
-
|
|
21457
|
-
|
|
21458
|
-
|
|
21459
|
-
|
|
21460
|
-
|
|
21461
|
-
|
|
21462
|
-
|
|
21463
|
-
|
|
21464
|
-
|
|
21465
|
-
|
|
21466
|
-
|
|
21467
|
-
|
|
21468
|
-
this.connected = true;
|
|
21469
|
-
log("CONNECT", "IPC \u8FDE\u63A5\u5EFA\u7ACB\u5B8C\u6210");
|
|
21491
|
+
writeCredentials({
|
|
21492
|
+
apiKey,
|
|
21493
|
+
apiBase: env.ZLTQUANT_API_BASE,
|
|
21494
|
+
source: "trae-mcp"
|
|
21495
|
+
}, env);
|
|
21496
|
+
return getAuthStatus(env);
|
|
21497
|
+
}
|
|
21498
|
+
function writeCredentials(input, env = process.env) {
|
|
21499
|
+
const apiKey = input.apiKey.trim();
|
|
21500
|
+
const source = input.source.trim();
|
|
21501
|
+
if (!apiKey)
|
|
21502
|
+
throw new Error("ZLTQuant API key is required");
|
|
21503
|
+
if (!source)
|
|
21504
|
+
throw new Error("ZLTQuant credential source is required");
|
|
21505
|
+
if (env.ZLTQUANT_CREDENTIALS?.trim() && tryReadCredentials(env)) {
|
|
21506
|
+
return getAuthStatus(env);
|
|
21470
21507
|
}
|
|
21471
|
-
|
|
21472
|
-
|
|
21473
|
-
|
|
21474
|
-
|
|
21475
|
-
|
|
21476
|
-
|
|
21477
|
-
|
|
21478
|
-
|
|
21479
|
-
|
|
21480
|
-
|
|
21481
|
-
|
|
21482
|
-
|
|
21483
|
-
|
|
21484
|
-
|
|
21485
|
-
|
|
21486
|
-
|
|
21487
|
-
|
|
21488
|
-
if (colon > 0)
|
|
21489
|
-
request.headers.set(header.substring(0, colon), header.substring(colon + 1));
|
|
21490
|
-
}
|
|
21491
|
-
request.content = body;
|
|
21492
|
-
const bodyPreview = body.length > 200 ? `${body.substring(0, 200)}...` : body;
|
|
21493
|
-
log("REQ", `seq=${seq} uri=${fullUri} body=${bodyPreview} timeout=${timeout}`);
|
|
21494
|
-
const timer = setTimeout(() => {
|
|
21495
|
-
this.pendingRequests.delete(seq);
|
|
21496
|
-
log("REQ", `seq=${seq} \u8D85\u65F6 (timeout=${timeout}ms)`);
|
|
21497
|
-
reject(new Error(`RPC timeout for ${uri} (seq=${seq})`));
|
|
21498
|
-
}, timeout);
|
|
21499
|
-
this.pendingRequests.set(seq, { resolve: resolve9, reject, timer });
|
|
21500
|
-
this.workSocket.write(request.generatePacket());
|
|
21501
|
-
});
|
|
21508
|
+
const credentialsPath = resolveCredentialsPath(env);
|
|
21509
|
+
const credentials = {
|
|
21510
|
+
apiKey,
|
|
21511
|
+
apiBase: input.apiBase?.trim() || DEFAULT_ZLTQUANT_API_BASE,
|
|
21512
|
+
source,
|
|
21513
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
21514
|
+
};
|
|
21515
|
+
fs7.mkdirSync(path7.dirname(credentialsPath), { recursive: true });
|
|
21516
|
+
const tempPath = `${credentialsPath}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`;
|
|
21517
|
+
try {
|
|
21518
|
+
fs7.writeFileSync(tempPath, `${JSON.stringify(credentials, null, 2)}
|
|
21519
|
+
`, { encoding: "utf-8", mode: 384 });
|
|
21520
|
+
chmodOwnerOnly(tempPath);
|
|
21521
|
+
fs7.renameSync(tempPath, credentialsPath);
|
|
21522
|
+
chmodOwnerOnly(credentialsPath);
|
|
21523
|
+
} finally {
|
|
21524
|
+
fs7.rmSync(tempPath, { force: true });
|
|
21502
21525
|
}
|
|
21503
|
-
|
|
21504
|
-
|
|
21505
|
-
|
|
21506
|
-
|
|
21507
|
-
|
|
21508
|
-
|
|
21509
|
-
|
|
21510
|
-
|
|
21511
|
-
|
|
21512
|
-
|
|
21513
|
-
|
|
21514
|
-
|
|
21515
|
-
|
|
21516
|
-
|
|
21517
|
-
|
|
21518
|
-
|
|
21526
|
+
return fileAuthStatus(credentialsPath, resolveZltQuantHome(env), credentials);
|
|
21527
|
+
}
|
|
21528
|
+
function getAuthStatus(env = process.env) {
|
|
21529
|
+
const credentialsPath = resolveCredentialsPath(env);
|
|
21530
|
+
const zltquantHome = resolveZltQuantHome(env);
|
|
21531
|
+
const credentials = readCredentials(env);
|
|
21532
|
+
if (env.ZLTQUANT_CREDENTIALS?.trim() && credentials) {
|
|
21533
|
+
return {
|
|
21534
|
+
configured: true,
|
|
21535
|
+
source: "file",
|
|
21536
|
+
credentialsPath,
|
|
21537
|
+
zltquantHome,
|
|
21538
|
+
apiKeyMask: maskApiKey(credentials.apiKey),
|
|
21539
|
+
apiBase: credentials.apiBase,
|
|
21540
|
+
updatedAt: credentials.updatedAt
|
|
21541
|
+
};
|
|
21519
21542
|
}
|
|
21520
|
-
|
|
21521
|
-
|
|
21522
|
-
|
|
21523
|
-
|
|
21524
|
-
|
|
21525
|
-
|
|
21526
|
-
|
|
21527
|
-
|
|
21528
|
-
|
|
21529
|
-
|
|
21530
|
-
|
|
21531
|
-
this.workSocket.on("data", (data) => this.onData(data));
|
|
21532
|
-
this.workSocket.on("end", () => this.handleServerDisconnect("end"));
|
|
21533
|
-
this.workSocket.on("close", () => this.handleServerDisconnect("close"));
|
|
21534
|
-
});
|
|
21543
|
+
const envKey = env.ZLTQUANT_API_KEY?.trim();
|
|
21544
|
+
if (envKey) {
|
|
21545
|
+
return {
|
|
21546
|
+
configured: true,
|
|
21547
|
+
source: "env",
|
|
21548
|
+
credentialsPath,
|
|
21549
|
+
zltquantHome,
|
|
21550
|
+
apiKeyMask: maskApiKey(envKey),
|
|
21551
|
+
apiBase: env.ZLTQUANT_API_BASE?.trim() || DEFAULT_ZLTQUANT_API_BASE,
|
|
21552
|
+
updatedAt: ""
|
|
21553
|
+
};
|
|
21535
21554
|
}
|
|
21536
|
-
|
|
21537
|
-
|
|
21538
|
-
|
|
21539
|
-
|
|
21540
|
-
|
|
21541
|
-
|
|
21542
|
-
|
|
21543
|
-
|
|
21544
|
-
|
|
21545
|
-
}
|
|
21546
|
-
this.pendingRequests.clear();
|
|
21547
|
-
this.onDisconnect?.();
|
|
21555
|
+
if (credentials) {
|
|
21556
|
+
return {
|
|
21557
|
+
configured: true,
|
|
21558
|
+
source: "file",
|
|
21559
|
+
credentialsPath,
|
|
21560
|
+
zltquantHome,
|
|
21561
|
+
apiKeyMask: maskApiKey(credentials.apiKey),
|
|
21562
|
+
apiBase: credentials.apiBase,
|
|
21563
|
+
updatedAt: credentials.updatedAt
|
|
21564
|
+
};
|
|
21548
21565
|
}
|
|
21549
|
-
|
|
21550
|
-
|
|
21551
|
-
|
|
21552
|
-
|
|
21553
|
-
|
|
21554
|
-
|
|
21555
|
-
|
|
21556
|
-
|
|
21557
|
-
|
|
21558
|
-
|
|
21559
|
-
|
|
21560
|
-
|
|
21561
|
-
|
|
21562
|
-
|
|
21563
|
-
|
|
21564
|
-
|
|
21565
|
-
|
|
21566
|
-
|
|
21567
|
-
|
|
21568
|
-
|
|
21569
|
-
|
|
21570
|
-
|
|
21571
|
-
|
|
21572
|
-
reject(error2);
|
|
21573
|
-
});
|
|
21574
|
-
});
|
|
21566
|
+
return {
|
|
21567
|
+
configured: false,
|
|
21568
|
+
source: "missing",
|
|
21569
|
+
credentialsPath,
|
|
21570
|
+
zltquantHome,
|
|
21571
|
+
apiKeyMask: "",
|
|
21572
|
+
apiBase: env.ZLTQUANT_API_BASE?.trim() || DEFAULT_ZLTQUANT_API_BASE,
|
|
21573
|
+
updatedAt: ""
|
|
21574
|
+
};
|
|
21575
|
+
}
|
|
21576
|
+
function maskApiKey(apiKey) {
|
|
21577
|
+
const trimmed = apiKey.trim();
|
|
21578
|
+
if (!trimmed)
|
|
21579
|
+
return "";
|
|
21580
|
+
if (trimmed.length <= 8)
|
|
21581
|
+
return `****${trimmed.slice(-2)}`;
|
|
21582
|
+
return `${trimmed.slice(0, 4)}...${trimmed.slice(-4)}`;
|
|
21583
|
+
}
|
|
21584
|
+
function expandHome(input) {
|
|
21585
|
+
if (input === "~")
|
|
21586
|
+
return os3.homedir();
|
|
21587
|
+
if (input.startsWith("~/") || input.startsWith("~\\")) {
|
|
21588
|
+
return path7.join(os3.homedir(), input.slice(2));
|
|
21575
21589
|
}
|
|
21576
|
-
|
|
21577
|
-
|
|
21578
|
-
|
|
21579
|
-
|
|
21580
|
-
|
|
21581
|
-
|
|
21582
|
-
|
|
21583
|
-
const seq = packet.headers.get("Content-SEQ");
|
|
21584
|
-
if (seq) {
|
|
21585
|
-
const pending = this.pendingRequests.get(seq);
|
|
21586
|
-
if (pending) {
|
|
21587
|
-
clearTimeout(pending.timer);
|
|
21588
|
-
this.pendingRequests.delete(seq);
|
|
21589
|
-
const preview = packet.content.length > 300 ? `${packet.content.substring(0, 300)}... (${packet.contentLength} bytes)` : packet.content;
|
|
21590
|
-
log("RESP", `seq=${seq} status=${packet.statusCode} content=${preview}`);
|
|
21591
|
-
pending.resolve(packet);
|
|
21592
|
-
} else {
|
|
21593
|
-
log("RESP", `seq=${seq} status=${packet.statusCode} (\u65E0\u5339\u914D\u8BF7\u6C42\uFF0C\u4E22\u5F03)`);
|
|
21594
|
-
}
|
|
21595
|
-
} else {
|
|
21596
|
-
log("PUSH", `status=${packet.statusCode} content=${packet.content.substring(0, 200)}`);
|
|
21597
|
-
}
|
|
21598
|
-
}
|
|
21590
|
+
return path7.resolve(input);
|
|
21591
|
+
}
|
|
21592
|
+
function tryReadCredentials(env) {
|
|
21593
|
+
try {
|
|
21594
|
+
return readCredentials(env);
|
|
21595
|
+
} catch {
|
|
21596
|
+
return null;
|
|
21599
21597
|
}
|
|
21600
|
-
}
|
|
21598
|
+
}
|
|
21599
|
+
function chmodOwnerOnly(filePath) {
|
|
21600
|
+
try {
|
|
21601
|
+
fs7.chmodSync(filePath, 384);
|
|
21602
|
+
} catch {
|
|
21603
|
+
}
|
|
21604
|
+
}
|
|
21605
|
+
function fileAuthStatus(credentialsPath, zltquantHome, credentials) {
|
|
21606
|
+
return {
|
|
21607
|
+
configured: true,
|
|
21608
|
+
source: "file",
|
|
21609
|
+
credentialsPath,
|
|
21610
|
+
zltquantHome,
|
|
21611
|
+
apiKeyMask: maskApiKey(credentials.apiKey),
|
|
21612
|
+
apiBase: credentials.apiBase,
|
|
21613
|
+
updatedAt: credentials.updatedAt
|
|
21614
|
+
};
|
|
21615
|
+
}
|
|
21601
21616
|
|
|
21602
21617
|
// src/config.ts
|
|
21603
|
-
var config_exports = {};
|
|
21604
|
-
__export(config_exports, {
|
|
21605
|
-
discoverPipePath: () => discoverPipePath,
|
|
21606
|
-
loadConfig: () => loadConfig,
|
|
21607
|
-
matchingPipeNames: () => matchingPipeNames2,
|
|
21608
|
-
resolveDefaultConfigPath: () => resolveDefaultConfigPath,
|
|
21609
|
-
resolveDefaultRuntimeConfigPath: () => resolveDefaultRuntimeConfigPath
|
|
21610
|
-
});
|
|
21611
|
-
var fs8 = __toESM(require("fs"), 1);
|
|
21612
|
-
var path8 = __toESM(require("path"), 1);
|
|
21613
21618
|
function loadConfig(configPath) {
|
|
21614
21619
|
const raw = fs8.readFileSync(configPath, "utf-8");
|
|
21615
21620
|
return JSON.parse(raw);
|
|
@@ -21671,18 +21676,6 @@ function hasHighBytes(str) {
|
|
|
21671
21676
|
var { loadConfig: loadConfig2, discoverPipePath: discoverPipePath2 } = config_exports;
|
|
21672
21677
|
var RESPONSE_FILE_THRESHOLD = 1024;
|
|
21673
21678
|
var HISTORY_MAX_LINES = 1e3;
|
|
21674
|
-
var KEEPALIVE_READY_TIMEOUT_MS = 3e4;
|
|
21675
|
-
var KEEPALIVE_READY_POLL_MS = 50;
|
|
21676
|
-
var KEEPALIVE_RETRY_MS = 2e3;
|
|
21677
|
-
var KEEPALIVE_LOCK_INIT_RETRY_MS = 10;
|
|
21678
|
-
var KEEPALIVE_LOCK_INIT_RETRIES = 5;
|
|
21679
|
-
var KEEPALIVE_HEARTBEAT_INTERVAL_MS = 1e4;
|
|
21680
|
-
var KEEPALIVE_HEARTBEAT_LEASE_MS = 6e4;
|
|
21681
|
-
var KEEPALIVE_CLOCK_SKEW_MS = 5e3;
|
|
21682
|
-
var KEEPALIVE_LOCK_PATH_ENV = "ZLT_MCP_KEEPALIVE_LOCK_PATH";
|
|
21683
|
-
var KEEPALIVE_LOCK_TOKEN_ENV = "ZLT_MCP_KEEPALIVE_LOCK_TOKEN";
|
|
21684
|
-
var KEEPALIVE_ATTEMPT_STARTED_AT_ENV = "ZLT_MCP_KEEPALIVE_ATTEMPT_STARTED_AT_MS";
|
|
21685
|
-
var KEEPALIVE_RESULT_BASELINE_ENV = "ZLT_MCP_KEEPALIVE_RESULT_BASELINE";
|
|
21686
21679
|
var ASYNC_BACKTEST_TOOLS = /* @__PURE__ */ new Set(["mcp-create-and-run-backtest", "mcp-re-backtest"]);
|
|
21687
21680
|
function getOutputDir(clientRootDir) {
|
|
21688
21681
|
const root = clientRootDir.replace(/\/+$/, "");
|
|
@@ -21891,7 +21884,7 @@ function parseMcpResult(result) {
|
|
|
21891
21884
|
}
|
|
21892
21885
|
}
|
|
21893
21886
|
function backtestHandoff(result) {
|
|
21894
|
-
if (result.isError === true) return null;
|
|
21887
|
+
if (result.isError === true || (mcpErrorCode(result) ?? 0) !== 0) return null;
|
|
21895
21888
|
const payload = parseMcpResult(result);
|
|
21896
21889
|
const data = payload?.Data;
|
|
21897
21890
|
if (!data || typeof data !== "object" || Array.isArray(data)) return null;
|
|
@@ -21904,394 +21897,59 @@ function backtestHandoff(result) {
|
|
|
21904
21897
|
const rawCodePath = typeof record3.codePath === "string" ? record3.codePath.trim() : typeof evidence?.runDir === "string" ? evidence.runDir.trim() : "";
|
|
21905
21898
|
return {
|
|
21906
21899
|
runId,
|
|
21907
|
-
...rawCodePath && path9.isAbsolute(rawCodePath) ? { codePath: rawCodePath } : {}
|
|
21900
|
+
...rawCodePath && path9.isAbsolute(rawCodePath) ? { codePath: rawCodePath } : {},
|
|
21901
|
+
...record3.attemptFence !== void 0 ? { attemptFence: record3.attemptFence } : {}
|
|
21908
21902
|
};
|
|
21909
21903
|
}
|
|
21910
|
-
function keepaliveLockPath(runId) {
|
|
21911
|
-
const runKey = (0, import_crypto4.createHash)("sha256").update(runId).digest("hex");
|
|
21912
|
-
return path9.join(os4.tmpdir(), `zlt-mcp-keepalive-${runKey}.lock`);
|
|
21913
|
-
}
|
|
21914
|
-
function parseKeepaliveLockRecord(raw) {
|
|
21915
|
-
try {
|
|
21916
|
-
const parsed = JSON.parse(raw.toString("utf-8"));
|
|
21917
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
21918
|
-
const record3 = parsed;
|
|
21919
|
-
const processIdentity = parseRuntimeProcessIdentity(record3.processIdentity);
|
|
21920
|
-
return typeof record3.token === "string" && record3.token.length > 0 && Number.isSafeInteger(record3.pid) && Number(record3.pid) > 0 && processIdentity?.pid === Number(record3.pid) && Number.isSafeInteger(record3.heartbeatAt) && Number(record3.heartbeatAt) > 0 ? {
|
|
21921
|
-
token: record3.token,
|
|
21922
|
-
pid: Number(record3.pid),
|
|
21923
|
-
processIdentity,
|
|
21924
|
-
heartbeatAt: Number(record3.heartbeatAt)
|
|
21925
|
-
} : null;
|
|
21926
|
-
} catch {
|
|
21927
|
-
return null;
|
|
21928
|
-
}
|
|
21929
|
-
}
|
|
21930
|
-
function parseRuntimeProcessIdentity(value) {
|
|
21931
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
21932
|
-
const record3 = value;
|
|
21933
|
-
return Number.isSafeInteger(record3.pid) && Number(record3.pid) > 0 && typeof record3.executablePath === "string" && record3.executablePath.length > 0 && typeof record3.creationTime === "string" && record3.creationTime.length > 0 ? {
|
|
21934
|
-
pid: Number(record3.pid),
|
|
21935
|
-
executablePath: record3.executablePath,
|
|
21936
|
-
creationTime: record3.creationTime
|
|
21937
|
-
} : null;
|
|
21938
|
-
}
|
|
21939
|
-
function readKeepaliveLock(lockPath) {
|
|
21940
|
-
try {
|
|
21941
|
-
const before = fs9.statSync(lockPath);
|
|
21942
|
-
const raw = fs9.readFileSync(lockPath);
|
|
21943
|
-
const after = fs9.statSync(lockPath);
|
|
21944
|
-
if (before.mtimeMs !== after.mtimeMs || before.size !== after.size) return null;
|
|
21945
|
-
return {
|
|
21946
|
-
record: parseKeepaliveLockRecord(raw),
|
|
21947
|
-
identity: {
|
|
21948
|
-
sha256: (0, import_crypto4.createHash)("sha256").update(raw).digest("hex"),
|
|
21949
|
-
mtimeMs: after.mtimeMs,
|
|
21950
|
-
size: after.size
|
|
21951
|
-
}
|
|
21952
|
-
};
|
|
21953
|
-
} catch {
|
|
21954
|
-
return null;
|
|
21955
|
-
}
|
|
21956
|
-
}
|
|
21957
|
-
function sameFileIdentity(left, right) {
|
|
21958
|
-
return left.sha256 === right.sha256 && left.mtimeMs === right.mtimeMs && left.size === right.size;
|
|
21959
|
-
}
|
|
21960
|
-
function processIsAlive(pid) {
|
|
21961
|
-
try {
|
|
21962
|
-
process.kill(pid, 0);
|
|
21963
|
-
return true;
|
|
21964
|
-
} catch (error2) {
|
|
21965
|
-
const code = error2.code;
|
|
21966
|
-
if (code === "ESRCH") return false;
|
|
21967
|
-
return true;
|
|
21968
|
-
}
|
|
21969
|
-
}
|
|
21970
|
-
function sameProcessIdentity(left, right) {
|
|
21971
|
-
return left.pid === right.pid && path9.resolve(left.executablePath).toLowerCase() === path9.resolve(right.executablePath).toLowerCase() && left.creationTime === right.creationTime;
|
|
21972
|
-
}
|
|
21973
|
-
function currentKeepaliveProcessIdentity() {
|
|
21974
|
-
const identity = inspectRuntimeProcess(process.pid);
|
|
21975
|
-
if (!identity) throw new Error(`Unable to identify keepalive process pid=${process.pid}`);
|
|
21976
|
-
return identity;
|
|
21977
|
-
}
|
|
21978
|
-
function keepaliveProcessIsCurrent(record3) {
|
|
21979
|
-
if (!processIsAlive(record3.pid)) return false;
|
|
21980
|
-
const current = inspectRuntimeProcess(record3.pid);
|
|
21981
|
-
return current ? sameProcessIdentity(current, record3.processIdentity) : true;
|
|
21982
|
-
}
|
|
21983
|
-
function writeNewKeepaliveLock(lockPath, record3) {
|
|
21984
|
-
const descriptor = fs9.openSync(lockPath, "wx", 384);
|
|
21985
|
-
try {
|
|
21986
|
-
fs9.writeFileSync(descriptor, JSON.stringify(record3), "utf-8");
|
|
21987
|
-
} finally {
|
|
21988
|
-
fs9.closeSync(descriptor);
|
|
21989
|
-
}
|
|
21990
|
-
}
|
|
21991
|
-
function updateKeepaliveLockIfOwned(ownership) {
|
|
21992
|
-
let descriptor;
|
|
21993
|
-
try {
|
|
21994
|
-
descriptor = fs9.openSync(ownership.lockPath, "r+");
|
|
21995
|
-
const current = parseKeepaliveLockRecord(fs9.readFileSync(descriptor));
|
|
21996
|
-
if (current?.token !== ownership.token) return false;
|
|
21997
|
-
const encoded = Buffer.from(JSON.stringify({
|
|
21998
|
-
token: ownership.token,
|
|
21999
|
-
pid: ownership.processIdentity.pid,
|
|
22000
|
-
processIdentity: ownership.processIdentity,
|
|
22001
|
-
heartbeatAt: Date.now()
|
|
22002
|
-
}), "utf-8");
|
|
22003
|
-
fs9.ftruncateSync(descriptor, 0);
|
|
22004
|
-
fs9.writeSync(descriptor, encoded, 0, encoded.length, 0);
|
|
22005
|
-
fs9.fsyncSync(descriptor);
|
|
22006
|
-
const published = readKeepaliveLock(ownership.lockPath)?.record;
|
|
22007
|
-
return published?.token === ownership.token && sameProcessIdentity(published.processIdentity, ownership.processIdentity);
|
|
22008
|
-
} catch {
|
|
22009
|
-
return false;
|
|
22010
|
-
} finally {
|
|
22011
|
-
if (descriptor !== void 0) fs9.closeSync(descriptor);
|
|
22012
|
-
}
|
|
22013
|
-
}
|
|
22014
|
-
function restoreMovedKeepaliveLock(movedPath, lockPath) {
|
|
22015
|
-
let restored = false;
|
|
22016
|
-
try {
|
|
22017
|
-
fs9.linkSync(movedPath, lockPath);
|
|
22018
|
-
restored = true;
|
|
22019
|
-
} catch (error2) {
|
|
22020
|
-
if (error2.code === "EEXIST") {
|
|
22021
|
-
restored = true;
|
|
22022
|
-
} else {
|
|
22023
|
-
try {
|
|
22024
|
-
fs9.copyFileSync(movedPath, lockPath, fs9.constants.COPYFILE_EXCL);
|
|
22025
|
-
restored = true;
|
|
22026
|
-
} catch (restoreError) {
|
|
22027
|
-
if (restoreError.code === "EEXIST") restored = true;
|
|
22028
|
-
}
|
|
22029
|
-
}
|
|
22030
|
-
}
|
|
22031
|
-
if (restored) {
|
|
22032
|
-
fs9.rmSync(movedPath, { force: true });
|
|
22033
|
-
}
|
|
22034
|
-
}
|
|
22035
|
-
function retireKeepaliveLockIfUnchanged(lockPath, expected) {
|
|
22036
|
-
const movedPath = `${lockPath}.${process.pid}.${(0, import_crypto4.randomUUID)()}.retired`;
|
|
22037
|
-
try {
|
|
22038
|
-
fs9.renameSync(lockPath, movedPath);
|
|
22039
|
-
} catch (error2) {
|
|
22040
|
-
if (error2.code === "ENOENT") return false;
|
|
22041
|
-
throw error2;
|
|
22042
|
-
}
|
|
22043
|
-
const moved = readKeepaliveLock(movedPath);
|
|
22044
|
-
if (!moved || !sameFileIdentity(moved.identity, expected)) {
|
|
22045
|
-
restoreMovedKeepaliveLock(movedPath, lockPath);
|
|
22046
|
-
return false;
|
|
22047
|
-
}
|
|
22048
|
-
fs9.rmSync(movedPath, { force: true });
|
|
22049
|
-
return true;
|
|
22050
|
-
}
|
|
22051
|
-
function releaseKeepaliveLock(ownership) {
|
|
22052
|
-
const current = readKeepaliveLock(ownership.lockPath);
|
|
22053
|
-
if (current?.record?.token === ownership.token) {
|
|
22054
|
-
retireKeepaliveLockIfUnchanged(ownership.lockPath, current.identity);
|
|
22055
|
-
}
|
|
22056
|
-
}
|
|
22057
|
-
function keepaliveLeaseIsFresh(record3) {
|
|
22058
|
-
return keepaliveTimestampIsFresh(record3.heartbeatAt);
|
|
22059
|
-
}
|
|
22060
|
-
function keepaliveTimestampIsFresh(timestamp) {
|
|
22061
|
-
const age = Date.now() - timestamp;
|
|
22062
|
-
return age >= -KEEPALIVE_CLOCK_SKEW_MS && age <= KEEPALIVE_HEARTBEAT_LEASE_MS;
|
|
22063
|
-
}
|
|
22064
|
-
async function claimKeepaliveLock(runId) {
|
|
22065
|
-
const lockPath = keepaliveLockPath(runId);
|
|
22066
|
-
const processIdentity = currentKeepaliveProcessIdentity();
|
|
22067
|
-
const ownership = { lockPath, token: (0, import_crypto4.randomUUID)(), processIdentity };
|
|
22068
|
-
let incompleteReads = 0;
|
|
22069
|
-
for (; ; ) {
|
|
22070
|
-
try {
|
|
22071
|
-
writeNewKeepaliveLock(lockPath, {
|
|
22072
|
-
token: ownership.token,
|
|
22073
|
-
pid: processIdentity.pid,
|
|
22074
|
-
processIdentity,
|
|
22075
|
-
heartbeatAt: Date.now()
|
|
22076
|
-
});
|
|
22077
|
-
return ownership;
|
|
22078
|
-
} catch (error2) {
|
|
22079
|
-
if (error2.code !== "EEXIST") throw error2;
|
|
22080
|
-
const existing = readKeepaliveLock(lockPath);
|
|
22081
|
-
if (existing?.record && keepaliveLeaseIsFresh(existing.record) && keepaliveProcessIsCurrent(existing.record)) return null;
|
|
22082
|
-
if ((!existing || !existing.record) && incompleteReads < KEEPALIVE_LOCK_INIT_RETRIES) {
|
|
22083
|
-
incompleteReads += 1;
|
|
22084
|
-
await new Promise((resolve9) => setTimeout(resolve9, KEEPALIVE_LOCK_INIT_RETRY_MS));
|
|
22085
|
-
continue;
|
|
22086
|
-
}
|
|
22087
|
-
if (!existing || !existing.record && keepaliveTimestampIsFresh(existing.identity.mtimeMs)) return null;
|
|
22088
|
-
if (!existing || !retireKeepaliveLockIfUnchanged(lockPath, existing.identity)) continue;
|
|
22089
|
-
incompleteReads = 0;
|
|
22090
|
-
}
|
|
22091
|
-
}
|
|
22092
|
-
}
|
|
22093
|
-
function adoptKeepaliveLock(runId) {
|
|
22094
|
-
const rawLockPath = process.env[KEEPALIVE_LOCK_PATH_ENV]?.trim();
|
|
22095
|
-
const token = process.env[KEEPALIVE_LOCK_TOKEN_ENV]?.trim();
|
|
22096
|
-
if (!rawLockPath && !token) return void 0;
|
|
22097
|
-
if (!rawLockPath || !token) return null;
|
|
22098
|
-
const lockPath = path9.resolve(rawLockPath);
|
|
22099
|
-
if (lockPath !== path9.resolve(keepaliveLockPath(runId))) return null;
|
|
22100
|
-
const ownership = { lockPath, token, processIdentity: currentKeepaliveProcessIdentity() };
|
|
22101
|
-
return updateKeepaliveLockIfOwned(ownership) ? ownership : null;
|
|
22102
|
-
}
|
|
22103
|
-
async function waitForKeepaliveProcessIdentity(pid) {
|
|
22104
|
-
const deadline = Date.now() + KEEPALIVE_READY_TIMEOUT_MS;
|
|
22105
|
-
while (Date.now() < deadline) {
|
|
22106
|
-
const identity = inspectRuntimeProcess(pid);
|
|
22107
|
-
if (identity) return identity;
|
|
22108
|
-
await new Promise((resolve9) => setTimeout(resolve9, KEEPALIVE_READY_POLL_MS));
|
|
22109
|
-
}
|
|
22110
|
-
return null;
|
|
22111
|
-
}
|
|
22112
|
-
function waitForKeepaliveReady(readyFile, child) {
|
|
22113
|
-
const startedAt = Date.now();
|
|
22114
|
-
return new Promise((resolve9, reject) => {
|
|
22115
|
-
const poll = () => {
|
|
22116
|
-
if (fs9.existsSync(readyFile)) {
|
|
22117
|
-
resolve9();
|
|
22118
|
-
return;
|
|
22119
|
-
}
|
|
22120
|
-
if (child.exitCode !== null) {
|
|
22121
|
-
reject(new Error(`runtime keepalive exited before handoff (exit=${child.exitCode})`));
|
|
22122
|
-
return;
|
|
22123
|
-
}
|
|
22124
|
-
if (Date.now() - startedAt >= KEEPALIVE_READY_TIMEOUT_MS) {
|
|
22125
|
-
child.kill();
|
|
22126
|
-
reject(new Error("runtime keepalive did not accept the handoff within 30 seconds"));
|
|
22127
|
-
return;
|
|
22128
|
-
}
|
|
22129
|
-
setTimeout(poll, KEEPALIVE_READY_POLL_MS).unref();
|
|
22130
|
-
};
|
|
22131
|
-
poll();
|
|
22132
|
-
});
|
|
22133
|
-
}
|
|
22134
|
-
async function handoffBacktestKeepalive(entrypoint, runId, codePath, attemptFence) {
|
|
22135
|
-
const ownership = await claimKeepaliveLock(runId);
|
|
22136
|
-
if (!ownership) return;
|
|
22137
|
-
const readyFile = path9.join(os4.tmpdir(), `zlt-mcp-keepalive-${process.pid}-${(0, import_crypto4.randomUUID)()}.ready`);
|
|
22138
|
-
const childArgs = [entrypoint, "__keepalive", "backtest", runId];
|
|
22139
|
-
if (codePath) childArgs.push(codePath);
|
|
22140
|
-
try {
|
|
22141
|
-
const child = (0, import_child_process4.spawn)(process.execPath, childArgs, {
|
|
22142
|
-
detached: true,
|
|
22143
|
-
stdio: "ignore",
|
|
22144
|
-
windowsHide: true,
|
|
22145
|
-
env: {
|
|
22146
|
-
...process.env,
|
|
22147
|
-
ZLT_MCP_KEEPALIVE_READY_FILE: readyFile,
|
|
22148
|
-
[KEEPALIVE_LOCK_PATH_ENV]: ownership.lockPath,
|
|
22149
|
-
[KEEPALIVE_LOCK_TOKEN_ENV]: ownership.token,
|
|
22150
|
-
...attemptFence ? { [KEEPALIVE_ATTEMPT_STARTED_AT_ENV]: String(attemptFence.attemptStartedAtMs) } : {},
|
|
22151
|
-
...attemptFence?.resultBaseline ? { [KEEPALIVE_RESULT_BASELINE_ENV]: JSON.stringify(attemptFence.resultBaseline) } : {}
|
|
22152
|
-
}
|
|
22153
|
-
});
|
|
22154
|
-
if (!child.pid) throw new Error("runtime keepalive process did not return a PID");
|
|
22155
|
-
const childIdentity = await waitForKeepaliveProcessIdentity(child.pid);
|
|
22156
|
-
const childOwnership = childIdentity ? { ...ownership, processIdentity: childIdentity } : null;
|
|
22157
|
-
if (!childOwnership || !updateKeepaliveLockIfOwned(childOwnership)) {
|
|
22158
|
-
child.kill();
|
|
22159
|
-
return;
|
|
22160
|
-
}
|
|
22161
|
-
child.unref();
|
|
22162
|
-
await waitForKeepaliveReady(readyFile, child);
|
|
22163
|
-
} catch (error2) {
|
|
22164
|
-
releaseKeepaliveLock(ownership);
|
|
22165
|
-
throw error2;
|
|
22166
|
-
} finally {
|
|
22167
|
-
fs9.rmSync(readyFile, { force: true });
|
|
22168
|
-
}
|
|
22169
|
-
}
|
|
22170
|
-
function backtestStatus(result) {
|
|
22171
|
-
const payload = parseMcpResult(result);
|
|
22172
|
-
const data = payload?.Data;
|
|
22173
|
-
if (!data || typeof data !== "object" || Array.isArray(data)) return null;
|
|
22174
|
-
const status = Number(data.status);
|
|
22175
|
-
return Number.isFinite(status) ? status : null;
|
|
22176
|
-
}
|
|
22177
21904
|
function mcpErrorCode(result) {
|
|
22178
21905
|
const payload = parseMcpResult(result);
|
|
22179
21906
|
const code = Number(payload?.ErrNo);
|
|
22180
21907
|
return Number.isFinite(code) ? code : null;
|
|
22181
21908
|
}
|
|
22182
|
-
|
|
22183
|
-
|
|
22184
|
-
|
|
22185
|
-
|
|
22186
|
-
|
|
22187
|
-
const
|
|
22188
|
-
|
|
22189
|
-
}
|
|
22190
|
-
|
|
22191
|
-
|
|
22192
|
-
|
|
22193
|
-
|
|
22194
|
-
|
|
22195
|
-
|
|
22196
|
-
|
|
22197
|
-
|
|
22198
|
-
}
|
|
22199
|
-
|
|
22200
|
-
|
|
22201
|
-
|
|
22202
|
-
|
|
22203
|
-
|
|
22204
|
-
|
|
22205
|
-
|
|
22206
|
-
|
|
22207
|
-
|
|
22208
|
-
|
|
22209
|
-
|
|
22210
|
-
|
|
22211
|
-
|
|
22212
|
-
|
|
22213
|
-
|
|
22214
|
-
|
|
22215
|
-
}
|
|
22216
|
-
|
|
22217
|
-
|
|
22218
|
-
|
|
22219
|
-
|
|
22220
|
-
|
|
22221
|
-
|
|
22222
|
-
};
|
|
22223
|
-
|
|
22224
|
-
|
|
22225
|
-
|
|
22226
|
-
if (ownership === null) return;
|
|
22227
|
-
const attemptStartedAtMs = parseAttemptStartedAt(process.env[KEEPALIVE_ATTEMPT_STARTED_AT_ENV]);
|
|
22228
|
-
const resultBaseline = parseResultBaseline(process.env[KEEPALIVE_RESULT_BASELINE_ENV]);
|
|
22229
|
-
let ownershipCurrent = true;
|
|
22230
|
-
const heartbeat = ownership ? setInterval(() => {
|
|
22231
|
-
ownershipCurrent = updateKeepaliveLockIfOwned(ownership);
|
|
22232
|
-
}, KEEPALIVE_HEARTBEAT_INTERVAL_MS) : void 0;
|
|
22233
|
-
heartbeat?.unref();
|
|
22234
|
-
try {
|
|
22235
|
-
for (; ; ) {
|
|
22236
|
-
if (!ownershipCurrent) return;
|
|
22237
|
-
const { client, transport } = createMcpClient(options);
|
|
22238
|
-
try {
|
|
22239
|
-
await client.connect(transport);
|
|
22240
|
-
const result = await client.callTool(
|
|
22241
|
-
{
|
|
22242
|
-
name: "mcp-wait",
|
|
22243
|
-
arguments: {
|
|
22244
|
-
kind: "backtest",
|
|
22245
|
-
id: runId,
|
|
22246
|
-
...codePath ? { codePath } : {},
|
|
22247
|
-
...attemptStartedAtMs ? { __attemptStartedAtMs: attemptStartedAtMs } : {},
|
|
22248
|
-
...resultBaseline ? { __resultBaseline: resultBaseline } : {}
|
|
22249
|
-
}
|
|
22250
|
-
},
|
|
22251
|
-
void 0,
|
|
22252
|
-
{
|
|
22253
|
-
timeout: options.timeoutMs ?? 6e4,
|
|
22254
|
-
maxTotalTimeout: options.maxTotalTimeoutMs,
|
|
22255
|
-
resetTimeoutOnProgress: true,
|
|
22256
|
-
// Always attach a progress receiver: mcp-wait intentionally rejects
|
|
22257
|
-
// clients without a progress token, even when diagnostics are hidden.
|
|
22258
|
-
onprogress: () => void 0
|
|
22259
|
-
}
|
|
22260
|
-
);
|
|
22261
|
-
const payload = parseMcpResult(result);
|
|
22262
|
-
const errorCode = mcpErrorCode(result);
|
|
22263
|
-
if (result.isError === true || errorCode !== null && errorCode !== 0) {
|
|
22264
|
-
if (errorCode === 10048) {
|
|
22265
|
-
await keepaliveDelay();
|
|
22266
|
-
continue;
|
|
22267
|
-
}
|
|
22268
|
-
return;
|
|
22269
|
-
}
|
|
22270
|
-
const data = payload?.Data;
|
|
22271
|
-
if (data && typeof data === "object" && !Array.isArray(data) && data.waitStopped === "no-progress") {
|
|
22272
|
-
continue;
|
|
22273
|
-
}
|
|
22274
|
-
const status = backtestStatus(result);
|
|
22275
|
-
if (status === 0 || status === 1) {
|
|
22276
|
-
continue;
|
|
22277
|
-
}
|
|
22278
|
-
if (status !== null) return;
|
|
22279
|
-
throw new Error("runtime keepalive received an unreadable backtest state");
|
|
22280
|
-
} catch (error2) {
|
|
22281
|
-
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
22282
|
-
if (/connection|transport|pipe|disconnect|closed|timeout|request/i.test(message)) {
|
|
22283
|
-
await keepaliveDelay();
|
|
22284
|
-
continue;
|
|
22285
|
-
}
|
|
22286
|
-
throw error2;
|
|
22287
|
-
} finally {
|
|
22288
|
-
await client.close().catch(() => void 0);
|
|
22289
|
-
}
|
|
22290
|
-
}
|
|
22291
|
-
} finally {
|
|
22292
|
-
if (heartbeat) clearInterval(heartbeat);
|
|
22293
|
-
if (ownership) releaseKeepaliveLock(ownership);
|
|
22294
|
-
}
|
|
21909
|
+
function mergeBacktestWait(launched, waited, handoff) {
|
|
21910
|
+
const launchPayload = parseMcpResult(launched);
|
|
21911
|
+
const waitPayload = parseMcpResult(waited);
|
|
21912
|
+
if (!waitPayload) throw new Error("Backtest wait returned an unreadable response");
|
|
21913
|
+
const data = waitPayload.Data && typeof waitPayload.Data === "object" && !Array.isArray(waitPayload.Data) ? waitPayload.Data : {};
|
|
21914
|
+
for (const id of [data.runId, data.backtestId]) {
|
|
21915
|
+
if (id !== void 0 && id !== handoff.runId) throw new Error("Backtest wait returned a different run ID");
|
|
21916
|
+
}
|
|
21917
|
+
if (data.codePath !== void 0 && handoff.codePath && (typeof data.codePath !== "string" || path9.resolve(data.codePath).toLowerCase() !== path9.resolve(handoff.codePath).toLowerCase())) {
|
|
21918
|
+
throw new Error("Backtest wait returned a different run directory");
|
|
21919
|
+
}
|
|
21920
|
+
const status = typeof data.status === "number" || typeof data.status === "string" && data.status.trim() ? Number(data.status) : NaN;
|
|
21921
|
+
const terminal = [2, 3, 4, 5].includes(status) && data.isTerminal === true;
|
|
21922
|
+
const paused = [0, 1].includes(status) && data.waitStopped === "no-progress" && data.isTerminal !== true;
|
|
21923
|
+
if (waited.isError !== true && (mcpErrorCode(waited) ?? 0) === 0 && !terminal && !paused) {
|
|
21924
|
+
throw new Error("Backtest wait returned neither a terminal state nor an actionable pause");
|
|
21925
|
+
}
|
|
21926
|
+
const context = { ...launchPayload.Data };
|
|
21927
|
+
for (const key of [
|
|
21928
|
+
"status",
|
|
21929
|
+
"progress",
|
|
21930
|
+
"isTerminal",
|
|
21931
|
+
"backtestOutcome",
|
|
21932
|
+
"nextAction",
|
|
21933
|
+
"waitStopped",
|
|
21934
|
+
"pollingStopped",
|
|
21935
|
+
"evidenceSource",
|
|
21936
|
+
"failureCause",
|
|
21937
|
+
"error_code",
|
|
21938
|
+
"error_msg",
|
|
21939
|
+
"action",
|
|
21940
|
+
"userAction"
|
|
21941
|
+
]) delete context[key];
|
|
21942
|
+
const mergedData = { ...context, ...handoff, ...data };
|
|
21943
|
+
if (context.evidence && typeof context.evidence === "object" && !Array.isArray(context.evidence) && data.evidence && typeof data.evidence === "object" && !Array.isArray(data.evidence)) {
|
|
21944
|
+
mergedData.evidence = { ...context.evidence, ...data.evidence };
|
|
21945
|
+
}
|
|
21946
|
+
const payload = { ...waitPayload, Data: mergedData };
|
|
21947
|
+
const content = Array.isArray(waited.content) ? [...waited.content] : [];
|
|
21948
|
+
const textIndex = content.findIndex((item) => item && typeof item === "object" && item.type === "text");
|
|
21949
|
+
const text = { type: "text", text: JSON.stringify(payload) };
|
|
21950
|
+
if (textIndex < 0) content.push(text);
|
|
21951
|
+
else content[textIndex] = text;
|
|
21952
|
+
return { ...waited, content, ...waited.structuredContent ? { structuredContent: payload } : {} };
|
|
22295
21953
|
}
|
|
22296
21954
|
async function callMcpTool(name, args = {}, options = {}) {
|
|
22297
21955
|
const { client, transport } = createMcpClient(options);
|
|
@@ -22299,31 +21957,85 @@ async function callMcpTool(name, args = {}, options = {}) {
|
|
|
22299
21957
|
await client.connect(transport);
|
|
22300
21958
|
const timeout = options.timeoutMs ?? 6e4;
|
|
22301
21959
|
const showProgress = options.showProgress !== false;
|
|
22302
|
-
const
|
|
22303
|
-
|
|
22304
|
-
|
|
22305
|
-
|
|
22306
|
-
|
|
22307
|
-
|
|
22308
|
-
|
|
22309
|
-
|
|
22310
|
-
|
|
22311
|
-
|
|
22312
|
-
|
|
22313
|
-
|
|
22314
|
-
|
|
22315
|
-
|
|
21960
|
+
const startedAt = Date.now();
|
|
21961
|
+
let lastProgressMessage;
|
|
21962
|
+
const requestOptions = {
|
|
21963
|
+
timeout,
|
|
21964
|
+
resetTimeoutOnProgress: true,
|
|
21965
|
+
// Even --no-progress needs the token that keeps mcp-wait alive.
|
|
21966
|
+
onprogress: (progress) => {
|
|
21967
|
+
if (showProgress) {
|
|
21968
|
+
if (progress.message) {
|
|
21969
|
+
if (progress.message !== lastProgressMessage) {
|
|
21970
|
+
process.stderr.write(`[zlt-mcp-cli] ${progress.message}
|
|
21971
|
+
`);
|
|
21972
|
+
lastProgressMessage = progress.message;
|
|
21973
|
+
}
|
|
21974
|
+
return;
|
|
21975
|
+
}
|
|
21976
|
+
const total = progress.total === void 0 ? "" : `/${progress.total}`;
|
|
21977
|
+
process.stderr.write(`[zlt-mcp-cli] progress ${progress.progress}${total}
|
|
21978
|
+
`);
|
|
21979
|
+
}
|
|
21980
|
+
}
|
|
21981
|
+
};
|
|
21982
|
+
const callWithDeadline = async (tool, toolArgs, totalTimeoutMs) => {
|
|
21983
|
+
const cancellation = totalTimeoutMs === void 0 ? void 0 : new AbortController();
|
|
21984
|
+
const deadlineTimer = cancellation ? setTimeout(() => {
|
|
21985
|
+
cancellation.abort(new Error("MCP call exceeded --max-total-timeout-ms"));
|
|
21986
|
+
}, totalTimeoutMs) : void 0;
|
|
21987
|
+
try {
|
|
21988
|
+
return await client.callTool({ name: tool, arguments: toolArgs }, void 0, {
|
|
21989
|
+
...requestOptions,
|
|
21990
|
+
...cancellation ? { signal: cancellation.signal } : {}
|
|
21991
|
+
});
|
|
21992
|
+
} finally {
|
|
21993
|
+
if (deadlineTimer !== void 0) clearTimeout(deadlineTimer);
|
|
21994
|
+
}
|
|
21995
|
+
};
|
|
21996
|
+
let result = await callWithDeadline(name, args, options.maxTotalTimeoutMs);
|
|
21997
|
+
if (name === "zlt-runtime-install" && result.isError !== true && (mcpErrorCode(result) ?? 0) === 0) {
|
|
21998
|
+
const payload = parseMcpResult(result);
|
|
21999
|
+
const data = payload?.Data;
|
|
22000
|
+
if (data && (data.status === "queued" || data.status === "running" || data.status === "completed" && data.isTerminal === false)) {
|
|
22001
|
+
const taskId = typeof data.taskId === "string" ? data.taskId.trim() : "";
|
|
22002
|
+
if (!taskId) throw new Error("Installation returned an active task without taskId; inspect installation state before retrying.");
|
|
22003
|
+
const task = { taskId, ...typeof data.logPath === "string" ? { logPath: data.logPath } : {} };
|
|
22004
|
+
process.stderr.write(`[zlt-mcp-cli] install ${JSON.stringify(task)}
|
|
22316
22005
|
`);
|
|
22006
|
+
try {
|
|
22007
|
+
const remaining = options.maxTotalTimeoutMs === void 0 ? void 0 : options.maxTotalTimeoutMs - (Date.now() - startedAt);
|
|
22008
|
+
if (remaining !== void 0 && remaining <= 0) throw new Error("Installation call exceeded --max-total-timeout-ms");
|
|
22009
|
+
result = await callWithDeadline("mcp-wait", { kind: "install", id: taskId }, remaining);
|
|
22010
|
+
const waited = parseMcpResult(result)?.Data;
|
|
22011
|
+
if (result.isError !== true && (mcpErrorCode(result) ?? 0) === 0 && (waited?.taskId !== taskId || waited?.status !== "completed" || waited?.isTerminal !== true)) {
|
|
22012
|
+
throw new Error("Install wait did not confirm completion of the requested task");
|
|
22317
22013
|
}
|
|
22014
|
+
} catch (error2) {
|
|
22015
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
22016
|
+
throw new Error(`Installation outcome is unknown for ${JSON.stringify(task)}: ${message}. Inspect task and installed state before retrying; the worker may have stopped with the host.`);
|
|
22318
22017
|
}
|
|
22319
22018
|
}
|
|
22320
|
-
|
|
22019
|
+
}
|
|
22321
22020
|
if (ASYNC_BACKTEST_TOOLS.has(name)) {
|
|
22322
22021
|
const handoff = backtestHandoff(result);
|
|
22323
22022
|
if (handoff) {
|
|
22324
|
-
|
|
22325
|
-
|
|
22326
|
-
|
|
22023
|
+
process.stderr.write(`[zlt-mcp-cli] backtest ${JSON.stringify(handoff)}
|
|
22024
|
+
`);
|
|
22025
|
+
try {
|
|
22026
|
+
const remaining = options.maxTotalTimeoutMs === void 0 ? void 0 : options.maxTotalTimeoutMs - (Date.now() - startedAt);
|
|
22027
|
+
if (remaining !== void 0 && remaining <= 0) throw new Error("Backtest call exceeded --max-total-timeout-ms");
|
|
22028
|
+
const waited = await callWithDeadline("mcp-wait", {
|
|
22029
|
+
kind: "backtest",
|
|
22030
|
+
id: handoff.runId,
|
|
22031
|
+
...handoff.codePath ? { codePath: handoff.codePath } : {},
|
|
22032
|
+
...handoff.attemptFence !== void 0 ? { attemptFence: handoff.attemptFence } : {}
|
|
22033
|
+
}, remaining);
|
|
22034
|
+
return mergeBacktestWait(result, waited, handoff);
|
|
22035
|
+
} catch (error2) {
|
|
22036
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
22037
|
+
throw Object.assign(new Error(`Backtest wait outcome is unknown for ${JSON.stringify(handoff)}: ${message}. Inspect this run before retrying; closing the host may stop its runtime.`), { backtest: handoff });
|
|
22038
|
+
}
|
|
22327
22039
|
}
|
|
22328
22040
|
}
|
|
22329
22041
|
return result;
|
|
@@ -23111,28 +22823,23 @@ var StdioServerTransport = class {
|
|
|
23111
22823
|
this.onclose?.();
|
|
23112
22824
|
}
|
|
23113
22825
|
send(message) {
|
|
23114
|
-
return new Promise((
|
|
22826
|
+
return new Promise((resolve8) => {
|
|
23115
22827
|
const json = serializeMessage(message);
|
|
23116
22828
|
if (this._stdout.write(json)) {
|
|
23117
|
-
|
|
22829
|
+
resolve8();
|
|
23118
22830
|
} else {
|
|
23119
|
-
this._stdout.once("drain",
|
|
22831
|
+
this._stdout.once("drain", resolve8);
|
|
23120
22832
|
}
|
|
23121
22833
|
});
|
|
23122
22834
|
}
|
|
23123
22835
|
};
|
|
23124
22836
|
|
|
23125
|
-
// src/mcp-server.ts
|
|
23126
|
-
var fs14 = __toESM(require("node:fs"), 1);
|
|
23127
|
-
var os6 = __toESM(require("node:os"), 1);
|
|
23128
|
-
var path15 = __toESM(require("node:path"), 1);
|
|
23129
|
-
|
|
23130
22837
|
// src/install-task.ts
|
|
23131
22838
|
var fs11 = __toESM(require("node:fs"), 1);
|
|
23132
|
-
var
|
|
22839
|
+
var os4 = __toESM(require("node:os"), 1);
|
|
23133
22840
|
var path11 = __toESM(require("node:path"), 1);
|
|
23134
22841
|
var import_node_child_process = require("node:child_process");
|
|
23135
|
-
var DEFAULT_TASK_ROOT = path11.join(
|
|
22842
|
+
var DEFAULT_TASK_ROOT = path11.join(os4.tmpdir(), "zlt-mcp-install-tasks");
|
|
23136
22843
|
var STARTUP_GRACE_MS = 3e4;
|
|
23137
22844
|
function taskRoot() {
|
|
23138
22845
|
return process.env.ZLT_MCP_INSTALL_TASK_ROOT || DEFAULT_TASK_ROOT;
|
|
@@ -23516,7 +23223,7 @@ function prepareToolCallArgs(tool, args, contexts) {
|
|
|
23516
23223
|
}
|
|
23517
23224
|
function validateDataRangeArguments(args) {
|
|
23518
23225
|
const errors = [];
|
|
23519
|
-
const error2 = (
|
|
23226
|
+
const error2 = (path16, message) => errors.push({ path: path16, message });
|
|
23520
23227
|
const input = stripControlParams(args);
|
|
23521
23228
|
for (const key of Object.keys(input)) {
|
|
23522
23229
|
if (key !== "params") error2(`$.${key}`, "Unsupported top-level field; query combinations belong in params[]. Date filters are not accepted.");
|
|
@@ -24725,14 +24432,14 @@ var BACKTEST_WAIT_POLL_IDENTITY = {
|
|
|
24725
24432
|
};
|
|
24726
24433
|
function sleepUnlessAborted(ms, abortSignal) {
|
|
24727
24434
|
if (abortSignal?.aborted) return Promise.resolve();
|
|
24728
|
-
return new Promise((
|
|
24435
|
+
return new Promise((resolve8) => {
|
|
24729
24436
|
const onAbort = () => {
|
|
24730
24437
|
clearTimeout(timer);
|
|
24731
|
-
|
|
24438
|
+
resolve8();
|
|
24732
24439
|
};
|
|
24733
24440
|
const timer = setTimeout(() => {
|
|
24734
24441
|
abortSignal?.removeEventListener("abort", onAbort);
|
|
24735
|
-
|
|
24442
|
+
resolve8();
|
|
24736
24443
|
}, ms);
|
|
24737
24444
|
abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
24738
24445
|
});
|
|
@@ -27101,7 +26808,6 @@ async function startMcpServer() {
|
|
|
27101
26808
|
})).workRoot ?? void 0;
|
|
27102
26809
|
runtimeLease = await acquireMcpRuntime(runtimeConfig, effectiveRoot);
|
|
27103
26810
|
}
|
|
27104
|
-
signalCliKeepaliveReady();
|
|
27105
26811
|
return runtimeLease.workRoot;
|
|
27106
26812
|
};
|
|
27107
26813
|
const recordActiveBacktest = (runId, active2) => {
|
|
@@ -27177,10 +26883,10 @@ async function startMcpServer() {
|
|
|
27177
26883
|
const { name, arguments: args } = request.params;
|
|
27178
26884
|
const progressToken = request.params._meta?.progressToken;
|
|
27179
26885
|
const waitControl = {
|
|
27180
|
-
heartbeat: progressToken === void 0 ? void 0 : (progress) => {
|
|
26886
|
+
heartbeat: progressToken === void 0 ? void 0 : (progress, details) => {
|
|
27181
26887
|
void extra.sendNotification({
|
|
27182
26888
|
method: "notifications/progress",
|
|
27183
|
-
params: { progressToken, progress, total: 100 }
|
|
26889
|
+
params: { progressToken, progress, ...details ?? { total: 100 } }
|
|
27184
26890
|
}).catch(() => {
|
|
27185
26891
|
});
|
|
27186
26892
|
},
|
|
@@ -27574,12 +27280,25 @@ async function handleRuntimeTool(handler, args, runtimeConfig, acquireRuntime, i
|
|
|
27574
27280
|
}
|
|
27575
27281
|
async function waitForInstallTask(taskId, control, doctor) {
|
|
27576
27282
|
if (!taskId) return jsonToolResult(10046, "\u6CA1\u6709 installTaskId \u5C31\u6CA1\u6709\u53EF\u7B49\u5F85\u7684\u5B89\u88C5\u4EFB\u52A1\u3002", {}, true);
|
|
27283
|
+
const waitStartedAt = Date.now();
|
|
27284
|
+
let lastDetail = "";
|
|
27285
|
+
let lastMessageAt = 0;
|
|
27286
|
+
let message = "";
|
|
27287
|
+
let elapsedSeconds = 0;
|
|
27577
27288
|
for (; ; ) {
|
|
27578
27289
|
if (control.abortSignal?.aborted) return jsonToolResult(10047, "\u5DF2\u53D6\u6D88\u7B49\u5F85\u5B89\u88C5\u3002", { taskId }, true);
|
|
27579
27290
|
const task = readInstallTask(taskId);
|
|
27580
27291
|
if (!task) return jsonToolResult(10046, "\u5B89\u88C5\u4EFB\u52A1\u4E0D\u5B58\u5728\u6216\u5DF2\u8FC7\u671F\u3002", { taskId }, true);
|
|
27581
|
-
const
|
|
27582
|
-
|
|
27292
|
+
const createdAt = Date.parse(task.createdAt);
|
|
27293
|
+
const now = Date.now();
|
|
27294
|
+
elapsedSeconds = Math.max(elapsedSeconds, Math.floor((now - (Number.isFinite(createdAt) ? createdAt : waitStartedAt)) / 1e3));
|
|
27295
|
+
const detail = task.status === "failed" ? `\u5B89\u88C5\u5931\u8D25\uFF1A${task.error || "\u539F\u56E0\u672A\u77E5"}` : task.status === "completed" ? "\u5B89\u88C5\u6B65\u9AA4\u5B8C\u6210\uFF0C\u6B63\u5728\u9A8C\u8BC1\u8FD0\u884C\u73AF\u5883" : task.message || (task.status === "queued" ? "\u7B49\u5F85\u5B89\u88C5\u5DE5\u4F5C\u8FDB\u7A0B\u542F\u52A8" : "\u5B89\u88C5\u8FDB\u884C\u4E2D");
|
|
27296
|
+
if (detail !== lastDetail || !message || now - lastMessageAt >= 3e4) {
|
|
27297
|
+
message = `\u5B89\u88C5\u8FDB\u5EA6\uFF08\u5DF2\u7528\u65F6 ${elapsedSeconds}\u79D2\uFF09\uFF1A${detail}`;
|
|
27298
|
+
lastDetail = detail;
|
|
27299
|
+
lastMessageAt = now;
|
|
27300
|
+
}
|
|
27301
|
+
control.heartbeat?.(elapsedSeconds, { message });
|
|
27583
27302
|
if (task.status === "completed") {
|
|
27584
27303
|
const doctorResult = await doctor(task.workRoot);
|
|
27585
27304
|
const ready = doctorResult.runtimeFilesComplete === true && doctorResult.backtestDependenciesComplete === true && doctorResult.ipcReachable === true;
|
|
@@ -27591,8 +27310,8 @@ async function waitForInstallTask(taskId, control, doctor) {
|
|
|
27591
27310
|
}, !ready);
|
|
27592
27311
|
}
|
|
27593
27312
|
if (task.status === "failed") return jsonToolResult(10012, task.error || "runtime \u5B89\u88C5\u5931\u8D25\u3002", { ...task, isTerminal: true, nextAction: "inspect-error" }, true);
|
|
27594
|
-
await new Promise((
|
|
27595
|
-
const timer = setTimeout(
|
|
27313
|
+
await new Promise((resolve8, reject) => {
|
|
27314
|
+
const timer = setTimeout(resolve8, 2e3);
|
|
27596
27315
|
control.abortSignal?.addEventListener("abort", () => {
|
|
27597
27316
|
clearTimeout(timer);
|
|
27598
27317
|
reject(new Error("aborted"));
|
|
@@ -27607,7 +27326,6 @@ async function prepareRuntimeForIpc(options) {
|
|
|
27607
27326
|
if (explicitPipePath) {
|
|
27608
27327
|
const ipcClient2 = await options.connectPipe(explicitPipePath);
|
|
27609
27328
|
if (ipcClient2) {
|
|
27610
|
-
signalCliKeepaliveReady();
|
|
27611
27329
|
return {
|
|
27612
27330
|
ready: true,
|
|
27613
27331
|
ipcClient: ipcClient2,
|
|
@@ -27715,7 +27433,6 @@ async function prepareRuntimeForIpc(options) {
|
|
|
27715
27433
|
)
|
|
27716
27434
|
};
|
|
27717
27435
|
}
|
|
27718
|
-
signalCliKeepaliveReady();
|
|
27719
27436
|
return {
|
|
27720
27437
|
ready: true,
|
|
27721
27438
|
clientRootDir: workRoot,
|
|
@@ -27801,23 +27518,6 @@ function syncCredentialsFromEnvAtStartup() {
|
|
|
27801
27518
|
`);
|
|
27802
27519
|
}
|
|
27803
27520
|
}
|
|
27804
|
-
function signalCliKeepaliveReady() {
|
|
27805
|
-
const raw = process.env.ZLT_MCP_KEEPALIVE_READY_FILE?.trim();
|
|
27806
|
-
if (process.env.ZLT_MCP_CLI !== "1" || !raw) return;
|
|
27807
|
-
const readyFile = path15.resolve(raw);
|
|
27808
|
-
if (path15.dirname(readyFile) !== path15.resolve(os6.tmpdir()) || !path15.basename(readyFile).startsWith("zlt-mcp-keepalive-")) {
|
|
27809
|
-
return;
|
|
27810
|
-
}
|
|
27811
|
-
try {
|
|
27812
|
-
const fd = fs14.openSync(readyFile, "wx", 384);
|
|
27813
|
-
fs14.closeSync(fd);
|
|
27814
|
-
} catch (error2) {
|
|
27815
|
-
if (error2.code !== "EEXIST") {
|
|
27816
|
-
process.stderr.write(`[zlt-mcp-cli] keepalive readiness signal failed: ${error2 instanceof Error ? error2.message : String(error2)}
|
|
27817
|
-
`);
|
|
27818
|
-
}
|
|
27819
|
-
}
|
|
27820
|
-
}
|
|
27821
27521
|
function sanitizeRuntimeDoctor(doctor) {
|
|
27822
27522
|
if (!isRecord2(doctor)) return doctor;
|
|
27823
27523
|
const dependency = isRecord2(doctor.dependency) ? doctor.dependency : {};
|
|
@@ -27921,10 +27621,6 @@ if (process.argv.length <= 2) {
|
|
|
27921
27621
|
}));
|
|
27922
27622
|
});
|
|
27923
27623
|
program2.name(CLI_NAME).description("MCP proxy for ZLTHost IPC service").version(resolveCliVersion()).addHelpText("after", "\nDiscovery: list for names; list --tool <name> --json for one complete input schema.\nUse call --help for input, output and diagnostic handling.");
|
|
27924
|
-
program2.command("__keepalive <kind> <id> [codePath]", { hidden: true }).action(async (kind, id, codePath) => {
|
|
27925
|
-
if (kind !== "backtest") throw new Error(`Unsupported keepalive kind: ${kind}`);
|
|
27926
|
-
await keepMcpBacktestAlive(id, codePath);
|
|
27927
|
-
});
|
|
27928
27624
|
program2.command("call <tool>").description("Call any MCP tool through the bundled MCP server").configureOutput({
|
|
27929
27625
|
outputError: (message, write2) => {
|
|
27930
27626
|
write2(message);
|
|
@@ -27932,7 +27628,7 @@ if (process.argv.length <= 2) {
|
|
|
27932
27628
|
write2("CLI argument error: toolExecution=not_started; no tool was called. Tool fields belong inside one JSON object passed to --args-json (or --args-file), not --flags or key=value arguments. Use call --help and list --tool <tool-name> --json, correct the arguments, then retry.\n");
|
|
27933
27629
|
}
|
|
27934
27630
|
}
|
|
27935
|
-
}).option("--args-json <json>", "JSON object containing tool arguments").option("--args-file <path>", "Read the JSON argument object from a file").option("--output-json <path>", "Save the complete result to a new JSON file and print a compact receipt").option("--timeout-ms <ms>", "MCP request inactivity timeout in milliseconds").option("--max-total-timeout-ms <ms>", "Optional hard upper bound for the
|
|
27631
|
+
}).option("--args-json <json>", "JSON object containing tool arguments").option("--args-file <path>", "Read the JSON argument object from a file").option("--output-json <path>", "Save the complete result to a new JSON file and print a compact receipt").option("--timeout-ms <ms>", "MCP request inactivity timeout in milliseconds").option("--max-total-timeout-ms <ms>", "Optional hard upper bound for the call, including install/backtest wait").option("--no-progress", "Suppress progress diagnostics on stderr").addHelpText("after", `
|
|
27936
27632
|
Input: omitted arguments mean {}; use --args-json for small objects and --args-file
|
|
27937
27633
|
for nested configuration or shell-sensitive text. Follow the selected tool schema
|
|
27938
27634
|
from list --tool <name> --json. Windows paths must be native paths (C:/...), not /c/....
|
|
@@ -27943,6 +27639,21 @@ JSON business responses are inside content[].text (or structuredContent when pre
|
|
|
27943
27639
|
Use --output-json for large results or downstream evidence: it saves the complete
|
|
27944
27640
|
envelope and prints only a compact receipt. The parent directory must exist and the
|
|
27945
27641
|
file must be new. A receipt is not the full business response.
|
|
27642
|
+
Installation: call zlt-runtime-install stays running through mcp-wait on the same
|
|
27643
|
+
connection and returns the terminal install result. Keep the host command alive;
|
|
27644
|
+
use its supported background-task mode if needed. Task ID/log path are on stderr.
|
|
27645
|
+
Install progress includes the current component, step percentage and elapsed time;
|
|
27646
|
+
step percentages may reset between components. Base installer success is not runtime
|
|
27647
|
+
readiness. If stderr is redirected, read that log while the background task runs.
|
|
27648
|
+
Omit --max-total-timeout-ms unless a hard deadline is required; it can interrupt
|
|
27649
|
+
a healthy first install while dependencies are still being installed.
|
|
27650
|
+
Timeout or cancellation leaves the install outcome unknown; inspect before retrying.
|
|
27651
|
+
Backtests: create-and-run/re-backtest keep the same MCP consumer until mcp-wait
|
|
27652
|
+
returns a terminal state or requires action (such as no-progress). The JSON keeps
|
|
27653
|
+
launch identity/configuration plus authoritative wait state. No detached keeper.
|
|
27654
|
+
If isTerminal=true, finalize that run directly; do not wait again. The total timeout
|
|
27655
|
+
covers launch plus wait. Interrupted waits print backtest runId/codePath/attemptFence
|
|
27656
|
+
for recovery; the runtime may stop when the host closes. Never restart automatically.
|
|
27946
27657
|
Diagnostics: preserve stderr separately and check this process's exit code before
|
|
27947
27658
|
parsing output. Do not discard stderr, merge it into JSON, or pipe calls through
|
|
27948
27659
|
head/tail/parsers that can hide the CLI exit code. --no-progress only disables progress.
|
|
@@ -27962,9 +27673,9 @@ Credentials belong in the configured local credential store, never in arguments.
|
|
|
27962
27673
|
const args = parseMcpArgs(options.argsJson, options.argsFile);
|
|
27963
27674
|
const timeoutMs = parseTimeoutOption(options.timeoutMs, "--timeout-ms");
|
|
27964
27675
|
const maxTotalTimeoutMs = parseTimeoutOption(options.maxTotalTimeoutMs, "--max-total-timeout-ms");
|
|
27965
|
-
const resultFile = options.outputJson === void 0 ? void 0 :
|
|
27676
|
+
const resultFile = options.outputJson === void 0 ? void 0 : path15.resolve(options.outputJson);
|
|
27966
27677
|
stage = "output_prepare";
|
|
27967
|
-
if (resultFile !== void 0) outputFd =
|
|
27678
|
+
if (resultFile !== void 0) outputFd = fs14.openSync(resultFile, "wx");
|
|
27968
27679
|
stage = "tool_call";
|
|
27969
27680
|
toolExecution = "unknown";
|
|
27970
27681
|
const result = await callMcpTool(tool, args, {
|
|
@@ -27979,8 +27690,8 @@ Credentials belong in the configured local credential store, never in arguments.
|
|
|
27979
27690
|
if (outputFd !== void 0 && resultFile !== void 0) {
|
|
27980
27691
|
stage = "output_write";
|
|
27981
27692
|
try {
|
|
27982
|
-
|
|
27983
|
-
|
|
27693
|
+
fs14.writeFileSync(outputFd, serialized, "utf-8");
|
|
27694
|
+
fs14.closeSync(outputFd);
|
|
27984
27695
|
outputFd = void 0;
|
|
27985
27696
|
} catch (error2) {
|
|
27986
27697
|
process.stdout.write(serialized);
|
|
@@ -28005,12 +27716,13 @@ Credentials belong in the configured local credential store, never in arguments.
|
|
|
28005
27716
|
toolExecution,
|
|
28006
27717
|
retry,
|
|
28007
27718
|
...typeof code === "string" ? { code } : {},
|
|
27719
|
+
...error2?.backtest ? { backtest: error2.backtest } : {},
|
|
28008
27720
|
message
|
|
28009
27721
|
})}
|
|
28010
27722
|
`);
|
|
28011
27723
|
process.exitCode = 1;
|
|
28012
27724
|
} finally {
|
|
28013
|
-
if (outputFd !== void 0)
|
|
27725
|
+
if (outputFd !== void 0) fs14.closeSync(outputFd);
|
|
28014
27726
|
}
|
|
28015
27727
|
});
|
|
28016
27728
|
program2.command("list").description("List MCP tools exposed by the bundled server").option("--json", "Emit the complete tools/list response as JSON").option("--tool <name>", "Select one exact tool name; combine with --json for its complete schema").addHelpText("after", "\nReuse discovery within a task. Query one schema with list --tool <name> --json.\nUnknown names fail with exit code 1. Preserve stderr separately from JSON stdout.").action(async (options) => {
|
|
@@ -28095,17 +27807,17 @@ function resolveCliVersion() {
|
|
|
28095
27807
|
return resolveCliPackageProvenance().packageVersion;
|
|
28096
27808
|
}
|
|
28097
27809
|
function resolveCliPackageProvenance() {
|
|
28098
|
-
let current =
|
|
27810
|
+
let current = path15.dirname(path15.resolve(process.argv[1] || process.cwd()));
|
|
28099
27811
|
for (let depth = 0; depth < 6; depth += 1) {
|
|
28100
|
-
const manifestPath =
|
|
27812
|
+
const manifestPath = path15.join(current, "package.json");
|
|
28101
27813
|
try {
|
|
28102
|
-
const manifest = JSON.parse(
|
|
27814
|
+
const manifest = JSON.parse(fs14.readFileSync(manifestPath, "utf-8"));
|
|
28103
27815
|
if ((manifest.name === "@zltquant/zlt-mcp" || manifest.name === "zlt-mcp-proxy") && typeof manifest.version === "string") {
|
|
28104
27816
|
return { packageName: manifest.name, packageVersion: manifest.version };
|
|
28105
27817
|
}
|
|
28106
27818
|
} catch {
|
|
28107
27819
|
}
|
|
28108
|
-
const parent =
|
|
27820
|
+
const parent = path15.dirname(current);
|
|
28109
27821
|
if (parent === current) break;
|
|
28110
27822
|
current = parent;
|
|
28111
27823
|
}
|