@zltquant/zlt-mcp 0.6.1-beta.6 → 0.6.1-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/config.json CHANGED
@@ -416,7 +416,7 @@
416
416
  },
417
417
  {
418
418
  "name": "mcp-get-cache-diff",
419
- "description": "比对云端与本地缓存,直接回答「还差哪些区间、多少个文件、多大」。只读,不创建任务,不改本地缓存。Data 返回 series、nextAction 和 resultKind=cache-diff(结果类型标记,向用户转述时可忽略):series 每项含 missing(本地没有的区间)与 changed(已覆盖但元数据对不上的区间),两者都已按序列合并相邻与交叠段。\n\n**changed 的文件同样要整份重下,所以补齐全部缺口的下载量是 missingBytes 与 changedBytes 两者之和**;向用户报体量时必须相加,只报 missingBytes 会少算。nextAction=up-to-date 表示本地已经齐了。本工具需要云端枚举,开销相当于一次下载的列举阶段,不要在轮询循环里反复调用。",
419
+ "description": "比对云端与本地缓存,直接回答「还差哪些区间、多少个文件、多大」。只读,不创建任务,不改本地缓存。Data 返回 series、nextAction、assessment、evidence 和 resultKind=cache-diff(结果类型标记,向用户转述时可忽略):series 每项含 missing(本地没有的区间)与 changed(已覆盖但元数据对不上的区间),两者都已按序列合并相邻与交叠段。\n\n**changed 的文件同样要整份重下,所以补齐已返回缺口的下载量是 missingBytes 与 changedBytes 两者之和**;向用户报体量时必须相加,只报 missingBytes 会少算。nextAction=plan-download 只表示返回的有效 series 中发现缺口;cachediff 是差异结果,不是云端目录,未返回的 series 状态未知。evidence.requestCoverage=unverified 表示上游没有证明响应覆盖调用方的完整请求范围。report-unknown 时停止作请求级结论;不要靠扩大日期、无界重试或承诺重新下载即可一致来补造覆盖证据。本工具需要云端枚举,开销相当于一次下载的列举阶段,不要在轮询循环里反复调用。",
420
420
  "inputSchema": {
421
421
  "type": "object",
422
422
  "properties": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zltquant/zlt-mcp",
3
- "version": "0.6.1-beta.6",
3
+ "version": "0.6.1-beta.8",
4
4
  "description": "智量通 ZLT Quant MCP server(Windows x64;量化策略创建与本地回测)",
5
5
  "bin": {
6
6
  "zlt-mcp": "./zlt-mcp-proxy.bundle.cjs"
@@ -26171,17 +26171,39 @@ function toCacheDiffWindows(value) {
26171
26171
  }
26172
26172
  return unionDataRangeIntervals(intervals).map(([startDate, endDate]) => ({ startDate, endDate }));
26173
26173
  }
26174
+ function hasInvalidCacheDiffWindow(value) {
26175
+ return value.some((item) => !isRecord2(item) || !compactDataRangeDate(item.begin ?? item.start) || !compactDataRangeDate(item.end));
26176
+ }
26174
26177
  function formatCacheDiffResult(rawResult) {
26175
26178
  if (!isRecord2(rawResult)) return rawResult;
26176
- if (isRecord2(rawResult.Data) && rawResult.Data.resultKind === CACHE_DIFF_RESULT_KIND) return rawResult;
26179
+ if (isRecord2(rawResult.Data) && rawResult.Data.resultKind === CACHE_DIFF_RESULT_KIND && typeof rawResult.Data.assessment === "string" && isRecord2(rawResult.Data.evidence)) {
26180
+ if (rawResult.Data.evidence.requestCoverage === "unverified") return rawResult;
26181
+ return {
26182
+ ...rawResult,
26183
+ Data: {
26184
+ ...rawResult.Data,
26185
+ evidence: { ...rawResult.Data.evidence, requestCoverage: "unverified" }
26186
+ }
26187
+ };
26188
+ }
26177
26189
  const { Data: upstream, ...envelope } = rawResult;
26178
26190
  const payload = isRecord2(upstream) ? upstream : {};
26191
+ const hasResultsField = Object.prototype.hasOwnProperty.call(payload, "results");
26179
26192
  const results = Array.isArray(payload.results) ? payload.results : [];
26193
+ const resultsShape = !hasResultsField ? "missing" : !Array.isArray(payload.results) ? "invalid" : results.length === 0 ? "empty" : "array";
26180
26194
  const series = [];
26195
+ let uncertainSeries = 0;
26181
26196
  for (const item of results) {
26182
- if (!isRecord2(item)) continue;
26183
- const token = splitDataTypeToken(typeof item.data_type === "string" ? item.data_type : "");
26197
+ if (!isRecord2(item) || typeof item.data_type !== "string" || item.data_type.length === 0) continue;
26198
+ const differenceFields = ["missing", "changed", "files"];
26199
+ const presentFields = differenceFields.filter((field) => Object.prototype.hasOwnProperty.call(item, field));
26200
+ if (presentFields.length === 0 || presentFields.some((field) => !Array.isArray(item[field]))) continue;
26201
+ const token = splitDataTypeToken(item.data_type);
26202
+ const missing = Array.isArray(item.missing) ? item.missing : [];
26203
+ const changed = Array.isArray(item.changed) ? item.changed : [];
26184
26204
  const files = Array.isArray(item.files) ? item.files : [];
26205
+ const hasUnusableMember = hasInvalidCacheDiffWindow(missing) || hasInvalidCacheDiffWindow(changed) || files.some((file) => !isRecord2(file) || file.state !== "missing" && file.state !== "changed");
26206
+ if (hasUnusableMember) uncertainSeries += 1;
26185
26207
  let missingFiles = 0;
26186
26208
  let changedFiles = 0;
26187
26209
  let missingBytes = 0;
@@ -26200,8 +26222,8 @@ function formatCacheDiffResult(rawResult) {
26200
26222
  market: describeDataRangeMarket(item.exchange_id, MARKET_ID_TO_NAME, MARKET_CODE_TO_NAME),
26201
26223
  datatype: DATATYPE_TO_NAME[token.family] || token.family || "\u672A\u77E5\u9891\u7387",
26202
26224
  sectype: describeDataRangeSecurityClass(void 0, token.securityClass, SECTYPE_TO_NAME),
26203
- missing: toCacheDiffWindows(item.missing),
26204
- changed: toCacheDiffWindows(item.changed),
26225
+ missing: toCacheDiffWindows(missing),
26226
+ changed: toCacheDiffWindows(changed),
26205
26227
  missingFiles,
26206
26228
  changedFiles,
26207
26229
  missingBytes,
@@ -26210,12 +26232,25 @@ function formatCacheDiffResult(rawResult) {
26210
26232
  }
26211
26233
  const errNo = Number(rawResult.ErrNo);
26212
26234
  const upstreamFailed = Number.isFinite(errNo) && errNo !== 0;
26213
- const hasWork = series.some((s) => s.missing.length > 0 || s.changed.length > 0);
26235
+ const hasWork = series.some((s) => s.missing.length > 0 || s.changed.length > 0 || s.missingFiles > 0 || s.changedFiles > 0);
26236
+ const rejectedSeries = results.length - series.length;
26237
+ const partialResult = resultsShape === "array" && (rejectedSeries > 0 || uncertainSeries > 0);
26238
+ const assessment = upstreamFailed ? "upstream-error" : partialResult ? "partial-result" : resultsShape !== "array" ? "indeterminate-result" : hasWork ? "differences-found" : "no-differences-in-returned-series";
26239
+ const nextAction = upstreamFailed ? "report-error" : partialResult || resultsShape !== "array" || !hasWork ? "report-unknown" : "plan-download";
26214
26240
  return {
26215
26241
  ...envelope,
26216
26242
  Data: {
26217
26243
  series: upstreamFailed ? [] : series,
26218
- nextAction: upstreamFailed ? "report-error" : hasWork ? "plan-download" : "up-to-date",
26244
+ nextAction,
26245
+ assessment,
26246
+ evidence: {
26247
+ requestCoverage: "unverified",
26248
+ resultsShape,
26249
+ resultCount: results.length,
26250
+ interpretedSeries: series.length,
26251
+ rejectedSeries,
26252
+ uncertainSeries
26253
+ },
26219
26254
  resultKind: CACHE_DIFF_RESULT_KIND
26220
26255
  }
26221
26256
  };
@@ -27686,6 +27721,15 @@ function runtimeRecoveryStopData(message, extra = {}, handler = "runtimeStart")
27686
27721
  var CLI_NAME = "zlt-mcp";
27687
27722
  var CLI_FALLBACK_PACKAGE_NAME = "@zltquant/zlt-mcp";
27688
27723
  var CLI_FALLBACK_VERSION = "0.5.0-beta.0";
27724
+ function writeCliArgumentError(message, write2) {
27725
+ write2(message);
27726
+ if (!message.includes("unknown option")) return;
27727
+ if (message.includes("--registry")) {
27728
+ write2("CLI argument error: toolExecution=not_started; no tool was called. --registry is an npm/npx option, not a zlt-mcp or tool option. Put it before the package name: npx --yes --registry=https://registry.npmjs.org @zltquant/zlt-mcp@<version> <command>. The override applies to one invocation; repeat it on every npx command before claiming that command used the official registry.\n");
27729
+ return;
27730
+ }
27731
+ write2("CLI argument error: toolExecution=not_started; no tool was called. Tool fields belong inside one JSON object passed to --args-json (or --args-file), not --flags or key=value arguments. Use call --help and list --tool <tool-name> --json, correct the arguments, then retry.\n");
27732
+ }
27689
27733
  if (process.argv.length <= 2) {
27690
27734
  startMcpServer();
27691
27735
  } else {
@@ -27703,15 +27747,8 @@ if (process.argv.length <= 2) {
27703
27747
  startRuntime: false
27704
27748
  }));
27705
27749
  });
27706
- program2.name(CLI_NAME).description("MCP proxy for ZLTHost IPC service").version(resolveCliVersion()).addHelpText("after", "\nDiscovery: list for names; list --tool <name> --json for one complete input schema.\nUse call --help for input, output and diagnostic handling.");
27707
- program2.command("call <tool>").description("Call any MCP tool through the bundled MCP server").configureOutput({
27708
- outputError: (message, write2) => {
27709
- write2(message);
27710
- if (message.includes("unknown option")) {
27711
- write2("CLI argument error: toolExecution=not_started; no tool was called. Tool fields belong inside one JSON object passed to --args-json (or --args-file), not --flags or key=value arguments. Use call --help and list --tool <tool-name> --json, correct the arguments, then retry.\n");
27712
- }
27713
- }
27714
- }).option("--args-json <json>", "JSON object containing tool arguments").option("--args-file <path>", "Read the JSON argument object from a file").option("--output-json <path>", "Save the complete result to a new JSON file and print a compact receipt").option("--timeout-ms <ms>", "MCP request inactivity timeout in milliseconds").option("--max-total-timeout-ms <ms>", "Optional hard upper bound for the call, including install/backtest wait").option("--no-progress", "Suppress progress diagnostics on stderr").addHelpText("after", `
27750
+ program2.name(CLI_NAME).description("MCP proxy for ZLTHost IPC service").version(resolveCliVersion()).configureOutput({ outputError: writeCliArgumentError }).addHelpText("after", "\nDiscovery: list for names; list --tool <name> --json for one complete input schema.\nUse call --help for input, output and diagnostic handling.\nFor npx registry selection, put --registry before the package name; it is not a zlt-mcp option.");
27751
+ program2.command("call <tool>").description("Call any MCP tool through the bundled MCP server").configureOutput({ outputError: writeCliArgumentError }).option("--args-json <json>", "JSON object containing tool arguments").option("--args-file <path>", "Read the JSON argument object from a file").option("--output-json <path>", "Save the complete result to a new JSON file and print a compact receipt").option("--timeout-ms <ms>", "MCP request inactivity timeout in milliseconds").option("--max-total-timeout-ms <ms>", "Optional hard upper bound for the call, including install/backtest wait").option("--no-progress", "Suppress progress diagnostics on stderr").addHelpText("after", `
27715
27752
  Input: omitted arguments mean {}; use --args-json for small objects and --args-file
27716
27753
  for nested configuration or shell-sensitive text. Follow the selected tool schema
27717
27754
  from list --tool <name> --json. Windows paths must be native paths (C:/...), not /c/....