@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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/zlt-mcp-proxy.bundle.cjs +1255 -1543
@@ -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 path17 = require("node:path");
1151
- var fs16 = require("node:fs");
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 (fs16.existsSync(executableFile)) return;
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 = path17.resolve(baseDir, baseName);
2151
- if (fs16.existsSync(localBin)) return localBin;
2152
- if (sourceExt.includes(path17.extname(baseName))) return void 0;
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) => fs16.existsSync(`${localBin}${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 = fs16.realpathSync(this._scriptPath);
2166
+ resolvedScriptPath = fs15.realpathSync(this._scriptPath);
2167
2167
  } catch {
2168
2168
  resolvedScriptPath = this._scriptPath;
2169
2169
  }
2170
- executableDir = path17.resolve(
2171
- path17.dirname(resolvedScriptPath),
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 = path17.basename(
2178
+ const legacyName = path16.basename(
2179
2179
  this._scriptPath,
2180
- path17.extname(this._scriptPath)
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(path17.extname(executableFile));
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 = path17.basename(filename, path17.extname(filename));
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(path18) {
3053
- if (path18 === void 0) return this._executableDir;
3054
- this._executableDir = path18;
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, constants3) {
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, constants3);
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, constants3) {
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, constants3);
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, constants3) {
3789
- this.code = optimizeExpr(this.code, names, constants3);
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, constants3) {
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, constants3))
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, constants3) {
3876
+ optimizeNames(names, constants2) {
3877
3877
  var _a;
3878
- this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants3);
3879
- if (!(super.optimizeNames(names, constants3) || this.else))
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, constants3);
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, constants3) {
3905
- if (!super.optimizeNames(names, constants3))
3904
+ optimizeNames(names, constants2) {
3905
+ if (!super.optimizeNames(names, constants2))
3906
3906
  return;
3907
- this.iteration = optimizeExpr(this.iteration, names, constants3);
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, constants3) {
3944
- if (!super.optimizeNames(names, constants3))
3943
+ optimizeNames(names, constants2) {
3944
+ if (!super.optimizeNames(names, constants2))
3945
3945
  return;
3946
- this.iterable = optimizeExpr(this.iterable, names, constants3);
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, constants3) {
3988
+ optimizeNames(names, constants2) {
3989
3989
  var _a, _b;
3990
- super.optimizeNames(names, constants3);
3991
- (_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants3);
3992
- (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants3);
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, constants3) {
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 = constants3[n.str];
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 && constants3[c.str] !== void 0);
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 = resolve9.call(this, root, ref);
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 resolve9(root, ref) {
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(path17) {
6520
- let input = path17;
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 [path17, query] = wsComponent.resourceName.split("?");
6720
- wsComponent.path = path17 && path17 !== "/" ? path17 : void 0;
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 resolve9(baseURI, relativeURI, options) {
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: resolve9,
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, fs16, exportName) {
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, fs16[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 fs16 = require("fs");
10101
- function checkPathExt(path17, options) {
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 && path17.substr(-p.length).toLowerCase() === 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, path17, options) {
10118
+ function checkStat(stat, path16, options) {
10119
10119
  if (!stat.isSymbolicLink() && !stat.isFile()) {
10120
10120
  return false;
10121
10121
  }
10122
- return checkPathExt(path17, options);
10122
+ return checkPathExt(path16, options);
10123
10123
  }
10124
- function isexe(path17, options, cb) {
10125
- fs16.stat(path17, function(er, stat) {
10126
- cb(er, er ? false : checkStat(stat, path17, options));
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(path17, options) {
10130
- return checkStat(fs16.statSync(path17), path17, options);
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 fs16 = require("fs");
10141
- function isexe(path17, options, cb) {
10142
- fs16.stat(path17, function(er, stat) {
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(path17, options) {
10147
- return checkStat(fs16.statSync(path17), options);
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 fs16 = require("fs");
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(path17, options, cb) {
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(resolve9, reject) {
10190
- isexe(path17, options || {}, function(er, is) {
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
- resolve9(is);
10194
+ resolve8(is);
10195
10195
  }
10196
10196
  });
10197
10197
  });
10198
10198
  }
10199
- core(path17, options || {}, function(er, is) {
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(path17, options) {
10209
+ function sync(path16, options) {
10210
10210
  try {
10211
- return core.sync(path17, options || {});
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 path17 = require("path");
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((resolve9, reject) => {
10260
+ const step = (i) => new Promise((resolve8, reject) => {
10261
10261
  if (i === pathEnv.length)
10262
- return opt.all && found.length ? resolve9(found) : reject(getNotFoundError(cmd));
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 = path17.join(pathPart, cmd);
10265
+ const pCmd = path16.join(pathPart, cmd);
10266
10266
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
10267
- resolve9(subStep(p, i, 0));
10267
+ resolve8(subStep(p, i, 0));
10268
10268
  });
10269
- const subStep = (p, i, ii) => new Promise((resolve9, reject) => {
10269
+ const subStep = (p, i, ii) => new Promise((resolve8, reject) => {
10270
10270
  if (ii === pathExt.length)
10271
- return resolve9(step(i + 1));
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 resolve9(p + ext);
10278
+ return resolve8(p + ext);
10279
10279
  }
10280
- return resolve9(subStep(p, i, ii + 1));
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 = path17.join(pathPart, cmd);
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 path17 = require("path");
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 ? path17.delimiter : void 0
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 = path17.resolve(hasCustomCwd ? parsed.options.cwd : "", 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 [path17, argument] = match[0].replace(/#! ?/, "").split(" ");
10422
- const binary = path17.split("/").pop();
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 fs16 = require("fs");
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 = fs16.openSync(command, "r");
10443
- fs16.readSync(fd, buffer, 0, size, 0);
10444
- fs16.closeSync(fd);
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 path17 = require("path");
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 = path17.normalize(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 spawn5(command, args, options) {
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 = spawn5;
10585
- module2.exports.spawn = spawn5;
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 fs15 = __toESM(require("node:fs"), 1);
10611
- var path16 = __toESM(require("node:path"), 1);
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, path17) {
10816
- if (!path17)
10812
+ function getElementAtPath(obj, path16) {
10813
+ if (!path16)
10817
10814
  return obj;
10818
- return path17.reduce((acc, key) => acc?.[key], obj);
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(path17, issues) {
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(path17);
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((resolve9) => setTimeout(resolve9, pollInterval));
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((resolve9, reject) => {
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
- resolve9(parseResult.data);
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((resolve9, reject) => {
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(resolve9, interval);
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((resolve9, reject) => {
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
- resolve9();
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((resolve9) => {
17845
+ const closePromise = new Promise((resolve8) => {
17849
17846
  processToClose.once("close", () => {
17850
- resolve9();
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((resolve9) => setTimeout(resolve9, 2e3).unref())]);
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((resolve9) => setTimeout(resolve9, 2e3).unref())]);
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((resolve9) => {
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
- resolve9();
17878
+ resolve8();
17882
17879
  } else {
17883
- this._process.stdin.once("drain", resolve9);
17880
+ this._process.stdin.once("drain", resolve8);
17884
17881
  }
17885
17882
  });
17886
17883
  }
17887
17884
  };
17888
17885
 
17889
- // ../zlt-runtime-core/dist/config.js
17890
- var fs = __toESM(require("fs"), 1);
17891
- var EXDATA_SERVICE_INDEX = 2;
17892
- var FACTOR_SERVICE_INDEX = 3;
17893
- var SDK_SERVICE_INDEX = 6;
17894
- var TY_MODULE_INDEX = 1;
17895
- var CLIENT_PLUGIN_MODULE_INDEX = 4;
17896
- var DEFAULT_BACKTEST_SERVICE_INDICES = [
17897
- EXDATA_SERVICE_INDEX,
17898
- FACTOR_SERVICE_INDEX,
17899
- SDK_SERVICE_INDEX
17900
- ];
17901
- var DEFAULT_STARTUP_CHECK_INDICES = [SDK_SERVICE_INDEX];
17902
- var DEFAULT_BACKTEST_MODULE_INDICES = [TY_MODULE_INDEX];
17903
- var DEBUG_ASSISTANT_INSTALLER_URL = "https://beta.zltquant.com/download/setup-ZLTStudio-Dbg-mini-20260714.4.exe";
17904
- var PUBLIC_PYTHON_SDK_INDEX_URL = "https://pypip.zltquant.com/";
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
- function officialVersionIndexUrl(mirror = "public") {
17993
- return `${OFFICIAL_MIRROR_ROOTS[mirror]}/VscodeMarketPlugin/zlt_quant_version_index.json`;
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
- var INTERNAL_PYTHON_SDK_INDEX_URL = "https://192.168.1.32:9100/pypi/simple/";
17996
- var INTERNAL_PYTHON_SDK_TRUSTED_HOST = "192.168.1.32";
17997
- var PYTHON_SDK_PACKAGES = ["zltquant", "zltsdk-plugin"];
17998
- var PUBLIC_PYTHON_SDK_PACKAGES = [...PYTHON_SDK_PACKAGES];
17999
- var INTERNAL_PYTHON_SDK_PACKAGES = [...PYTHON_SDK_PACKAGES];
18000
- var PROD_PYTHON_SDK_PACKAGES = [...PYTHON_SDK_PACKAGES];
18001
- var DEV_PYTHON_SDK_PACKAGES = [...PYTHON_SDK_PACKAGES];
18002
- var PYTHON_SDK_ABI_TAG = "cp310";
18003
- var PYTHON_PIP_WHEEL_URL = "https://repo.huaweicloud.com/repository/pypi/packages/5d/95/6b5cb3461ea5673ba0995989746db58eb18b91b54dbf331e72f569540946/pip-26.1.2-py3-none-any.whl";
18004
- var PYTHON_PIP_WHEEL_SHA256 = "382FF9F685EE3BC25864F820AA50505825F10F5458FFFF07E30A6D96E5715CAB";
18005
- var PYTHON_RUNTIME_INDEX_URL = "https://repo.huaweicloud.com/repository/pypi/simple/";
18006
- var defaultAssistantRuntimeConfig = {
18007
- registryKeys: {
18008
- OFFICIAL: "Zlt.Std.Official_is1",
18009
- REL: "Zlt.Std.Rel_is1",
18010
- DEBUG: "Zlt.Std.Dbg_is1"
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
- // Exact artifact digests. A URL update requires a matching digest update in the
18028
- // same reviewed change; downloadRuntimeInstaller fails closed when it is absent.
18029
- // OFFICIAL 的取值来自 OFFICIAL_INSTALLERS.public —— URL/版本/摘要三者同源,只有那一处可改。
18030
- // 这里恒取公网表:模块级默认必须公网可达(runtime.test.ts 的 LAN 守卫钉的就是它),
18031
- // 内网镜像那档由 applyEnvOverrides 按镜像轴整行换掉。
18032
- backserviceDownloadSha256: {
18033
- OFFICIAL: {
18034
- full: OFFICIAL_INSTALLERS.public.full.sha256,
18035
- mini: OFFICIAL_INSTALLERS.public.mini.sha256
18036
- },
18037
- REL: { full: "", mini: "" },
18038
- DEBUG: {
18039
- full: "05C57A5D212684A801665774E9F0813EFC1AA4762D1540EC353BB41173712B07",
18040
- mini: "05C57A5D212684A801665774E9F0813EFC1AA4762D1540EC353BB41173712B07"
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
- // 本体升级判定拿它当「我们能立刻交付的版本下限」。OFFICIAL 与 URL 同源自
18044
- // OFFICIAL_INSTALLERS,结构上不可能只改 URL 不改这里。
18045
- backserviceDownloadVersion: {
18046
- OFFICIAL: {
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
- // 我们自己发布的版本索引:versions[] 按**本插件**的发布序列给出各组件的 min/max,
18057
- // 形状沿用李扬的 zlt_version_index.json,方便日后合并。
18058
- //
18059
- // 为什么不复用李扬那份:它的 versions[] 编号是 claw 插件的版本序列,与我们合并后的
18060
- // 1.0.x 撞车 —— 远程 1.0.1 条目写的是 claw 1.0.1 的门槛(ClientPlugin.min = 2026.06.05.1),
18061
- // 按我们的 VSIX 1.0.1 去区间匹配就会读到一个与我们无关、且明显偏低的下限。
18062
- //
18063
- // REL/DEBUG 没有对应发布面,留空即跳过远程判定。地址不可达或文件不存在同样 fail-open,
18064
- // 所以这条链路默认是关的,直到有人把文件传上去 —— 见 deploy/README.md。
18065
- // 与安装包同源自 OFFICIAL_MIRROR_ROOTS:内测构建把安装包指到内网时,这条也必须跟着走,
18066
- // 否则一个 -internal 产物会拿公网索引判闸门 —— 而索引取不到时闸门是 fail-open。
18067
- baseRequirementUrl: {
18068
- OFFICIAL: officialVersionIndexUrl("public"),
18069
- REL: "",
18070
- DEBUG: ""
18071
- },
18072
- // 用来做区间匹配的插件版本。VSCode 侧由 loadVscodeRuntimeConfig 填当前 VSIX 版本;
18073
- // 没有插件版本概念的消费者(zlt-mcp-proxy)留空,留空即整条远程判定跳过。
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(fs.readFileSync(configPath, "utf-8"));
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((resolve9, reject) => {
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
- resolve9(stdout.trim());
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 fs2 = __toESM(require("fs"), 1);
18457
- var path = __toESM(require("path"), 1);
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(fs2.readdirSync("\\\\.\\pipe\\"), prefix);
18849
+ return matchingPipeNames(fs3.readdirSync("\\\\.\\pipe\\"), prefix);
18479
18850
  }
18480
18851
  const socketResults = [];
18481
- for (const name of matchingPipeNames(fs2.readdirSync("/tmp"), prefix)) {
18482
- const fullPath = path.join("/tmp", name);
18852
+ for (const name of matchingPipeNames(fs3.readdirSync("/tmp"), prefix)) {
18853
+ const fullPath = path2.join("/tmp", name);
18483
18854
  try {
18484
- if (!fs2.statSync(fullPath).isSocket())
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 fs2.existsSync(pipePath);
18878
+ return fs3.existsSync(pipePath);
18508
18879
  } catch {
18509
18880
  return false;
18510
18881
  }
18511
18882
  }
18512
18883
  function readZltHostPipeName(clientRootDir) {
18513
- let configPath = path.join(clientRootDir, "zlthost.json");
18514
- if (!fs2.existsSync(configPath)) {
18515
- configPath = path.join(clientRootDir, "zltHost", "zlthost.json");
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 (!fs2.existsSync(configPath))
18888
+ if (!fs3.existsSync(configPath))
18518
18889
  return null;
18519
- const parsed = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
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 = path.join(clientRootDir, "Temporary", "zlt");
18524
- if (!fs2.existsSync(zltFile))
18894
+ const zltFile = path2.join(clientRootDir, "Temporary", "zlt");
18895
+ if (!fs3.existsSync(zltFile))
18525
18896
  return null;
18526
- return fs2.readFileSync(zltFile, "utf-8").trim() || null;
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 fs5 = __toESM(require("fs"), 1);
18566
- var os = __toESM(require("os"), 1);
18567
- var path5 = __toESM(require("path"), 1);
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 net = __toESM(require("net"), 1);
18575
- var path2 = __toESM(require("path"), 1);
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((resolve9, reject) => {
18847
- const socket = net.connect(pipePath);
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
- resolve9();
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((resolve9, reject) => {
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
- resolve9();
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((resolve9, reject) => {
18910
- const socket = net.connect(pipePath);
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
- resolve9();
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((resolve9, reject) => {
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: resolve9, reject, timer });
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?.(`\u6295\u7814\u6A21\u5757\u5305\u4E0B\u8F7D\u72B6\u6001: moduleIndex=${moduleIndex}, status=${progress.status}, phase=${progress.phase}, process=${progress.process}`);
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?.(`\u6295\u7814\u6A21\u5757\u5305\u8986\u76D6\u5B89\u88C5\u72B6\u6001: moduleIndex=${moduleIndex}, status=${progress.status}, phase=${progress.phase}, process=${progress.process}`);
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 fs16 = await import("fs");
19170
- const path17 = await import("path");
19171
- const zltFile = path17.join(workRoot, temporaryZltFile || "Temporary/zlt");
19172
- return fs16.existsSync(zltFile) ? fs16.readFileSync(zltFile, "utf-8").trim() : "";
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 fs16 = await import("fs");
19531
+ const fs15 = await import("fs");
19176
19532
  try {
19177
19533
  if (process.platform === "win32") {
19178
- return fs16.readdirSync("\\\\.\\pipe\\").includes(pipeName);
19534
+ return fs15.readdirSync("\\\\.\\pipe\\").includes(pipeName);
19179
19535
  }
19180
- return fs16.existsSync(`/tmp/${pipeName}`);
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 = path2.join(workRoot, "vscode", "Code.exe").toLowerCase();
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((resolve9) => setTimeout(resolve9, ms));
19664
+ return new Promise((resolve8) => setTimeout(resolve8, ms));
19303
19665
  }
19304
19666
 
19305
19667
  // ../zlt-runtime-core/dist/runtime-lifecycle.js
19306
- var fs3 = __toESM(require("fs"), 1);
19307
- var path3 = __toESM(require("path"), 1);
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 = path3.join("Temporary", "zlt-mcp-runtime");
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: path3.resolve(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
- fs3.rmSync(leasePath(stateDir, handle.token), { force: true });
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
- fs3.rmSync(ownerPath(stateDir), { force: true });
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
- fs3.rmSync(ownerPath(stateDir), { force: true });
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 = path3.join(process.env.SystemRoot || "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
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 = path3.join(process.env.SystemRoot || "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
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((resolve9) => setTimeout(resolve9, ms))
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
- fs3.mkdirSync(path3.join(stateDir, "leases"), { recursive: true });
19479
- const lockPath = path3.join(stateDir, "lifecycle.lock");
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 = fs3.openSync(lockPath, "wx");
19850
+ const descriptor = fs4.openSync(lockPath, "wx");
19489
19851
  try {
19490
- fs3.writeFileSync(descriptor, JSON.stringify(lock), "utf8");
19852
+ fs4.writeFileSync(descriptor, JSON.stringify(lock), "utf8");
19491
19853
  } finally {
19492
- fs3.closeSync(descriptor);
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 = fs3.statSync(lockPath);
19521
- const raw = fs3.readFileSync(lockPath);
19522
- const after = fs3.statSync(lockPath);
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
- fs3.linkSync(movedPath, lockPath);
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
- fs3.copyFileSync(movedPath, lockPath, fs3.constants.COPYFILE_EXCL);
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
- fs3.rmSync(movedPath, { force: true });
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
- fs3.renameSync(lockPath, movedPath);
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
- fs3.rmSync(movedPath, { force: true });
19946
+ fs4.rmSync(movedPath, { force: true });
19585
19947
  return true;
19586
19948
  }
19587
19949
  function readAndPruneStore(stateDir, deps) {
19588
- const leasesDir = path3.join(stateDir, "leases");
19950
+ const leasesDir = path4.join(stateDir, "leases");
19589
19951
  const leases = [];
19590
- for (const entry of fs3.readdirSync(leasesDir, { withFileTypes: true })) {
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 = path3.join(leasesDir, entry.name);
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
- fs3.rmSync(filePath, { force: true });
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
- fs3.rmSync(ownerPath(stateDir), { force: true });
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 = path3.resolve(workRoot);
19643
- const stateDir = path3.resolve(resolvedRoot, STATE_RELATIVE_PATH);
19644
- const prefix = `${resolvedRoot}${path3.sep}`.toLowerCase();
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 = path3.resolve(workRoot, "zltaf", "zltaf.exe");
19651
- if (path3.resolve(identity.executablePath).toLowerCase() !== expected.toLowerCase()) {
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 && path3.resolve(left.executablePath).toLowerCase() === path3.resolve(right.executablePath).toLowerCase() && left.creationTime === right.creationTime;
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 path3.join(stateDir, "owner.json");
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 path3.join(stateDir, "leases", `${token}.json`);
20032
+ return path4.join(stateDir, "leases", `${token}.json`);
19671
20033
  }
19672
20034
  function readJson(filePath) {
19673
20035
  try {
19674
- return JSON.parse(fs3.readFileSync(filePath, "utf8"));
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
- fs3.writeFileSync(temporary, JSON.stringify(value), "utf8");
19682
- fs3.renameSync(temporary, filePath);
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 fs4 = __toESM(require("fs"), 1);
19687
- var path4 = __toESM(require("path"), 1);
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 = fs4.readFileSync(path4.join(workRoot, INSTALL_INFO_FILE), "utf-8");
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 fs5.existsSync("D:\\") ? "D:\\ZLTClient" : "C:\\ZLTClient";
20203
+ return fs6.existsSync("D:\\") ? "D:\\ZLTClient" : "C:\\ZLTClient";
19842
20204
  }
19843
- return path5.join(os.homedir(), "ZLTClient");
20205
+ return path6.join(os2.homedir(), "ZLTClient");
19844
20206
  }
19845
20207
  function validateWorkRootComplete(workRoot, _config) {
19846
- if (!fs5.existsSync(workRoot)) {
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 (!fs5.existsSync(item.filePath)) {
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 (!fs5.existsSync(workRoot))
20223
+ if (!fs6.existsSync(workRoot))
19862
20224
  return { complete: false, reason: `\u5DE5\u7A0B\u8DEF\u5F84\u4E0D\u5B58\u5728: ${workRoot}` };
19863
- const hostPath = path5.join(workRoot, config2.hostPath);
19864
- return fs5.existsSync(hostPath) ? { complete: true } : { complete: false, reason: `\u7F3A\u5C11\u667A\u80FD\u7BA1\u5BB6\u7A0B\u5E8F: ${hostPath}` };
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 (!fs5.existsSync(item.filePath)) {
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 = path5.join(workRoot, "Users", "projects");
19889
- if (fs5.existsSync(projectsDir)) {
19890
- if (!fs5.statSync(projectsDir).isDirectory()) {
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
- fs5.mkdirSync(projectsDir, { recursive: true });
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 = path5.resolve(workRoot).toLowerCase();
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 ? path5.join(workRoot, config2.temporaryZltFile) : void 0;
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 (!fs5.existsSync(zltafPath)) {
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 (!fs5.existsSync(configPath)) {
20385
+ if (!fs6.existsSync(configPath)) {
20024
20386
  throw new Error(`ZLTAF \u914D\u7F6E\u4E0D\u5B58\u5728: ${configPath}`);
20025
20387
  }
20026
- const tmpDir = path5.join(workRoot, "zltaf", "tmp");
20027
- fs5.mkdirSync(tmpDir, { recursive: true });
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: path5.dirname(zltafPath),
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: ${path5.join(workRoot, config2.temporaryZltFile)}`);
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 = path5.join("Temporary", "upgradeFinsh.lock");
20457
+ var ASSISTANT_UPGRADE_FINISH_LOCK = path6.join("Temporary", "upgradeFinsh.lock");
20096
20458
  function launchAssistantHost(workRoot, config2, onProgress) {
20097
- const hostPath = path5.join(workRoot, config2.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: path5.dirname(hostPath),
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 = path5.join(workRoot, ASSISTANT_UPGRADE_FINISH_LOCK);
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 (!fs5.existsSync(finishLockPath)) {
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
- fs5.mkdirSync(installDir, { recursive: true });
20189
- const installerLogPath = path5.join(installDir, "Temporary", "logs", "install.log");
20190
- fs5.mkdirSync(path5.dirname(installerLogPath), { recursive: true });
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
- fs5.rmSync(path5.join(workRoot, ASSISTANT_UPGRADE_FINISH_LOCK), { force: true });
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
- fs5.rmSync(path5.join(workRoot, ASSISTANT_UPGRADE_FINISH_LOCK), { force: true });
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 (!fs5.existsSync(targetPython)) {
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 = path5.join(path5.dirname(targetPython), `python${PYTHON_SDK_ABI_TAG.replace(/^cp/, "")}.dll`);
20366
- if (!fs5.existsSync(abiDll)) {
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 path5.join(os.tmpdir(), "zlt-runtime-toolchains");
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 (fs5.existsSync(destination)) {
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
- fs5.rmSync(destination, { force: true });
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 = path5.join(toolchainDownloadCacheDir(), "pip-26.1.2-py3-none-any.whl");
20395
- fs5.mkdirSync(path5.dirname(destination), { recursive: true });
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(fs5.readFileSync(filePath)).digest("hex").toUpperCase();
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 = path5.resolve(workRoot, "vscode", "Code.exe");
20417
- const jsserviceRoot = `${path5.resolve(workRoot, "jsservice")}${path5.sep}`.toLowerCase();
20418
- const managedGitRoot = path5.resolve(workRoot, "mingit");
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
- path5.join(workRoot, "zltaf", "zltaf.exe"),
20422
- path5.join(workRoot, "python", "python.exe"),
20423
- path5.join(workRoot, "mingit", "cmd", "git.exe"),
20424
- path5.join(workRoot, "zltHost", "ZltDcmClient.exe"),
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 = path5.resolve(candidate);
20789
+ const resolved = path6.resolve(candidate);
20428
20790
  assertPathInside(workRoot, resolved);
20429
20791
  return resolved;
20430
20792
  });
20431
- const installedExecutablePaths = executablePaths.filter((candidate) => fs5.existsSync(candidate));
20432
- const installedExecutableRoots = fs5.existsSync(managedGitRoot) ? [`${managedGitRoot}${path5.sep}`] : [];
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 (path5.resolve(item.executablePath).toLowerCase() !== managedCodePath.toLowerCase())
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
- path5.join(workRoot, config2.hostPath),
20495
- path5.join(workRoot, config2.backservicePath),
20496
- path5.join(workRoot, "zltHost", "zlthost.exe"),
20497
- path5.join(workRoot, "zltaf", "zltaf.exe")
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 = path5.resolve(candidate);
20861
+ const resolved = path6.resolve(candidate);
20500
20862
  assertPathInside(workRoot, resolved);
20501
20863
  return resolved;
20502
20864
  });
20503
- const installedExecutablePaths = executablePaths.filter((candidate) => fs5.existsSync(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 = path5.resolve(workRoot, config2.temporaryZltFile || "Temporary/zlt");
20878
+ const zltMarker = path6.resolve(workRoot, config2.temporaryZltFile || "Temporary/zlt");
20517
20879
  assertPathInside(workRoot, zltMarker);
20518
- fs5.rmSync(zltMarker, { force: true });
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 : path5.basename(item.ExecutablePath),
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 || !path5.isAbsolute(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 path5.join(systemRoot, "System32", ...relativePath.split("/"));
20961
+ return path6.join(systemRoot, "System32", ...relativePath.split("/"));
20600
20962
  }
20601
20963
  function ensureGitToolchain(workRoot) {
20602
20964
  const targetGit = getGitExePath(workRoot);
20603
- if (!fs5.existsSync(targetGit)) {
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 (!fs5.existsSync(pythonPath)) {
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 (!fs5.existsSync(pythonPath)) {
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 = path5.basename(new URL(url).pathname) || "zlt-runtime-installer.exe";
20755
- const dir = path5.join(os.tmpdir(), config2.downloadTempDir);
20756
- const destination = path5.join(dir, filename);
20757
- fs5.mkdirSync(dir, { recursive: true });
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
- fs5.rmSync(destination, { force: true });
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((resolve9, reject) => {
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
- resolve9(code);
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((resolve9, reject) => {
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
- resolve9();
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
- fs5.mkdirSync(path5.dirname(destination), { recursive: true });
21261
+ fs6.mkdirSync(path6.dirname(destination), { recursive: true });
20900
21262
  const partialPath = `${destination}.${process.pid}.${(0, import_crypto3.randomUUID)()}.part`;
20901
- return new Promise((resolve9, reject) => {
21263
+ return new Promise((resolve8, reject) => {
20902
21264
  let settled = false;
20903
21265
  let file;
20904
21266
  const cleanupPartial = () => {
20905
21267
  file?.destroy();
20906
- fs5.rmSync(partialPath, { force: true });
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
- fs5.rmSync(destination, { force: true });
20920
- fs5.renameSync(partialPath, destination);
21281
+ fs6.rmSync(destination, { force: true });
21282
+ fs6.renameSync(partialPath, destination);
20921
21283
  settled = true;
20922
- resolve9();
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
- resolve9();
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 = fs5.createWriteStream(partialPath, { flags: "wx" });
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((resolve9) => setTimeout(resolve9, ms));
21344
+ return new Promise((resolve8) => setTimeout(resolve8, ms));
20983
21345
  }
20984
21346
  function getZltafExePath(workRoot) {
20985
- return path5.join(workRoot, "zltaf", "zltaf.exe");
21347
+ return path6.join(workRoot, "zltaf", "zltaf.exe");
20986
21348
  }
20987
21349
  function getZltafConfigPath(workRoot) {
20988
- return path5.join(workRoot, "zltaf", "application-local.properties");
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 = path5.join(workRoot, "zltaf", config2.zltafConfigFile);
20995
- if (fs5.existsSync(preferred)) {
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
- return {
21205
- configured: false,
21206
- source: "missing",
21207
- credentialsPath,
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 maskApiKey(apiKey) {
21215
- const trimmed = apiKey.trim();
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 expandHome(input) {
21223
- if (input === "~")
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 tryReadCredentials(env) {
21231
- try {
21232
- return readCredentials(env);
21233
- } catch {
21234
- return null;
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 chmodOwnerOnly(filePath) {
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.chmodSync(filePath, 384);
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 fileAuthStatus(credentialsPath, zltquantHome, credentials) {
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
- // ../zlt-runtime-core/dist/zltaf-ipc.js
21256
- var import_node_crypto = require("node:crypto");
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 urlDecode(value) {
21276
- const bytes = [];
21277
- for (let index = 0; index < value.length; index += 1) {
21278
- const char = value[index];
21279
- if (char === "+") {
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
- var ZltafHttpPacket = class {
21296
- httpVersion = "HTTP/1.1";
21297
- statusCode = 200;
21298
- statusMessage = "OK";
21299
- content = "";
21300
- contentLength = 0;
21301
- uri = "";
21302
- method = "";
21303
- headers = /* @__PURE__ */ new Map();
21304
- params = /* @__PURE__ */ new Map();
21305
- xErr = /* @__PURE__ */ new Map();
21306
- xOption = /* @__PURE__ */ new Map();
21307
- headerLength = 0;
21308
- isBodyComplete = false;
21309
- remainingBodyLength = 0;
21310
- generatePacket() {
21311
- let packet = `POST ${this.uri} ${this.httpVersion}\r
21312
- `;
21313
- for (const [key, value] of this.headers)
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
- function flushLogQueue() {
21425
- if (logWriteInFlight || pendingLogLines.length === 0)
21426
- return;
21427
- logWriteInFlight = true;
21428
- const batch = pendingLogLines.splice(0).join("");
21429
- try {
21430
- fs7.appendFile(LOG_FILE, batch, "utf8", () => {
21431
- logWriteInFlight = false;
21432
- flushLogQueue();
21433
- });
21434
- } catch {
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 getZltafIpcLogFilePath() {
21439
- return LOG_FILE;
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
- var ZltafIpcClient = class {
21442
- mainSocket = null;
21443
- workSocket = null;
21444
- buffer = Buffer.alloc(0);
21445
- seqCounter = 0;
21446
- pendingRequests = /* @__PURE__ */ new Map();
21447
- connected = false;
21448
- onDisconnect = null;
21449
- isConnected() {
21450
- return this.connected;
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
- async connect(pipePath, timeout = 5e3) {
21453
- log("CONNECT", `\u5F00\u59CB\u8FDE\u63A5\u4E3B\u7BA1\u9053: ${pipePath}`);
21454
- const uuid2 = (0, import_node_crypto.randomUUID)();
21455
- const handshake = new ZltafHttpPacket();
21456
- handshake.uri = `/ipcHandshake/pipName?ipcUUID=${uuid2}&supportFullDuplex=0`;
21457
- handshake.content = "{}";
21458
- log("HANDSHAKE", `\u53D1\u9001\u63E1\u624B\u8BF7\u6C42, uuid=${uuid2}`);
21459
- const response = await this.connectAndSend(pipePath, handshake.generatePacket(), timeout);
21460
- if (!response) {
21461
- log("HANDSHAKE", "\u63E1\u624B\u5931\u8D25: \u672A\u6536\u5230\u54CD\u5E94");
21462
- throw new Error("Handshake failed: no response from main pipe");
21463
- }
21464
- log("HANDSHAKE", `\u63E1\u624B\u6210\u529F, statusCode=${response.statusCode}`);
21465
- const workPipeName = pipePath.replace(/[^\\/]+$/, uuid2);
21466
- log("CONNECT", `\u8FDE\u63A5\u5DE5\u4F5C\u7BA1\u9053: ${workPipeName}`);
21467
- await this.connectWorkPipe(workPipeName, timeout);
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
- invoke(uri, params, body = "{}", timeout = 5e3, customHeaders = []) {
21472
- return new Promise((resolve9, reject) => {
21473
- if (!this.workSocket || !this.connected) {
21474
- log("INVOKE", `\u8C03\u7528\u5931\u8D25: \u672A\u8FDE\u63A5 (hasSocket=${Boolean(this.workSocket)}, connected=${this.connected})`);
21475
- reject(new Error("Not connected"));
21476
- return;
21477
- }
21478
- const seq = String(++this.seqCounter);
21479
- const paramString = Object.entries(params).filter(([, value]) => value !== void 0 && value !== "").map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join("&");
21480
- const baseUri = uri.startsWith("/") ? uri.substring(1) : uri;
21481
- const fullUri = paramString ? `${baseUri}?${paramString}` : baseUri;
21482
- const request = new ZltafHttpPacket();
21483
- request.uri = fullUri;
21484
- request.headers.set("Content-SEQ", seq);
21485
- request.headers.set("Msg-Type", "2");
21486
- for (const header of customHeaders) {
21487
- const colon = header.indexOf(":");
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
- async disconnect() {
21504
- this.connected = false;
21505
- if (this.workSocket) {
21506
- this.workSocket.destroy();
21507
- this.workSocket = null;
21508
- }
21509
- if (this.mainSocket) {
21510
- this.mainSocket.destroy();
21511
- this.mainSocket = null;
21512
- }
21513
- for (const [, pending] of this.pendingRequests) {
21514
- clearTimeout(pending.timer);
21515
- pending.reject(new Error("Disconnected"));
21516
- }
21517
- this.pendingRequests.clear();
21518
- log("DISCONNECT", "\u4E3B\u52A8\u65AD\u5F00\u8FDE\u63A5");
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
- connectWorkPipe(pipeName, timeout) {
21521
- return new Promise((resolve9, reject) => {
21522
- const timer = setTimeout(() => reject(new Error(`Work pipe connect timeout: ${pipeName}`)), timeout);
21523
- this.workSocket = net2.connect(pipeName, () => {
21524
- clearTimeout(timer);
21525
- resolve9();
21526
- });
21527
- this.workSocket.on("error", (error2) => {
21528
- clearTimeout(timer);
21529
- reject(error2);
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
- handleServerDisconnect(event) {
21537
- if (!this.connected)
21538
- return;
21539
- this.connected = false;
21540
- log("DISCONNECT", `IPC \u670D\u52A1\u7AEF\u65AD\u5F00\u8FDE\u63A5 (event=${event}), pending=${this.pendingRequests.size}`);
21541
- for (const [seq, pending] of this.pendingRequests) {
21542
- clearTimeout(pending.timer);
21543
- pending.reject(new Error("IPC server disconnected"));
21544
- log("DISCONNECT", `\u6E05\u7406 pending \u8BF7\u6C42: seq=${seq}`);
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
- connectAndSend(pipePath, data, timeout) {
21550
- return new Promise((resolve9, reject) => {
21551
- const timer = setTimeout(() => {
21552
- if (this.mainSocket) {
21553
- this.mainSocket.destroy();
21554
- this.mainSocket = null;
21555
- }
21556
- resolve9(null);
21557
- }, timeout);
21558
- let responseBuffer = Buffer.alloc(0);
21559
- this.mainSocket = net2.connect(pipePath, () => this.mainSocket.write(data));
21560
- this.mainSocket.on("data", (chunk) => {
21561
- responseBuffer = Buffer.concat([responseBuffer, chunk]);
21562
- const packet = new ZltafHttpPacket();
21563
- if (packet.parsePacket(responseBuffer)) {
21564
- clearTimeout(timer);
21565
- this.mainSocket.destroy();
21566
- this.mainSocket = null;
21567
- resolve9(packet);
21568
- }
21569
- });
21570
- this.mainSocket.on("error", (error2) => {
21571
- clearTimeout(timer);
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
- onData(data) {
21577
- this.buffer = Buffer.concat([this.buffer, data]);
21578
- while (this.buffer.length > 0) {
21579
- const packet = new ZltafHttpPacket();
21580
- if (!packet.parsePacket(this.buffer))
21581
- break;
21582
- this.buffer = this.buffer.subarray(packet.getTotalLength());
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
- async function keepaliveDelay() {
22183
- await new Promise((resolve9) => setTimeout(resolve9, KEEPALIVE_RETRY_MS));
22184
- }
22185
- function parseAttemptStartedAt(raw) {
22186
- if (!raw) return void 0;
22187
- const value = Number(raw);
22188
- return Number.isSafeInteger(value) && value > 0 ? value : void 0;
22189
- }
22190
- function parseResultBaseline(raw) {
22191
- if (!raw) return void 0;
22192
- try {
22193
- const parsed = JSON.parse(raw);
22194
- return typeof parsed.sha256 === "string" && /^[a-f0-9]{64}$/i.test(parsed.sha256) && typeof parsed.mtimeMs === "number" && Number.isFinite(parsed.mtimeMs) && parsed.mtimeMs >= 0 && Number.isSafeInteger(parsed.size) && Number(parsed.size) >= 0 ? { sha256: parsed.sha256, mtimeMs: parsed.mtimeMs, size: Number(parsed.size) } : void 0;
22195
- } catch {
22196
- return void 0;
22197
- }
22198
- }
22199
- function readResultBaseline(codePath) {
22200
- if (typeof codePath !== "string" || !path9.isAbsolute(codePath.trim())) return void 0;
22201
- try {
22202
- const resultPath = path9.join(codePath.trim(), "log", "result.json");
22203
- const before = fs9.statSync(resultPath);
22204
- const raw = fs9.readFileSync(resultPath);
22205
- const after = fs9.statSync(resultPath);
22206
- if (before.mtimeMs !== after.mtimeMs || before.size !== after.size) return void 0;
22207
- return {
22208
- sha256: (0, import_crypto4.createHash)("sha256").update(raw).digest("hex"),
22209
- mtimeMs: after.mtimeMs,
22210
- size: after.size
22211
- };
22212
- } catch {
22213
- return void 0;
22214
- }
22215
- }
22216
- function captureBacktestAttemptFence(name, args) {
22217
- if (!ASYNC_BACKTEST_TOOLS.has(name)) return void 0;
22218
- const resultBaseline = readResultBaseline(args.codePath);
22219
- return {
22220
- attemptStartedAtMs: Date.now(),
22221
- ...resultBaseline ? { resultBaseline } : {}
22222
- };
22223
- }
22224
- async function keepMcpBacktestAlive(runId, codePath, options = {}) {
22225
- const ownership = adoptKeepaliveLock(runId);
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 attemptFence = captureBacktestAttemptFence(name, args);
22303
- const result = await client.callTool(
22304
- { name, arguments: args },
22305
- void 0,
22306
- {
22307
- timeout,
22308
- maxTotalTimeout: options.maxTotalTimeoutMs,
22309
- resetTimeoutOnProgress: true,
22310
- // Suppressing diagnostics must not suppress the MCP progress token;
22311
- // mcp-wait depends on that token to reset its inactivity timeout.
22312
- onprogress: (progress) => {
22313
- if (showProgress) {
22314
- const total = progress.total === void 0 ? "" : `/${progress.total}`;
22315
- process.stderr.write(`[zlt-mcp-cli] progress ${progress.progress}${total}
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
- const entrypoint = options.entrypoint || process.argv[1];
22325
- if (!entrypoint) throw new Error("Unable to determine the zlt-mcp bundle entrypoint");
22326
- await handoffBacktestKeepalive(entrypoint, handoff.runId, handoff.codePath, attemptFence);
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((resolve9) => {
22826
+ return new Promise((resolve8) => {
23115
22827
  const json = serializeMessage(message);
23116
22828
  if (this._stdout.write(json)) {
23117
- resolve9();
22829
+ resolve8();
23118
22830
  } else {
23119
- this._stdout.once("drain", resolve9);
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 os5 = __toESM(require("node:os"), 1);
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(os5.tmpdir(), "zlt-mcp-install-tasks");
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 = (path17, message) => errors.push({ path: path17, message });
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((resolve9) => {
24435
+ return new Promise((resolve8) => {
24729
24436
  const onAbort = () => {
24730
24437
  clearTimeout(timer);
24731
- resolve9();
24438
+ resolve8();
24732
24439
  };
24733
24440
  const timer = setTimeout(() => {
24734
24441
  abortSignal?.removeEventListener("abort", onAbort);
24735
- resolve9();
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 progress = task.status === "completed" ? 100 : task.status === "failed" ? 100 : task.status === "running" ? 50 : 0;
27582
- control.heartbeat?.(progress);
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((resolve9, reject) => {
27595
- const timer = setTimeout(resolve9, 2e3);
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 request").option("--no-progress", "Suppress progress diagnostics on stderr").addHelpText("after", `
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 : path16.resolve(options.outputJson);
27676
+ const resultFile = options.outputJson === void 0 ? void 0 : path15.resolve(options.outputJson);
27966
27677
  stage = "output_prepare";
27967
- if (resultFile !== void 0) outputFd = fs15.openSync(resultFile, "wx");
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
- fs15.writeFileSync(outputFd, serialized, "utf-8");
27983
- fs15.closeSync(outputFd);
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) fs15.closeSync(outputFd);
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 = path16.dirname(path16.resolve(process.argv[1] || process.cwd()));
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 = path16.join(current, "package.json");
27812
+ const manifestPath = path15.join(current, "package.json");
28101
27813
  try {
28102
- const manifest = JSON.parse(fs15.readFileSync(manifestPath, "utf-8"));
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 = path16.dirname(current);
27820
+ const parent = path15.dirname(current);
28109
27821
  if (parent === current) break;
28110
27822
  current = parent;
28111
27823
  }