@zltquant/zlt-mcp 0.7.2 → 0.7.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.
@@ -1147,7 +1147,7 @@ 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 path27 = require("node:path");
1150
+ var path28 = require("node:path");
1151
1151
  var fs28 = require("node:fs");
1152
1152
  var process4 = require("node:process");
1153
1153
  var { Argument: Argument2, humanReadableArgName } = require_argument();
@@ -2147,9 +2147,9 @@ 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 = path27.resolve(baseDir, baseName);
2150
+ const localBin = path28.resolve(baseDir, baseName);
2151
2151
  if (fs28.existsSync(localBin)) return localBin;
2152
- if (sourceExt.includes(path27.extname(baseName))) return void 0;
2152
+ if (sourceExt.includes(path28.extname(baseName))) return void 0;
2153
2153
  const foundExt = sourceExt.find(
2154
2154
  (ext) => fs28.existsSync(`${localBin}${ext}`)
2155
2155
  );
@@ -2167,17 +2167,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
2167
2167
  } catch {
2168
2168
  resolvedScriptPath = this._scriptPath;
2169
2169
  }
2170
- executableDir = path27.resolve(
2171
- path27.dirname(resolvedScriptPath),
2170
+ executableDir = path28.resolve(
2171
+ path28.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 = path27.basename(
2178
+ const legacyName = path28.basename(
2179
2179
  this._scriptPath,
2180
- path27.extname(this._scriptPath)
2180
+ path28.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(path27.extname(executableFile));
2191
+ launchWithNode = sourceExt.includes(path28.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 = path27.basename(filename, path27.extname(filename));
3038
+ this._name = path28.basename(filename, path28.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(path28) {
3053
- if (path28 === void 0) return this._executableDir;
3054
- this._executableDir = path28;
3052
+ executableDir(path29) {
3053
+ if (path29 === void 0) return this._executableDir;
3054
+ this._executableDir = path29;
3055
3055
  return this;
3056
3056
  }
3057
3057
  /**
@@ -6516,8 +6516,8 @@ var require_utils = __commonJS({
6516
6516
  }
6517
6517
  return ind;
6518
6518
  }
6519
- function removeDotSegments(path27) {
6520
- let input = path27;
6519
+ function removeDotSegments(path28) {
6520
+ let input = path28;
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 [path27, query] = wsComponent.resourceName.split("?");
6720
- wsComponent.path = path27 && path27 !== "/" ? path27 : void 0;
6719
+ const [path28, query] = wsComponent.resourceName.split("?");
6720
+ wsComponent.path = path28 && path28 !== "/" ? path28 : void 0;
6721
6721
  wsComponent.query = query;
6722
6722
  wsComponent.resourceName = void 0;
6723
6723
  }
@@ -10098,7 +10098,7 @@ var require_windows = __commonJS({
10098
10098
  module2.exports = isexe;
10099
10099
  isexe.sync = sync;
10100
10100
  var fs28 = require("fs");
10101
- function checkPathExt(path27, options) {
10101
+ function checkPathExt(path28, 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 && path27.substr(-p.length).toLowerCase() === p) {
10112
+ if (p && path28.substr(-p.length).toLowerCase() === p) {
10113
10113
  return true;
10114
10114
  }
10115
10115
  }
10116
10116
  return false;
10117
10117
  }
10118
- function checkStat(stat, path27, options) {
10118
+ function checkStat(stat, path28, options) {
10119
10119
  if (!stat.isSymbolicLink() && !stat.isFile()) {
10120
10120
  return false;
10121
10121
  }
10122
- return checkPathExt(path27, options);
10122
+ return checkPathExt(path28, options);
10123
10123
  }
10124
- function isexe(path27, options, cb) {
10125
- fs28.stat(path27, function(er, stat) {
10126
- cb(er, er ? false : checkStat(stat, path27, options));
10124
+ function isexe(path28, options, cb) {
10125
+ fs28.stat(path28, function(er, stat) {
10126
+ cb(er, er ? false : checkStat(stat, path28, options));
10127
10127
  });
10128
10128
  }
10129
- function sync(path27, options) {
10130
- return checkStat(fs28.statSync(path27), path27, options);
10129
+ function sync(path28, options) {
10130
+ return checkStat(fs28.statSync(path28), path28, options);
10131
10131
  }
10132
10132
  }
10133
10133
  });
@@ -10138,13 +10138,13 @@ var require_mode = __commonJS({
10138
10138
  module2.exports = isexe;
10139
10139
  isexe.sync = sync;
10140
10140
  var fs28 = require("fs");
10141
- function isexe(path27, options, cb) {
10142
- fs28.stat(path27, function(er, stat) {
10141
+ function isexe(path28, options, cb) {
10142
+ fs28.stat(path28, function(er, stat) {
10143
10143
  cb(er, er ? false : checkStat(stat, options));
10144
10144
  });
10145
10145
  }
10146
- function sync(path27, options) {
10147
- return checkStat(fs28.statSync(path27), options);
10146
+ function sync(path28, options) {
10147
+ return checkStat(fs28.statSync(path28), options);
10148
10148
  }
10149
10149
  function checkStat(stat, options) {
10150
10150
  return stat.isFile() && checkMode(stat, options);
@@ -10177,7 +10177,7 @@ var require_isexe = __commonJS({
10177
10177
  }
10178
10178
  module2.exports = isexe;
10179
10179
  isexe.sync = sync;
10180
- function isexe(path27, options, cb) {
10180
+ function isexe(path28, options, cb) {
10181
10181
  if (typeof options === "function") {
10182
10182
  cb = options;
10183
10183
  options = {};
@@ -10187,7 +10187,7 @@ var require_isexe = __commonJS({
10187
10187
  throw new TypeError("callback not provided");
10188
10188
  }
10189
10189
  return new Promise(function(resolve12, reject) {
10190
- isexe(path27, options || {}, function(er, is) {
10190
+ isexe(path28, options || {}, function(er, is) {
10191
10191
  if (er) {
10192
10192
  reject(er);
10193
10193
  } else {
@@ -10196,7 +10196,7 @@ var require_isexe = __commonJS({
10196
10196
  });
10197
10197
  });
10198
10198
  }
10199
- core(path27, options || {}, function(er, is) {
10199
+ core(path28, 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(path27, options) {
10209
+ function sync(path28, options) {
10210
10210
  try {
10211
- return core.sync(path27, options || {});
10211
+ return core.sync(path28, 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 path27 = require("path");
10227
+ var path28 = 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" });
@@ -10262,7 +10262,7 @@ var require_which = __commonJS({
10262
10262
  return opt.all && found.length ? resolve12(found) : reject(getNotFoundError(cmd));
10263
10263
  const ppRaw = pathEnv[i];
10264
10264
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
10265
- const pCmd = path27.join(pathPart, cmd);
10265
+ const pCmd = path28.join(pathPart, cmd);
10266
10266
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
10267
10267
  resolve12(subStep(p, i, 0));
10268
10268
  });
@@ -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 = path27.join(pathPart, cmd);
10292
+ const pCmd = path28.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 path27 = require("path");
10340
+ var path28 = 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 ? path27.delimiter : void 0
10358
+ pathExt: withoutPathExt ? path28.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 = path27.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
10367
+ resolved = path28.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 [path27, argument] = match[0].replace(/#! ?/, "").split(" ");
10422
- const binary = path27.split("/").pop();
10421
+ const [path28, argument] = match[0].replace(/#! ?/, "").split(" ");
10422
+ const binary = path28.split("/").pop();
10423
10423
  if (binary === "env") {
10424
10424
  return argument;
10425
10425
  }
@@ -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 path27 = require("path");
10457
+ var path28 = 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 = path27.normalize(parsed.command);
10482
+ parsed.command = path28.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(" ");
@@ -10801,10 +10801,20 @@ var COMMON_CALL_HELP = `
10801
10801
  Input: omitted arguments mean {}; use --args-json for a JSON object or --args-file
10802
10802
  for nested or shell-sensitive input. Read the current schema with
10803
10803
  list --tool <name> --json; schema properties are JSON keys, not CLI flags.
10804
- Output: stdout contains the complete MCP JSON envelope by default. --output-json
10805
- saves that envelope to a new file and prints a compact receipt. --evidence-dir
10806
- saves an execution record in a new directory; it cannot be combined with
10807
- --output-json. Preserve stderr and the CLI exit code before parsing business data.
10804
+ Output: stdout carries the MCP JSON response by default. Its underlying
10805
+ business data may be large; size and completeness are controlled
10806
+ by the selected tool rather than this CLI.
10807
+ --output-json saves the complete envelope to a new file and prints a compact
10808
+ receipt. --evidence-dir saves an execution record in a new directory; it
10809
+ cannot be combined with --output-json. Preserve stderr and the CLI exit code
10810
+ before parsing business data. The complete result.json is evidence, not the
10811
+ default conversational payload.
10812
+ For more detail or smaller model context, use only schema-exposed
10813
+ reportSections, offset/limit, page/pageSize, or fields, selecting the smallest
10814
+ set needed for the next decision. Do not invent parameter names. includeReport,
10815
+ when exposed, may be large and is not promised to truncate. result.json saves
10816
+ the complete CLI response for the selected request; it cannot restore omitted
10817
+ business data. The detail contract does not change public CLI flags.
10808
10818
  For mcp-download-data, --verify-download submits once on one MCP connection,
10809
10819
  waits for that uuid, and only after a verifiable DONE collects range, disk-space,
10810
10820
  and bounded physical-file evidence. Files never prove continuous coverage.
@@ -10824,9 +10834,12 @@ same MCP connection through mcp-wait. Progress can remain unchanged while data i
10824
10834
  prepared; read stderr and do not restart from a progress warning. If isTerminal=true,
10825
10835
  finalize that run without waiting again. Interrupted waits identify the runId,
10826
10836
  codePath, and attemptFence for inspection; never restart automatically.`;
10827
- var REFERENCING_TOOLS = /* @__PURE__ */ new Set(["mcp-get-cache-diff", "mcp-get-cloud-data-list"]);
10828
10837
  var REFERENCE_SOURCE_TOOL = "mcp-download-data";
10829
- var REFERENCE_PROPERTY = "exchange_id";
10838
+ var REFERENCED_PROPERTIES_BY_TOOL = /* @__PURE__ */ new Map([
10839
+ ["mcp-get-cache-diff", ["exchange_id"]],
10840
+ ["mcp-get-cloud-data-list", ["exchange_id"]],
10841
+ ["mcp-get-data-range", ["exchange_id", "data_type"]]
10842
+ ]);
10830
10843
  function record(value) {
10831
10844
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
10832
10845
  }
@@ -10857,28 +10870,28 @@ var UNSUPPORTED_SCHEMA_KEYWORDS = [
10857
10870
  "propertyNames",
10858
10871
  "unevaluatedProperties"
10859
10872
  ];
10860
- function unsupportedSchemaConstraint(schemaValue, path27 = "inputSchema") {
10873
+ function unsupportedSchemaConstraint(schemaValue, path28 = "inputSchema") {
10861
10874
  const schema = record(schemaValue);
10862
- if (!schema) return path27;
10875
+ if (!schema) return path28;
10863
10876
  for (const keyword of UNSUPPORTED_SCHEMA_KEYWORDS) {
10864
- if (Object.prototype.hasOwnProperty.call(schema, keyword)) return `${path27}.${keyword}`;
10877
+ if (Object.prototype.hasOwnProperty.call(schema, keyword)) return `${path28}.${keyword}`;
10865
10878
  }
10866
10879
  const properties = record(schema.properties);
10867
10880
  if (properties) {
10868
10881
  for (const [name, property] of Object.entries(properties)) {
10869
- const unsupported = unsupportedSchemaConstraint(property, `${path27}.properties.${name}`);
10882
+ const unsupported = unsupportedSchemaConstraint(property, `${path28}.properties.${name}`);
10870
10883
  if (unsupported) return unsupported;
10871
10884
  }
10872
10885
  }
10873
10886
  if (schema.items !== void 0) {
10874
- const unsupported = unsupportedSchemaConstraint(schema.items, `${path27}.items`);
10887
+ const unsupported = unsupportedSchemaConstraint(schema.items, `${path28}.items`);
10875
10888
  if (unsupported) return unsupported;
10876
10889
  }
10877
10890
  return void 0;
10878
10891
  }
10879
- function explicitValue(schemaValue, path27) {
10892
+ function explicitValue(schemaValue, path28) {
10880
10893
  const schema = record(schemaValue);
10881
- if (!schema) return { available: false, missing: [path27] };
10894
+ if (!schema) return { available: false, missing: [path28] };
10882
10895
  if (Object.prototype.hasOwnProperty.call(schema, "example")) {
10883
10896
  return { available: true, value: cloneValue(schema.example), missing: [] };
10884
10897
  }
@@ -10900,13 +10913,13 @@ function explicitValue(schemaValue, path27) {
10900
10913
  const value = {};
10901
10914
  const missing = [];
10902
10915
  for (const name of required2) {
10903
- const child = explicitValue(properties[name], path27 ? `${path27}.${name}` : name);
10916
+ const child = explicitValue(properties[name], path28 ? `${path28}.${name}` : name);
10904
10917
  if (child.available) value[name] = child.value;
10905
10918
  missing.push(...child.missing);
10906
10919
  }
10907
10920
  return { available: missing.length === 0, value, missing };
10908
10921
  }
10909
- return { available: false, missing: [path27] };
10922
+ return { available: false, missing: [path28] };
10910
10923
  }
10911
10924
  function buildArgumentExample(tool) {
10912
10925
  const schema = record(tool.inputSchema);
@@ -10942,17 +10955,22 @@ function buildArgumentExample(tool) {
10942
10955
  }
10943
10956
  function relatedParameterHelp(tool, tools) {
10944
10957
  const name = typeof tool.name === "string" ? tool.name : "";
10945
- if (!REFERENCING_TOOLS.has(name)) return void 0;
10946
- const referenced = schemaProperty(tool, REFERENCE_PROPERTY);
10947
- if (typeof referenced?.description !== "string" || !referenced.description.includes(REFERENCE_SOURCE_TOOL)) return void 0;
10958
+ const properties = REFERENCED_PROPERTIES_BY_TOOL.get(name);
10959
+ if (!properties) return void 0;
10948
10960
  const source = tools.find((candidate) => candidate.name === REFERENCE_SOURCE_TOOL);
10949
- const sourceProperty = source && schemaProperty(source, REFERENCE_PROPERTY);
10950
- if (typeof sourceProperty?.description !== "string" || sourceProperty.description.length === 0) return void 0;
10951
- return [{
10952
- sourceTool: REFERENCE_SOURCE_TOOL,
10953
- property: REFERENCE_PROPERTY,
10954
- description: sourceProperty.description
10955
- }];
10961
+ if (!source) return void 0;
10962
+ const related = [];
10963
+ for (const property of properties) {
10964
+ const referenced = schemaProperty(tool, property);
10965
+ const sourceProperty = schemaProperty(source, property);
10966
+ if (typeof referenced?.description !== "string" || !referenced.description.includes(REFERENCE_SOURCE_TOOL) || typeof sourceProperty?.description !== "string" || sourceProperty.description.length === 0) return void 0;
10967
+ related.push({
10968
+ sourceTool: REFERENCE_SOURCE_TOOL,
10969
+ property,
10970
+ description: sourceProperty.description
10971
+ });
10972
+ }
10973
+ return related;
10956
10974
  }
10957
10975
  function buildCliUsage(tool, tools) {
10958
10976
  const name = typeof tool.name === "string" ? tool.name : "";
@@ -10967,7 +10985,11 @@ function buildCliUsage(tool, tools) {
10967
10985
  example: buildArgumentExample(tool)
10968
10986
  },
10969
10987
  output: {
10970
- default: "Read the complete MCP JSON envelope from stdout and preserve stderr and the CLI exit code.",
10988
+ default: "Read the MCP JSON envelope from stdout and preserve stderr and the CLI exit code. The selected tool may return a large business payload; use schema-exposed reportSections, offset/limit, page/pageSize, or fields to select detail for routine model context.",
10989
+ detail: {
10990
+ contract: "Follow the selected tool schema and do not invent parameter names. includeReport may be large; it is not a promise of truncation or a substitute for explicit selection where the schema provides it.",
10991
+ completeEvidence: "result.json in evidence mode is the complete CLI response for the selected request, page, and fields; it cannot recover underlying business data omitted by that request."
10992
+ },
10971
10993
  outputJson: {
10972
10994
  option: "--output-json <new-file>",
10973
10995
  result: "The complete envelope is saved; stdout is a compact receipt."
@@ -10999,11 +11021,11 @@ function buildCliUsage(tool, tools) {
10999
11021
 
11000
11022
  // src/index.ts
11001
11023
  var fs27 = __toESM(require("node:fs"), 1);
11002
- var path26 = __toESM(require("node:path"), 1);
11024
+ var path27 = __toESM(require("node:path"), 1);
11003
11025
 
11004
11026
  // src/cli.ts
11005
11027
  var fs15 = __toESM(require("fs"), 1);
11006
- var path14 = __toESM(require("path"), 1);
11028
+ var path15 = __toESM(require("path"), 1);
11007
11029
 
11008
11030
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/core.js
11009
11031
  var NEVER = Object.freeze({
@@ -11200,10 +11222,10 @@ function assignProp(target, prop, value) {
11200
11222
  configurable: true
11201
11223
  });
11202
11224
  }
11203
- function getElementAtPath(obj, path27) {
11204
- if (!path27)
11225
+ function getElementAtPath(obj, path28) {
11226
+ if (!path28)
11205
11227
  return obj;
11206
- return path27.reduce((acc, key) => acc?.[key], obj);
11228
+ return path28.reduce((acc, key) => acc?.[key], obj);
11207
11229
  }
11208
11230
  function promiseAllObject(promisesObj) {
11209
11231
  const keys = Object.keys(promisesObj);
@@ -11523,11 +11545,11 @@ function aborted(x, startIndex = 0) {
11523
11545
  }
11524
11546
  return false;
11525
11547
  }
11526
- function prefixIssues(path27, issues) {
11548
+ function prefixIssues(path28, issues) {
11527
11549
  return issues.map((iss) => {
11528
11550
  var _a;
11529
11551
  (_a = iss).path ?? (_a.path = []);
11530
- iss.path.unshift(path27);
11552
+ iss.path.unshift(path28);
11531
11553
  return iss;
11532
11554
  });
11533
11555
  }
@@ -18314,6 +18336,7 @@ var OFFICIAL_INSTALLERS = {
18314
18336
  full: {
18315
18337
  artifact: "zlt_client",
18316
18338
  version: "v1.14.2",
18339
+ installedVersion: "2026.09.11.4",
18317
18340
  sha256: "B65F39EAE5F37545D79F1149C3DC436B5ED9E1BEC8F21893FB91BD5A09081B0F"
18318
18341
  },
18319
18342
  // 2026-08-15 抬到 2026.08.14.5:公网 OSS 与内网镜像是同一份字节(ETag 113b3cff…、
@@ -18330,9 +18353,11 @@ var OFFICIAL_INSTALLERS = {
18330
18353
  // VSCODE_INSTALL_TYPE),full 槽位只在已装 full 的机器上参与升级判定。
18331
18354
  // **本版没有装机验证**:本机停在 2026.08.28.7,08-30 对 .7 做的那轮活体复核
18332
18355
  // (三进程起得来、ZLTHQHost 管道在、两轮 check:npm-live 全绿)不适用于本版。
18356
+ // Exact pinned bytes report FileVersion 2026.09.11.5; post-install InstallInfo.xml acceptance is pending.
18333
18357
  mini: {
18334
18358
  artifact: "zlt_plugin",
18335
18359
  version: "v1.14.2",
18360
+ installedVersion: "2026.09.11.5",
18336
18361
  sha256: "4E96214F0DDA6A6560D5C820D6BC230466BFF06095336C5250A90C44B4A52BB6"
18337
18362
  }
18338
18363
  },
@@ -18341,11 +18366,13 @@ var OFFICIAL_INSTALLERS = {
18341
18366
  full: {
18342
18367
  artifact: "zlt_client",
18343
18368
  version: "v1.14.2",
18369
+ installedVersion: "2026.09.11.4",
18344
18370
  sha256: "B65F39EAE5F37545D79F1149C3DC436B5ED9E1BEC8F21893FB91BD5A09081B0F"
18345
18371
  },
18346
18372
  mini: {
18347
18373
  artifact: "zlt_plugin",
18348
18374
  version: "v1.14.2",
18375
+ installedVersion: "2026.09.11.5",
18349
18376
  sha256: "4E96214F0DDA6A6560D5C820D6BC230466BFF06095336C5250A90C44B4A52BB6"
18350
18377
  }
18351
18378
  }
@@ -18357,6 +18384,10 @@ function officialInstallerUrl(slot, mirror = "public") {
18357
18384
  const spec = OFFICIAL_INSTALLERS[mirror][slot];
18358
18385
  return `${OFFICIAL_MIRROR_ROOTS[mirror]}/pkg/${spec.artifact}_${spec.version}.exe`;
18359
18386
  }
18387
+ function officialInstallerVersionIndexUrl(slot, mirror = "public") {
18388
+ const name = slot === "full" ? "zlt_client_versions.json" : "zlt_plugin_versions.json";
18389
+ return `${OFFICIAL_MIRROR_ROOTS[mirror]}/pkg/${name}`;
18390
+ }
18360
18391
  function officialVersionIndexUrl(mirror = "public") {
18361
18392
  return `${OFFICIAL_MIRROR_ROOTS[mirror]}/VscodeMarketPlugin/zlt_quant_version_index.json`;
18362
18393
  }
@@ -18412,8 +18443,8 @@ var defaultAssistantRuntimeConfig = {
18412
18443
  // OFFICIAL_INSTALLERS,结构上不可能只改 URL 不改这里。
18413
18444
  backserviceDownloadVersion: {
18414
18445
  OFFICIAL: {
18415
- full: OFFICIAL_INSTALLERS.public.full.version,
18416
- mini: OFFICIAL_INSTALLERS.public.mini.version
18446
+ full: OFFICIAL_INSTALLERS.public.full.installedVersion,
18447
+ mini: OFFICIAL_INSTALLERS.public.mini.installedVersion
18417
18448
  },
18418
18449
  REL: { full: "", mini: "" },
18419
18450
  DEBUG: {
@@ -18670,7 +18701,7 @@ function applyInstallerMirror(config2, mirror) {
18670
18701
  },
18671
18702
  backserviceDownloadVersion: {
18672
18703
  ...config2.backserviceDownloadVersion,
18673
- OFFICIAL: { full: pins.full.version, mini: pins.mini.version }
18704
+ OFFICIAL: { full: pins.full.installedVersion, mini: pins.mini.installedVersion }
18674
18705
  }
18675
18706
  };
18676
18707
  }
@@ -18932,7 +18963,7 @@ function pipeExists(clientRootDir, explicitPipeName) {
18932
18963
  // ../zlt-runtime-core/dist/runtime.js
18933
18964
  var fs7 = __toESM(require("fs"), 1);
18934
18965
  var os2 = __toESM(require("os"), 1);
18935
- var path7 = __toESM(require("path"), 1);
18966
+ var path8 = __toESM(require("path"), 1);
18936
18967
  var import_child_process4 = require("child_process");
18937
18968
 
18938
18969
  // ../zlt-runtime-core/dist/assistant-ipc.js
@@ -19640,8 +19671,8 @@ async function waitForPipe(workRoot, pipePrefix, timeout) {
19640
19671
  }
19641
19672
  async function readZltContent(workRoot, temporaryZltFile) {
19642
19673
  const fs28 = await import("fs");
19643
- const path27 = await import("path");
19644
- const zltFile = path27.join(workRoot, temporaryZltFile || "Temporary/zlt");
19674
+ const path28 = await import("path");
19675
+ const zltFile = path28.join(workRoot, temporaryZltFile || "Temporary/zlt");
19645
19676
  return fs28.existsSync(zltFile) ? fs28.readFileSync(zltFile, "utf-8").trim() : "";
19646
19677
  }
19647
19678
  async function pipeExists2(pipeName) {
@@ -19978,6 +20009,7 @@ function inspectRuntimeProcess(pid) {
19978
20009
  "if ($p) { [pscustomobject]@{ pid=[int]$p.ProcessId; executablePath=[string]$p.ExecutablePath; creationTime=$p.CreationDate.ToUniversalTime().ToString('o') } | ConvertTo-Json -Compress }"
19979
20010
  ].join("; ");
19980
20011
  const result = (0, import_child_process2.spawnSync)(powershell, ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", command], {
20012
+ stdio: ["ignore", "pipe", "pipe"],
19981
20013
  encoding: "utf8",
19982
20014
  env: { ...process.env, ZLT_RUNTIME_PID: String(pid) },
19983
20015
  timeout: 1e4,
@@ -20012,6 +20044,7 @@ var defaultRuntimeLifecycleDeps = {
20012
20044
  "Stop-Process -Id $p.ProcessId -Force -ErrorAction Stop"
20013
20045
  ].join("; ");
20014
20046
  const result = (0, import_child_process2.spawnSync)(powershell, ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", command], {
20047
+ stdio: ["ignore", "pipe", "pipe"],
20015
20048
  encoding: "utf8",
20016
20049
  env: {
20017
20050
  ...process.env,
@@ -20241,13 +20274,130 @@ function writeJson(filePath, value) {
20241
20274
 
20242
20275
  // ../zlt-runtime-core/dist/assistant-base-upgrade.js
20243
20276
  var fs5 = __toESM(require("fs"), 1);
20244
- var path5 = __toESM(require("path"), 1);
20277
+ var path6 = __toESM(require("path"), 1);
20245
20278
 
20246
20279
  // ../zlt-runtime-core/dist/version-gates.js
20247
20280
  function versionGatesDisabled() {
20248
20281
  return ""?.trim() === "1";
20249
20282
  }
20250
20283
 
20284
+ // ../zlt-runtime-core/dist/assistant-installer-descriptor.js
20285
+ var path5 = __toESM(require("path"), 1);
20286
+ async function resolveAssistantInstallerDescriptor(config2, installType, options = {}) {
20287
+ const normalized = normalizeAssistantInstallType(installType);
20288
+ const fallback = resolvePinnedAssistantInstallerDescriptor(config2, normalized);
20289
+ const mirror = matchingOfficialMirror(config2, normalized);
20290
+ if (!mirror)
20291
+ return fallback;
20292
+ const indexUrl = officialInstallerVersionIndexUrl(normalized, mirror);
20293
+ const fetchImpl = options.fetchImpl ?? ((url, init) => fetch(url, init));
20294
+ const controller = new AbortController();
20295
+ const timer = setTimeout(() => controller.abort(), config2.baseRequirementTimeout);
20296
+ try {
20297
+ const response = await fetchImpl(indexUrl, { signal: controller.signal });
20298
+ if (!response.ok)
20299
+ return { ...fallback, fallbackReason: `\u5B89\u88C5\u5305\u7248\u672C\u5217\u8868\u8BF7\u6C42\u5931\u8D25: HTTP ${response.status}` };
20300
+ const body = await response.json();
20301
+ if (!Array.isArray(body))
20302
+ return { ...fallback, fallbackReason: "\u5B89\u88C5\u5305\u7248\u672C\u5217\u8868\u4E0D\u662F JSON \u6570\u7EC4" };
20303
+ const records = body.filter((item) => Boolean(item) && typeof item === "object" && !Array.isArray(item)).flatMap((record5) => {
20304
+ const version2 = normalizeStableProductVersion(record5.version);
20305
+ return version2 ? [{ record: record5, version: version2 }] : [];
20306
+ }).sort((left, right) => compareNumericVersion(right.version, left.version));
20307
+ if (records.length === 0)
20308
+ return { ...fallback, fallbackReason: "\u5B89\u88C5\u5305\u7248\u672C\u5217\u8868\u6CA1\u6709\u7A33\u5B9A\u8BED\u4E49\u7248\u672C" };
20309
+ const latest = records[0];
20310
+ const latestRecords = records.filter((item) => item.version === latest.version);
20311
+ if (latestRecords.some((item) => JSON.stringify(item.record) !== JSON.stringify(latest.record))) {
20312
+ return { ...fallback, fallbackReason: `\u6700\u65B0\u5B89\u88C5\u5305\u7248\u672C ${latest.version} \u5B58\u5728\u91CD\u590D\u8BB0\u5F55` };
20313
+ }
20314
+ const validated = validateLatestRecord(latest.record, normalized);
20315
+ if (typeof validated === "string")
20316
+ return { ...fallback, fallbackReason: `\u6700\u65B0\u5B89\u88C5\u5305\u8BB0\u5F55\u65E0\u6548: ${validated}` };
20317
+ if (compareNumericVersion(validated.internalVersion, fallback.internalVersion) < 0) {
20318
+ return { ...fallback, fallbackReason: "\u6700\u65B0\u5B89\u88C5\u5305 internalVersion \u4F4E\u4E8E\u5185\u7F6E fallback" };
20319
+ }
20320
+ return {
20321
+ source: "dynamic",
20322
+ installType: normalized,
20323
+ url: new URL(validated.fileName, `${indexUrl.slice(0, indexUrl.lastIndexOf("/") + 1)}`).toString(),
20324
+ productVersion: latest.version,
20325
+ internalVersion: validated.internalVersion,
20326
+ fileName: validated.fileName,
20327
+ fileSize: validated.fileSize
20328
+ };
20329
+ } catch (error2) {
20330
+ return {
20331
+ ...fallback,
20332
+ fallbackReason: `\u5B89\u88C5\u5305\u7248\u672C\u5217\u8868\u4E0D\u53EF\u7528: ${error2 instanceof Error ? error2.message : String(error2)}`
20333
+ };
20334
+ } finally {
20335
+ clearTimeout(timer);
20336
+ }
20337
+ }
20338
+ function resolvePinnedAssistantInstallerDescriptor(config2, installType) {
20339
+ const normalized = normalizeAssistantInstallType(installType);
20340
+ const url = config2.backserviceDownload[config2.envMode][normalized]?.trim() || "";
20341
+ return {
20342
+ source: "pinned",
20343
+ installType: normalized,
20344
+ url,
20345
+ productVersion: path5.basename(safeUrlPath(url)).replace(/^zlt_(?:client|plugin)_/i, "").replace(/\.exe$/i, ""),
20346
+ internalVersion: config2.backserviceDownloadVersion[config2.envMode][normalized]?.trim() || "",
20347
+ fileName: path5.basename(safeUrlPath(url)) || "zlt-runtime-installer.exe",
20348
+ sha256: config2.backserviceDownloadSha256[config2.envMode][normalized]?.trim() || void 0
20349
+ };
20350
+ }
20351
+ function matchingOfficialMirror(config2, installType) {
20352
+ if (config2.envMode !== "OFFICIAL")
20353
+ return null;
20354
+ for (const mirror of ["public", "internal"]) {
20355
+ const pin = OFFICIAL_INSTALLERS[mirror][installType];
20356
+ if (config2.backserviceDownload.OFFICIAL[installType] === officialInstallerUrl(installType, mirror) && config2.backserviceDownloadVersion.OFFICIAL[installType] === pin.installedVersion && config2.backserviceDownloadSha256.OFFICIAL[installType].toUpperCase() === pin.sha256)
20357
+ return mirror;
20358
+ }
20359
+ return null;
20360
+ }
20361
+ function validateLatestRecord(record5, installType) {
20362
+ const internalVersion = typeof record5.internalVersion === "string" ? record5.internalVersion.trim() : "";
20363
+ if (!/^\d+(?:\.\d+)+$/.test(internalVersion) || internalVersion.split(".").some((part) => !Number.isSafeInteger(Number(part)))) {
20364
+ return "internalVersion \u7F3A\u5931\u6216\u4E0D\u662F\u5B89\u5168\u7684\u6570\u5B57\u70B9\u5206\u7248\u672C";
20365
+ }
20366
+ const fileName = typeof record5.fileName === "string" ? record5.fileName.trim() : "";
20367
+ if (!fileName || path5.basename(fileName) !== fileName || !/^[A-Za-z0-9._-]+\.exe$/i.test(fileName)) {
20368
+ return "fileName \u5FC5\u987B\u662F\u7EAF\u6587\u4EF6\u540D";
20369
+ }
20370
+ const prefix = installType === "full" ? "zlt_client_" : "zlt_plugin_";
20371
+ if (!fileName.toLowerCase().startsWith(prefix) || !fileName.toLowerCase().endsWith(".exe")) {
20372
+ return `fileName \u5FC5\u987B\u5339\u914D ${prefix}*.exe`;
20373
+ }
20374
+ const fileSize = Number.isSafeInteger(record5.fileSize) && Number(record5.fileSize) > 0 ? Number(record5.fileSize) : void 0;
20375
+ return { internalVersion, fileName, fileSize };
20376
+ }
20377
+ function normalizeStableProductVersion(value) {
20378
+ if (typeof value !== "string")
20379
+ return null;
20380
+ const normalized = value.trim().replace(/^v/i, "");
20381
+ return /^\d+\.\d+\.\d+$/.test(normalized) && normalized.split(".").every((part) => Number.isSafeInteger(Number(part))) ? normalized : null;
20382
+ }
20383
+ function compareNumericVersion(left, right) {
20384
+ const leftParts = left.split(".").map(Number);
20385
+ const rightParts = right.split(".").map(Number);
20386
+ for (let index = 0; index < Math.max(leftParts.length, rightParts.length); index++) {
20387
+ const delta = (leftParts[index] || 0) - (rightParts[index] || 0);
20388
+ if (delta !== 0)
20389
+ return delta < 0 ? -1 : 1;
20390
+ }
20391
+ return 0;
20392
+ }
20393
+ function safeUrlPath(url) {
20394
+ try {
20395
+ return new URL(url).pathname;
20396
+ } catch {
20397
+ return url;
20398
+ }
20399
+ }
20400
+
20251
20401
  // ../zlt-runtime-core/dist/assistant-base-upgrade.js
20252
20402
  var INSTALL_INFO_FILE = "InstallInfo.xml";
20253
20403
  var REQUIREMENT_CACHE_TTL_MS = 5 * 6e4;
@@ -20255,7 +20405,7 @@ var requirementCache = /* @__PURE__ */ new Map();
20255
20405
  var requirementInFlight = /* @__PURE__ */ new Map();
20256
20406
  function readInstalledAssistantBaseVersion(workRoot) {
20257
20407
  try {
20258
- const content = fs5.readFileSync(path5.join(workRoot, INSTALL_INFO_FILE), "utf-8");
20408
+ const content = fs5.readFileSync(path6.join(workRoot, INSTALL_INFO_FILE), "utf-8");
20259
20409
  const matched = content.match(/<InstallAppReleaseVer>(.*?)<\/InstallAppReleaseVer>/i);
20260
20410
  const version2 = matched?.[1]?.trim();
20261
20411
  return version2 ? version2 : null;
@@ -20264,8 +20414,8 @@ function readInstalledAssistantBaseVersion(workRoot) {
20264
20414
  }
20265
20415
  }
20266
20416
  function compareAssistantVersions(left, right) {
20267
- const leftParts = left.split(".");
20268
- const rightParts = right.split(".");
20417
+ const leftParts = left.trim().replace(/^v(?=\d)/i, "").split(".");
20418
+ const rightParts = right.trim().replace(/^v(?=\d)/i, "").split(".");
20269
20419
  const length = Math.max(leftParts.length, rightParts.length);
20270
20420
  for (let index = 0; index < length; index++) {
20271
20421
  const leftPart = parseVersionPart(leftParts[index]);
@@ -20306,7 +20456,9 @@ async function fetchRemoteBaseRequirement(config2, installType, options = {}) {
20306
20456
  return attempt;
20307
20457
  }
20308
20458
  async function checkAssistantBaseUpgrade(workRoot, config2, installType, options = {}) {
20309
- const pinnedVersion = resolveAssistantDownloadVersion(config2, installType);
20459
+ const normalizedInstallType = normalizeAssistantInstallType(installType);
20460
+ let installer = resolvePinnedAssistantInstallerDescriptor(config2, normalizedInstallType);
20461
+ let pinnedVersion = installer.internalVersion || resolveAssistantDownloadVersion(config2, installType);
20310
20462
  if (versionGatesDisabled()) {
20311
20463
  return {
20312
20464
  updateAvailable: false,
@@ -20316,10 +20468,16 @@ async function checkAssistantBaseUpgrade(workRoot, config2, installType, options
20316
20468
  pinnedVersion,
20317
20469
  remoteMin: null,
20318
20470
  blockedByPlugin: false,
20319
- installType: normalizeAssistantInstallType(installType),
20471
+ installType: normalizedInstallType,
20472
+ installer,
20473
+ installerFallbackReason: installer.fallbackReason,
20320
20474
  reason: "\u5185\u6D4B\u6784\u5EFA\u5DF2\u5173\u95ED\u667A\u80FD\u7BA1\u5BB6\u7248\u672C\u6821\u9A8C\uFF08ZLT_DISABLE_VERSION_GATES=1\uFF09\uFF0C\u8DF3\u8FC7\u672C\u4F53\u5347\u7EA7\u5224\u5B9A"
20321
20475
  };
20322
20476
  }
20477
+ installer = await resolveAssistantInstallerDescriptor(config2, normalizedInstallType, {
20478
+ fetchImpl: options.installerFetchImpl
20479
+ });
20480
+ pinnedVersion = installer.internalVersion || pinnedVersion;
20323
20481
  const requirement = await fetchRemoteBaseRequirement(config2, installType, options);
20324
20482
  const remoteMin = requirement?.min?.trim() || null;
20325
20483
  const installed = readInstalledAssistantBaseVersion(workRoot);
@@ -20334,7 +20492,9 @@ async function checkAssistantBaseUpgrade(workRoot, config2, installType, options
20334
20492
  remoteMin,
20335
20493
  // 远程要求高于我们钉住的安装包:装我们这份也满足不了,必须升级插件本身。
20336
20494
  blockedByPlugin: Boolean(remoteMin) && Boolean(pinnedVersion) && compareAssistantVersions(remoteMin, pinnedVersion) > 0,
20337
- installType: normalizeAssistantInstallType(installType)
20495
+ installType: normalizedInstallType,
20496
+ installer,
20497
+ installerFallbackReason: installer.fallbackReason
20338
20498
  };
20339
20499
  if (!installed) {
20340
20500
  return { ...verdict, reason: `\u672A\u80FD\u4ECE ${INSTALL_INFO_FILE} \u8BFB\u53D6\u667A\u80FD\u7BA1\u5BB6\u672C\u4F53\u7248\u672C\uFF0C\u8DF3\u8FC7\u672C\u4F53\u5347\u7EA7\u5224\u5B9A` };
@@ -20392,7 +20552,7 @@ function parseVersionPart(part) {
20392
20552
  // ../zlt-runtime-core/dist/runtime-install.js
20393
20553
  var fs6 = __toESM(require("fs"), 1);
20394
20554
  var os = __toESM(require("os"), 1);
20395
- var path6 = __toESM(require("path"), 1);
20555
+ var path7 = __toESM(require("path"), 1);
20396
20556
  var http = __toESM(require("http"), 1);
20397
20557
  var https = __toESM(require("https"), 1);
20398
20558
  var import_crypto3 = require("crypto");
@@ -20400,7 +20560,7 @@ var import_child_process3 = require("child_process");
20400
20560
  var MANAGED_PROCESS_EXIT_TIMEOUT_MS = 5e3;
20401
20561
  var MANAGED_PROCESS_EXIT_INTERVAL_MS = 200;
20402
20562
  var MANAGED_PROCESS_RESPAWN_RETRY_ROUNDS = 3;
20403
- var ASSISTANT_UPGRADE_FINISH_LOCK = path6.join("Temporary", "upgradeFinsh.lock");
20563
+ var ASSISTANT_UPGRADE_FINISH_LOCK = path7.join("Temporary", "upgradeFinsh.lock");
20404
20564
  async function installRuntimeTransaction(host, options) {
20405
20565
  if (!options.installerPath && options.installModules === false) {
20406
20566
  const baseRoot = options.installDir || await host.readRegistryInstallLocationRaw(options.config);
@@ -20428,10 +20588,11 @@ async function installRuntimeTransaction(host, options) {
20428
20588
  }
20429
20589
  }
20430
20590
  const installDir = options.installDir || host.getDefaultInstallPath();
20431
- const installerPath = options.installerPath || await downloadRuntimeInstaller(options.config, options.onProgress, options.installType || "full");
20591
+ const selectedInstaller = options.installerPath ? void 0 : options.installerDescriptor ?? await resolveAssistantInstallerDescriptor(options.config, options.installType || "full");
20592
+ const installerPath = options.installerPath || await downloadRuntimeInstaller(options.config, options.onProgress, options.installType || "full", selectedInstaller);
20432
20593
  fs6.mkdirSync(installDir, { recursive: true });
20433
- const installerLogPath = path6.join(installDir, "Temporary", "logs", "install.log");
20434
- fs6.mkdirSync(path6.dirname(installerLogPath), { recursive: true });
20594
+ const installerLogPath = path7.join(installDir, "Temporary", "logs", "install.log");
20595
+ fs6.mkdirSync(path7.dirname(installerLogPath), { recursive: true });
20435
20596
  options.onProgress?.(`\u6267\u884C\u5B89\u88C5\u7A0B\u5E8F: ${installerPath}`);
20436
20597
  const exitCode = await executeInstallerProcess(installerPath, installDir, installerLogPath);
20437
20598
  options.onProgress?.(`\u5B89\u88C5\u8FDB\u7A0B\u9000\u51FA\u7801: ${exitCode}`);
@@ -20446,6 +20607,12 @@ async function installRuntimeTransaction(host, options) {
20446
20607
  options.onProgress?.(`\u5B89\u88C5\u7A0B\u5E8F\u9000\u51FA\u7801\u975E 0\uFF0C\u4F46\u57FA\u7840 runtime \u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u7EE7\u7EED\u521D\u59CB\u5316: ${exitCode}`);
20447
20608
  }
20448
20609
  const workRoot = options.installModules === false ? await verifyInstalledBaseRoot(host, installDir, options.config, options.verifyTimeoutMs ?? 10 * 6e4, options.onProgress) : await verifyInstalledWorkRoot(host, installDir, options.config, options.verifyTimeoutMs ?? 10 * 6e4, options.onProgress);
20610
+ if (selectedInstaller?.source === "dynamic") {
20611
+ const installedVersion = readInstalledAssistantBaseVersion(workRoot);
20612
+ if (!installedVersion || compareAssistantVersions(installedVersion, selectedInstaller.internalVersion) < 0) {
20613
+ throw new Error(`\u667A\u80FD\u7BA1\u5BB6\u5B89\u88C5\u540E\u7248\u672C\u4E0D\u6EE1\u8DB3\u6240\u9009\u5B89\u88C5\u5305: \u5F53\u524D ${installedVersion || "\u672A\u77E5"}\uFF0C\u6240\u9009 ${selectedInstaller.internalVersion}`);
20614
+ }
20615
+ }
20449
20616
  if (options.installModules !== false) {
20450
20617
  await initializeInstalledRuntimeTransaction(host, workRoot, options.config, {
20451
20618
  installModules: true,
@@ -20466,7 +20633,7 @@ async function upgradeOutdatedInstalledBase(host, workRoot, config2, onProgress)
20466
20633
  if (!verdict.updateAvailable)
20467
20634
  return null;
20468
20635
  if (verdict.blockedByPlugin) {
20469
- onProgress?.(`\u5DF2\u5B89\u88C5\u7684\u667A\u80FD\u7BA1\u5BB6\u672C\u4F53\u4E3A ${verdict.installed ?? "\u672A\u77E5"}\uFF0C\u8981\u6C42 ${verdict.required}\uFF0C\u9AD8\u4E8E\u672C\u63D2\u4EF6\u5185\u7F6E\u7684\u5B89\u88C5\u5305\uFF0C\u8BF7\u5347\u7EA7 ZLT Quant \u63D2\u4EF6\u540E\u91CD\u8BD5`);
20636
+ onProgress?.(`\u5DF2\u5B89\u88C5\u7684\u667A\u80FD\u7BA1\u5BB6\u672C\u4F53\u4E3A ${verdict.installed ?? "\u672A\u77E5"}\uFF0C\u8981\u6C42 ${verdict.required}\uFF0C\u9AD8\u4E8E\u5F53\u524D\u7248\u672C\u5217\u8868\u4E2D\u53EF\u7528\u7684\u5B89\u88C5\u5305\uFF0C\u8BF7\u7B49\u5F85\u5B89\u88C5\u5305\u7248\u672C\u5217\u8868\u66F4\u65B0\u540E\u91CD\u8BD5`);
20470
20637
  return null;
20471
20638
  }
20472
20639
  onProgress?.(`\u5DF2\u5B89\u88C5\u7684\u667A\u80FD\u7BA1\u5BB6\u672C\u4F53\u8FC7\u65E7\uFF08${verdict.installed ?? "\u672A\u77E5"} \u2192 ${verdict.required}\uFF09\uFF0C\u5148\u8986\u76D6\u5B89\u88C5\u672C\u4F53`);
@@ -20517,7 +20684,7 @@ async function installMissingBacktestModulesTransaction(host, workRoot, config2,
20517
20684
  if (moduleIndex !== clientModuleIndex && moduleIndex !== TY_MODULE_INDEX)
20518
20685
  return;
20519
20686
  if (moduleIndex === clientModuleIndex) {
20520
- fs6.rmSync(path6.join(workRoot, ASSISTANT_UPGRADE_FINISH_LOCK), { force: true });
20687
+ fs6.rmSync(path7.join(workRoot, ASSISTANT_UPGRADE_FINISH_LOCK), { force: true });
20521
20688
  }
20522
20689
  await quiesceTyModuleProcesses(workRoot, onProgress, (selected) => {
20523
20690
  stoppedPayloadProcesses = [...stoppedPayloadProcesses, ...selected];
@@ -20536,7 +20703,7 @@ async function installMissingBacktestModulesTransaction(host, workRoot, config2,
20536
20703
  } else {
20537
20704
  await installBacktestModules(workRoot, upgradedZltContent, config2, onProgress, installHooks);
20538
20705
  }
20539
- fs6.rmSync(path6.join(workRoot, ASSISTANT_UPGRADE_FINISH_LOCK), { force: true });
20706
+ fs6.rmSync(path7.join(workRoot, ASSISTANT_UPGRADE_FINISH_LOCK), { force: true });
20540
20707
  }
20541
20708
  } catch (error2) {
20542
20709
  if (runtimeStopped || stoppedPayloadProcesses.length > 0) {
@@ -20563,14 +20730,14 @@ function shouldInstallBacktestModules(workRoot, config2) {
20563
20730
  async function upgradeAssistantBaseTransaction(host, workRoot, config2, onProgress, options = {}) {
20564
20731
  const verdict = options.verdict ?? await checkAssistantBaseUpgrade(workRoot, config2, await host.readRegistryInstallType(config2));
20565
20732
  if (verdict.blockedByPlugin) {
20566
- throw new Error(`\u8FDC\u7A0B\u8981\u6C42\u7684\u667A\u80FD\u7BA1\u5BB6\u7248\u672C ${verdict.required} \u9AD8\u4E8E\u5F53\u524D\u63D2\u4EF6\u5185\u7F6E\u7684\u5B89\u88C5\u5305 ${verdict.pinnedVersion}\uFF0C\u8BF7\u5148\u5347\u7EA7 ZLT Quant \u63D2\u4EF6`);
20733
+ throw new Error(`\u8FDC\u7A0B\u8981\u6C42\u7684\u667A\u80FD\u7BA1\u5BB6\u7248\u672C ${verdict.required} \u9AD8\u4E8E\u5F53\u524D\u7248\u672C\u5217\u8868\u4E2D\u53EF\u7528\u7684\u5B89\u88C5\u5305 ${verdict.pinnedVersion}`);
20567
20734
  }
20568
20735
  if (!verdict.updateAvailable)
20569
20736
  return verdict.installed || "";
20570
20737
  onProgress?.(`\u51C6\u5907\u8986\u76D6\u5B89\u88C5\u667A\u80FD\u7BA1\u5BB6\u672C\u4F53: ${verdict.installed} \u2192 ${verdict.required}`);
20571
20738
  const stopped = await quiesceRuntimeForBaseUpgrade(workRoot, config2, onProgress);
20572
20739
  try {
20573
- const installerPath = await downloadRuntimeInstaller(config2, onProgress, verdict.installType);
20740
+ const installerPath = await downloadRuntimeInstaller(config2, onProgress, verdict.installType, verdict.installer);
20574
20741
  await installRuntimeTransaction(host, {
20575
20742
  config: config2,
20576
20743
  installerPath,
@@ -20609,14 +20776,14 @@ function ensurePythonToolchain(workRoot) {
20609
20776
  if (!fs6.existsSync(targetPython)) {
20610
20777
  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`);
20611
20778
  }
20612
- const abiDll = path6.join(path6.dirname(targetPython), `python${PYTHON_SDK_ABI_TAG.replace(/^cp/, "")}.dll`);
20779
+ const abiDll = path7.join(path7.dirname(targetPython), `python${PYTHON_SDK_ABI_TAG.replace(/^cp/, "")}.dll`);
20613
20780
  if (!fs6.existsSync(abiDll)) {
20614
20781
  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`);
20615
20782
  }
20616
20783
  return targetPython;
20617
20784
  }
20618
20785
  function toolchainDownloadCacheDir() {
20619
- return path6.join(os.tmpdir(), "zlt-runtime-toolchains");
20786
+ return path7.join(os.tmpdir(), "zlt-runtime-toolchains");
20620
20787
  }
20621
20788
  async function ensureVerifiedToolchainAsset(options) {
20622
20789
  const { label, url, sha256, destination, timeoutMs, onProgress } = options;
@@ -20638,8 +20805,8 @@ async function ensureVerifiedToolchainAsset(options) {
20638
20805
  onProgress?.(`${label} SHA256 \u6821\u9A8C\u901A\u8FC7: ${sha256}`);
20639
20806
  }
20640
20807
  async function ensureManagedPipWheel(workRoot, config2, onProgress) {
20641
- const destination = path6.join(toolchainDownloadCacheDir(), "pip-26.1.2-py3-none-any.whl");
20642
- fs6.mkdirSync(path6.dirname(destination), { recursive: true });
20808
+ const destination = path7.join(toolchainDownloadCacheDir(), "pip-26.1.2-py3-none-any.whl");
20809
+ fs6.mkdirSync(path7.dirname(destination), { recursive: true });
20643
20810
  await ensureVerifiedToolchainAsset({
20644
20811
  label: "pip 26.1.2 wheel",
20645
20812
  url: config2.pythonPipWheelUrl,
@@ -20660,27 +20827,27 @@ function assertFileSha256(filePath, expectedSha256) {
20660
20827
  async function quiesceTyModuleProcesses(workRoot, onProgress, onWillStop) {
20661
20828
  if (process.platform !== "win32")
20662
20829
  return [];
20663
- const managedCodePath = path6.resolve(workRoot, "vscode", "Code.exe");
20664
- const jsserviceRoot = `${path6.resolve(workRoot, "jsservice")}${path6.sep}`.toLowerCase();
20665
- const managedGitRoot = path6.resolve(workRoot, "mingit");
20830
+ const managedCodePath = path7.resolve(workRoot, "vscode", "Code.exe");
20831
+ const jsserviceRoot = `${path7.resolve(workRoot, "jsservice")}${path7.sep}`.toLowerCase();
20832
+ const managedGitRoot = path7.resolve(workRoot, "mingit");
20666
20833
  assertPathInside(workRoot, managedGitRoot);
20667
20834
  const executablePaths = [
20668
- path6.join(workRoot, "zltaf", "zltaf.exe"),
20669
- path6.join(workRoot, "python", "python.exe"),
20670
- path6.join(workRoot, "mingit", "cmd", "git.exe"),
20671
- path6.join(workRoot, "zltHost", "ZltDcmClient.exe"),
20835
+ path7.join(workRoot, "zltaf", "zltaf.exe"),
20836
+ path7.join(workRoot, "python", "python.exe"),
20837
+ path7.join(workRoot, "mingit", "cmd", "git.exe"),
20838
+ path7.join(workRoot, "zltHost", "ZltDcmClient.exe"),
20672
20839
  managedCodePath
20673
20840
  ].map((candidate) => {
20674
- const resolved = path6.resolve(candidate);
20841
+ const resolved = path7.resolve(candidate);
20675
20842
  assertPathInside(workRoot, resolved);
20676
20843
  return resolved;
20677
20844
  });
20678
20845
  const installedExecutablePaths = executablePaths.filter((candidate) => fs6.existsSync(candidate));
20679
- const installedExecutableRoots = fs6.existsSync(managedGitRoot) ? [`${managedGitRoot}${path6.sep}`] : [];
20846
+ const installedExecutableRoots = fs6.existsSync(managedGitRoot) ? [`${managedGitRoot}${path7.sep}`] : [];
20680
20847
  if (installedExecutablePaths.length === 0 && installedExecutableRoots.length === 0)
20681
20848
  return [];
20682
20849
  const selectTyPayloadProcesses = () => listManagedRuntimeProcesses(installedExecutablePaths, installedExecutableRoots).filter((item) => {
20683
- if (path6.resolve(item.executablePath).toLowerCase() !== managedCodePath.toLowerCase())
20850
+ if (path7.resolve(item.executablePath).toLowerCase() !== managedCodePath.toLowerCase())
20684
20851
  return true;
20685
20852
  const commandLine = item.commandLine.replaceAll("/", "\\").toLowerCase();
20686
20853
  return commandLine.includes(jsserviceRoot) && commandLine.includes("--ms-enable-electron-run-as-node");
@@ -20738,12 +20905,12 @@ async function stopManagedRuntimeProcesses(workRoot, config2, onProgress, messag
20738
20905
  if (process.platform !== "win32")
20739
20906
  return [];
20740
20907
  const executablePaths = [
20741
- path6.join(workRoot, config2.hostPath),
20742
- path6.join(workRoot, config2.backservicePath),
20743
- path6.join(workRoot, "zltHost", "zlthost.exe"),
20744
- path6.join(workRoot, "zltaf", "zltaf.exe")
20908
+ path7.join(workRoot, config2.hostPath),
20909
+ path7.join(workRoot, config2.backservicePath),
20910
+ path7.join(workRoot, "zltHost", "zlthost.exe"),
20911
+ path7.join(workRoot, "zltaf", "zltaf.exe")
20745
20912
  ].map((candidate) => {
20746
- const resolved = path6.resolve(candidate);
20913
+ const resolved = path7.resolve(candidate);
20747
20914
  assertPathInside(workRoot, resolved);
20748
20915
  return resolved;
20749
20916
  });
@@ -20760,7 +20927,7 @@ async function stopManagedRuntimeProcesses(workRoot, config2, onProgress, messag
20760
20927
  throw new Error(`${messages.failed}: ${formatManagedProcessList(remaining)}\u3002\u8BF7\u5173\u95ED\u667A\u91CF\u901A\u76F8\u5173\u4EFB\u52A1\u540E\u91CD\u8BD5\u5B89\u88C5\u3002`);
20761
20928
  }
20762
20929
  }
20763
- const zltMarker = path6.resolve(workRoot, config2.temporaryZltFile || "Temporary/zlt");
20930
+ const zltMarker = path7.resolve(workRoot, config2.temporaryZltFile || "Temporary/zlt");
20764
20931
  assertPathInside(workRoot, zltMarker);
20765
20932
  fs6.rmSync(zltMarker, { force: true });
20766
20933
  if (running.length > 0)
@@ -20771,6 +20938,7 @@ function killManagedRuntimeProcesses(running) {
20771
20938
  const taskkill = windowsSystemToolPath("taskkill.exe");
20772
20939
  for (const item of running) {
20773
20940
  (0, import_child_process3.spawnSync)(taskkill, ["/PID", String(item.pid), "/T", "/F"], {
20941
+ stdio: ["ignore", "pipe", "pipe"],
20774
20942
  encoding: "utf8",
20775
20943
  timeout: 15e3,
20776
20944
  windowsHide: true
@@ -20804,6 +20972,7 @@ function listManagedRuntimeProcesses(executablePaths, executableRoots = []) {
20804
20972
  "-Command",
20805
20973
  command
20806
20974
  ], {
20975
+ stdio: ["ignore", "pipe", "pipe"],
20807
20976
  encoding: "utf8",
20808
20977
  env: { ...process.env, ZLT_MANAGED_RUNTIME_PATHS: encodedPaths },
20809
20978
  timeout: 15e3,
@@ -20832,7 +21001,7 @@ ${result.stderr || ""}`);
20832
21001
  return [];
20833
21002
  return [{
20834
21003
  pid,
20835
- name: typeof item.Name === "string" ? item.Name : path6.basename(item.ExecutablePath),
21004
+ name: typeof item.Name === "string" ? item.Name : path7.basename(item.ExecutablePath),
20836
21005
  executablePath: item.ExecutablePath,
20837
21006
  commandLine: typeof item.CommandLine === "string" ? item.CommandLine : ""
20838
21007
  }];
@@ -20840,10 +21009,10 @@ ${result.stderr || ""}`);
20840
21009
  }
20841
21010
  function windowsSystemToolPath(relativePath) {
20842
21011
  const systemRoot = process.env.SystemRoot || process.env.WINDIR;
20843
- if (!systemRoot || !path6.isAbsolute(systemRoot)) {
21012
+ if (!systemRoot || !path7.isAbsolute(systemRoot)) {
20844
21013
  throw new Error("\u65E0\u6CD5\u5B89\u5168\u5B9A\u4F4D Windows \u7CFB\u7EDF\u5DE5\u5177: SystemRoot \u672A\u8BBE\u7F6E");
20845
21014
  }
20846
- return path6.join(systemRoot, "System32", ...relativePath.split("/"));
21015
+ return path7.join(systemRoot, "System32", ...relativePath.split("/"));
20847
21016
  }
20848
21017
  function ensureGitToolchain(workRoot) {
20849
21018
  const targetGit = getGitExePath(workRoot);
@@ -20888,6 +21057,7 @@ function validatePythonSdkComplete(workRoot, config2) {
20888
21057
  "sys.exit(1 if missing else 0)"
20889
21058
  ].join("\n");
20890
21059
  const result = (0, import_child_process3.spawnSync)(pythonPath, ["-c", probe, JSON.stringify(pinned), JSON.stringify(imports)], {
21060
+ stdio: ["ignore", "pipe", "pipe"],
20891
21061
  encoding: "utf8",
20892
21062
  timeout: config2.pythonSdkImportTimeout,
20893
21063
  windowsHide: true
@@ -20995,22 +21165,29 @@ function buildManagedPipEnvironment(runtimeIndexUrl, baseEnvironment = process.e
20995
21165
  no_proxy: noProxy
20996
21166
  };
20997
21167
  }
20998
- async function downloadRuntimeInstaller(config2, onProgress, installType = "full") {
20999
- const url = resolveAssistantDownloadUrl(config2, installType);
21000
- const sha256 = resolveAssistantDownloadSha256(config2, installType);
21001
- const filename = path6.basename(new URL(url).pathname) || "zlt-runtime-installer.exe";
21002
- const dir = path6.join(os.tmpdir(), config2.downloadTempDir);
21003
- const destination = path6.join(dir, filename);
21168
+ async function downloadRuntimeInstaller(config2, onProgress, installType = "full", descriptor) {
21169
+ const selected = descriptor ?? await resolveAssistantInstallerDescriptor(config2, installType);
21170
+ const url = selected.url || resolveAssistantDownloadUrl(config2, installType);
21171
+ if (selected.source === "pinned" && !/^[a-fA-F0-9]{64}$/.test(selected.sha256 || "")) {
21172
+ throw new Error(`\u5F53\u524D\u73AF\u5883\u6A21\u5F0F ${config2.envMode} \u672A\u914D\u7F6E ${installType} \u5B89\u88C5\u5305 SHA256`);
21173
+ }
21174
+ const filename = selected.fileName || path7.basename(new URL(url).pathname) || "zlt-runtime-installer.exe";
21175
+ const dir = path7.join(os.tmpdir(), config2.downloadTempDir);
21176
+ const destination = path7.join(dir, filename);
21004
21177
  fs6.mkdirSync(dir, { recursive: true });
21005
21178
  onProgress?.(`\u4E0B\u8F7D\u5B89\u88C5\u5305: ${url}`);
21179
+ if (selected.fallbackReason)
21180
+ onProgress?.(`\u52A8\u6001\u5B89\u88C5\u5305\u4E0D\u53EF\u7528\uFF0C\u4F7F\u7528\u5185\u7F6E fallback: ${selected.fallbackReason}`);
21006
21181
  await downloadFile(url, destination);
21007
21182
  try {
21008
- assertFileSha256(destination, sha256);
21183
+ if (selected.source !== "dynamic") {
21184
+ assertFileSha256(destination, selected.sha256 || resolveAssistantDownloadSha256(config2, installType));
21185
+ }
21009
21186
  } catch (error2) {
21010
21187
  fs6.rmSync(destination, { force: true });
21011
21188
  throw error2;
21012
21189
  }
21013
- onProgress?.(`\u5B89\u88C5\u5305 SHA256 \u6821\u9A8C\u901A\u8FC7: ${sha256}`);
21190
+ onProgress?.(selected.source === "dynamic" ? `\u5B89\u88C5\u5305\u5DF2\u4E0B\u8F7D\uFF08\u7248\u672C\u5217\u8868 fileSize \u4EC5\u4F9B\u5C55\u793A: ${selected.fileSize ?? "\u672A\u63D0\u4F9B"}\uFF09` : `\u5B89\u88C5\u5305 SHA256 \u6821\u9A8C\u901A\u8FC7: ${selected.sha256}`);
21014
21191
  return destination;
21015
21192
  }
21016
21193
  function describeInstallerExitCode(exitCode) {
@@ -21143,7 +21320,7 @@ function downloadFile(url, destination, redirectCount = 0, timeoutMs = 0, initia
21143
21320
  if (redirectCount > 5) {
21144
21321
  return Promise.reject(new Error(`\u4E0B\u8F7D\u91CD\u5B9A\u5411\u8FC7\u591A: ${url}`));
21145
21322
  }
21146
- fs6.mkdirSync(path6.dirname(destination), { recursive: true });
21323
+ fs6.mkdirSync(path7.dirname(destination), { recursive: true });
21147
21324
  const partialPath = `${destination}.${process.pid}.${(0, import_crypto3.randomUUID)()}.part`;
21148
21325
  return new Promise((resolve12, reject) => {
21149
21326
  let settled = false;
@@ -21229,10 +21406,10 @@ function delay(ms) {
21229
21406
  return new Promise((resolve12) => setTimeout(resolve12, ms));
21230
21407
  }
21231
21408
  function getPythonExePath(workRoot) {
21232
- return path6.join(workRoot, "python", "python.exe");
21409
+ return path7.join(workRoot, "python", "python.exe");
21233
21410
  }
21234
21411
  function getGitExePath(workRoot) {
21235
- return path6.join(workRoot, "mingit", "cmd", "git.exe");
21412
+ return path7.join(workRoot, "mingit", "cmd", "git.exe");
21236
21413
  }
21237
21414
  function resolveManagedPythonExe(workRoot) {
21238
21415
  return getPythonExePath(workRoot || getDefaultInstallPath());
@@ -21250,19 +21427,19 @@ function getDefaultInstallPath() {
21250
21427
  if (process.platform === "win32") {
21251
21428
  return fs6.existsSync("D:\\") ? "D:\\ZLTClient" : "C:\\ZLTClient";
21252
21429
  }
21253
- return path6.join(os.homedir(), "ZLTClient");
21430
+ return path7.join(os.homedir(), "ZLTClient");
21254
21431
  }
21255
21432
  function getZltafExePath(workRoot) {
21256
- return path6.join(workRoot, "zltaf", "zltaf.exe");
21433
+ return path7.join(workRoot, "zltaf", "zltaf.exe");
21257
21434
  }
21258
21435
  function getZltafConfigPath(workRoot) {
21259
- return path6.join(workRoot, "zltaf", "application-local.properties");
21436
+ return path7.join(workRoot, "zltaf", "application-local.properties");
21260
21437
  }
21261
21438
  function assertPathInside(root2, targetPath) {
21262
- const resolvedRoot = path6.resolve(root2);
21263
- const resolvedTarget = path6.resolve(targetPath);
21264
- const relative2 = path6.relative(resolvedRoot, resolvedTarget);
21265
- if (relative2.startsWith("..") || path6.isAbsolute(relative2)) {
21439
+ const resolvedRoot = path7.resolve(root2);
21440
+ const resolvedTarget = path7.resolve(targetPath);
21441
+ const relative2 = path7.relative(resolvedRoot, resolvedTarget);
21442
+ if (relative2.startsWith("..") || path7.isAbsolute(relative2)) {
21266
21443
  throw new Error(`\u62D2\u7EDD\u5199\u5165\u5B89\u88C5\u76EE\u5F55\u5916\u8DEF\u5F84: ${resolvedTarget}`);
21267
21444
  }
21268
21445
  }
@@ -21278,7 +21455,7 @@ function normalizeRequiredPythonPackages(config2) {
21278
21455
  function areBundledSitePackagesPresent(workRoot, packages) {
21279
21456
  if (packages.some(hasPythonVersionSpecifier))
21280
21457
  return false;
21281
- const sitePackages = path6.join(workRoot, "python", "Lib", "site-packages");
21458
+ const sitePackages = path7.join(workRoot, "python", "Lib", "site-packages");
21282
21459
  if (!fs6.existsSync(sitePackages))
21283
21460
  return false;
21284
21461
  let entries = [];
@@ -21292,10 +21469,10 @@ function areBundledSitePackagesPresent(workRoot, packages) {
21292
21469
  const normalized = normalizePythonPackageName(requirementName);
21293
21470
  const importName = pythonDistributionImportName(packageName);
21294
21471
  const candidateFiles = [
21295
- path6.join(sitePackages, requirementName, "__init__.py"),
21296
- path6.join(sitePackages, `${requirementName}.py`),
21297
- path6.join(sitePackages, importName, "__init__.py"),
21298
- path6.join(sitePackages, `${importName}.py`)
21472
+ path7.join(sitePackages, requirementName, "__init__.py"),
21473
+ path7.join(sitePackages, `${requirementName}.py`),
21474
+ path7.join(sitePackages, importName, "__init__.py"),
21475
+ path7.join(sitePackages, `${importName}.py`)
21299
21476
  ];
21300
21477
  return candidateFiles.some((candidate) => fs6.existsSync(candidate)) || entries.some((entry) => entry.startsWith(`${normalized}-`) && (entry.endsWith(".dist-info") || entry.endsWith(".egg-info")));
21301
21478
  });
@@ -21326,7 +21503,7 @@ function getDefaultInstallPath2() {
21326
21503
  if (process.platform === "win32") {
21327
21504
  return fs7.existsSync("D:\\") ? "D:\\ZLTClient" : "C:\\ZLTClient";
21328
21505
  }
21329
- return path7.join(os2.homedir(), "ZLTClient");
21506
+ return path8.join(os2.homedir(), "ZLTClient");
21330
21507
  }
21331
21508
  function validateWorkRootComplete(workRoot, _config) {
21332
21509
  if (!fs7.existsSync(workRoot)) {
@@ -21346,7 +21523,7 @@ function validateWorkRootComplete(workRoot, _config) {
21346
21523
  function validateAssistantBaseComplete(workRoot, config2) {
21347
21524
  if (!fs7.existsSync(workRoot))
21348
21525
  return { complete: false, reason: `\u5DE5\u7A0B\u8DEF\u5F84\u4E0D\u5B58\u5728: ${workRoot}` };
21349
- const hostPath = path7.join(workRoot, config2.hostPath);
21526
+ const hostPath = path8.join(workRoot, config2.hostPath);
21350
21527
  return fs7.existsSync(hostPath) ? { complete: true } : { complete: false, reason: `\u7F3A\u5C11\u667A\u80FD\u7BA1\u5BB6\u7A0B\u5E8F: ${hostPath}` };
21351
21528
  }
21352
21529
  function validateDependencyWorkRootComplete(workRoot, config2) {
@@ -21371,7 +21548,7 @@ function validateRuntimeLaunchReady(workRoot, config2) {
21371
21548
  return { complete: true };
21372
21549
  }
21373
21550
  function ensureUsersProjectsDirectory(workRoot) {
21374
- const projectsDir = path7.join(workRoot, "Users", "projects");
21551
+ const projectsDir = path8.join(workRoot, "Users", "projects");
21375
21552
  if (fs7.existsSync(projectsDir)) {
21376
21553
  if (!fs7.statSync(projectsDir).isDirectory()) {
21377
21554
  throw new Error(`Users\\projects \u8DEF\u5F84\u5DF2\u5B58\u5728\u4F46\u4E0D\u662F\u76EE\u5F55: ${projectsDir}`);
@@ -21417,7 +21594,7 @@ async function resolveRuntimeRoot(config2, options = {}) {
21417
21594
  const workRoot = candidate?.trim();
21418
21595
  if (!workRoot)
21419
21596
  continue;
21420
- const key = path7.resolve(workRoot).toLowerCase();
21597
+ const key = path8.resolve(workRoot).toLowerCase();
21421
21598
  if (seen.has(key))
21422
21599
  continue;
21423
21600
  seen.add(key);
@@ -21460,7 +21637,7 @@ async function runDoctor(config2, options = {}) {
21460
21637
  }
21461
21638
  const assistant = workRoot ? validateWorkRootComplete(workRoot, config2) : { complete: false, reason: "\u672A\u53D1\u73B0\u53EF\u7528 InstallLocation" };
21462
21639
  const dependency = workRoot ? validateDependencyWorkRootComplete(workRoot, config2) : { complete: false, reason: "\u672A\u53D1\u73B0\u53EF\u7528 InstallLocation" };
21463
- const zltFile = workRoot ? path7.join(workRoot, config2.temporaryZltFile) : void 0;
21640
+ const zltFile = workRoot ? path8.join(workRoot, config2.temporaryZltFile) : void 0;
21464
21641
  let pipePath;
21465
21642
  let ipcReachable = false;
21466
21643
  const explicitPipeName = process.env.ZLT_PIPE_NAME?.trim();
@@ -21509,13 +21686,13 @@ function startZltafRuntime(workRoot, config2) {
21509
21686
  if (!fs7.existsSync(configPath)) {
21510
21687
  throw new Error(`ZLTAF \u914D\u7F6E\u4E0D\u5B58\u5728: ${configPath}`);
21511
21688
  }
21512
- const tmpDir = path7.join(workRoot, "zltaf", "tmp");
21689
+ const tmpDir = path8.join(workRoot, "zltaf", "tmp");
21513
21690
  fs7.mkdirSync(tmpDir, { recursive: true });
21514
21691
  const child = (0, import_child_process4.spawn)(zltafPath, [
21515
21692
  `-Dconfig.path=${configPath}`,
21516
21693
  `-Djava.io.tmpdir=${tmpDir}`
21517
21694
  ], {
21518
- cwd: path7.dirname(zltafPath),
21695
+ cwd: path8.dirname(zltafPath),
21519
21696
  detached: true,
21520
21697
  stdio: "ignore",
21521
21698
  windowsHide: true
@@ -21580,15 +21757,15 @@ async function ensureAssistantHostRunning(workRoot, config2, onProgress, options
21580
21757
  if (zltContent && masterPipeExists(zltContent))
21581
21758
  return zltContent;
21582
21759
  }
21583
- 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: ${path7.join(workRoot, config2.temporaryZltFile)}`);
21760
+ 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: ${path8.join(workRoot, config2.temporaryZltFile)}`);
21584
21761
  }
21585
- var ASSISTANT_UPGRADE_FINISH_LOCK2 = path7.join("Temporary", "upgradeFinsh.lock");
21762
+ var ASSISTANT_UPGRADE_FINISH_LOCK2 = path8.join("Temporary", "upgradeFinsh.lock");
21586
21763
  function launchAssistantHost(workRoot, config2, onProgress) {
21587
- const hostPath = path7.join(workRoot, config2.hostPath);
21764
+ const hostPath = path8.join(workRoot, config2.hostPath);
21588
21765
  onProgress?.("\u542F\u52A8\u667A\u80FD\u7BA1\u5BB6");
21589
21766
  const { ELECTRON_RUN_AS_NODE: _dropped, ...env } = process.env;
21590
21767
  const child = (0, import_child_process4.spawn)(hostPath, ["startwithplugin", "selfstart"], {
21591
- cwd: path7.dirname(hostPath),
21768
+ cwd: path8.dirname(hostPath),
21592
21769
  detached: true,
21593
21770
  stdio: "ignore",
21594
21771
  windowsHide: true,
@@ -21605,7 +21782,7 @@ async function locateInstalledRuntime(config2) {
21605
21782
  return workRoot;
21606
21783
  }
21607
21784
  async function waitForUpgradedAssistantClient(workRoot, config2, onProgress, versionBefore) {
21608
- const finishLockPath = path7.join(workRoot, ASSISTANT_UPGRADE_FINISH_LOCK2);
21785
+ const finishLockPath = path8.join(workRoot, ASSISTANT_UPGRADE_FINISH_LOCK2);
21609
21786
  const finishStartedAt = Date.now();
21610
21787
  const versionRaised = () => {
21611
21788
  if (!versionBefore)
@@ -21668,21 +21845,21 @@ function delay2(ms) {
21668
21845
  return delay(ms);
21669
21846
  }
21670
21847
  function getZltafExePath2(workRoot) {
21671
- return path7.join(workRoot, "zltaf", "zltaf.exe");
21848
+ return path8.join(workRoot, "zltaf", "zltaf.exe");
21672
21849
  }
21673
21850
  function getZltafConfigPath2(workRoot) {
21674
- return path7.join(workRoot, "zltaf", "application-local.properties");
21851
+ return path8.join(workRoot, "zltaf", "application-local.properties");
21675
21852
  }
21676
21853
  function resolveZltafLaunchConfigPath(workRoot, config2) {
21677
21854
  if (config2.zltafConfigFile === ZLTAF_CONFIG_FILE_DEFAULT) {
21678
21855
  return getZltafConfigPath2(workRoot);
21679
21856
  }
21680
- const preferred = path7.join(workRoot, "zltaf", config2.zltafConfigFile);
21857
+ const preferred = path8.join(workRoot, "zltaf", config2.zltafConfigFile);
21681
21858
  if (fs7.existsSync(preferred)) {
21682
21859
  return preferred;
21683
21860
  }
21684
21861
  const base = getZltafConfigPath2(workRoot);
21685
- process.stderr.write(`[zlt-runtime] ZLTAF \u914D\u7F6E ${config2.zltafConfigFile} \u4E0D\u5B58\u5728\uFF0C\u56DE\u9000\u5230 ${path7.basename(base)}
21862
+ process.stderr.write(`[zlt-runtime] ZLTAF \u914D\u7F6E ${config2.zltafConfigFile} \u4E0D\u5B58\u5728\uFF0C\u56DE\u9000\u5230 ${path8.basename(base)}
21686
21863
  `);
21687
21864
  return base;
21688
21865
  }
@@ -21707,7 +21884,7 @@ async function waitForZltafPipe(workRoot, config2, options) {
21707
21884
  // ../zlt-runtime-core/dist/auth.js
21708
21885
  var fs9 = __toESM(require("fs"), 1);
21709
21886
  var os3 = __toESM(require("os"), 1);
21710
- var path8 = __toESM(require("path"), 1);
21887
+ var path9 = __toESM(require("path"), 1);
21711
21888
 
21712
21889
  // ../zlt-runtime-core/dist/private-path.js
21713
21890
  var fs8 = __toESM(require("node:fs"), 1);
@@ -21758,13 +21935,13 @@ function resolveZltQuantHome(env = process.env) {
21758
21935
  const configuredHome = env.ZLTQUANT_HOME?.trim();
21759
21936
  if (configuredHome)
21760
21937
  return expandHome(configuredHome);
21761
- return path8.join(os3.homedir(), ".zltquant");
21938
+ return path9.join(os3.homedir(), ".zltquant");
21762
21939
  }
21763
21940
  function resolveCredentialsPath(env = process.env) {
21764
21941
  const configuredPath = env.ZLTQUANT_CREDENTIALS?.trim();
21765
21942
  if (configuredPath)
21766
21943
  return expandHome(configuredPath);
21767
- return path8.join(resolveZltQuantHome(env), "credentials.json");
21944
+ return path9.join(resolveZltQuantHome(env), "credentials.json");
21768
21945
  }
21769
21946
  function readCredentials(env = process.env) {
21770
21947
  const credentialsPath = resolveCredentialsPath(env);
@@ -21813,7 +21990,7 @@ function writeCredentials(input, env = process.env) {
21813
21990
  source,
21814
21991
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
21815
21992
  };
21816
- fs9.mkdirSync(path8.dirname(credentialsPath), { recursive: true });
21993
+ fs9.mkdirSync(path9.dirname(credentialsPath), { recursive: true });
21817
21994
  const tempPath = `${credentialsPath}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`;
21818
21995
  try {
21819
21996
  if (source === "zlt-mcp-device-login") {
@@ -21920,9 +22097,9 @@ function expandHome(input) {
21920
22097
  if (input === "~")
21921
22098
  return os3.homedir();
21922
22099
  if (input.startsWith("~/") || input.startsWith("~\\")) {
21923
- return path8.join(os3.homedir(), input.slice(2));
22100
+ return path9.join(os3.homedir(), input.slice(2));
21924
22101
  }
21925
- return path8.resolve(input);
22102
+ return path9.resolve(input);
21926
22103
  }
21927
22104
  function tryReadCredentials(env) {
21928
22105
  try {
@@ -22032,7 +22209,7 @@ function persistDeviceAuthorization(grant, env) {
22032
22209
  throw new DeviceAuthorizationError("credentials_conflict", "Persisted device credential is not effective");
22033
22210
  return { status: "success", authStatus: authStatus2 };
22034
22211
  }
22035
- async function requestJson(options, base, path27, payload, allowPoll400 = false) {
22212
+ async function requestJson(options, base, path28, payload, allowPoll400 = false) {
22036
22213
  const controller = new AbortController();
22037
22214
  const externalAbort = () => controller.abort();
22038
22215
  if (options.signal?.aborted)
@@ -22041,7 +22218,7 @@ async function requestJson(options, base, path27, payload, allowPoll400 = false)
22041
22218
  options.signal?.addEventListener("abort", externalAbort, { once: true });
22042
22219
  const timeout = setTimeout(() => controller.abort(), options.requestTimeoutMs ?? 15e3);
22043
22220
  try {
22044
- const response = await (options.fetch ?? globalThis.fetch)(new URL(path27, base), {
22221
+ const response = await (options.fetch ?? globalThis.fetch)(new URL(path28, base), {
22045
22222
  method: "POST",
22046
22223
  redirect: "error",
22047
22224
  headers: { "content-type": "application/json" },
@@ -22175,7 +22352,7 @@ var import_node_crypto = require("node:crypto");
22175
22352
  var fs10 = __toESM(require("node:fs"), 1);
22176
22353
  var net2 = __toESM(require("node:net"), 1);
22177
22354
  var os4 = __toESM(require("node:os"), 1);
22178
- var path9 = __toESM(require("node:path"), 1);
22355
+ var path10 = __toESM(require("node:path"), 1);
22179
22356
  function urlEncode(value) {
22180
22357
  let result = "";
22181
22358
  for (const code of Buffer.from(value, "utf8")) {
@@ -22328,7 +22505,7 @@ var ZltafHttpPacket = class {
22328
22505
  }
22329
22506
  }
22330
22507
  };
22331
- var LOG_FILE = path9.join(os4.tmpdir(), "zlt-mcp-proxy.log");
22508
+ var LOG_FILE = path10.join(os4.tmpdir(), "zlt-mcp-proxy.log");
22332
22509
  var pendingLogLines = [];
22333
22510
  var logWriteInFlight = false;
22334
22511
  function log(tag, message) {
@@ -22527,17 +22704,17 @@ __export(config_exports, {
22527
22704
  resolveDefaultRuntimeConfigPath: () => resolveDefaultRuntimeConfigPath
22528
22705
  });
22529
22706
  var fs11 = __toESM(require("fs"), 1);
22530
- var path10 = __toESM(require("path"), 1);
22707
+ var path11 = __toESM(require("path"), 1);
22531
22708
  function loadConfig(configPath) {
22532
22709
  const raw = fs11.readFileSync(configPath, "utf-8");
22533
22710
  return JSON.parse(raw);
22534
22711
  }
22535
22712
  function resolveDefaultConfigPath() {
22536
22713
  if (process.env.ZLT_MCP_CONFIG) return process.env.ZLT_MCP_CONFIG;
22537
- const cwdCandidate = path10.resolve(process.cwd(), "config.json");
22714
+ const cwdCandidate = path11.resolve(process.cwd(), "config.json");
22538
22715
  const candidates = [
22539
- path10.resolve(path10.dirname(process.argv[1] || ""), "..", "config.json"),
22540
- path10.resolve(path10.dirname(process.argv[1] || ""), "config.json"),
22716
+ path11.resolve(path11.dirname(process.argv[1] || ""), "..", "config.json"),
22717
+ path11.resolve(path11.dirname(process.argv[1] || ""), "config.json"),
22541
22718
  cwdCandidate
22542
22719
  ];
22543
22720
  for (const candidate of candidates) {
@@ -22548,9 +22725,9 @@ function resolveDefaultConfigPath() {
22548
22725
  function resolveDefaultRuntimeConfigPath() {
22549
22726
  if (process.env.ZLT_RUNTIME_CONFIG) return process.env.ZLT_RUNTIME_CONFIG;
22550
22727
  const candidates = [
22551
- path10.resolve(path10.dirname(process.argv[1] || ""), "..", "runtime.cfg.json"),
22552
- path10.resolve(path10.dirname(process.argv[1] || ""), "runtime.cfg.json"),
22553
- path10.resolve(process.cwd(), "runtime.cfg.json")
22728
+ path11.resolve(path11.dirname(process.argv[1] || ""), "..", "runtime.cfg.json"),
22729
+ path11.resolve(path11.dirname(process.argv[1] || ""), "runtime.cfg.json"),
22730
+ path11.resolve(process.cwd(), "runtime.cfg.json")
22554
22731
  ];
22555
22732
  return candidates.find((candidate) => fs11.existsSync(candidate));
22556
22733
  }
@@ -22587,7 +22764,7 @@ function hasHighBytes(str) {
22587
22764
 
22588
22765
  // src/download-verification.ts
22589
22766
  var fs12 = __toESM(require("node:fs"), 1);
22590
- var path11 = __toESM(require("node:path"), 1);
22767
+ var path12 = __toESM(require("node:path"), 1);
22591
22768
  var MAX_INVENTORY_ENTRIES = 25e3;
22592
22769
  var MAX_INVENTORY_DEPTH = 8;
22593
22770
  var SAFE_SEGMENT = /^[A-Za-z0-9_-]+$/;
@@ -22684,11 +22861,11 @@ async function downloadAndVerify(args, invoke, inventory, onUuid) {
22684
22861
  }
22685
22862
  function configuredDownloadHome(clientRootDir) {
22686
22863
  try {
22687
- const configPath = path11.join(clientRootDir, "zltHost", "moudles", "dcm.json");
22864
+ const configPath = path12.join(clientRootDir, "zltHost", "moudles", "dcm.json");
22688
22865
  const config2 = JSON.parse(fs12.readFileSync(configPath, "utf8"));
22689
22866
  if (!isRecord2(config2) || typeof config2.download_home !== "string" || !config2.download_home.trim()) return null;
22690
22867
  const expanded = config2.download_home.trim().replace(/%HomePath%/gi, clientRootDir);
22691
- return path11.isAbsolute(expanded) ? path11.resolve(expanded) : path11.resolve(clientRootDir, expanded);
22868
+ return path12.isAbsolute(expanded) ? path12.resolve(expanded) : path12.resolve(clientRootDir, expanded);
22692
22869
  } catch {
22693
22870
  return null;
22694
22871
  }
@@ -22697,7 +22874,7 @@ function diskSpaceDownloadHome(result) {
22697
22874
  const data = dataRecord(result);
22698
22875
  if (!data) return null;
22699
22876
  const value = data.download_home ?? data.downloadHome;
22700
- return typeof value === "string" && value.trim() ? path11.resolve(value.trim()) : null;
22877
+ return typeof value === "string" && value.trim() ? path12.resolve(value.trim()) : null;
22701
22878
  }
22702
22879
  function requestedScopes(params) {
22703
22880
  if (!Array.isArray(params) || params.length === 0) return null;
@@ -22724,7 +22901,7 @@ function inventoryDownloadedFiles(clientRootDir, params, diskSpace, limits = {})
22724
22901
  if (!configured) return unknown2("download-home-config-unavailable");
22725
22902
  const reported = diskSpaceDownloadHome(diskSpace);
22726
22903
  if (!reported) return unknown2("disk-space-download-home-unavailable", configured);
22727
- if (path11.resolve(configured).toLowerCase() !== path11.resolve(reported).toLowerCase()) return unknown2("download-home-mismatch", configured);
22904
+ if (path12.resolve(configured).toLowerCase() !== path12.resolve(reported).toLowerCase()) return unknown2("download-home-mismatch", configured);
22728
22905
  const scopes = requestedScopes(params);
22729
22906
  if (!scopes) return unknown2("invalid-request-scope", configured);
22730
22907
  if (scopes.some((scope) => !scope.exchangeId || !/^(dk|mk|tk)[a-z0-9_-]*$/.test(scope.dataType))) {
@@ -22751,7 +22928,7 @@ function inventoryDownloadedFiles(clientRootDir, params, diskSpace, limits = {})
22751
22928
  let candidate = root2;
22752
22929
  let present = true;
22753
22930
  for (const segment of ["hqdata", lane, scope.exchangeId, scope.dataType]) {
22754
- candidate = path11.join(candidate, segment);
22931
+ candidate = path12.join(candidate, segment);
22755
22932
  let component;
22756
22933
  try {
22757
22934
  component = fs12.lstatSync(candidate);
@@ -22778,7 +22955,7 @@ function inventoryDownloadedFiles(clientRootDir, params, diskSpace, limits = {})
22778
22955
  for (const entry of fs12.readdirSync(current.dir, { withFileTypes: true })) {
22779
22956
  entries += 1;
22780
22957
  if (entries > (limits.maxEntries ?? MAX_INVENTORY_ENTRIES)) return unknown2("inventory-entry-limit", configured);
22781
- const full = path11.join(current.dir, entry.name);
22958
+ const full = path12.join(current.dir, entry.name);
22782
22959
  if (entry.isSymbolicLink()) return unknown2("symlink-or-reparse-point", configured);
22783
22960
  const stat = fs12.lstatSync(full);
22784
22961
  const attrs = stat.attributes;
@@ -22801,7 +22978,7 @@ function inventoryDownloadedFiles(clientRootDir, params, diskSpace, limits = {})
22801
22978
  // src/local-auth-guard.ts
22802
22979
  var fs13 = __toESM(require("node:fs"), 1);
22803
22980
  var os5 = __toESM(require("node:os"), 1);
22804
- var path12 = __toESM(require("node:path"), 1);
22981
+ var path13 = __toESM(require("node:path"), 1);
22805
22982
  var RECOVERY_HANDLERS = /* @__PURE__ */ new Set([
22806
22983
  "currentUser",
22807
22984
  "runtimeDoctor",
@@ -22814,8 +22991,8 @@ function resolveLocalCredentialsPath(env = process.env) {
22814
22991
  const configuredPath = env.ZLTQUANT_CREDENTIALS?.trim();
22815
22992
  if (configuredPath) return expandHome2(configuredPath);
22816
22993
  const configuredHome = env.ZLTQUANT_HOME?.trim();
22817
- const home = configuredHome ? expandHome2(configuredHome) : path12.join(os5.homedir(), ".zltquant");
22818
- return path12.join(home, "credentials.json");
22994
+ const home = configuredHome ? expandHome2(configuredHome) : path13.join(os5.homedir(), ".zltquant");
22995
+ return path13.join(home, "credentials.json");
22819
22996
  }
22820
22997
  function inspectLocalCredential(env = process.env) {
22821
22998
  const credentialsPath = resolveLocalCredentialsPath(env);
@@ -22883,8 +23060,8 @@ function preservedTaskIdentity(args) {
22883
23060
  }
22884
23061
  function expandHome2(input) {
22885
23062
  if (input === "~") return os5.homedir();
22886
- if (input.startsWith("~/") || input.startsWith("~\\")) return path12.join(os5.homedir(), input.slice(2));
22887
- return path12.resolve(input);
23063
+ if (input.startsWith("~/") || input.startsWith("~\\")) return path13.join(os5.homedir(), input.slice(2));
23064
+ return path13.resolve(input);
22888
23065
  }
22889
23066
  function isRecord3(value) {
22890
23067
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -22892,14 +23069,14 @@ function isRecord3(value) {
22892
23069
 
22893
23070
  // src/local-runtime-readiness.ts
22894
23071
  var fs14 = __toESM(require("node:fs"), 1);
22895
- var path13 = __toESM(require("node:path"), 1);
23072
+ var path14 = __toESM(require("node:path"), 1);
22896
23073
  function inspectLocalRuntimeReadiness(workRoot) {
22897
23074
  const required2 = [
22898
23075
  ["\u5DE5\u7A0B\u8DEF\u5F84", workRoot],
22899
- ["ZLTAF \u7A0B\u5E8F", path13.join(workRoot, "zltaf", "zltaf.exe")],
22900
- ["ZLTAF \u914D\u7F6E", path13.join(workRoot, "zltaf", "application-local.properties")],
22901
- ["Python \u7A0B\u5E8F", path13.join(workRoot, "python", "python.exe")],
22902
- ["MinGit \u7A0B\u5E8F", path13.join(workRoot, "mingit", "cmd", "git.exe")]
23076
+ ["ZLTAF \u7A0B\u5E8F", path14.join(workRoot, "zltaf", "zltaf.exe")],
23077
+ ["ZLTAF \u914D\u7F6E", path14.join(workRoot, "zltaf", "application-local.properties")],
23078
+ ["Python \u7A0B\u5E8F", path14.join(workRoot, "python", "python.exe")],
23079
+ ["MinGit \u7A0B\u5E8F", path14.join(workRoot, "mingit", "cmd", "git.exe")]
22903
23080
  ];
22904
23081
  for (const [label, filePath] of required2) {
22905
23082
  if (!fs14.existsSync(filePath)) {
@@ -22931,13 +23108,13 @@ function ensureDir(dir) {
22931
23108
  function writeResponseFile(outputDir, content) {
22932
23109
  ensureDir(outputDir);
22933
23110
  const filename = `resp_${getTimestamp()}.json`;
22934
- const filePath = path14.join(outputDir, filename);
23111
+ const filePath = path15.join(outputDir, filename);
22935
23112
  fs15.writeFileSync(filePath, content, "utf-8");
22936
23113
  return filePath;
22937
23114
  }
22938
23115
  function appendHistory(outputDir, uri, statusCode, contentSize, respFile) {
22939
23116
  ensureDir(outputDir);
22940
- const historyPath = path14.join(outputDir, "history.jsonl");
23117
+ const historyPath = path15.join(outputDir, "history.jsonl");
22941
23118
  if (fs15.existsSync(historyPath)) {
22942
23119
  const lines = fs15.readFileSync(historyPath, "utf-8").split("\n").filter((l) => l.trim());
22943
23120
  if (lines.length > HISTORY_MAX_LINES) {
@@ -22962,7 +23139,7 @@ function cleanOutput(clientRootDir, maxDays = 1) {
22962
23139
  let removed = 0;
22963
23140
  for (const entry of fs15.readdirSync(outputDir)) {
22964
23141
  if (!entry.startsWith("resp_") || !entry.endsWith(".json")) continue;
22965
- const filePath = path14.join(outputDir, entry);
23142
+ const filePath = path15.join(outputDir, entry);
22966
23143
  const stat = fs15.statSync(filePath);
22967
23144
  if (stat.mtimeMs < cutoff) {
22968
23145
  fs15.unlinkSync(filePath);
@@ -22973,7 +23150,7 @@ function cleanOutput(clientRootDir, maxDays = 1) {
22973
23150
  }
22974
23151
  async function execCommand(funcName, options) {
22975
23152
  const resolver = resolveDefaultConfigPath;
22976
- const configPath = typeof resolver === "function" ? resolver() : process.env.ZLT_MCP_CONFIG || path14.resolve(process.cwd(), "config.json");
23153
+ const configPath = typeof resolver === "function" ? resolver() : process.env.ZLT_MCP_CONFIG || path15.resolve(process.cwd(), "config.json");
22977
23154
  const config2 = loadConfig2(configPath);
22978
23155
  const tool = config2.tools.find((t) => t.name === funcName);
22979
23156
  if (!tool) {
@@ -23159,7 +23336,7 @@ function backtestHandoff(result) {
23159
23336
  const rawCodePath = typeof record5.codePath === "string" ? record5.codePath.trim() : typeof evidence?.runDir === "string" ? evidence.runDir.trim() : "";
23160
23337
  return {
23161
23338
  runId,
23162
- ...rawCodePath && path14.isAbsolute(rawCodePath) ? { codePath: rawCodePath } : {},
23339
+ ...rawCodePath && path15.isAbsolute(rawCodePath) ? { codePath: rawCodePath } : {},
23163
23340
  ...record5.attemptFence !== void 0 ? { attemptFence: record5.attemptFence } : {}
23164
23341
  };
23165
23342
  }
@@ -23176,7 +23353,7 @@ function mergeBacktestWait(launched, waited, handoff) {
23176
23353
  for (const id of [data.runId, data.backtestId]) {
23177
23354
  if (id !== void 0 && id !== handoff.runId) throw new Error("Backtest wait returned a different run ID");
23178
23355
  }
23179
- if (data.codePath !== void 0 && handoff.codePath && (typeof data.codePath !== "string" || path14.resolve(data.codePath).toLowerCase() !== path14.resolve(handoff.codePath).toLowerCase())) {
23356
+ if (data.codePath !== void 0 && handoff.codePath && (typeof data.codePath !== "string" || path15.resolve(data.codePath).toLowerCase() !== path15.resolve(handoff.codePath).toLowerCase())) {
23180
23357
  throw new Error("Backtest wait returned a different run directory");
23181
23358
  }
23182
23359
  const status = typeof data.status === "number" || typeof data.status === "string" && data.status.trim() ? Number(data.status) : NaN;
@@ -23414,7 +23591,7 @@ function buildIpcTimeout(tool, options, defaultTimeout) {
23414
23591
 
23415
23592
  // src/skill-generator.ts
23416
23593
  var fs16 = __toESM(require("fs"), 1);
23417
- var path15 = __toESM(require("path"), 1);
23594
+ var path16 = __toESM(require("path"), 1);
23418
23595
  function generateSkills(configPath, opts) {
23419
23596
  const config2 = loadConfig(configPath);
23420
23597
  const toolsWithSkills = config2.tools.filter((t) => t.skill);
@@ -23434,7 +23611,7 @@ ${content}
23434
23611
  if (!fs16.existsSync(outDir)) {
23435
23612
  fs16.mkdirSync(outDir, { recursive: true });
23436
23613
  }
23437
- const filePath = path15.join(outDir, `zlt-${tool.name.replace(/_/g, "-")}.md`);
23614
+ const filePath = path16.join(outDir, `zlt-${tool.name.replace(/_/g, "-")}.md`);
23438
23615
  fs16.writeFileSync(filePath, content);
23439
23616
  process.stderr.write(`Generated: ${filePath}
23440
23617
  `);
@@ -24132,15 +24309,15 @@ var fs25 = __toESM(require("node:fs"), 1);
24132
24309
  // src/install-task.ts
24133
24310
  var fs17 = __toESM(require("node:fs"), 1);
24134
24311
  var os6 = __toESM(require("node:os"), 1);
24135
- var path16 = __toESM(require("node:path"), 1);
24312
+ var path17 = __toESM(require("node:path"), 1);
24136
24313
  var import_node_child_process2 = require("node:child_process");
24137
- var DEFAULT_TASK_ROOT = path16.join(os6.tmpdir(), "zlt-mcp-install-tasks");
24314
+ var DEFAULT_TASK_ROOT = path17.join(os6.tmpdir(), "zlt-mcp-install-tasks");
24138
24315
  var STARTUP_GRACE_MS = 3e4;
24139
24316
  function taskRoot() {
24140
24317
  return process.env.ZLT_MCP_INSTALL_TASK_ROOT || DEFAULT_TASK_ROOT;
24141
24318
  }
24142
24319
  function taskPath(taskId) {
24143
- return path16.join(taskRoot(), `${taskId}.json`);
24320
+ return path17.join(taskRoot(), `${taskId}.json`);
24144
24321
  }
24145
24322
  function write(record5) {
24146
24323
  fs17.mkdirSync(taskRoot(), { recursive: true });
@@ -24213,7 +24390,7 @@ function startInstallTask(entrypoint, argsJson, spawnProcess = import_node_child
24213
24390
  status: "queued",
24214
24391
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
24215
24392
  launcherPid: process.pid,
24216
- logPath: path16.join(taskRoot(), `${taskId}.log`)
24393
+ logPath: path17.join(taskRoot(), `${taskId}.log`)
24217
24394
  };
24218
24395
  write(record5);
24219
24396
  let logFd;
@@ -24265,7 +24442,7 @@ var import_promises = require("node:timers/promises");
24265
24442
 
24266
24443
  // src/tool-pipeline.ts
24267
24444
  var fs24 = __toESM(require("node:fs"), 1);
24268
- var path23 = __toESM(require("node:path"), 1);
24445
+ var path24 = __toESM(require("node:path"), 1);
24269
24446
  var import_node_crypto4 = require("node:crypto");
24270
24447
 
24271
24448
  // src/feature-set.ts
@@ -24277,7 +24454,7 @@ var MASKED_FUTURES_MESSAGE = "\u671F\u8D27\u56DE\u6D4B\u5728\u5F53\u524D\u7248\u
24277
24454
 
24278
24455
  // src/backtest-config.ts
24279
24456
  var fs18 = __toESM(require("node:fs"), 1);
24280
- var path17 = __toESM(require("node:path"), 1);
24457
+ var path18 = __toESM(require("node:path"), 1);
24281
24458
  var import_node_crypto2 = require("node:crypto");
24282
24459
  var BACKTEST_CONFIG_KEYS = [
24283
24460
  "start",
@@ -24323,12 +24500,12 @@ function readBacktestBaseline(tool, args) {
24323
24500
  if (!create && tool !== "mcp-re-backtest") return void 0;
24324
24501
  const directory = args[create ? "strategyPath" : "codePath"];
24325
24502
  if (directory === void 0) return void 0;
24326
- if (typeof directory !== "string" || !path17.isAbsolute(directory)) throw new Error("Configuration baseline requires an absolute directory path");
24503
+ if (typeof directory !== "string" || !path18.isAbsolute(directory)) throw new Error("Configuration baseline requires an absolute directory path");
24327
24504
  const root2 = fs18.realpathSync(directory);
24328
- if (create && path17.basename(path17.dirname(root2)).toLowerCase() === "backtest") {
24505
+ if (create && path18.basename(path18.dirname(root2)).toLowerCase() === "backtest") {
24329
24506
  throw new Error("strategyPath must identify the strategy root, not a historical backtest directory");
24330
24507
  }
24331
- const file = path17.join(root2, ".vscode", "tradesetting.json");
24508
+ const file = path18.join(root2, ".vscode", "tradesetting.json");
24332
24509
  const raw = fs18.readFileSync(file);
24333
24510
  let config2;
24334
24511
  try {
@@ -24390,7 +24567,7 @@ function reconcileBaselineCapital(params, overrides) {
24390
24567
 
24391
24568
  // src/backtest-execution-progress.ts
24392
24569
  var fs19 = __toESM(require("node:fs"), 1);
24393
- var path18 = __toESM(require("node:path"), 1);
24570
+ var path19 = __toESM(require("node:path"), 1);
24394
24571
  var MAX_TAIL_BYTES = 128 * 1024;
24395
24572
  var FUTURE_SKEW_MS = 5e3;
24396
24573
  function beijingTimestamp(value) {
@@ -24405,9 +24582,9 @@ function readBacktestExecutionProgress(input) {
24405
24582
  const { runId, codePath, attemptStartedAtMs, nowMs = Date.now() } = input;
24406
24583
  if (!runId || !codePath || !Number.isFinite(attemptStartedAtMs) || attemptStartedAtMs <= 0 || !Number.isFinite(nowMs)) return void 0;
24407
24584
  try {
24408
- const config2 = JSON.parse(fs19.readFileSync(path18.join(codePath, ".vscode", "tradesetting.json"), "utf8"));
24585
+ const config2 = JSON.parse(fs19.readFileSync(path19.join(codePath, ".vscode", "tradesetting.json"), "utf8"));
24409
24586
  if (config2?.backtest_id !== runId) return void 0;
24410
- const fd = fs19.openSync(path18.join(codePath, "log", "strategy.log"), "r");
24587
+ const fd = fs19.openSync(path19.join(codePath, "log", "strategy.log"), "r");
24411
24588
  let text2;
24412
24589
  try {
24413
24590
  const before = fs19.fstatSync(fd);
@@ -24454,6 +24631,261 @@ function toFiniteNumber(value) {
24454
24631
  return Number.isFinite(n) ? n : 0;
24455
24632
  }
24456
24633
 
24634
+ // src/list-result-disclosure.ts
24635
+ var LIST_DISCLOSURE_TOOLS = /* @__PURE__ */ new Set([
24636
+ "mcp-get-strategy-list",
24637
+ "mcp-strategy-get-template-list",
24638
+ "mcp-get-strategy-tree-list"
24639
+ ]);
24640
+ var MAX_BYTES = 8 * 1024;
24641
+ var MAX_FIELDS = 50;
24642
+ var MAX_FIELD_NAME_BYTES = 128;
24643
+ var MAX_UNKNOWN_FIELDS = 50;
24644
+ var MAX_OMITTED_FIELDS = 100;
24645
+ function shapeListResultDisclosure(tool, args, result) {
24646
+ if (!LIST_DISCLOSURE_TOOLS.has(tool.name) || result.isError) return result;
24647
+ try {
24648
+ const envelope = JSON.parse(result.content[0]?.text ?? "");
24649
+ if (!isRecord4(envelope) || envelope.disclosure || Number(envelope.ErrNo ?? 0) !== 0) return result;
24650
+ if (!Array.isArray(envelope.Data)) return result;
24651
+ const source = envelope.Data;
24652
+ const offset = integer2(args.offset, 0, 0, Number.MAX_SAFE_INTEGER);
24653
+ const limit = integer2(args.limit, 20, 1, 50);
24654
+ const fields = Array.isArray(args.fields) ? [...new Set(args.fields.filter((field) => typeof field === "string"))].slice(0, MAX_FIELDS).map((field) => field.slice(0, MAX_FIELD_NAME_BYTES)) : [];
24655
+ const allAvailableFields = [...new Set(source.flatMap((row) => isRecord4(row) ? Object.keys(row) : []))];
24656
+ const availableFields = allAvailableFields.slice(0, MAX_FIELDS).map((field) => field.slice(0, MAX_FIELD_NAME_BYTES));
24657
+ const rows = [];
24658
+ let nextCursor = offset;
24659
+ const omittedFields = [];
24660
+ const metadata = () => {
24661
+ const detail = {
24662
+ total: source.length,
24663
+ offset,
24664
+ returned: rows.length,
24665
+ hasMore: nextCursor < source.length,
24666
+ nextOffset: nextCursor < source.length ? nextCursor : null,
24667
+ availableFields,
24668
+ ...fields.length ? (() => {
24669
+ const unknownFields = fields.filter((field) => !allAvailableFields.includes(field));
24670
+ return {
24671
+ unknownFields: unknownFields.slice(0, MAX_UNKNOWN_FIELDS).map((field) => field.slice(0, MAX_FIELD_NAME_BYTES)),
24672
+ ...unknownFields.length > MAX_UNKNOWN_FIELDS ? { unknownFieldsTruncated: true } : {}
24673
+ };
24674
+ })() : {},
24675
+ ...allAvailableFields.length > availableFields.length ? { availableFieldsTruncated: true } : {},
24676
+ ...omittedFields.length ? {
24677
+ omittedFields: omittedFields.slice(0, MAX_OMITTED_FIELDS).map((entry) => ({ ...entry, field: entry.field.slice(0, MAX_FIELD_NAME_BYTES) })),
24678
+ ...omittedFields.length > MAX_OMITTED_FIELDS ? { omittedFieldsTruncated: true } : {},
24679
+ nextAction: "Fields marked readable can be requested alone using fields at the same offset and limit:1. Fields marked readable:false exceed this bounded interface; inspect local raw data or use an additional interface. Repeating the list call cannot recover them."
24680
+ } : {}
24681
+ };
24682
+ for (const key of ["omittedFields", "unknownFields", "availableFields"]) {
24683
+ const entries = detail[key];
24684
+ if (!Array.isArray(entries)) continue;
24685
+ while (valueBytes(detail) > 2048 && entries.length) {
24686
+ entries.pop();
24687
+ detail[`${key}Truncated`] = true;
24688
+ }
24689
+ }
24690
+ return detail;
24691
+ };
24692
+ const bytes = (candidateRows = rows) => Buffer.byteLength(JSON.stringify({ ...envelope, Data: candidateRows, disclosure: metadata() }), "utf8");
24693
+ for (let index = offset; index < Math.min(source.length, offset + limit); index++) {
24694
+ const raw = source[index];
24695
+ const omissionStart = omittedFields.length;
24696
+ let row = isRecord4(raw) ? Object.fromEntries(Object.entries(raw).filter(([key]) => !fields.length || fields.includes(key))) : raw;
24697
+ if (bytes([...rows, row]) > MAX_BYTES && rows.length > 0 && bytes([row]) <= MAX_BYTES) break;
24698
+ if (bytes([row]) > MAX_BYTES && isRecord4(row)) {
24699
+ const largest = Object.keys(row).filter((key) => !/^(id|.*Id|name|title)$/i.test(key)).sort((a, b) => valueBytes(row[b]) - valueBytes(row[a]));
24700
+ for (const field of largest) {
24701
+ if (bytes([row]) <= MAX_BYTES) break;
24702
+ const size = valueBytes(row[field]);
24703
+ delete row[field];
24704
+ omittedFields.push({ index, field, bytes: size, readable: size < MAX_BYTES - 1024, reason: "json-budget-exceeded" });
24705
+ }
24706
+ if (bytes([row]) > MAX_BYTES) {
24707
+ const identity = Object.keys(row).filter((key) => /^(id|.*Id|name|title)$/i.test(key)).sort((a, b) => valueBytes(row[b]) - valueBytes(row[a]));
24708
+ let identityRemoved = false;
24709
+ for (const field of identity) {
24710
+ if (bytes([row]) <= MAX_BYTES) break;
24711
+ const size = valueBytes(row[field]);
24712
+ delete row[field];
24713
+ identityRemoved = true;
24714
+ omittedFields.push({ index, field, bytes: size, readable: false, reason: "identity-field-exceeds-json-budget" });
24715
+ }
24716
+ if (identityRemoved || bytes([row]) > MAX_BYTES) {
24717
+ row = { _omittedIndex: index, _omittedReason: "row-exceeds-json-budget" };
24718
+ omittedFields.push({ index, field: "*row*", bytes: valueBytes(raw), readable: false, reason: "row-exceeds-json-budget" });
24719
+ }
24720
+ }
24721
+ }
24722
+ if (bytes([...rows, row]) > MAX_BYTES) {
24723
+ if (rows.length === 0) {
24724
+ row = { _omittedIndex: index, _omittedReason: "row-exceeds-json-budget" };
24725
+ omittedFields.push({ index, field: "*row*", bytes: valueBytes(raw), readable: false, reason: "row-exceeds-json-budget" });
24726
+ if (bytes([row]) <= MAX_BYTES) rows.push(row);
24727
+ } else {
24728
+ omittedFields.splice(omissionStart);
24729
+ break;
24730
+ }
24731
+ nextCursor = index + 1;
24732
+ break;
24733
+ }
24734
+ rows.push(row);
24735
+ nextCursor = index + 1;
24736
+ }
24737
+ return replace(envelope, rows, metadata(), result);
24738
+ } catch {
24739
+ return result;
24740
+ }
24741
+ }
24742
+ function integer2(value, fallback, min, max) {
24743
+ return typeof value === "number" && Number.isInteger(value) ? Math.min(max, Math.max(min, value)) : fallback;
24744
+ }
24745
+ function valueBytes(value) {
24746
+ return Buffer.byteLength(JSON.stringify(value), "utf8");
24747
+ }
24748
+ function replace(envelope, data, disclosure, result) {
24749
+ return { ...result, content: [{ type: "text", text: JSON.stringify({ ...envelope, Data: data, disclosure }) }] };
24750
+ }
24751
+
24752
+ // src/data-result-disclosure.ts
24753
+ var ARRAY_BUDGET = 8 * 1024;
24754
+ var KIND = "data-result-page-v1";
24755
+ var DATA_DISCLOSURE_TOOLS = /* @__PURE__ */ new Set(["mcp-get-data-range", "mcp-get-cache-diff"]);
24756
+ var DECISION_FIELDS = /* @__PURE__ */ new Set([
24757
+ "coverageStatus",
24758
+ "blocksBacktest",
24759
+ "assessment",
24760
+ "nextAction",
24761
+ "reasonCode",
24762
+ "verificationEvidenceComplete",
24763
+ "requestCoverage"
24764
+ ]);
24765
+ function utf8Bytes(value) {
24766
+ return Buffer.byteLength(JSON.stringify(value) ?? "", "utf8");
24767
+ }
24768
+ function fitDataBudget(data, budget, preserveSeriesCoverage = false) {
24769
+ const fitted = { ...data };
24770
+ const omitted = {};
24771
+ const keysBySize = () => Object.keys(fitted).filter((key) => key !== "disclosure" && key !== "disclosureOmitted" && !DECISION_FIELDS.has(key) && !["ranges", "series", "missing", "changed", "windows"].includes(key) && !(preserveSeriesCoverage && key === "seriesCoverage")).map((key) => ({ key, bytes: utf8Bytes(fitted[key]) })).sort((a, b) => b.bytes - a.bytes);
24772
+ while (utf8Bytes(fitted) > budget) {
24773
+ const candidate = keysBySize()[0];
24774
+ if (!candidate) break;
24775
+ const value = fitted[candidate.key];
24776
+ omitted[candidate.key] = candidate.bytes;
24777
+ delete fitted[candidate.key];
24778
+ }
24779
+ if (Object.keys(omitted).length > 0) fitted.disclosureOmitted = omitted;
24780
+ return fitted;
24781
+ }
24782
+ function boundSeriesCoverage(data) {
24783
+ const value = data.seriesCoverage;
24784
+ if (!Array.isArray(value) || utf8Bytes(value) <= 2048) return data;
24785
+ let keep = value.length;
24786
+ while (keep > 0 && utf8Bytes(value.slice(0, keep)) > 2048) keep--;
24787
+ return { ...data, seriesCoverage: value.slice(0, keep), seriesCoverageOmitted: value.length - keep };
24788
+ }
24789
+ function shapeDataResultDisclosure(tool, args, result) {
24790
+ if (!DATA_DISCLOSURE_TOOLS.has(tool.name) || result.isError) return result;
24791
+ try {
24792
+ const parsed = JSON.parse(result.content[0]?.text ?? "");
24793
+ if (!isRecord4(parsed) || !isRecord4(parsed.Data) || Number(parsed.ErrNo ?? 0) !== 0) return result;
24794
+ const original = parsed.Data;
24795
+ if (isRecord4(original.disclosure) && original.disclosure.kind === KIND) return result;
24796
+ const units = [];
24797
+ const totals = /* @__PURE__ */ new Map();
24798
+ const selectedIndexes = /* @__PURE__ */ new Map();
24799
+ const target = (path28) => /\.(ranges|series|missing|changed|windows)$/.test(path28);
24800
+ const nested = (entry) => isRecord4(entry) && Object.entries(entry).some(([key, child]) => target(`.${key}`) && Array.isArray(child) && child.length > 0);
24801
+ const scan = (value, jsonPath) => {
24802
+ if (Array.isArray(value)) {
24803
+ if (target(jsonPath)) {
24804
+ totals.set(jsonPath, value.length);
24805
+ value.forEach((entry, index) => {
24806
+ if (!nested(entry)) units.push({ path: jsonPath, index });
24807
+ });
24808
+ }
24809
+ value.forEach((entry, index) => scan(entry, `${jsonPath}[${index}]`));
24810
+ return;
24811
+ }
24812
+ if (isRecord4(value)) for (const [key, child] of Object.entries(value)) scan(child, `${jsonPath}.${key}`);
24813
+ };
24814
+ const displaySource = fitDataBudget(boundSeriesCoverage(original), ARRAY_BUDGET - 2048, true);
24815
+ scan(displaySource, "$.Data");
24816
+ const explicit = args.offset !== void 0 || args.limit !== void 0;
24817
+ const offset = Number.isInteger(args.offset) && Number(args.offset) >= 0 ? Number(args.offset) : 0;
24818
+ const limit = Number.isInteger(args.limit) && Number(args.limit) > 0 ? Math.min(50, Number(args.limit)) : 20;
24819
+ const selected = /* @__PURE__ */ new Set();
24820
+ const render = (value, jsonPath) => {
24821
+ if (Array.isArray(value)) {
24822
+ const indexes = selectedIndexes.get(jsonPath);
24823
+ if (target(jsonPath)) return value.flatMap((entry, index) => {
24824
+ const entryPath = `${jsonPath}[${index}]`;
24825
+ if (!indexes?.has(index) && ![...selected].some((key) => key.startsWith(`${entryPath}.`))) return [];
24826
+ return [render(entry, entryPath)];
24827
+ });
24828
+ return value.map((entry, index) => render(entry, `${jsonPath}[${index}]`));
24829
+ }
24830
+ if (!isRecord4(value)) return value;
24831
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, render(child, `${jsonPath}.${key}`)]));
24832
+ };
24833
+ const arrayBytes = (value) => {
24834
+ if (Array.isArray(value)) return Buffer.byteLength(JSON.stringify(value), "utf8");
24835
+ return isRecord4(value) ? Object.values(value).reduce((sum, child) => sum + arrayBytes(child), 0) : 0;
24836
+ };
24837
+ if (!explicit && units.length <= limit && utf8Bytes(original) <= ARRAY_BUDGET) return result;
24838
+ let cursor = Math.min(offset, units.length);
24839
+ let oversized = 0;
24840
+ while (cursor < units.length && selected.size < limit) {
24841
+ const unit = units[cursor];
24842
+ const key = `${unit.path}[${unit.index}]`;
24843
+ selected.add(key);
24844
+ const indexes = selectedIndexes.get(unit.path) ?? /* @__PURE__ */ new Set();
24845
+ indexes.add(unit.index);
24846
+ selectedIndexes.set(unit.path, indexes);
24847
+ if (utf8Bytes(render(displaySource, "$.Data")) > ARRAY_BUDGET - 2048) {
24848
+ selected.delete(key);
24849
+ indexes.delete(unit.index);
24850
+ if (selected.size > 0) break;
24851
+ oversized++;
24852
+ }
24853
+ cursor++;
24854
+ }
24855
+ let data = render(displaySource, "$.Data");
24856
+ data = fitDataBudget(data, ARRAY_BUDGET - 2048);
24857
+ const paths = [...totals.keys()].filter((path28) => !path28.includes("[") || selectedIndexes.has(path28));
24858
+ const shownPaths = paths.slice(0, 50);
24859
+ const arrays = shownPaths.map((path28) => {
24860
+ const returnedCount = new Set([...selected].filter((key) => key.startsWith(`${path28}[`)).map((key) => key.slice(path28.length + 1).split("]")[0])).size;
24861
+ return { path: path28, total: totals.get(path28), returned: returnedCount, omitted: totals.get(path28) - returnedCount };
24862
+ });
24863
+ data.disclosure = {
24864
+ kind: KIND,
24865
+ unit: "leaf-array-entry",
24866
+ offset,
24867
+ limit,
24868
+ total: units.length,
24869
+ returned: selected.size,
24870
+ omitted: units.length - selected.size,
24871
+ hasMore: cursor < units.length,
24872
+ nextOffset: cursor < units.length ? cursor : null,
24873
+ arrayBytes: arrayBytes(data),
24874
+ dataBytes: utf8Bytes(data),
24875
+ dataByteBudget: ARRAY_BUDGET,
24876
+ oversizedEntriesOmitted: oversized,
24877
+ arrays,
24878
+ omittedArrayMetadata: totals.size - shownPaths.length,
24879
+ decisionsUseFullResult: true,
24880
+ displayIsPartial: selected.size < units.length,
24881
+ nextAction: "Repeat the same tool and params with offset=nextOffset; the cursor is over leaf array entries. Or narrow params by exchange_id/data_type (cache-diff also accepts start/end). Never treat this displayed page as complete coverage; retain the full-result coverageStatus/blocksBacktest/assessment and evidence."
24882
+ };
24883
+ return { ...result, content: [{ type: "text", text: JSON.stringify({ ...parsed, Data: data }) }, ...result.content.slice(1)] };
24884
+ } catch {
24885
+ return result;
24886
+ }
24887
+ }
24888
+
24457
24889
  // src/ipc-tool-result.ts
24458
24890
  function normalizeResponse(raw) {
24459
24891
  if (raw && typeof raw === "object" && "ErrNo" in raw) return raw;
@@ -24567,6 +24999,8 @@ function annotateSkippedCalculation(tool, result) {
24567
24999
  }
24568
25000
  }
24569
25001
  var FACTOR_DETECT_RESULT_KIND = "factor-detect";
25002
+ var FACTOR_REPORT_SECTION_MAX_BYTES = 8 * 1024;
25003
+ var FACTOR_REPORT_SECTION_MAX_ITEMS = 10;
24570
25004
  var FACTOR_DETECT_OMIT_KEYS = [
24571
25005
  "ranking",
24572
25006
  "returnsByQuantile",
@@ -24584,6 +25018,48 @@ function pickByPeriod(source, period, index) {
24584
25018
  if (isRecord4(source)) return numberOrNull(source[period]);
24585
25019
  return null;
24586
25020
  }
25021
+ function ownPathValue(root2, path28) {
25022
+ const parts = path28.split(".").filter(Boolean);
25023
+ if (parts.length === 0) return { found: false };
25024
+ let current = root2;
25025
+ for (const part of parts) {
25026
+ if (!isRecord4(current) || !Object.prototype.hasOwnProperty.call(current, part)) return { found: false };
25027
+ current = current[part];
25028
+ }
25029
+ return { found: true, value: current };
25030
+ }
25031
+ function reportPathParent(root2, path28) {
25032
+ const parts = path28.split(".").filter(Boolean);
25033
+ if (parts.length === 0) return void 0;
25034
+ const parentPath = parts.slice(0, -1).join(".");
25035
+ const parent = parentPath ? ownPathValue(root2, parentPath).value : root2;
25036
+ if (!isRecord4(parent)) return void 0;
25037
+ return { path: parentPath, fields: Object.keys(parent) };
25038
+ }
25039
+ function jsonBytes(value) {
25040
+ return Buffer.byteLength(JSON.stringify(value) ?? "", "utf8");
25041
+ }
25042
+ function reportType(value) {
25043
+ if (value === null) return "null";
25044
+ if (Array.isArray(value)) return "array";
25045
+ return typeof value;
25046
+ }
25047
+ function omitUndistillableReport(parsed, data, reportJson, reason, validJson) {
25048
+ const { reportJson: _raw, ...scalars } = data;
25049
+ return {
25050
+ content: [{ type: "text", text: JSON.stringify({
25051
+ ...parsed,
25052
+ Data: {
25053
+ ...scalars,
25054
+ resultKind: FACTOR_DETECT_RESULT_KIND,
25055
+ ...reason === "Invalid report JSON." ? { reportParseError: true } : {},
25056
+ reportParse: { validJson, type: reportType(reportJson) },
25057
+ reportOmitted: { bytes: jsonBytes(reportJson), reason },
25058
+ nextAction: "The report was omitted from the default response. Use includeReport:true only for an explicit raw-evidence request."
25059
+ }
25060
+ }) }]
25061
+ };
25062
+ }
24587
25063
  function distillFactorDetectReport(tool, args, result) {
24588
25064
  if (tool.name !== "mcp-factor-detect-detail" || result.isError) return result;
24589
25065
  if (args.includeReport === true) return result;
@@ -24593,14 +25069,58 @@ function distillFactorDetectReport(tool, args, result) {
24593
25069
  if (!isRecord4(parsed) || !isRecord4(parsed.Data)) return result;
24594
25070
  const data = parsed.Data;
24595
25071
  if (data.resultKind === FACTOR_DETECT_RESULT_KIND) return result;
24596
- if (typeof data.reportJson !== "string" || data.reportJson.length === 0) return result;
25072
+ if (!Object.prototype.hasOwnProperty.call(data, "reportJson")) return result;
25073
+ const rawReport = data.reportJson;
25074
+ if (typeof rawReport !== "string") {
25075
+ return omitUndistillableReport(parsed, data, rawReport, "Valid report JSON is not an object; raw report omitted.", false);
25076
+ }
25077
+ if (rawReport.length === 0) return omitUndistillableReport(parsed, data, rawReport, "Invalid report JSON.", false);
24597
25078
  let report;
24598
25079
  try {
24599
- report = JSON.parse(data.reportJson);
25080
+ report = JSON.parse(rawReport);
24600
25081
  } catch {
24601
- return result;
25082
+ return omitUndistillableReport(parsed, data, rawReport, "Invalid report JSON.", false);
25083
+ }
25084
+ if (!isRecord4(report)) return omitUndistillableReport(parsed, data, report, "Valid report JSON is not an object; raw report omitted.", true);
25085
+ const requestedSections = Array.isArray(args.reportSections) ? [...new Set(args.reportSections.filter((section) => typeof section === "string"))].slice(0, FACTOR_REPORT_SECTION_MAX_ITEMS) : [];
25086
+ const reportOffset = Math.max(0, Math.floor(Number(args.reportOffset) || 0));
25087
+ const reportLimit = Math.min(50, Math.max(1, Math.floor(Number(args.reportLimit) || 20)));
25088
+ const reportSections = /* @__PURE__ */ Object.create(null);
25089
+ const unknownReportSections = [];
25090
+ const availableReportFields = /* @__PURE__ */ Object.create(null);
25091
+ const omittedReportSections = [];
25092
+ let disclosedBytes = 0;
25093
+ if (requestedSections.length > 0) {
25094
+ for (const section of requestedSections) {
25095
+ const selected = ownPathValue(report, section);
25096
+ if (selected.found) {
25097
+ const value = selected.value;
25098
+ const total = Array.isArray(value) ? value.length : typeof value === "string" ? Array.from(value).length : void 0;
25099
+ const paged = Array.isArray(value) ? { items: value.slice(reportOffset, reportOffset + reportLimit), total, offset: reportOffset, limit: reportLimit } : typeof value === "string" ? { value: Array.from(value).slice(reportOffset, reportOffset + reportLimit).join(""), total, offset: reportOffset, limit: reportLimit } : { value };
25100
+ const shaped = total !== void 0 ? { ...paged, hasMore: reportOffset + reportLimit < total, ...reportOffset + reportLimit < total ? { nextOffset: reportOffset + reportLimit } : {} } : value;
25101
+ const bytes = jsonBytes(shaped) + jsonBytes(section) + 1;
25102
+ const remainingBytes = FACTOR_REPORT_SECTION_MAX_BYTES - disclosedBytes;
25103
+ if (bytes <= remainingBytes) {
25104
+ reportSections[section] = shaped;
25105
+ disclosedBytes += bytes;
25106
+ } else if (!omittedReportSections.some((item) => item.name === section)) {
25107
+ omittedReportSections.push({
25108
+ name: section,
25109
+ bytes,
25110
+ maxBytes: remainingBytes,
25111
+ reason: "Section exceeds the remaining progressive-disclosure budget; narrow the path or page further."
25112
+ });
25113
+ if (isRecord4(value)) {
25114
+ availableReportFields[section] = Object.keys(value);
25115
+ }
25116
+ }
25117
+ } else if (!unknownReportSections.includes(section)) {
25118
+ unknownReportSections.push(section);
25119
+ const parent = reportPathParent(report, section);
25120
+ if (parent) availableReportFields[parent.path] = parent.fields;
25121
+ }
25122
+ }
24602
25123
  }
24603
- if (!isRecord4(report)) return result;
24604
25124
  const alphalens = isRecord4(report.alphalens) ? report.alphalens : {};
24605
25125
  const ic = isRecord4(alphalens.ic) ? alphalens.ic : {};
24606
25126
  const periodNames = Array.isArray(alphalens.periods) ? alphalens.periods.filter((p) => typeof p === "string") : [];
@@ -24619,13 +25139,21 @@ function distillFactorDetectReport(tool, args, result) {
24619
25139
  const omittedKeys = {};
24620
25140
  let omittedBytes = 0;
24621
25141
  for (const key of FACTOR_DETECT_OMIT_KEYS) {
24622
- const source = key in report ? report[key] : alphalens[key];
25142
+ const topLevel = Object.prototype.hasOwnProperty.call(report, key);
25143
+ if (Object.prototype.hasOwnProperty.call(reportSections, topLevel ? key : "alphalens")) continue;
25144
+ const source = topLevel ? report[key] : alphalens[key];
24623
25145
  if (source === void 0) continue;
24624
- const size = JSON.stringify(source).length;
25146
+ const size = jsonBytes(source);
24625
25147
  omittedKeys[key] = size;
24626
25148
  omittedBytes += size;
24627
25149
  }
24628
25150
  const { reportJson, ...scalars } = data;
25151
+ const disclosedSections = requestedSections.length > 0 ? {
25152
+ reportSections,
25153
+ ...unknownReportSections.length > 0 ? { unknownReportSections } : {},
25154
+ ...Object.keys(availableReportFields).length > 0 ? { availableReportFields } : {},
25155
+ ...omittedReportSections.length > 0 ? { omittedReportSections } : {}
25156
+ } : {};
24629
25157
  return {
24630
25158
  content: [{
24631
25159
  type: "text",
@@ -24644,12 +25172,14 @@ function distillFactorDetectReport(tool, args, result) {
24644
25172
  effective: report.effectivePreprocess ?? null,
24645
25173
  stats: report.preprocessStats ?? null
24646
25174
  },
25175
+ ...disclosedSections,
25176
+ availableReportSections: Object.keys(report),
24647
25177
  reportOmitted: {
24648
25178
  bytes: omittedBytes,
24649
25179
  keys: omittedKeys,
24650
25180
  reason: "Alphalens plot series, not needed to read IC or layered returns."
24651
25181
  },
24652
- nextAction: "Read IC from periods[]: icMean/icIr with tStat and pValue for the SAME period. A near-zero icMean with |tStat| under 2 and pValue above 0.05 does not support any claim about the factor working \u2014 say so rather than reporting the sign. quantileMean holds the layered returns, verifyPassed the platform's own threshold verdict. The plot series listed in reportOmitted were dropped to keep this readable; pass includeReport:true to get the raw report back (it is over 1 MB and will be truncated)."
25182
+ nextAction: `Read IC from periods[]: icMean/icIr with tStat and pValue for the SAME period. A near-zero icMean with |tStat| under 2 and pValue above 0.05 does not support any claim about the factor working \u2014 say so rather than reporting the sign. quantileMean holds the layered returns, verifyPassed the platform's own threshold verdict. The plot series listed in reportOmitted were dropped to keep this readable; pass reportSections:["path"] with reportOffset/reportLimit to disclose a narrow section or page (the combined disclosure budget is 8 KiB; unavailable fields are listed in availableReportFields), or use includeReport:true only for an explicit raw-evidence request.`
24653
25183
  }
24654
25184
  })
24655
25185
  }]
@@ -24807,7 +25337,7 @@ function buildIpcBody2(tool, args) {
24807
25337
  if (tool.bodyParamKey) {
24808
25338
  return JSON.stringify(args[tool.bodyParamKey] ?? {});
24809
25339
  }
24810
- return tool.bodyFromParams ? JSON.stringify(stripControlParams(args)) : "{}";
25340
+ return tool.bodyFromParams ? JSON.stringify(stripControlParams(args, tool.name)) : "{}";
24811
25341
  }
24812
25342
  function buildIpcTimeout2(tool, args, defaultTimeout) {
24813
25343
  const declared = Number(tool.timeoutMs);
@@ -24828,9 +25358,24 @@ var CONTROL_PARAMS = [
24828
25358
  "__attemptStartedAtMs",
24829
25359
  "__resultBaseline"
24830
25360
  ];
24831
- function stripControlParams(args) {
25361
+ function stripControlParams(args, toolName) {
24832
25362
  const filtered = { ...args };
24833
25363
  for (const key of CONTROL_PARAMS) delete filtered[key];
25364
+ if (toolName && LIST_DISCLOSURE_TOOLS.has(toolName)) {
25365
+ delete filtered.offset;
25366
+ delete filtered.limit;
25367
+ delete filtered.fields;
25368
+ }
25369
+ if (toolName && DATA_DISCLOSURE_TOOLS.has(toolName)) {
25370
+ delete filtered.offset;
25371
+ delete filtered.limit;
25372
+ }
25373
+ if (toolName === "mcp-factor-detect-detail") {
25374
+ delete filtered.includeReport;
25375
+ delete filtered.reportSections;
25376
+ delete filtered.reportOffset;
25377
+ delete filtered.reportLimit;
25378
+ }
24834
25379
  return filtered;
24835
25380
  }
24836
25381
  function applySchemaDefaults(schema, value) {
@@ -24899,11 +25444,11 @@ function cloneDefaultValue(value) {
24899
25444
 
24900
25445
  // src/factor-operations.ts
24901
25446
  var fs21 = __toESM(require("node:fs"), 1);
24902
- var path20 = __toESM(require("node:path"), 1);
25447
+ var path21 = __toESM(require("node:path"), 1);
24903
25448
 
24904
25449
  // src/data-result-transforms.ts
24905
25450
  var fs20 = __toESM(require("node:fs"), 1);
24906
- var path19 = __toESM(require("node:path"), 1);
25451
+ var path20 = __toESM(require("node:path"), 1);
24907
25452
  var MARKET_ID_TO_NAME = {
24908
25453
  29544: "\u4E0A\u4EA4\u6240(sh)",
24909
25454
  29562: "\u6DF1\u4EA4\u6240(sz)",
@@ -24952,6 +25497,17 @@ var MARKET_CODE_TO_NAME = {
24952
25497
  sj: "\u4E0A\u91D1\u6240(sj)",
24953
25498
  bs: "\u6E24\u5546(bs)"
24954
25499
  };
25500
+ var LEGACY_MARKET_ID_TO_CODE = {
25501
+ 29544: "sh",
25502
+ 29562: "sz",
25503
+ 31338: "zj",
25504
+ 31347: "zs",
25505
+ 25715: "ds",
25506
+ 29553: "sq",
25507
+ 26481: "gq",
25508
+ 29546: "sj",
25509
+ 25203: "bs"
25510
+ };
24955
25511
  var DC_SDK_CONFIG_SEGMENTS = ["python", "Lib", "site-packages", "zltsdk", "moudles", "dc_sdk.json"];
24956
25512
  var DCM_CONFIG_SEGMENTS = ["zltHost", "moudles", "dcm.json"];
24957
25513
  var dataRootsCache = /* @__PURE__ */ new Map();
@@ -24976,8 +25532,8 @@ function resolveDataRoots(clientRootDir) {
24976
25532
  const cached2 = Date.now() - readAt < DATA_ROOTS_TTL_MS ? dataRootsCache.get(clientRootDir) : void 0;
24977
25533
  if (cached2) return cached2;
24978
25534
  const root2 = clientRootDir.replace(/[\\/]+$/, "");
24979
- const dcSdk = readJsonFile(path19.join(root2, ...DC_SDK_CONFIG_SEGMENTS));
24980
- const dcm = readJsonFile(path19.join(root2, ...DCM_CONFIG_SEGMENTS));
25535
+ const dcSdk = readJsonFile(path20.join(root2, ...DC_SDK_CONFIG_SEGMENTS));
25536
+ const dcm = readJsonFile(path20.join(root2, ...DCM_CONFIG_SEGMENTS));
24981
25537
  const engineRoot = normalizeDataRoot(isRecord4(dcSdk?.mdf) ? dcSdk.mdf.path : void 0, root2);
24982
25538
  const downloadRoot = normalizeDataRoot(dcm?.download_home, root2);
24983
25539
  const resolved = Boolean(engineRoot && downloadRoot);
@@ -24992,6 +25548,36 @@ function resolveDataRoots(clientRootDir) {
24992
25548
  return status;
24993
25549
  }
24994
25550
  var HQ_DATA_FAMILIES = /* @__PURE__ */ new Set(["dk", "mk", "tk"]);
25551
+ function requestedSeriesKey(series) {
25552
+ return JSON.stringify([series.exchangeId, series.dataType]);
25553
+ }
25554
+ function seriesIdentity(value) {
25555
+ if (!isRecord4(value)) return void 0;
25556
+ const exchangeRaw = value.exchange_id ?? value.exchangeid ?? value.exchange;
25557
+ const legacyExchange = finiteDataRangeNumber(exchangeRaw);
25558
+ const exchangeId = LEGACY_MARKET_ID_TO_CODE[legacyExchange] ?? String(exchangeRaw ?? "").trim().toLowerCase();
25559
+ let dataType = String(value.data_type ?? value.datatype ?? "").trim().toLowerCase();
25560
+ if (/^(dk|mk|tk)$/.test(dataType)) {
25561
+ const securityType = finiteDataRangeNumber(value.securitytype ?? value.sectype);
25562
+ if (securityType > 0 && securityType % 16 === 0) dataType += (securityType / 16).toString(16);
25563
+ }
25564
+ if (!dataType) return void 0;
25565
+ return { exchangeId, dataType };
25566
+ }
25567
+ function requestedSeriesFromParams(value) {
25568
+ if (!Array.isArray(value)) return [];
25569
+ const seen = /* @__PURE__ */ new Set();
25570
+ const series = [];
25571
+ for (const item of value) {
25572
+ const identity = seriesIdentity(item);
25573
+ if (!identity) continue;
25574
+ const key = requestedSeriesKey(identity);
25575
+ if (seen.has(key)) continue;
25576
+ seen.add(key);
25577
+ series.push(identity);
25578
+ }
25579
+ return series;
25580
+ }
24995
25581
  function hqSeriesFromResults(resultItems) {
24996
25582
  const series = [];
24997
25583
  for (const item of resultItems) {
@@ -25006,17 +25592,25 @@ function hqSeriesFromResults(resultItems) {
25006
25592
  }
25007
25593
  function engineHasAnyHqSeries(engineRoot, series) {
25008
25594
  if (!engineRoot || series.length === 0) return void 0;
25009
- for (const { exchangeId, dataType } of series) {
25010
- const dir = path19.join(engineRoot, "hqdata", "his", exchangeId, dataType);
25011
- try {
25012
- if (fs20.existsSync(dir) && fs20.readdirSync(dir).length > 0) return true;
25013
- } catch {
25014
- return void 0;
25015
- }
25595
+ for (const requested of series) {
25596
+ const present = engineHasHqSeries(engineRoot, requested);
25597
+ if (present === true) return true;
25598
+ if (present === void 0) return void 0;
25016
25599
  }
25017
25600
  return false;
25018
25601
  }
25019
- function formatDataRangeResult(rawResult, dataRoots) {
25602
+ function engineHasHqSeries(engineRoot, series) {
25603
+ if (!engineRoot || !series.exchangeId || !HQ_DATA_FAMILIES.has(splitDataTypeToken(series.dataType).family)) {
25604
+ return void 0;
25605
+ }
25606
+ const dir = path20.join(engineRoot, "hqdata", "his", series.exchangeId, series.dataType);
25607
+ try {
25608
+ return fs20.readdirSync(dir).length > 0;
25609
+ } catch (error2) {
25610
+ return isRecord4(error2) && error2.code === "ENOENT" ? false : void 0;
25611
+ }
25612
+ }
25613
+ function formatDataRangeResult(rawResult, dataRoots, requestedParams) {
25020
25614
  if (!isRecord4(rawResult)) return rawResult;
25021
25615
  const nestedStatus = isRecord4(rawResult.Data) ? rawResult.Data.coverageStatus : void 0;
25022
25616
  if (isDataRangeCoverageStatus(nestedStatus) || isDataRangeCoverageStatus(rawResult.coverageStatus)) {
@@ -25027,8 +25621,27 @@ function formatDataRangeResult(rawResult, dataRoots) {
25027
25621
  const resultItems = Array.isArray(data) ? data : isRecord4(data) && Array.isArray(data.results) ? data.results : [];
25028
25622
  const seriesOrder = [];
25029
25623
  const seriesByKey = /* @__PURE__ */ new Map();
25624
+ const returnedSeriesOrder = [];
25625
+ const returnedSeriesByKey = /* @__PURE__ */ new Map();
25030
25626
  for (const item of resultItems) {
25031
25627
  if (!isRecord4(item)) continue;
25628
+ const identity = seriesIdentity(item);
25629
+ let returnedEvidence;
25630
+ if (identity) {
25631
+ const identityKey = requestedSeriesKey(identity);
25632
+ returnedEvidence = returnedSeriesByKey.get(identityKey);
25633
+ if (!returnedEvidence) {
25634
+ returnedEvidence = {
25635
+ ...identity,
25636
+ hasIntervals: false,
25637
+ explicitMissing: hasExplicitMissingMarker(item)
25638
+ };
25639
+ returnedSeriesByKey.set(identityKey, returnedEvidence);
25640
+ returnedSeriesOrder.push(identityKey);
25641
+ } else if (hasExplicitMissingMarker(item)) {
25642
+ returnedEvidence.explicitMissing = true;
25643
+ }
25644
+ }
25032
25645
  const exchangeRaw = item.exchange_id ?? item.exchangeid ?? item.exchange;
25033
25646
  const datatypeRaw = item.data_type ?? item.datatype;
25034
25647
  const sectypeRaw = item.securitytype ?? item.sectype;
@@ -25051,6 +25664,7 @@ function formatDataRangeResult(rawResult, dataRoots) {
25051
25664
  const endDate = compactDataRangeDate(time3.end);
25052
25665
  if (!startDate || !endDate) continue;
25053
25666
  series.intervals.push([startDate, endDate]);
25667
+ if (returnedEvidence) returnedEvidence.hasIntervals = true;
25054
25668
  }
25055
25669
  }
25056
25670
  const ranges = [];
@@ -25062,8 +25676,58 @@ function formatDataRangeResult(rawResult, dataRoots) {
25062
25676
  }
25063
25677
  }
25064
25678
  const errNo = Number(rawResult.ErrNo);
25065
- if (Number.isFinite(errNo) && errNo !== 0) {
25066
- return withDataRangeInterpretation(rawResult, "unknown", true, "upstream-error", [], "report-error");
25679
+ const upstreamFailed = Number.isFinite(errNo) && errNo !== 0;
25680
+ const rootSplit = Boolean(dataRoots?.resolved && !dataRoots.agree);
25681
+ const explicitGlobalMissing = hasExplicitMissingMarker(data);
25682
+ const requestedSeries = requestedSeriesFromParams(requestedParams);
25683
+ const coverageOrder = [...requestedSeries.map(requestedSeriesKey)];
25684
+ const coverageByKey = new Map(requestedSeries.map((series) => [requestedSeriesKey(series), series]));
25685
+ for (const key of returnedSeriesOrder) {
25686
+ if (coverageByKey.has(key)) continue;
25687
+ const returned = returnedSeriesByKey.get(key);
25688
+ if (!returned) continue;
25689
+ coverageByKey.set(key, returned);
25690
+ coverageOrder.push(key);
25691
+ }
25692
+ const seriesCoverage = coverageOrder.map((key) => {
25693
+ const series = coverageByKey.get(key);
25694
+ const returned = returnedSeriesByKey.get(key);
25695
+ const identity = {
25696
+ ...series.exchangeId ? { exchange_id: series.exchangeId } : {},
25697
+ data_type: series.dataType
25698
+ };
25699
+ if (upstreamFailed) {
25700
+ return { ...identity, coverageStatus: "unknown", blocksBacktest: true, reasonCode: "upstream-error", nextAction: "report-error" };
25701
+ }
25702
+ if (rootSplit) {
25703
+ return { ...identity, coverageStatus: "unknown", blocksBacktest: true, reasonCode: "data-root-split", nextAction: "resolve-data-root-split" };
25704
+ }
25705
+ if (!returned) {
25706
+ if (explicitGlobalMissing) {
25707
+ return { ...identity, coverageStatus: "unknown", blocksBacktest: true, reasonCode: "explicit-missing", nextAction: "report-missing-data" };
25708
+ }
25709
+ return { ...identity, coverageStatus: "unknown", blocksBacktest: false, reasonCode: "upstream-omitted", nextAction: "recheck-coverage" };
25710
+ }
25711
+ if (returned.explicitMissing) {
25712
+ return { ...identity, coverageStatus: "missing", blocksBacktest: true, reasonCode: "explicit-missing", nextAction: "report-missing-data" };
25713
+ }
25714
+ if (explicitGlobalMissing) {
25715
+ return { ...identity, coverageStatus: "unknown", blocksBacktest: true, reasonCode: "explicit-missing", nextAction: "report-missing-data" };
25716
+ }
25717
+ if (returned.hasIntervals) {
25718
+ return { ...identity, coverageStatus: "available", blocksBacktest: false, reasonCode: "explicit-ranges", nextAction: "run-backtest" };
25719
+ }
25720
+ const family = splitDataTypeToken(series.dataType).family;
25721
+ if (dataRoots?.resolved && dataRoots.agree && HQ_DATA_FAMILIES.has(family)) {
25722
+ const present = engineHasHqSeries(dataRoots.engineRoot, series);
25723
+ if (present === false) {
25724
+ return { ...identity, coverageStatus: "missing", blocksBacktest: true, reasonCode: "no-local-files", nextAction: "download-and-recheck" };
25725
+ }
25726
+ }
25727
+ return { ...identity, coverageStatus: "unknown", blocksBacktest: false, reasonCode: "no-local-coverage", nextAction: "run-backtest" };
25728
+ });
25729
+ if (upstreamFailed) {
25730
+ return withDataRangeInterpretation(rawResult, "unknown", true, "upstream-error", [], "report-error", seriesCoverage);
25067
25731
  }
25068
25732
  if (dataRoots?.resolved && !dataRoots.agree) {
25069
25733
  return withDataRangeInterpretation(
@@ -25072,15 +25736,44 @@ function formatDataRangeResult(rawResult, dataRoots) {
25072
25736
  true,
25073
25737
  "data-root-split",
25074
25738
  ranges,
25075
- `\u6570\u636E\u6839\u4E0D\u4E00\u81F4\uFF1A\u4E0B\u8F7D\u5668\u5199\u5165 ${dataRoots.downloadRoot}\uFF0C\u800C\u7B56\u7565\u5F15\u64CE\u8BFB\u53D6 ${dataRoots.engineRoot}\u3002\u672C\u5730\u6587\u4EF6\u5373\u4F7F\u5B58\u5728\uFF0C\u56DE\u6D4B\u4E5F\u8BFB\u4E0D\u5230\uFF0C\u4F1A\u62A5\u300C\u672C\u5730\u6570\u636E\u4E0D\u8DB3\u300D\u3002\u4E0D\u8981\u636E\u6B64\u5F00\u59CB\u56DE\u6D4B\uFF1B\u8BF7\u5411\u7528\u6237\u62A5\u544A\u8FD9\u4E24\u4E2A\u8DEF\u5F84\uFF0C\u5E76\u8BF4\u660E\u9700\u8981\u4FEE\u590D\u6295\u7814\u6A21\u5757\u7684\u6570\u636E\u6839\u914D\u7F6E\uFF08dc_sdk.json \u7684 mdf.path \u4E0E dcm.json \u7684 download_home\uFF09\u3002`
25739
+ `\u6570\u636E\u6839\u4E0D\u4E00\u81F4\uFF1A\u4E0B\u8F7D\u5668\u5199\u5165 ${dataRoots.downloadRoot}\uFF0C\u800C\u7B56\u7565\u5F15\u64CE\u8BFB\u53D6 ${dataRoots.engineRoot}\u3002\u672C\u5730\u6587\u4EF6\u5373\u4F7F\u5B58\u5728\uFF0C\u56DE\u6D4B\u4E5F\u8BFB\u4E0D\u5230\uFF0C\u4F1A\u62A5\u300C\u672C\u5730\u6570\u636E\u4E0D\u8DB3\u300D\u3002\u4E0D\u8981\u636E\u6B64\u5F00\u59CB\u56DE\u6D4B\uFF1B\u8BF7\u5411\u7528\u6237\u62A5\u544A\u8FD9\u4E24\u4E2A\u8DEF\u5F84\uFF0C\u5E76\u8BF4\u660E\u9700\u8981\u4FEE\u590D\u6295\u7814\u6A21\u5757\u7684\u6570\u636E\u6839\u914D\u7F6E\uFF08dc_sdk.json \u7684 mdf.path \u4E0E dcm.json \u7684 download_home\uFF09\u3002`,
25740
+ seriesCoverage
25741
+ );
25742
+ }
25743
+ if (explicitGlobalMissing) {
25744
+ return withDataRangeInterpretation(rawResult, "missing", true, "explicit-missing", ranges, "report-missing-data", seriesCoverage);
25745
+ }
25746
+ const missingSeries = seriesCoverage.filter((series) => series.coverageStatus === "missing");
25747
+ if (missingSeries.length > 0) {
25748
+ const wanted = missingSeries.map((series) => `${series.exchange_id ? `${series.exchange_id}/` : ""}${series.data_type}`).join("\u3001");
25749
+ const { Data: _rawData, ...envelope } = rawResult;
25750
+ const source = ranges.length > 0 ? envelope : rawResult;
25751
+ return withDataRangeInterpretation(
25752
+ source,
25753
+ "missing",
25754
+ true,
25755
+ missingSeries.every((series) => series.reasonCode === "no-local-files") ? "no-local-files" : "series-missing",
25756
+ ranges,
25757
+ `\u672C\u5730\u7F3A\u5C11 ${wanted}\u3002\u5148\u7528 mcp-download-data \u4E0B\u8F7D\uFF0C\u518D\u7528 mcp-wait kind=download \u7B49\u5F85\u7EC8\u6001\uFF0C\u7136\u540E\u91CD\u65B0\u67E5\u8BE2\u8986\u76D6\u3002`,
25758
+ seriesCoverage
25076
25759
  );
25077
25760
  }
25078
- if (hasExplicitMissingMarker(data)) {
25079
- return withDataRangeInterpretation(rawResult, "missing", true, "explicit-missing", ranges, "report-missing-data");
25761
+ const incompleteSeries = seriesCoverage.some((series) => series.coverageStatus === "unknown");
25762
+ if (ranges.length > 0 && incompleteSeries) {
25763
+ const { Data: _rawData, ...withoutRawData } = rawResult;
25764
+ return withDataRangeInterpretation(
25765
+ withoutRawData,
25766
+ "unknown",
25767
+ false,
25768
+ "incomplete-series-coverage",
25769
+ ranges,
25770
+ "recheck-coverage",
25771
+ seriesCoverage
25772
+ );
25080
25773
  }
25081
25774
  if (ranges.length > 0) {
25082
25775
  const { Data: _rawData, ...withoutRawData } = rawResult;
25083
- return withDataRangeInterpretation(withoutRawData, "available", false, "explicit-ranges", ranges, "run-backtest");
25776
+ return withDataRangeInterpretation(withoutRawData, "available", false, "explicit-ranges", ranges, "run-backtest", seriesCoverage);
25084
25777
  }
25085
25778
  const reasonCode = isEmptyRecord(data) || hasResultCollection && resultItems.length === 0 ? "empty-summary" : hasResultCollection && resultItems.length > 0 ? "no-local-coverage" : "unrecognized-shape";
25086
25779
  if (reasonCode === "no-local-coverage" && dataRoots?.resolved) {
@@ -25093,11 +25786,13 @@ function formatDataRangeResult(rawResult, dataRoots) {
25093
25786
  true,
25094
25787
  "no-local-files",
25095
25788
  [],
25096
- `\u7B56\u7565\u5F15\u64CE\u7684\u6570\u636E\u6839 ${dataRoots.engineRoot} \u4E0B\u6CA1\u6709 ${wanted} \u7684\u4EFB\u4F55\u6587\u4EF6\uFF0C\u672C\u5730\u786E\u5B9E\u6CA1\u6709\u8FD9\u6279\u884C\u60C5\u3002\u5148\u7528 mcp-download-data \u4E0B\u8F7D\uFF0C\u7528 mcp-get-download-progress \u8F6E\u8BE2\u5230\u7EC8\u6001\uFF0C\u518D\u91CD\u65B0\u67E5\u8986\u76D6\uFF1B\u4E0D\u8981\u76F4\u63A5\u5F00\u59CB\u56DE\u6D4B\u3002`
25789
+ `\u7B56\u7565\u5F15\u64CE\u7684\u6570\u636E\u6839 ${dataRoots.engineRoot} \u4E0B\u6CA1\u6709 ${wanted} \u7684\u4EFB\u4F55\u6587\u4EF6\uFF0C\u672C\u5730\u786E\u5B9E\u6CA1\u6709\u8FD9\u6279\u884C\u60C5\u3002\u5148\u7528 mcp-download-data \u4E0B\u8F7D\uFF0C\u518D\u7528 mcp-wait kind=download \u7B49\u5F85\u7EC8\u6001\uFF0C\u7136\u540E\u91CD\u65B0\u67E5\u8986\u76D6\uFF1B\u4E0D\u8981\u76F4\u63A5\u5F00\u59CB\u56DE\u6D4B\u3002`,
25790
+ seriesCoverage
25097
25791
  );
25098
25792
  }
25099
25793
  }
25100
- return withDataRangeInterpretation(rawResult, "unknown", false, reasonCode, [], "run-backtest");
25794
+ const finalReasonCode = requestedSeries.length > 0 && seriesCoverage.some((series) => series.reasonCode === "upstream-omitted") ? "incomplete-series-coverage" : reasonCode;
25795
+ return withDataRangeInterpretation(rawResult, "unknown", false, finalReasonCode, [], "run-backtest", seriesCoverage);
25101
25796
  }
25102
25797
  function unionDataRangeIntervals(intervals) {
25103
25798
  const sorted = [...intervals].sort((a, b) => a[0] === b[0] ? a[1].localeCompare(b[1]) : a[0].localeCompare(b[0]));
@@ -25112,9 +25807,9 @@ function unionDataRangeIntervals(intervals) {
25112
25807
  }
25113
25808
  return merged;
25114
25809
  }
25115
- function withDataRangeInterpretation(rawResult, coverageStatus, blocksBacktest, reasonCode, ranges, nextAction) {
25810
+ function withDataRangeInterpretation(rawResult, coverageStatus, blocksBacktest, reasonCode, ranges, nextAction, seriesCoverage) {
25116
25811
  const { Data: upstreamData, ...envelope } = rawResult;
25117
- const data = { coverageStatus, blocksBacktest, reasonCode, nextAction, ranges };
25812
+ const data = { coverageStatus, blocksBacktest, reasonCode, nextAction, ranges, seriesCoverage };
25118
25813
  if (isRecord4(upstreamData)) {
25119
25814
  for (const [key, value] of Object.entries(upstreamData)) {
25120
25815
  if (!(key in data)) data[key] = value;
@@ -25417,7 +26112,7 @@ function compactDataRangeDate(value) {
25417
26112
 
25418
26113
  // src/tool-response.ts
25419
26114
  var identityRepairHint = (data) => data;
25420
- function handleIpcResponse(response, tool, repairHint = identityRepairHint, dataRoots) {
26115
+ function handleIpcResponse(response, tool, repairHint = identityRepairHint, dataRoots, requestedDataRanges) {
25421
26116
  const parsed = parseIpcRawResponse(response);
25422
26117
  if (!parsed.isSuccess) {
25423
26118
  return {
@@ -25426,18 +26121,18 @@ function handleIpcResponse(response, tool, repairHint = identityRepairHint, data
25426
26121
  };
25427
26122
  }
25428
26123
  const data = repairHint(parsed.data);
25429
- const text2 = typeof data === "string" ? applyResponseTransform(data, tool, dataRoots) : applyResponseTransform(JSON.stringify(data), tool, dataRoots);
26124
+ const text2 = typeof data === "string" ? applyResponseTransform(data, tool, dataRoots, requestedDataRanges) : applyResponseTransform(JSON.stringify(data), tool, dataRoots, requestedDataRanges);
25430
26125
  return {
25431
26126
  content: [{ type: "text", text: text2 }],
25432
26127
  isError: isIpcBusinessError(data) || void 0
25433
26128
  };
25434
26129
  }
25435
- function applyResponseTransform(text2, tool, dataRoots) {
26130
+ function applyResponseTransform(text2, tool, dataRoots, requestedDataRanges) {
25436
26131
  if (!tool?.responseTransform || !text2) return text2;
25437
26132
  try {
25438
26133
  const parsed = JSON.parse(text2);
25439
26134
  if (tool.responseTransform === "dataRange") {
25440
- return JSON.stringify(formatDataRangeResult(parsed, dataRoots));
26135
+ return JSON.stringify(formatDataRangeResult(parsed, dataRoots, requestedDataRanges));
25441
26136
  }
25442
26137
  if (tool.responseTransform === "downloadProgress") {
25443
26138
  return JSON.stringify(formatDownloadProgressResult(parsed));
@@ -25489,18 +26184,18 @@ function resolveFactorProjectRoot(clientRootDir) {
25489
26184
  if (cached2) return cached2;
25490
26185
  const root2 = clientRootDir.replace(/[\\/]+$/, "");
25491
26186
  const configured = expandSlaveValue(
25492
- readSlaveProperties(path20.join(root2, ...ZLTAF_CONFIG_SEGMENTS)),
26187
+ readSlaveProperties(path21.join(root2, ...ZLTAF_CONFIG_SEGMENTS)),
25493
26188
  "slave.factor.project-path",
25494
26189
  root2
25495
26190
  );
25496
- const resolved = configured ? path20.normalize(configured) : path20.join(root2, ...FALLBACK_FACTOR_PROJECT_PATH);
26191
+ const resolved = configured ? path21.normalize(configured) : path21.join(root2, ...FALLBACK_FACTOR_PROJECT_PATH);
25497
26192
  factorProjectRootCache.set(clientRootDir, resolved);
25498
26193
  return resolved;
25499
26194
  }
25500
26195
  function resolveFactorWorkspacePath(clientRootDir, factorId) {
25501
26196
  if (!clientRootDir || !factorId) return void 0;
25502
26197
  const projectRoot = resolveFactorProjectRoot(clientRootDir);
25503
- return projectRoot ? path20.join(projectRoot, factorId) : void 0;
26198
+ return projectRoot ? path21.join(projectRoot, factorId) : void 0;
25504
26199
  }
25505
26200
  var MODULE_LEVEL_FACTOR_EXPORT = /^(?:(?:async\s+)?def\s+get_factor\s*\(|get_factor\s*=(?!=)|Factor\s*=(?!=))/m;
25506
26201
  function checkFactorSourceLoadable(clientRootDir, factorId) {
@@ -25508,7 +26203,7 @@ function checkFactorSourceLoadable(clientRootDir, factorId) {
25508
26203
  if (!workspacePath) return null;
25509
26204
  let source;
25510
26205
  try {
25511
- source = fs21.readFileSync(path20.join(workspacePath, "main.py"), "utf8");
26206
+ source = fs21.readFileSync(path21.join(workspacePath, "main.py"), "utf8");
25512
26207
  } catch {
25513
26208
  return null;
25514
26209
  }
@@ -25927,11 +26622,11 @@ async function queryFactorValuesForLatestRecord(tool, args, client2, timeout, se
25927
26622
 
25928
26623
  // src/strategy-operations.ts
25929
26624
  var fs22 = __toESM(require("node:fs"), 1);
25930
- var path21 = __toESM(require("node:path"), 1);
26625
+ var path22 = __toESM(require("node:path"), 1);
25931
26626
  var STRATEGY_DOCS_TOOLS = /* @__PURE__ */ new Set(["mcp-create-strategy", "mcp-create-strategy-with-template"]);
25932
26627
  function resolveStrategyDocsPath(clientRootDir) {
25933
26628
  if (!clientRootDir) return void 0;
25934
- const docsPath = path21.join(
26629
+ const docsPath = path22.join(
25935
26630
  clientRootDir,
25936
26631
  "python",
25937
26632
  "Lib",
@@ -25958,7 +26653,7 @@ function injectDebugRunId(tool, result) {
25958
26653
  const localPath = typeof parsed.Data.localPath === "string" ? parsed.Data.localPath.trim() : "";
25959
26654
  if (!localPath) return result;
25960
26655
  const settings = JSON.parse(
25961
- fs22.readFileSync(path21.join(localPath, ".vscode", "tradesetting.json"), "utf8")
26656
+ fs22.readFileSync(path22.join(localPath, ".vscode", "tradesetting.json"), "utf8")
25962
26657
  );
25963
26658
  const debugRunId = isRecord4(settings) && typeof settings.backtest_id === "string" ? settings.backtest_id.trim() : "";
25964
26659
  if (!debugRunId) return result;
@@ -26363,7 +27058,7 @@ async function runWaitLoop(lane, client2, timeout, session, control) {
26363
27058
 
26364
27059
  // src/tool-steps.ts
26365
27060
  var fs23 = __toESM(require("node:fs"), 1);
26366
- var path22 = __toESM(require("node:path"), 1);
27061
+ var path23 = __toESM(require("node:path"), 1);
26367
27062
  var import_node_crypto3 = require("node:crypto");
26368
27063
  async function executeSteps(steps, client2, initialBody, timeout, repairHint = identityRepairHint, toolName) {
26369
27064
  let body = { ...initialBody };
@@ -26507,7 +27202,7 @@ function preflightCreatedBacktestSource(toolName, body) {
26507
27202
  const runId = typeof body.runId === "string" ? body.runId.trim() : "";
26508
27203
  const codePath = typeof body.codePath === "string" ? body.codePath.trim() : "";
26509
27204
  if (!codePath || !fs23.existsSync(codePath)) return null;
26510
- const sourcePath = path22.join(codePath, "main.py");
27205
+ const sourcePath = path23.join(codePath, "main.py");
26511
27206
  if (!fs23.existsSync(sourcePath)) return null;
26512
27207
  let source;
26513
27208
  try {
@@ -26656,8 +27351,8 @@ function validateToolCallArguments(tool, args) {
26656
27351
  }
26657
27352
  function validateDataRangeArguments(args) {
26658
27353
  const errors = [];
26659
- const error2 = (path27, message) => errors.push({ path: path27, message });
26660
- const input = stripControlParams(args);
27354
+ const error2 = (path28, message) => errors.push({ path: path28, message });
27355
+ const input = stripControlParams(args, "mcp-get-data-range");
26661
27356
  for (const key of Object.keys(input)) {
26662
27357
  if (key !== "params") error2(`$.${key}`, "Unsupported top-level field; query combinations belong in params[]. Date filters are not accepted.");
26663
27358
  }
@@ -26735,7 +27430,11 @@ async function dispatchSpecialTool(tool, args, client2, timeout, session, waitCo
26735
27430
  if (blocked) return blocked;
26736
27431
  }
26737
27432
  if (tool.name === "mcp-get-strategy-list") {
26738
- return listStrategies(client2, args, timeout, session.repairHint);
27433
+ return shapeListResultDisclosure(
27434
+ tool,
27435
+ args,
27436
+ await listStrategies(client2, args, timeout, session.repairHint)
27437
+ );
26739
27438
  }
26740
27439
  if (tool.name === "mcp-create-strategy") {
26741
27440
  return rejectDuplicateStrategyName(client2, args, timeout, session.repairHint);
@@ -26777,7 +27476,8 @@ function shapeToolResult(tool, args, result, session) {
26777
27476
  const withWorkspace = echoFactorWorkspacePath(tool, skipAware, session.clientRootDir);
26778
27477
  const diagnosed = tool.name === "mcp-factor-calculate-detail" ? diagnoseFactorFailure(withWorkspace) : withWorkspace;
26779
27478
  const distilled = distillFactorDetectReport(tool, args, diagnosed);
26780
- return injectDebugRunId(tool, injectStrategyDocsHint(tool, distilled, session.docsPath));
27479
+ const enriched = injectDebugRunId(tool, injectStrategyDocsHint(tool, distilled, session.docsPath));
27480
+ return shapeDataResultDisclosure(tool, args, shapeListResultDisclosure(tool, args, enriched));
26781
27481
  }
26782
27482
  function backtestStatusNumber(status) {
26783
27483
  return typeof status === "number" || typeof status === "string" && status.trim() !== "" ? Number(status) : NaN;
@@ -26943,7 +27643,7 @@ function backtestWindowPreflightError(tool, reason, message, details) {
26943
27643
  }, true);
26944
27644
  }
26945
27645
  function isExistingAbsoluteDirectory(value) {
26946
- if (!value || !path23.isAbsolute(value)) return false;
27646
+ if (!value || !path24.isAbsolute(value)) return false;
26947
27647
  try {
26948
27648
  return fs24.statSync(value).isDirectory();
26949
27649
  } catch {
@@ -26952,7 +27652,7 @@ function isExistingAbsoluteDirectory(value) {
26952
27652
  }
26953
27653
  function readBacktestIdFromCodePath(codePath) {
26954
27654
  try {
26955
- const tradesettingPath = path23.join(codePath, ".vscode", "tradesetting.json");
27655
+ const tradesettingPath = path24.join(codePath, ".vscode", "tradesetting.json");
26956
27656
  if (!fs24.existsSync(tradesettingPath)) return void 0;
26957
27657
  const parsed = JSON.parse(fs24.readFileSync(tradesettingPath, "utf-8"));
26958
27658
  if (!isRecord4(parsed)) return void 0;
@@ -27422,7 +28122,7 @@ function applyBacktestResultGuards(tool, args, result, states, contexts, activeR
27422
28122
  }
27423
28123
  function readRunResultFile(codePath) {
27424
28124
  try {
27425
- const resultPath = path23.join(codePath, "log", "result.json");
28125
+ const resultPath = path24.join(codePath, "log", "result.json");
27426
28126
  if (!fs24.existsSync(resultPath)) return null;
27427
28127
  const before = fs24.statSync(resultPath);
27428
28128
  const raw = fs24.readFileSync(resultPath);
@@ -27641,7 +28341,7 @@ function echoResolvedBacktestConfig(tool, args, result, contexts) {
27641
28341
  function hashBacktestSource(codePath) {
27642
28342
  if (!codePath) return void 0;
27643
28343
  try {
27644
- const sourcePath = path23.join(codePath, "main.py");
28344
+ const sourcePath = path24.join(codePath, "main.py");
27645
28345
  if (!fs24.statSync(sourcePath).isFile()) return void 0;
27646
28346
  return (0, import_node_crypto4.createHash)("sha256").update(fs24.readFileSync(sourcePath)).digest("hex");
27647
28347
  } catch {
@@ -28596,7 +29296,7 @@ async function startMcpServer() {
28596
29296
  }
28597
29297
  try {
28598
29298
  const response = await ipcClient.invoke(ipcUri, params, body, timeout);
28599
- const result = shapeToolResult(tool, toolArgs, handleIpcResponse(response, tool, withRuntimeRepairHint, dataRoots), session);
29299
+ const result = shapeToolResult(tool, toolArgs, handleIpcResponse(response, tool, withRuntimeRepairHint, dataRoots, toolArgs.params), session);
28600
29300
  if (name === "mcp-download-data") recordActiveDownload(result);
28601
29301
  return result;
28602
29302
  } catch (err) {
@@ -28604,7 +29304,7 @@ async function startMcpServer() {
28604
29304
  if (reconnectedClient) {
28605
29305
  try {
28606
29306
  const response = await reconnectedClient.invoke(ipcUri, params, body, timeout);
28607
- const result = shapeToolResult(tool, toolArgs, handleIpcResponse(response, tool, withRuntimeRepairHint, dataRoots), session);
29307
+ const result = shapeToolResult(tool, toolArgs, handleIpcResponse(response, tool, withRuntimeRepairHint, dataRoots, toolArgs.params), session);
28608
29308
  if (name === "mcp-download-data") recordActiveDownload(result);
28609
29309
  return result;
28610
29310
  } catch (retryErr) {
@@ -29275,7 +29975,7 @@ function runtimeRecoveryStopData(message, extra = {}, handler = "runtimeStart")
29275
29975
 
29276
29976
  // src/auth-cli.ts
29277
29977
  var fs26 = __toESM(require("node:fs"), 1);
29278
- var path25 = __toESM(require("node:path"), 1);
29978
+ var path26 = __toESM(require("node:path"), 1);
29279
29979
  var import_node_crypto5 = require("node:crypto");
29280
29980
  var SOURCE = "zlt-mcp-device-login";
29281
29981
  var IGNORED_API_ENV = /* @__PURE__ */ new Set(["ZLTQUANT_API_KEY", "ZLTQUANT_API_BASE"]);
@@ -29307,14 +30007,14 @@ function buildShowWidgetPayload(s) {
29307
30007
  }
29308
30008
  };
29309
30009
  }
29310
- var root = (e = process.env) => path25.join(resolveZltQuantHome(e), "device-auth-sessions");
30010
+ var root = (e = process.env) => path26.join(resolveZltQuantHome(e), "device-auth-sessions");
29311
30011
  function saveDeviceSession(s, e = process.env) {
29312
30012
  if (!validSession(s)) throw new Error("Invalid authentication session");
29313
30013
  const id = (0, import_node_crypto5.randomUUID)();
29314
30014
  fs26.mkdirSync(root(e), { recursive: true, mode: 448 });
29315
30015
  protectPrivatePath(root(e), true);
29316
30016
  fs26.writeFileSync(
29317
- path25.join(root(e), id + ".json"),
30017
+ path26.join(root(e), id + ".json"),
29318
30018
  JSON.stringify({ authorization: s, expiresAt: s.issuedAt + s.expiresIn * 1e3 }),
29319
30019
  { mode: 384, flag: "wx" }
29320
30020
  );
@@ -29350,7 +30050,7 @@ function authErrorMessage(error2) {
29350
30050
  }
29351
30051
  function sessionPath(id, e = process.env) {
29352
30052
  if (!SESSION_ID.test(id)) throw Error("Invalid authentication session");
29353
- return path25.join(root(e), id + ".json");
30053
+ return path26.join(root(e), id + ".json");
29354
30054
  }
29355
30055
  function validateAuthSessionId(id) {
29356
30056
  if (!SESSION_ID.test(id)) throw Error("Invalid authentication session");
@@ -29403,7 +30103,8 @@ async function runAuthLogin(o = {}) {
29403
30103
  status: "pending",
29404
30104
  verificationUri: s.verificationUri,
29405
30105
  userCode: s.userCode
29406
- }) + "\n" : `Open ${s.verificationUri} and enter code ${s.userCode}.
30106
+ }) + "\n" : `Open ${s.verificationUriComplete}
30107
+ If needed, visit ${s.verificationUri} and enter code ${s.userCode}.
29407
30108
  `
29408
30109
  );
29409
30110
  return finish(s, e, c, o.json, o.emit !== false);
@@ -29637,7 +30338,7 @@ if (process.argv.length <= 2) {
29637
30338
  const args = parseMcpArgs(options.argsJson, options.argsFile);
29638
30339
  const timeoutMs = parseTimeoutOption(options.timeoutMs, "--timeout-ms");
29639
30340
  const maxTotalTimeoutMs = parseTimeoutOption(options.maxTotalTimeoutMs, "--max-total-timeout-ms");
29640
- const resultFile = evidence?.resultFile ?? (options.outputJson === void 0 ? void 0 : path26.resolve(options.outputJson));
30341
+ const resultFile = evidence?.resultFile ?? (options.outputJson === void 0 ? void 0 : path27.resolve(options.outputJson));
29641
30342
  stage = "output_prepare";
29642
30343
  if (resultFile !== void 0) outputFd = fs27.openSync(resultFile, "wx");
29643
30344
  stage = "tool_call";
@@ -29870,9 +30571,9 @@ function resolveCliVersion() {
29870
30571
  return resolveCliPackageProvenance().packageVersion;
29871
30572
  }
29872
30573
  function resolveCliPackageProvenance() {
29873
- let current = path26.dirname(path26.resolve(process.argv[1] || process.cwd()));
30574
+ let current = path27.dirname(path27.resolve(process.argv[1] || process.cwd()));
29874
30575
  for (let depth = 0; depth < 6; depth += 1) {
29875
- const manifestPath = path26.join(current, "package.json");
30576
+ const manifestPath = path27.join(current, "package.json");
29876
30577
  try {
29877
30578
  const manifest = JSON.parse(fs27.readFileSync(manifestPath, "utf-8"));
29878
30579
  if ((manifest.name === "@zltquant/zlt-mcp" || manifest.name === "zlt-mcp-proxy") && typeof manifest.version === "string") {
@@ -29880,7 +30581,7 @@ function resolveCliPackageProvenance() {
29880
30581
  }
29881
30582
  } catch {
29882
30583
  }
29883
- const parent = path26.dirname(current);
30584
+ const parent = path27.dirname(current);
29884
30585
  if (parent === current) break;
29885
30586
  current = parent;
29886
30587
  }