@zltquant/zlt-mcp 0.1.0 → 0.3.0-beta.0
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 +3 -3
- package/package.json +1 -1
- package/zlt-mcp-proxy.bundle.cjs +433 -79
package/config.json
CHANGED
|
@@ -507,7 +507,7 @@
|
|
|
507
507
|
},
|
|
508
508
|
{
|
|
509
509
|
"name": "mcp-create-and-run-backtest",
|
|
510
|
-
"description": "创建并启动回测。strategyId 必须来自 mcp-create-strategy 返回的策略ID;runType 固定为 2;普通日线回测只传 strategyId,其余参数 MCP 补齐。未指定周期时 end 取自然日 T-1、start 从 end 往前推半年;ZLTAF 按实际交易日执行,非交易日不产生行情或策略调用。run/create 失败直接报错,不要去复用策略里自动生成的 debug runId(建策略时已回显为 debugRunId
|
|
510
|
+
"description": "创建并启动回测。strategyId 必须来自 mcp-create-strategy 返回的策略ID;runType 固定为 2;普通日线回测只传 strategyId,其余参数 MCP 补齐。未指定周期时 end 取自然日 T-1、start 从 end 往前推半年;ZLTAF 按实际交易日执行,非交易日不产生行情或策略调用。run/create 失败直接报错,不要去复用策略里自动生成的 debug runId(建策略时已回显为 debugRunId,跑它等于跑创建那一刻的模板快照)。run/create 生成快照后,MCP 会在真正启动前拒绝 get_current_data().get(...) 这种当前对象不支持的访问。\n\n**返回 runId 后立即调用 mcp-wait(kind=backtest,id=runId)阻塞等待回测结束,不要用 mcp-get-backtest-state 轮询。**\n\n日线类频率只可见到 context.previous_date:要用交易日 T 的收盘,end 必须设成 T 的下一个交易日;end 落在未来不报错但结果为空。展开见返回的 dailyVisibilityNote / endWarning。\n\n返回 Data 回显 resolvedStart/resolvedEnd/resolvedCapital——向用户汇报区间和初始资金时一律以这些字段为准,不要自行推算或臆测。evidence 给出 backtestId、实际 runDir、完整 effectiveRunParams 和代码快照 sourceSha256,后续结果必须与它对账。**基准不在此列**:回显的 requestedBenchmark 只是请求值,策略 initialize 里的 set_benchmark() 会覆盖它,收益产物里的「基准收益」按策略实际用的基准算。说基准是什么之前先读策略代码里的 set_benchmark,否则会把一只个股的涨跌报成指数的。\n\n**期货回测要同时改三处,少一处引擎就按股票跑**:runParams.marketIds 加上对应期货交易所(zj 中金所、zs 郑商所、ds 大商所、sq 上期所、gq 广期所),account_list 的 account_type 改成 2(实测用 6 直接废单),费率用 ratio_tpl_obj.future。合约代码形如 zjIM2605。基准保持默认 sz399300 即可,它对期货策略只是业绩比较基准。数据前置见 mcp-download-data:除行情外还必须有市场规则 mr。",
|
|
511
511
|
"inputSchema": {
|
|
512
512
|
"type": "object",
|
|
513
513
|
"properties": {
|
|
@@ -913,7 +913,7 @@
|
|
|
913
913
|
},
|
|
914
914
|
{
|
|
915
915
|
"name": "mcp-get-backtest-profit",
|
|
916
|
-
"description": "读取已完成回测的收益表现,只能在 mcp-get-backtest-state 返回 status=5 后调用。直接读回测副本目录下的 log/zlt_backtest_profit_detail.csv,不经过 ZLTAF。正常只传 mcp-create-and-run-backtest 返回的 runId;MCP 重启后上下文丢失时补传 codePath。\n\nperformance 是整轮汇总,取自产物最后一行。**名字带 Pct 的已经是百分数**:-15.62 就是 -15.62%,不要再乘 100。winRate 与 dailyWinRate 是 0-1 的比例,其余是无量纲比值。上游没有值时返回 null(原文是 nan 或空单元格),不要当成 0。\n\n另给 rows(逐日行数)、firstDate/lastDate、capital、maxDrawdownWindow
|
|
916
|
+
"description": "读取已完成回测的收益表现,只能在 mcp-get-backtest-state 返回 status=5 后调用。直接读回测副本目录下的 log/zlt_backtest_profit_detail.csv,不经过 ZLTAF。正常只传 mcp-create-and-run-backtest 返回的 runId;MCP 重启后上下文丢失时补传 codePath。\n\nperformance 是整轮汇总,取自产物最后一行。**名字带 Pct 的已经是百分数**:-15.62 就是 -15.62%,不要再乘 100。winRate 与 dailyWinRate 是 0-1 的比例,其余是无量纲比值。上游没有值时返回 null(原文是 nan 或空单元格),不要当成 0。\n\n另给 rows(逐日行数)、firstDate/lastDate、capital、maxDrawdownWindow(已按北京时间换算成日期)。evidence 对账 requestedBacktestId、artifactBacktestId、runDir、effectiveRunParams 和 sourceSha256;contextAvailable=false 表示 MCP 已重启,只能证明显式 codePath 和产物内 ID。逐日净值序列默认不返回,要画净值曲线才传 includeSeries=true。\n\n**notes 里的内容必须转述**:产物回测ID 与请求不一致,说明 codePath 指向了另一次运行,那批数字不属于本次回测;超额收益校验不通过,说明上游口径变了,此时三个收益数原样给出,不得自行重算,也不得据此宣称跑赢基准。",
|
|
917
917
|
"inputSchema": {
|
|
918
918
|
"type": "object",
|
|
919
919
|
"properties": {
|
|
@@ -928,7 +928,7 @@
|
|
|
928
928
|
"includeSeries": {
|
|
929
929
|
"type": "boolean",
|
|
930
930
|
"default": false,
|
|
931
|
-
"description": "返回逐日序列(date / totalAsset / benchmarkPrice / positionRatePct / turnoverRatePct)。超过 250
|
|
931
|
+
"description": "返回逐日序列(date / totalAsset / benchmarkPrice / positionRatePct / turnoverRatePct)。超过 250 行会**等距抽样**到 250 点并标 seriesTruncated:首尾保留、跨度完整、逐点数值真实,只是变稀——多年回测画净值曲线够用,不会只拿到末段。要每一行时 notes 会给出该次产物 CSV 的列号,照它读。"
|
|
932
932
|
}
|
|
933
933
|
},
|
|
934
934
|
"required": [
|
package/package.json
CHANGED
package/zlt-mcp-proxy.bundle.cjs
CHANGED
|
@@ -10496,7 +10496,95 @@ var DEFAULT_BACKTEST_MODULE_INDICES = [TY_MODULE_INDEX];
|
|
|
10496
10496
|
var DEBUG_ASSISTANT_INSTALLER_URL = "https://beta.zltquant.com/download/setup-ZLTStudio-Dbg-mini-20260714.4.exe";
|
|
10497
10497
|
var PUBLIC_PYTHON_SDK_INDEX_URL = "https://pypip.zltquant.com/";
|
|
10498
10498
|
var ZLTAF_CONFIG_FILE_DEFAULT = "application-local.properties";
|
|
10499
|
-
var
|
|
10499
|
+
var OFFICIAL_MIRROR_ROOTS = {
|
|
10500
|
+
public: "https://zlt-data-house.oss-cn-wuhan-lr.aliyuncs.com/zltkj.site/down/v1/up/Zlt.Std.Official",
|
|
10501
|
+
internal: "http://192.168.1.243:9000/zlt-data-house/zltkj.site/down/v1/up/Zlt.Std.Official"
|
|
10502
|
+
};
|
|
10503
|
+
var OFFICIAL_INSTALLERS = {
|
|
10504
|
+
public: {
|
|
10505
|
+
// 2026-08-31 抬到 2026.08.31.3,接替 2026.06.18.11 —— 运维已把件传上公网 OSS。
|
|
10506
|
+
// 摘要不必重下:公网与内网是同一份字节,HEAD 实测 Content-Length 168,548,568
|
|
10507
|
+
// 与 ETag(OSS 侧即 MD5)C404C12F…33DA 两边完全一致,所以沿用内网那份已核过的
|
|
10508
|
+
// SHA256=5BE939F0…5B19。
|
|
10509
|
+
// 卡在 2026.06.18.11 的代价是实打实的:它低于我们自己发布的
|
|
10510
|
+
// zlt_quant_version_index.json 里的 Client.min = 2026.08.12.3,于是一台 full
|
|
10511
|
+
// 装机撞上闸门只会得到 blockedByPlugin,被告知「请先升级 ZLT Quant 插件」——
|
|
10512
|
+
// 而插件已经是最新的那一版,闸门永远消不掉。
|
|
10513
|
+
// 本条与 internal.full 这次同版本,那是因为公网刚补齐,不是两张表从此必然同步。
|
|
10514
|
+
// **本版没有装机验证**,与 internal.full 同一句话。
|
|
10515
|
+
full: {
|
|
10516
|
+
artifact: "zlt_client",
|
|
10517
|
+
version: "2026.08.31.3",
|
|
10518
|
+
sha256: "5BE939F069E69C05F37017FBB06FF76DE4DBCBD4CBCAF1322479255A5CE55B19"
|
|
10519
|
+
},
|
|
10520
|
+
// 2026-08-15 抬到 2026.08.14.5:公网 OSS 与内网镜像是同一份字节(ETag 113b3cff…、
|
|
10521
|
+
// 75,075,160 字节两边一致),本机下载实测 SHA256=9D40AE9A…D551,与 2026-08-14 覆盖
|
|
10522
|
+
// 安装时校验过的摘要一致,两条独立路径互证。这一版是投研模块下限(≥2026.08.11.2)
|
|
10523
|
+
// 之上的第一个已发布 mini:低于它,投研模块 upgrade/check 直接以「客户端版本过低」
|
|
10524
|
+
// 拒绝,且该下限只在模块服务端。version 取安装包自身 FileVersion 的点分四段(不是
|
|
10525
|
+
// 构建目录名的紧凑形 20260814.5):升级判定拿它和 InstallInfo.xml 的
|
|
10526
|
+
// InstallAppReleaseVer 比,写成紧凑形会让「有可用更新」永远消不掉。
|
|
10527
|
+
// 2026-08-31 抬到 2026.08.31.4,接替 2026.08.14.5。判据与 full 同一条:HEAD 实测
|
|
10528
|
+
// Content-Length 79,605,832 与 ETag 7A53D1EE…1375 公网内网一致,摘要沿用内网已核过的
|
|
10529
|
+
// SHA256=115A3EED…83CE。
|
|
10530
|
+
// 这一槽位是市场版的首装路径 —— VSCode 只装 mini(runtime-profile.mjs 的
|
|
10531
|
+
// VSCODE_INSTALL_TYPE),full 槽位只在已装 full 的机器上参与升级判定。
|
|
10532
|
+
// **本版没有装机验证**:本机停在 2026.08.28.7,08-30 对 .7 做的那轮活体复核
|
|
10533
|
+
// (三进程起得来、ZLTHQHost 管道在、两轮 check:npm-live 全绿)不适用于本版。
|
|
10534
|
+
mini: {
|
|
10535
|
+
artifact: "zlt_plugin",
|
|
10536
|
+
version: "2026.08.31.4",
|
|
10537
|
+
sha256: "115A3EEDC07211F6FBE56696573F668AE8315E351B017FECB0F6136AAAD983CE"
|
|
10538
|
+
}
|
|
10539
|
+
},
|
|
10540
|
+
internal: {
|
|
10541
|
+
// 2026-08-31 抬到 2026.08.31.3(1.0.2 RC 用件),接替 2026.08.28.8。内网镜像下载
|
|
10542
|
+
// 核验:168,548,568 字节,SHA256=5BE939F0…5B19,安装包 FileVersion 自报
|
|
10543
|
+
// 2026.08.31.3(版本取它,不取文件名)。它仍高于 Client.min = 2026.08.12.3,
|
|
10544
|
+
// 所以内测通道上一台 full 装机不会以 blockedByPlugin 收场。
|
|
10545
|
+
// 公网 OSS 上这一版 404(2026-08-31 实测 HEAD),public.full 不动。
|
|
10546
|
+
full: {
|
|
10547
|
+
artifact: "zlt_client",
|
|
10548
|
+
version: "2026.08.31.3",
|
|
10549
|
+
sha256: "5BE939F069E69C05F37017FBB06FF76DE4DBCBD4CBCAF1322479255A5CE55B19"
|
|
10550
|
+
},
|
|
10551
|
+
// 2026-08-31 抬到 2026.08.31.4(1.0.2 RC 用件),接替 2026.08.28.7。下载核验:
|
|
10552
|
+
// 79,605,832 字节,SHA256=115A3EED…83CE,FileVersion 自报 2026.08.31.4。
|
|
10553
|
+
//
|
|
10554
|
+
// **本条两件都只核到字节与版本,没有装机验证。** 本机停在 2026.08.28.7
|
|
10555
|
+
// (InstallInfo.xml 的 InstallAppReleaseVer 实读如此),所以 08-30 对 .7 做的那轮
|
|
10556
|
+
// 活体复核(三进程起得来、ZLTHQHost 管道在、两轮 check:npm-live 全绿)**不适用于
|
|
10557
|
+
// 这两版**,别把它顺移过来当证据。RC 装机后要重新确认两件事:ZLTHome 起得来、
|
|
10558
|
+
// 且 InstallAppReleaseVer 回读等于本条点分四段(对不上会让「有可用更新」永远消不掉)。
|
|
10559
|
+
//
|
|
10560
|
+
// 这条 08-28 起的历史仍然有效,记着是因为它解释了为什么这批件在密集换版:
|
|
10561
|
+
// 2026.08.28.3 现场装过并 ZLTHome 启动即崩(TTaskFunc 持栈上 lambda 的悬垂引用,
|
|
10562
|
+
// 100% 复现,ZLTHQHost 管道从未存活);同版起把 zltaf 从投研模块的子模块集里去掉,
|
|
10563
|
+
// 修的是首装必炸的另一条权限死路 —— 安装器与模块各发一份 zltaf,模块解压要覆盖
|
|
10564
|
+
// 安装器以管理员身份写下的文件,而 ZLTBackService 跑在登录账户的 UAC 过滤令牌上,
|
|
10565
|
+
// 卷根 ACL 缺 Authenticated Users:(M) 时覆盖必被拒,2 毫秒失败在第一个文件上。
|
|
10566
|
+
// 见 docs/reports/2026-08-28-zltaf-submodule-extract-access-denied.md。
|
|
10567
|
+
// 这些版本都没进过本表,不要读成本槽位的版本序列(上一个 pin 是 2026.08.28.7)。
|
|
10568
|
+
//
|
|
10569
|
+
// 公网 OSS 上这一版同样 404,所以 public.mini 仍停在 2026.08.14.5 —— 两张表不同版本,
|
|
10570
|
+
// 这正是按镜像分表的理由。
|
|
10571
|
+
mini: {
|
|
10572
|
+
artifact: "zlt_plugin",
|
|
10573
|
+
version: "2026.08.31.4",
|
|
10574
|
+
sha256: "115A3EEDC07211F6FBE56696573F668AE8315E351B017FECB0F6136AAAD983CE"
|
|
10575
|
+
}
|
|
10576
|
+
}
|
|
10577
|
+
};
|
|
10578
|
+
function resolveInstallerMirror() {
|
|
10579
|
+
return false ? "internal" : "public";
|
|
10580
|
+
}
|
|
10581
|
+
function officialInstallerUrl(slot, mirror = "public") {
|
|
10582
|
+
const spec = OFFICIAL_INSTALLERS[mirror][slot];
|
|
10583
|
+
return `${OFFICIAL_MIRROR_ROOTS[mirror]}/pkg/${spec.artifact}_${spec.version}.exe`;
|
|
10584
|
+
}
|
|
10585
|
+
function officialVersionIndexUrl(mirror = "public") {
|
|
10586
|
+
return `${OFFICIAL_MIRROR_ROOTS[mirror]}/VscodeMarketPlugin/zlt_quant_version_index.json`;
|
|
10587
|
+
}
|
|
10500
10588
|
var INTERNAL_PYTHON_SDK_INDEX_URL = "https://192.168.1.32:9100/pypi/simple/";
|
|
10501
10589
|
var INTERNAL_PYTHON_SDK_TRUSTED_HOST = "192.168.1.32";
|
|
10502
10590
|
var PYTHON_SDK_PACKAGES = ["zltquant", "zltsdk-plugin"];
|
|
@@ -10517,8 +10605,8 @@ var defaultAssistantRuntimeConfig = {
|
|
|
10517
10605
|
envMode: "OFFICIAL",
|
|
10518
10606
|
backserviceDownload: {
|
|
10519
10607
|
OFFICIAL: {
|
|
10520
|
-
full: "
|
|
10521
|
-
mini: "
|
|
10608
|
+
full: officialInstallerUrl("full"),
|
|
10609
|
+
mini: officialInstallerUrl("mini")
|
|
10522
10610
|
},
|
|
10523
10611
|
REL: {
|
|
10524
10612
|
full: "",
|
|
@@ -10531,10 +10619,13 @@ var defaultAssistantRuntimeConfig = {
|
|
|
10531
10619
|
},
|
|
10532
10620
|
// Exact artifact digests. A URL update requires a matching digest update in the
|
|
10533
10621
|
// same reviewed change; downloadRuntimeInstaller fails closed when it is absent.
|
|
10622
|
+
// OFFICIAL 的取值来自 OFFICIAL_INSTALLERS.public —— URL/版本/摘要三者同源,只有那一处可改。
|
|
10623
|
+
// 这里恒取公网表:模块级默认必须公网可达(runtime.test.ts 的 LAN 守卫钉的就是它),
|
|
10624
|
+
// 内网镜像那档由 applyEnvOverrides 按镜像轴整行换掉。
|
|
10534
10625
|
backserviceDownloadSha256: {
|
|
10535
10626
|
OFFICIAL: {
|
|
10536
|
-
full:
|
|
10537
|
-
mini:
|
|
10627
|
+
full: OFFICIAL_INSTALLERS.public.full.sha256,
|
|
10628
|
+
mini: OFFICIAL_INSTALLERS.public.mini.sha256
|
|
10538
10629
|
},
|
|
10539
10630
|
REL: { full: "", mini: "" },
|
|
10540
10631
|
DEBUG: {
|
|
@@ -10542,15 +10633,12 @@ var defaultAssistantRuntimeConfig = {
|
|
|
10542
10633
|
mini: "05C57A5D212684A801665774E9F0813EFC1AA4762D1540EC353BB41173712B07"
|
|
10543
10634
|
}
|
|
10544
10635
|
},
|
|
10545
|
-
//
|
|
10546
|
-
//
|
|
10636
|
+
// 本体升级判定拿它当「我们能立刻交付的版本下限」。OFFICIAL 与 URL 同源自
|
|
10637
|
+
// OFFICIAL_INSTALLERS,结构上不可能只改 URL 不改这里。
|
|
10547
10638
|
backserviceDownloadVersion: {
|
|
10548
10639
|
OFFICIAL: {
|
|
10549
|
-
full:
|
|
10550
|
-
|
|
10551
|
-
// InstallInfo.xml 的 InstallAppReleaseVer 比,那边是点分四段。写成紧凑形会让
|
|
10552
|
-
// 20260814 > 2026 恒成立,「有可用更新」永远消不掉。
|
|
10553
|
-
mini: "2026.08.14.5"
|
|
10640
|
+
full: OFFICIAL_INSTALLERS.public.full.version,
|
|
10641
|
+
mini: OFFICIAL_INSTALLERS.public.mini.version
|
|
10554
10642
|
},
|
|
10555
10643
|
REL: { full: "", mini: "" },
|
|
10556
10644
|
DEBUG: {
|
|
@@ -10567,8 +10655,10 @@ var defaultAssistantRuntimeConfig = {
|
|
|
10567
10655
|
//
|
|
10568
10656
|
// REL/DEBUG 没有对应发布面,留空即跳过远程判定。地址不可达或文件不存在同样 fail-open,
|
|
10569
10657
|
// 所以这条链路默认是关的,直到有人把文件传上去 —— 见 deploy/README.md。
|
|
10658
|
+
// 与安装包同源自 OFFICIAL_MIRROR_ROOTS:内测构建把安装包指到内网时,这条也必须跟着走,
|
|
10659
|
+
// 否则一个 -internal 产物会拿公网索引判闸门 —— 而索引取不到时闸门是 fail-open。
|
|
10570
10660
|
baseRequirementUrl: {
|
|
10571
|
-
OFFICIAL: "
|
|
10661
|
+
OFFICIAL: officialVersionIndexUrl("public"),
|
|
10572
10662
|
REL: "",
|
|
10573
10663
|
DEBUG: ""
|
|
10574
10664
|
},
|
|
@@ -10771,13 +10861,16 @@ function applyEnvOverrides(config2) {
|
|
|
10771
10861
|
const sdkTrustedHostOverride = process.env.ZLT_PYTHON_SDK_TRUSTED_HOST;
|
|
10772
10862
|
const baseRequirementUrlOverride = process.env.ZLT_BASE_REQUIREMENT_URL?.trim();
|
|
10773
10863
|
const installer = parseInstallerOverride(process.env.ZLT_ASSISTANT_INSTALLER_OVERRIDE);
|
|
10864
|
+
const mirror = resolveInstallerMirror();
|
|
10865
|
+
const mirrored = applyInstallerMirror(config2, mirror);
|
|
10866
|
+
const mirroredIndex = mirror === "public" ? config2.baseRequirementUrl : { ...config2.baseRequirementUrl, OFFICIAL: officialVersionIndexUrl(mirror) };
|
|
10774
10867
|
return {
|
|
10775
10868
|
...config2,
|
|
10776
10869
|
envMode,
|
|
10777
|
-
baseRequirementUrl: baseRequirementUrlOverride ? { ...
|
|
10778
|
-
backserviceDownload: applyInstallerOverride(
|
|
10779
|
-
backserviceDownloadSha256: applyInstallerOverride(
|
|
10780
|
-
backserviceDownloadVersion: applyInstallerOverride(
|
|
10870
|
+
baseRequirementUrl: baseRequirementUrlOverride ? { ...mirroredIndex, [envMode]: baseRequirementUrlOverride } : mirroredIndex,
|
|
10871
|
+
backserviceDownload: applyInstallerOverride(mirrored.backserviceDownload, envMode, installer, "url"),
|
|
10872
|
+
backserviceDownloadSha256: applyInstallerOverride(mirrored.backserviceDownloadSha256, envMode, installer, "sha256"),
|
|
10873
|
+
backserviceDownloadVersion: applyInstallerOverride(mirrored.backserviceDownloadVersion, envMode, installer, "version"),
|
|
10781
10874
|
pythonRuntimePackages: runtimePackages.length > 0 ? runtimePackages : config2.pythonRuntimePackages,
|
|
10782
10875
|
pythonRuntimeIndexUrl: process.env.ZLT_PYTHON_RUNTIME_INDEX_URL?.trim() || config2.pythonRuntimeIndexUrl,
|
|
10783
10876
|
pythonSdkPackages: packages.length > 0 ? packages : envModeChanged ? config2.pythonSdkPackagesByMode[envMode] : config2.pythonSdkPackages,
|
|
@@ -10787,6 +10880,25 @@ function applyEnvOverrides(config2) {
|
|
|
10787
10880
|
pythonPipWheelSha256: process.env.ZLT_PYTHON_PIP_WHEEL_SHA256?.trim() || config2.pythonPipWheelSha256
|
|
10788
10881
|
};
|
|
10789
10882
|
}
|
|
10883
|
+
function applyInstallerMirror(config2, mirror) {
|
|
10884
|
+
if (mirror === "public")
|
|
10885
|
+
return config2;
|
|
10886
|
+
const pins = OFFICIAL_INSTALLERS[mirror];
|
|
10887
|
+
return {
|
|
10888
|
+
backserviceDownload: {
|
|
10889
|
+
...config2.backserviceDownload,
|
|
10890
|
+
OFFICIAL: { full: officialInstallerUrl("full", mirror), mini: officialInstallerUrl("mini", mirror) }
|
|
10891
|
+
},
|
|
10892
|
+
backserviceDownloadSha256: {
|
|
10893
|
+
...config2.backserviceDownloadSha256,
|
|
10894
|
+
OFFICIAL: { full: pins.full.sha256, mini: pins.mini.sha256 }
|
|
10895
|
+
},
|
|
10896
|
+
backserviceDownloadVersion: {
|
|
10897
|
+
...config2.backserviceDownloadVersion,
|
|
10898
|
+
OFFICIAL: { full: pins.full.version, mini: pins.mini.version }
|
|
10899
|
+
}
|
|
10900
|
+
};
|
|
10901
|
+
}
|
|
10790
10902
|
function parseInstallerOverride(raw) {
|
|
10791
10903
|
const text = raw?.trim();
|
|
10792
10904
|
if (!text)
|
|
@@ -11038,7 +11150,34 @@ var AssistantMasterIpcClient = class {
|
|
|
11038
11150
|
}
|
|
11039
11151
|
}
|
|
11040
11152
|
}
|
|
11041
|
-
|
|
11153
|
+
/**
|
|
11154
|
+
* 安装/启动通道动手前,先把 VSCode PID 注册进智能管家的监控表。
|
|
11155
|
+
*
|
|
11156
|
+
* 智能管家侧(xzs)每 ~10 秒查一次 monitor/check_reg_empty,注册表持续为空约 30 秒
|
|
11157
|
+
* 就把整族进程自退回收 —— 2026-08-25 全新装机实测:TY 模块 202MB 下载到 88% 时
|
|
11158
|
+
* ZLTBackService 被回收,ZLTHome 随后退出,下载轮询以管道断开告终
|
|
11159
|
+
* (FAILURE-PATTERNS #77)。常规注册挂在 ZLTAF connected 边沿(vscode-ext 的
|
|
11160
|
+
* assistant-monitor),而首次安装期间 ZLTAF 尚不存在,那条边沿永远等不到;
|
|
11161
|
+
* claw-host 的安装通道在每次 IPC 连接后都上报 PID
|
|
11162
|
+
* (assistant-installer.ts:1132/:1442),此处对齐。重复注册幂等。
|
|
11163
|
+
* 仅检测通道(checkBacktestModuleUpdates)刻意不注册 —— 后台检查若注册会阻止
|
|
11164
|
+
* 空闲自退,把「已装但未运行」这个合法状态挡掉。
|
|
11165
|
+
*
|
|
11166
|
+
* 注册失败绝不拦安装:旧本体可能没有 monitor API,失败只降级为一行进度日志。
|
|
11167
|
+
*
|
|
11168
|
+
* @param config 运行时配置,取其 ipcConnectTimeout 作为请求超时
|
|
11169
|
+
* @param onProgress 可选进度回调,仅在注册失败时收到一行说明
|
|
11170
|
+
*/
|
|
11171
|
+
async reportInstallLanePid(config2, onProgress) {
|
|
11172
|
+
try {
|
|
11173
|
+
await this.reportVSCodePid(process.pid, config2);
|
|
11174
|
+
} catch (error2) {
|
|
11175
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
11176
|
+
onProgress?.(`VSCode \u8FDB\u7A0B\u6CE8\u518C\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u5B89\u88C5\u7EE7\u7EED\uFF09: ${message}`);
|
|
11177
|
+
}
|
|
11178
|
+
}
|
|
11179
|
+
async startDefaultServices(config2, onProgress) {
|
|
11180
|
+
await this.reportInstallLanePid(config2, onProgress);
|
|
11042
11181
|
for (const serviceIndex of config2.manualServiceIndices) {
|
|
11043
11182
|
await this.sendRequest("zltMClient", "CallInnerRpc", {
|
|
11044
11183
|
modeType: 0,
|
|
@@ -11092,6 +11231,7 @@ var AssistantMasterIpcClient = class {
|
|
|
11092
11231
|
}
|
|
11093
11232
|
}
|
|
11094
11233
|
async installBacktestModules(workRoot, config2, onProgress, hooks = {}) {
|
|
11234
|
+
await this.reportInstallLanePid(config2, onProgress);
|
|
11095
11235
|
const moduleIndices = [
|
|
11096
11236
|
CLIENT_PLUGIN_MODULE_INDEX,
|
|
11097
11237
|
...config2.backtestModuleIndices.filter((moduleIndex) => moduleIndex !== CLIENT_PLUGIN_MODULE_INDEX)
|
|
@@ -11514,17 +11654,26 @@ var AssistantMasterIpcClient = class {
|
|
|
11514
11654
|
throw new Error(formatModuleInstallError("\u6295\u7814\u6A21\u5757\u5305\u8986\u76D6\u5B89\u88C5\u72B6\u6001\u8F6E\u8BE2\u8D85\u65F6", moduleIndex, lastProgress ?? { status: 0, process: 0, phase: 0, response: null }));
|
|
11515
11655
|
}
|
|
11516
11656
|
};
|
|
11517
|
-
async function startManualServices(workRoot, zltContent, config2) {
|
|
11657
|
+
async function startManualServices(workRoot, zltContent, config2, onProgress) {
|
|
11518
11658
|
const client = new AssistantMasterIpcClient();
|
|
11519
11659
|
try {
|
|
11520
11660
|
await client.connect(zltContent, config2);
|
|
11521
|
-
await client.startDefaultServices(config2);
|
|
11661
|
+
await client.startDefaultServices(config2, onProgress);
|
|
11522
11662
|
await client.pollStartupServices(config2);
|
|
11523
11663
|
await waitForPipe(workRoot, "ZLTAF", config2.zltafPipeWait);
|
|
11524
11664
|
} finally {
|
|
11525
11665
|
await client.disconnect();
|
|
11526
11666
|
}
|
|
11527
11667
|
}
|
|
11668
|
+
async function unregisterRuntimeConsumerPid(zltContent, config2) {
|
|
11669
|
+
const client = new AssistantMasterIpcClient();
|
|
11670
|
+
try {
|
|
11671
|
+
await client.connect(zltContent, config2);
|
|
11672
|
+
await client.logoutVSCodePid(process.pid, config2);
|
|
11673
|
+
} finally {
|
|
11674
|
+
await client.disconnect();
|
|
11675
|
+
}
|
|
11676
|
+
}
|
|
11528
11677
|
async function installBacktestModules(workRoot, zltContent, config2, onProgress, hooks = {}) {
|
|
11529
11678
|
const client = new AssistantMasterIpcClient();
|
|
11530
11679
|
try {
|
|
@@ -12224,25 +12373,11 @@ async function acquireMcpRuntime(config2, explicitWorkRoot) {
|
|
|
12224
12373
|
const workRoot = explicitWorkRoot ?? await locateInstalledRuntime(config2);
|
|
12225
12374
|
return acquireRuntimeLease(workRoot, "starter", {
|
|
12226
12375
|
ensureRuntime: async () => {
|
|
12227
|
-
|
|
12228
|
-
|
|
12229
|
-
return null;
|
|
12230
|
-
const identity = await waitForProcessIdentity(launchedPid, config2.serviceStartupWait);
|
|
12231
|
-
if (!identity)
|
|
12232
|
-
throw new Error(`\u65E0\u6CD5\u786E\u8BA4 MCP \u542F\u52A8\u7684 ZLTAF \u8FDB\u7A0B\u8EAB\u4EFD: pid=${launchedPid}`);
|
|
12233
|
-
return identity;
|
|
12376
|
+
await startAssistantManagedRuntime(workRoot, config2);
|
|
12377
|
+
return null;
|
|
12234
12378
|
}
|
|
12235
12379
|
});
|
|
12236
12380
|
}
|
|
12237
|
-
async function startRuntimeAndServices(workRoot, config2) {
|
|
12238
|
-
ensureUsersProjectsDirectory(workRoot);
|
|
12239
|
-
const launchReady = validateRuntimeLaunchReady(workRoot, config2);
|
|
12240
|
-
if (!launchReady.complete) {
|
|
12241
|
-
throw new Error(launchReady.reason || "ZLTAF runtime \u542F\u52A8\u4F9D\u8D56\u4E0D\u5B8C\u6574");
|
|
12242
|
-
}
|
|
12243
|
-
await startAssistantBackServices(workRoot, config2);
|
|
12244
|
-
return waitForZltafPipe(workRoot, config2, { startIfMissing: true });
|
|
12245
|
-
}
|
|
12246
12381
|
var AssistantNotRunningError = class extends Error {
|
|
12247
12382
|
code = "ASSISTANT_NOT_RUNNING";
|
|
12248
12383
|
constructor(message = "\u667A\u80FD\u7BA1\u5BB6\u5F53\u524D\u672A\u8FD0\u884C\uFF1B\u5F53\u524D\u64CD\u4F5C\u4EC5\u68C0\u6D4B runtime\uFF0C\u4E0D\u4F1A\u542F\u52A8\u667A\u80FD\u7BA1\u5BB6") {
|
|
@@ -12267,7 +12402,7 @@ async function startAssistantBackServices(workRoot, config2, onProgress, options
|
|
|
12267
12402
|
return;
|
|
12268
12403
|
const zltContent = await ensureAssistantHostRunning(workRoot, config2, onProgress, options);
|
|
12269
12404
|
onProgress?.("\u542F\u52A8\u667A\u80FD\u7BA1\u5BB6\u540E\u53F0\u670D\u52A1");
|
|
12270
|
-
await startManualServices(workRoot, zltContent, config2);
|
|
12405
|
+
await startManualServices(workRoot, zltContent, config2, onProgress);
|
|
12271
12406
|
}
|
|
12272
12407
|
async function ensureAssistantHostRunning(workRoot, config2, onProgress, options = {}) {
|
|
12273
12408
|
const masterPipeExists = (suffix) => pipeExists(workRoot, `${config2.masterPipePrefix}_${suffix}`);
|
|
@@ -12291,11 +12426,13 @@ var ASSISTANT_UPGRADE_FINISH_LOCK = path6.join("Temporary", "upgradeFinsh.lock")
|
|
|
12291
12426
|
function launchAssistantHost(workRoot, config2, onProgress) {
|
|
12292
12427
|
const hostPath = path6.join(workRoot, config2.hostPath);
|
|
12293
12428
|
onProgress?.("\u542F\u52A8\u667A\u80FD\u7BA1\u5BB6");
|
|
12429
|
+
const { ELECTRON_RUN_AS_NODE: _dropped, ...env } = process.env;
|
|
12294
12430
|
const child = (0, import_child_process3.spawn)(hostPath, ["startwithplugin", "selfstart"], {
|
|
12295
12431
|
cwd: path6.dirname(hostPath),
|
|
12296
12432
|
detached: true,
|
|
12297
12433
|
stdio: "ignore",
|
|
12298
|
-
windowsHide: true
|
|
12434
|
+
windowsHide: true,
|
|
12435
|
+
env
|
|
12299
12436
|
});
|
|
12300
12437
|
if (!child.pid)
|
|
12301
12438
|
throw new Error(`\u667A\u80FD\u7BA1\u5BB6\u542F\u52A8\u540E\u672A\u8FD4\u56DE PID: ${hostPath}`);
|
|
@@ -12379,15 +12516,18 @@ async function installRuntime(options) {
|
|
|
12379
12516
|
const installDir = options.installDir || getDefaultInstallPath();
|
|
12380
12517
|
const installerPath = options.installerPath || await downloadRuntimeInstaller(options.config, options.onProgress, options.installType || "full");
|
|
12381
12518
|
fs6.mkdirSync(installDir, { recursive: true });
|
|
12519
|
+
const installerLogPath = path6.join(installDir, "Temporary", "logs", "install.log");
|
|
12520
|
+
fs6.mkdirSync(path6.dirname(installerLogPath), { recursive: true });
|
|
12382
12521
|
options.onProgress?.(`\u6267\u884C\u5B89\u88C5\u7A0B\u5E8F: ${installerPath}`);
|
|
12383
|
-
const exitCode = await executeInstallerProcess(installerPath, installDir);
|
|
12522
|
+
const exitCode = await executeInstallerProcess(installerPath, installDir, installerLogPath);
|
|
12384
12523
|
options.onProgress?.(`\u5B89\u88C5\u8FDB\u7A0B\u9000\u51FA\u7801: ${exitCode}`);
|
|
12385
12524
|
if (exitCode !== 0) {
|
|
12386
12525
|
const validateInstalled = options.installModules === false ? validateAssistantBaseComplete : validateWorkRootComplete;
|
|
12387
12526
|
const directValidation = validateInstalled(installDir, options.config);
|
|
12388
12527
|
const registryWorkRoot = options.installModules === false ? await readRegistryInstallLocationRaw(options.config) : await readRegistryInstallLocation(options.config);
|
|
12389
12528
|
if (!directValidation.complete && !registryWorkRoot) {
|
|
12390
|
-
|
|
12529
|
+
const cause = describeInstallerExitCode(exitCode);
|
|
12530
|
+
throw new Error(`\u5B89\u88C5\u7A0B\u5E8F\u6267\u884C\u5931\u8D25\uFF08\u9000\u51FA\u7801 ${exitCode}\uFF09` + (cause ? `\uFF1A${cause}` : "") + (directValidation.reason ? `\uFF08${directValidation.reason}\uFF09` : "") + `\u3002\u5B89\u88C5\u65E5\u5FD7: ${installerLogPath}`);
|
|
12391
12531
|
}
|
|
12392
12532
|
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}`);
|
|
12393
12533
|
}
|
|
@@ -12956,7 +13096,28 @@ async function downloadRuntimeInstaller(config2, onProgress, installType = "full
|
|
|
12956
13096
|
onProgress?.(`\u5B89\u88C5\u5305 SHA256 \u6821\u9A8C\u901A\u8FC7: ${sha256}`);
|
|
12957
13097
|
return destination;
|
|
12958
13098
|
}
|
|
12959
|
-
function
|
|
13099
|
+
function describeInstallerExitCode(exitCode) {
|
|
13100
|
+
switch (exitCode) {
|
|
13101
|
+
case 1:
|
|
13102
|
+
return "\u5B89\u88C5\u7A0B\u5E8F\u672A\u80FD\u5F00\u59CB\u5B89\u88C5\uFF0C\u6700\u5E38\u89C1\u539F\u56E0\u662F\u53E6\u4E00\u4E2A\u667A\u80FD\u7BA1\u5BB6\u5B89\u88C5\u6216\u5378\u8F7D\u7A0B\u5E8F\u6B63\u5728\u8FD0\u884C\uFF08\u7A97\u53E3\u53EF\u80FD\u88AB\u906E\u6321\uFF0C\u6216\u505C\u5728\u63D0\u6743\u786E\u8BA4\u4E0A\uFF09\u3002\u8BF7\u5173\u95ED\u6240\u6709\u5B89\u88C5/\u5378\u8F7D\u7A97\u53E3\u540E\u91CD\u8BD5";
|
|
13103
|
+
case 2:
|
|
13104
|
+
return "\u5B89\u88C5\u5728\u5F00\u59CB\u524D\u88AB\u7528\u6237\u53D6\u6D88";
|
|
13105
|
+
case 3:
|
|
13106
|
+
case 4:
|
|
13107
|
+
return "\u5B89\u88C5\u8FC7\u7A0B\u4E2D\u53D1\u751F\u81F4\u547D\u9519\u8BEF\uFF08\u5E38\u89C1\u539F\u56E0\uFF1A\u78C1\u76D8\u7A7A\u95F4\u4E0D\u8DB3\u3001\u76EE\u6807\u6587\u4EF6\u88AB\u5176\u4ED6\u7A0B\u5E8F\u5360\u7528\u3001\u6216\u88AB\u5B89\u5168\u8F6F\u4EF6\u62E6\u622A\uFF09";
|
|
13108
|
+
case 5:
|
|
13109
|
+
return "\u5B89\u88C5\u8FC7\u7A0B\u4E2D\u88AB\u7528\u6237\u53D6\u6D88";
|
|
13110
|
+
case 7:
|
|
13111
|
+
return "\u5B89\u88C5\u524D\u68C0\u67E5\u5224\u5B9A\u5F53\u524D\u73AF\u5883\u65E0\u6CD5\u7EE7\u7EED\u5B89\u88C5";
|
|
13112
|
+
case 8:
|
|
13113
|
+
return "\u4E0A\u4E00\u6B21\u5B89\u88C5\u5C1A\u672A\u5B8C\u6210\uFF0C\u9700\u8981\u91CD\u542F\u7CFB\u7EDF\u540E\u624D\u80FD\u7EE7\u7EED\u5B89\u88C5";
|
|
13114
|
+
case 1223:
|
|
13115
|
+
return "\u5B89\u88C5\u7A0B\u5E8F\u8BF7\u6C42\u7BA1\u7406\u5458\u6743\u9650\u65F6\u88AB\u62D2\u7EDD\uFF08UAC\uFF09";
|
|
13116
|
+
default:
|
|
13117
|
+
return void 0;
|
|
13118
|
+
}
|
|
13119
|
+
}
|
|
13120
|
+
function executeInstallerProcess(installerPath, installDir, logPath) {
|
|
12960
13121
|
return new Promise((resolve5, reject) => {
|
|
12961
13122
|
const child = (0, import_child_process3.spawn)(installerPath, [
|
|
12962
13123
|
"/VERYSILENT",
|
|
@@ -12966,7 +13127,7 @@ function executeInstallerProcess(installerPath, installDir) {
|
|
|
12966
13127
|
"/NO_ICONS",
|
|
12967
13128
|
"/MERGETASKS=!desktopicon",
|
|
12968
13129
|
`/DIR=${installDir}`,
|
|
12969
|
-
`/LOG=${
|
|
13130
|
+
`/LOG=${logPath}`,
|
|
12970
13131
|
"/m"
|
|
12971
13132
|
], {
|
|
12972
13133
|
shell: false,
|
|
@@ -12975,7 +13136,7 @@ function executeInstallerProcess(installerPath, installDir) {
|
|
|
12975
13136
|
});
|
|
12976
13137
|
child.on("close", (code) => {
|
|
12977
13138
|
if (code === 2) {
|
|
12978
|
-
reject(new Error(
|
|
13139
|
+
reject(new Error(`\u5B89\u88C5\u7A0B\u5E8F\u6267\u884C\u5931\u8D25\uFF08\u9000\u51FA\u7801 2\uFF09\uFF1A${describeInstallerExitCode(2)}`));
|
|
12979
13140
|
} else if (code === null) {
|
|
12980
13141
|
reject(new Error("\u5B89\u88C5\u7A0B\u5E8F\u6267\u884C\u5931\u8D25\uFF0C\u672A\u8FD4\u56DE\u9000\u51FA\u7801"));
|
|
12981
13142
|
} else {
|
|
@@ -13257,16 +13418,6 @@ async function waitForZltafPipe(workRoot, config2, options) {
|
|
|
13257
13418
|
}
|
|
13258
13419
|
throw new Error(`\u7B49\u5F85 ZLTAF \u7BA1\u9053\u8D85\u65F6: ${discoverPipePath(workRoot, "ZLTAF")}`);
|
|
13259
13420
|
}
|
|
13260
|
-
async function waitForProcessIdentity(pid, timeoutMs) {
|
|
13261
|
-
const deadline = Date.now() + Math.max(1e3, timeoutMs);
|
|
13262
|
-
while (Date.now() <= deadline) {
|
|
13263
|
-
const identity = inspectRuntimeProcess(pid);
|
|
13264
|
-
if (identity)
|
|
13265
|
-
return identity;
|
|
13266
|
-
await delay(100);
|
|
13267
|
-
}
|
|
13268
|
-
return null;
|
|
13269
|
-
}
|
|
13270
13421
|
|
|
13271
13422
|
// ../zlt-runtime-core/dist/auth.js
|
|
13272
13423
|
var fs7 = __toESM(require("fs"), 1);
|
|
@@ -20885,6 +21036,16 @@ var NPM_PACKAGE_CONFIG_TOOL_NAMES = Object.freeze([
|
|
|
20885
21036
|
// src/tool-pipeline.ts
|
|
20886
21037
|
var fs11 = __toESM(require("node:fs"), 1);
|
|
20887
21038
|
var path11 = __toESM(require("node:path"), 1);
|
|
21039
|
+
var import_node_crypto2 = require("node:crypto");
|
|
21040
|
+
|
|
21041
|
+
// src/feature-set.ts
|
|
21042
|
+
function resolveFeatureSet() {
|
|
21043
|
+
return false ? "core" : "full";
|
|
21044
|
+
}
|
|
21045
|
+
var MASKED_FACTOR_MESSAGE = "\u56E0\u5B50\u7814\u7A76\u529F\u80FD\u5728\u5F53\u524D\u7248\u672C\u672A\u5F00\u653E\u3002";
|
|
21046
|
+
var MASKED_FUTURES_MESSAGE = "\u671F\u8D27\u56DE\u6D4B\u5728\u5F53\u524D\u7248\u672C\u672A\u5F00\u653E\uFF1ArunParams.marketIds \u542B\u671F\u8D27\u4EA4\u6613\u6240\uFF08zj/zs/ds/sq/gq\uFF09\u6216 account_list \u7684 account_type \u4E3A\u671F\u8D27\u3002\u8BF7\u4F7F\u7528\u80A1\u7968\u5E02\u573A\uFF08sh/sz\uFF09\u4E0E account_type=1\u3002";
|
|
21047
|
+
|
|
21048
|
+
// src/tool-pipeline.ts
|
|
20888
21049
|
var FUTURES_MARKET_IDS = /* @__PURE__ */ new Set(["zj", "zs", "ds", "sq", "gq"]);
|
|
20889
21050
|
function isFuturesRun(marketIds) {
|
|
20890
21051
|
if (!marketIds) return false;
|
|
@@ -20895,7 +21056,26 @@ function prepareToolArgs(tool, args, contexts) {
|
|
|
20895
21056
|
const inherited = inheritReBacktestRunParams(tool, args, contexts);
|
|
20896
21057
|
const dated = applyBacktestDateDefaults(tool, inherited);
|
|
20897
21058
|
const named = normalizeBacktestRunName(tool, dated);
|
|
20898
|
-
|
|
21059
|
+
const prepared = stripEmptyLegacyUserId(tool, named);
|
|
21060
|
+
return refuseMaskedFuturesBacktest(tool, prepared) ?? prepared;
|
|
21061
|
+
}
|
|
21062
|
+
var FUTURES_GATED_TOOLS = /* @__PURE__ */ new Set(["mcp-create-and-run-backtest", "mcp-re-backtest"]);
|
|
21063
|
+
var FUTURES_ACCOUNT_TYPES = /* @__PURE__ */ new Set([2, 6]);
|
|
21064
|
+
function refuseMaskedFuturesBacktest(tool, args) {
|
|
21065
|
+
if (!FUTURES_GATED_TOOLS.has(tool.name) || resolveFeatureSet() !== "core") return null;
|
|
21066
|
+
const runParams = args.runParams ?? {};
|
|
21067
|
+
const marketIds = Array.isArray(runParams.marketIds) ? runParams.marketIds : [];
|
|
21068
|
+
const accounts = Array.isArray(runParams.account_list) ? runParams.account_list : [];
|
|
21069
|
+
const futuresAccount = accounts.some(
|
|
21070
|
+
(account) => !!account && typeof account === "object" && FUTURES_ACCOUNT_TYPES.has(Number(account.account_type))
|
|
21071
|
+
);
|
|
21072
|
+
if (!isFuturesRun(marketIds) && !futuresAccount) return null;
|
|
21073
|
+
return jsonToolResult(10057, MASKED_FUTURES_MESSAGE, {
|
|
21074
|
+
retryableByAgent: false,
|
|
21075
|
+
tool: tool.name,
|
|
21076
|
+
marketIds,
|
|
21077
|
+
userAction: "\u5F53\u524D\u7248\u672C\u4EC5\u652F\u6301\u80A1\u7968\u56DE\u6D4B\uFF08sh/sz\uFF09\uFF1B\u671F\u8D27\u56DE\u6D4B\u8BF7\u7B49\u5F85\u540E\u7EED\u7248\u672C\u5F00\u653E\u3002"
|
|
21078
|
+
}, true);
|
|
20899
21079
|
}
|
|
20900
21080
|
async function dispatchSpecialTool(tool, args, client, timeout, session, waitControl) {
|
|
20901
21081
|
if (tool.name === "mcp-factor-task-status") {
|
|
@@ -20938,7 +21118,7 @@ function shapeToolResult(tool, args, result, session) {
|
|
|
20938
21118
|
if (tool.name === "mcp-stop-backtest" && !result.isError && typeof args.runId === "string") {
|
|
20939
21119
|
session.activeBacktestRunIds.delete(args.runId);
|
|
20940
21120
|
}
|
|
20941
|
-
const echoed = echoResolvedBacktestConfig(tool, args, result);
|
|
21121
|
+
const echoed = echoResolvedBacktestConfig(tool, args, result, session.backtestRunContexts);
|
|
20942
21122
|
const guarded = applyBacktestResultGuards(
|
|
20943
21123
|
tool,
|
|
20944
21124
|
args,
|
|
@@ -22098,6 +22278,12 @@ async function runWait(_tool, args, client, timeout, session, control) {
|
|
|
22098
22278
|
{ action: 'Pass kind="factor" with the executionId from a factor start tool, kind="backtest" with the runId from mcp-create-and-run-backtest, or kind="download" with the uuid from mcp-download-data.' }
|
|
22099
22279
|
);
|
|
22100
22280
|
}
|
|
22281
|
+
if (kind === "factor" && resolveFeatureSet() === "core") {
|
|
22282
|
+
return waitError(10057, MASKED_FACTOR_MESSAGE, {
|
|
22283
|
+
action: "Factor research is not available in this build; do not retry with other factor tools.",
|
|
22284
|
+
userAction: MASKED_FACTOR_MESSAGE
|
|
22285
|
+
});
|
|
22286
|
+
}
|
|
22101
22287
|
if (!id) {
|
|
22102
22288
|
if (kind === "factor") {
|
|
22103
22289
|
return waitError(
|
|
@@ -22244,13 +22430,22 @@ function captureBacktestRunContext(tool, args, result, contexts, activeRunIds) {
|
|
|
22244
22430
|
const codePath = typeof parsed.Data.codePath === "string" && parsed.Data.codePath.trim() ? parsed.Data.codePath.trim() : prior?.codePath;
|
|
22245
22431
|
if (runId) {
|
|
22246
22432
|
const marketIds = Array.isArray(runParams.marketIds) ? runParams.marketIds.filter((id) => typeof id === "string") : prior?.marketIds;
|
|
22247
|
-
|
|
22433
|
+
const sourceSha256 = hashBacktestSource(codePath) ?? prior?.sourceSha256;
|
|
22434
|
+
contexts.set(runId, {
|
|
22435
|
+
strategyId,
|
|
22436
|
+
start,
|
|
22437
|
+
end,
|
|
22438
|
+
codePath,
|
|
22439
|
+
marketIds,
|
|
22440
|
+
runParams: { ...runParams },
|
|
22441
|
+
sourceSha256
|
|
22442
|
+
});
|
|
22248
22443
|
activeRunIds.add(runId);
|
|
22249
22444
|
}
|
|
22250
22445
|
} catch {
|
|
22251
22446
|
}
|
|
22252
22447
|
}
|
|
22253
|
-
function echoResolvedBacktestConfig(tool, args, result) {
|
|
22448
|
+
function echoResolvedBacktestConfig(tool, args, result, contexts) {
|
|
22254
22449
|
if (tool.name !== "mcp-create-and-run-backtest" && tool.name !== "mcp-re-backtest" || result.isError || result.content.length === 0) return result;
|
|
22255
22450
|
const runParams = isRecord2(args.runParams) ? args.runParams : {};
|
|
22256
22451
|
const resolvedStart = typeof runParams.start === "string" ? runParams.start : "";
|
|
@@ -22268,10 +22463,23 @@ function echoResolvedBacktestConfig(tool, args, result) {
|
|
|
22268
22463
|
if (isDailyBacktestFrequency(runParams.freq)) echo.dailyVisibilityNote = DAILY_VISIBILITY_NOTE;
|
|
22269
22464
|
const endWarning = describeFutureBacktestEnd(resolvedEnd);
|
|
22270
22465
|
if (endWarning) echo.endWarning = endWarning;
|
|
22271
|
-
if (Object.keys(echo).length === 0) return result;
|
|
22272
22466
|
try {
|
|
22273
22467
|
const parsed = JSON.parse(result.content[0].text);
|
|
22274
22468
|
if (!isRecord2(parsed) || !isRecord2(parsed.Data)) return result;
|
|
22469
|
+
const echoedRunId = typeof parsed.Data.runId === "string" ? parsed.Data.runId.trim() : "";
|
|
22470
|
+
const runId = echoedRunId || (tool.name === "mcp-re-backtest" && typeof args.runId === "string" ? args.runId.trim() : "");
|
|
22471
|
+
const context = runId ? contexts.get(runId) : void 0;
|
|
22472
|
+
if (runId) {
|
|
22473
|
+
echo.evidence = {
|
|
22474
|
+
contextAvailable: Boolean(context),
|
|
22475
|
+
backtestId: runId,
|
|
22476
|
+
...context?.codePath ? { runDir: context.codePath } : {},
|
|
22477
|
+
...context?.strategyId ? { strategyId: context.strategyId } : {},
|
|
22478
|
+
...context?.runParams ? { effectiveRunParams: { ...context.runParams } } : {},
|
|
22479
|
+
...context?.sourceSha256 ? { sourceSha256: context.sourceSha256 } : {}
|
|
22480
|
+
};
|
|
22481
|
+
}
|
|
22482
|
+
if (Object.keys(echo).length === 0) return result;
|
|
22275
22483
|
return {
|
|
22276
22484
|
...result,
|
|
22277
22485
|
content: [{
|
|
@@ -22286,6 +22494,16 @@ function echoResolvedBacktestConfig(tool, args, result) {
|
|
|
22286
22494
|
return result;
|
|
22287
22495
|
}
|
|
22288
22496
|
}
|
|
22497
|
+
function hashBacktestSource(codePath) {
|
|
22498
|
+
if (!codePath) return void 0;
|
|
22499
|
+
try {
|
|
22500
|
+
const sourcePath = path11.join(codePath, "main.py");
|
|
22501
|
+
if (!fs11.statSync(sourcePath).isFile()) return void 0;
|
|
22502
|
+
return (0, import_node_crypto2.createHash)("sha256").update(fs11.readFileSync(sourcePath)).digest("hex");
|
|
22503
|
+
} catch {
|
|
22504
|
+
return void 0;
|
|
22505
|
+
}
|
|
22506
|
+
}
|
|
22289
22507
|
var BENCHMARK_OVERRIDE_NOTE = "\u8FD9\u662F\u8BF7\u6C42\u7684\u57FA\u51C6\uFF0C\u4E0D\u4E00\u5B9A\u662F\u5B9E\u9645\u751F\u6548\u7684\uFF1A\u7B56\u7565 initialize \u91CC\u7684 set_benchmark() \u4F1A\u8986\u76D6\u5B83\uFF0C\u6536\u76CA\u4EA7\u7269\u4E2D\u7684\u300C\u57FA\u51C6\u6536\u76CA\u300D\u6309\u7B56\u7565\u5B9E\u9645\u7528\u7684\u57FA\u51C6\u8BA1\u7B97\u3002\u62A5\u544A\u57FA\u51C6\u662F\u4EC0\u4E48\u4E4B\u524D\uFF0C\u5148\u8BFB\u7B56\u7565\u4EE3\u7801\u91CC\u7684 set_benchmark\u3002";
|
|
22290
22508
|
var DAILY_VISIBILITY_NOTE = "\u65E5\u7EBF\u7C7B\u9891\u7387\u7684\u7B80\u5355\u56DE\u6D4B\u53EA\u80FD\u770B\u5230 context.previous_date \u53CA\u4EE5\u524D\u7684\u5B8C\u6574\u65E5 K\uFF1B\u5F53\u65E5\u6536\u76D8\u5728\u56DE\u6D4B\u4E2D\u4E0D\u53EF\u89C1\uFF0Cafter_trading_end \u540C\u6837\u770B\u4E0D\u5230\u3002\u6240\u4EE5\u8981\u7528\u67D0\u4E2A\u4EA4\u6613\u65E5 T \u7684\u6536\u76D8\u505A\u7B5B\u9009\u6216\u8BA1\u7B97\uFF0CrunParams.end \u5FC5\u987B\u8BBE\u6210 T \u7684\u4E0B\u4E00\u4E2A\u4EA4\u6613\u65E5\uFF1B\u53EA\u8DD1 [T, T] \u5355\u65E5\uFF0C\u53D6\u5230\u7684\u662F T-1 \u7684\u6536\u76D8\u3002\u5206\u949F\u3001Tick\u3001\u7814\u7A76\u3001\u4EFF\u771F\u3001\u5B9E\u76D8\u4E0D\u53D7\u6B64\u9650\u3002";
|
|
22291
22509
|
function isDailyBacktestFrequency(value) {
|
|
@@ -22709,7 +22927,7 @@ function extractStrategyTreeIds(result) {
|
|
|
22709
22927
|
}
|
|
22710
22928
|
return ids;
|
|
22711
22929
|
}
|
|
22712
|
-
async function executeSteps(steps, client, initialBody, timeout, repairHint = identityRepairHint) {
|
|
22930
|
+
async function executeSteps(steps, client, initialBody, timeout, repairHint = identityRepairHint, toolName) {
|
|
22713
22931
|
let body = { ...initialBody };
|
|
22714
22932
|
for (let i = 0; i < steps.length; i++) {
|
|
22715
22933
|
const step = steps[i];
|
|
@@ -22746,6 +22964,10 @@ async function executeSteps(steps, client, initialBody, timeout, repairHint = id
|
|
|
22746
22964
|
}
|
|
22747
22965
|
}
|
|
22748
22966
|
}
|
|
22967
|
+
if (i < steps.length - 1) {
|
|
22968
|
+
const blocked = preflightCreatedBacktestSource(toolName, body);
|
|
22969
|
+
if (blocked) return blocked;
|
|
22970
|
+
}
|
|
22749
22971
|
if (i === steps.length - 1) {
|
|
22750
22972
|
const finalData = repairHint(mergeStepFieldsToFinalData(parsed.data, body, step.mergeToFinalData));
|
|
22751
22973
|
return {
|
|
@@ -22756,6 +22978,126 @@ async function executeSteps(steps, client, initialBody, timeout, repairHint = id
|
|
|
22756
22978
|
}
|
|
22757
22979
|
return { content: [{ type: "text", text: "{}" }] };
|
|
22758
22980
|
}
|
|
22981
|
+
function pythonCodeLines(source) {
|
|
22982
|
+
let state = null;
|
|
22983
|
+
return source.split(/\r?\n/).map((line) => {
|
|
22984
|
+
let code = "";
|
|
22985
|
+
for (let i = 0; i < line.length; ) {
|
|
22986
|
+
if (state === "'''" || state === '"""') {
|
|
22987
|
+
if (line.startsWith(state, i)) {
|
|
22988
|
+
i += 3;
|
|
22989
|
+
state = null;
|
|
22990
|
+
} else {
|
|
22991
|
+
code += " ";
|
|
22992
|
+
i += 1;
|
|
22993
|
+
}
|
|
22994
|
+
continue;
|
|
22995
|
+
}
|
|
22996
|
+
if (state === "'" || state === '"') {
|
|
22997
|
+
if (line[i] === "\\") {
|
|
22998
|
+
code += " ";
|
|
22999
|
+
i += 2;
|
|
23000
|
+
} else if (line[i] === state) {
|
|
23001
|
+
code += " ";
|
|
23002
|
+
i += 1;
|
|
23003
|
+
state = null;
|
|
23004
|
+
} else {
|
|
23005
|
+
code += " ";
|
|
23006
|
+
i += 1;
|
|
23007
|
+
}
|
|
23008
|
+
continue;
|
|
23009
|
+
}
|
|
23010
|
+
if (line[i] === "#") break;
|
|
23011
|
+
if (line.startsWith("'''", i) || line.startsWith('"""', i)) {
|
|
23012
|
+
state = line.slice(i, i + 3);
|
|
23013
|
+
code += " ";
|
|
23014
|
+
i += 3;
|
|
23015
|
+
continue;
|
|
23016
|
+
}
|
|
23017
|
+
if (line[i] === "'" || line[i] === '"') {
|
|
23018
|
+
state = line[i];
|
|
23019
|
+
code += " ";
|
|
23020
|
+
i += 1;
|
|
23021
|
+
continue;
|
|
23022
|
+
}
|
|
23023
|
+
code += line[i];
|
|
23024
|
+
i += 1;
|
|
23025
|
+
}
|
|
23026
|
+
if (state === "'" || state === '"') state = null;
|
|
23027
|
+
return code;
|
|
23028
|
+
});
|
|
23029
|
+
}
|
|
23030
|
+
function findUnsupportedCurrentDataGet(source) {
|
|
23031
|
+
const lines = pythonCodeLines(source);
|
|
23032
|
+
const aliases = /* @__PURE__ */ new Set();
|
|
23033
|
+
const assignment = /\b([A-Za-z_]\w*)\s*(?::[^=]+)?=\s*get_current_data\s*\(\s*\)/g;
|
|
23034
|
+
for (const line of lines) {
|
|
23035
|
+
assignment.lastIndex = 0;
|
|
23036
|
+
let match;
|
|
23037
|
+
while ((match = assignment.exec(line)) !== null) aliases.add(match[1]);
|
|
23038
|
+
}
|
|
23039
|
+
let changed = true;
|
|
23040
|
+
while (changed) {
|
|
23041
|
+
changed = false;
|
|
23042
|
+
for (const line of lines) {
|
|
23043
|
+
for (const alias of aliases) {
|
|
23044
|
+
const escaped = alias.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
23045
|
+
const copied = new RegExp(`\\b([A-Za-z_]\\w*)\\s*(?::[^=]+)?=\\s*${escaped}\\b`).exec(line);
|
|
23046
|
+
if (copied && !aliases.has(copied[1])) {
|
|
23047
|
+
aliases.add(copied[1]);
|
|
23048
|
+
changed = true;
|
|
23049
|
+
}
|
|
23050
|
+
}
|
|
23051
|
+
}
|
|
23052
|
+
}
|
|
23053
|
+
const violations = [];
|
|
23054
|
+
lines.forEach((line, index) => {
|
|
23055
|
+
if (/get_current_data\s*\(\s*\)\s*\.\s*get\s*\(/.test(line)) {
|
|
23056
|
+
violations.push({ line: index + 1, expression: "get_current_data().get(...)" });
|
|
23057
|
+
}
|
|
23058
|
+
for (const alias of aliases) {
|
|
23059
|
+
const escaped = alias.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
23060
|
+
if (new RegExp(`\\b${escaped}\\s*\\.\\s*get\\s*\\(`).test(line)) {
|
|
23061
|
+
violations.push({ line: index + 1, expression: `${alias}.get(...)` });
|
|
23062
|
+
}
|
|
23063
|
+
}
|
|
23064
|
+
});
|
|
23065
|
+
return violations.filter((item, index, all) => all.findIndex((candidate) => candidate.line === item.line && candidate.expression === item.expression) === index);
|
|
23066
|
+
}
|
|
23067
|
+
function preflightCreatedBacktestSource(toolName, body) {
|
|
23068
|
+
if (toolName !== "mcp-create-and-run-backtest") return null;
|
|
23069
|
+
const runId = typeof body.runId === "string" ? body.runId.trim() : "";
|
|
23070
|
+
const codePath = typeof body.codePath === "string" ? body.codePath.trim() : "";
|
|
23071
|
+
if (!codePath || !fs11.existsSync(codePath)) return null;
|
|
23072
|
+
const sourcePath = path11.join(codePath, "main.py");
|
|
23073
|
+
if (!fs11.existsSync(sourcePath)) return null;
|
|
23074
|
+
let source;
|
|
23075
|
+
try {
|
|
23076
|
+
source = fs11.readFileSync(sourcePath, "utf8");
|
|
23077
|
+
} catch (error2) {
|
|
23078
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
23079
|
+
return jsonToolResult(10061, "\u56DE\u6D4B\u4EE3\u7801\u5FEB\u7167\u65E0\u6CD5\u8BFB\u53D6\uFF0C\u672A\u542F\u52A8\u7B56\u7565\u5F15\u64CE\u3002", {
|
|
23080
|
+
retryableByAgent: false,
|
|
23081
|
+
runId,
|
|
23082
|
+
codePath,
|
|
23083
|
+
sourcePath,
|
|
23084
|
+
sourcePreflight: "blocked",
|
|
23085
|
+
reason: message
|
|
23086
|
+
}, true);
|
|
23087
|
+
}
|
|
23088
|
+
const violations = findUnsupportedCurrentDataGet(source);
|
|
23089
|
+
if (violations.length === 0) return null;
|
|
23090
|
+
return jsonToolResult(10061, "\u56DE\u6D4B\u4EE3\u7801\u4F7F\u7528\u4E86 get_current_data().get(...)\uFF0C\u5F53\u524D\u5BF9\u8C61\u4E0D\u652F\u6301 .get()\uFF1B\u5DF2\u521B\u5EFA\u5FEB\u7167\u4F46\u672A\u542F\u52A8\u7B56\u7565\u5F15\u64CE\u3002", {
|
|
23091
|
+
retryableByAgent: false,
|
|
23092
|
+
runId,
|
|
23093
|
+
codePath,
|
|
23094
|
+
sourcePath,
|
|
23095
|
+
sourcePreflight: "blocked",
|
|
23096
|
+
sourceSha256: (0, import_node_crypto2.createHash)("sha256").update(source).digest("hex"),
|
|
23097
|
+
violations,
|
|
23098
|
+
userAction: "\u628A current_data.get(security) \u6539\u4E3A current_data[security]\uFF0C\u5E76\u7528 KeyError \u5904\u7406\u7F3A\u5931\u8BC1\u5238\uFF1B\u7136\u540E\u91CD\u65B0\u521B\u5EFA\u5E76\u8FD0\u884C\u56DE\u6D4B\u3002"
|
|
23099
|
+
}, true);
|
|
23100
|
+
}
|
|
22759
23101
|
function buildStepBody(step, body) {
|
|
22760
23102
|
if (!step.bodyMapping) return body;
|
|
22761
23103
|
const mappedBody = {};
|
|
@@ -23793,7 +24135,7 @@ function summarizeBacktestProfit(runDir, options = {}) {
|
|
|
23793
24135
|
function handleBacktestProfitTool(args, contexts) {
|
|
23794
24136
|
const backtestId = typeof args.backtestId === "string" ? args.backtestId.trim() : "";
|
|
23795
24137
|
if (!backtestId) {
|
|
23796
|
-
return toolText({ ErrNo:
|
|
24138
|
+
return toolText({ ErrNo: 10060, ErrMsg: "\u7F3A\u5C11 backtestId\uFF0C\u65E0\u6CD5\u5B9A\u4F4D\u56DE\u6D4B\u4EA7\u7269\u76EE\u5F55\u3002", Data: { retryableByAgent: true } }, true);
|
|
23797
24139
|
}
|
|
23798
24140
|
const explicit = typeof args.codePath === "string" ? args.codePath.trim() : "";
|
|
23799
24141
|
const runDir = explicit || contexts.get(backtestId)?.codePath || "";
|
|
@@ -23804,13 +24146,24 @@ function handleBacktestProfitTool(args, contexts) {
|
|
|
23804
24146
|
Data: null
|
|
23805
24147
|
}, true);
|
|
23806
24148
|
}
|
|
24149
|
+
const context = contexts.get(backtestId);
|
|
24150
|
+
const summary = summarizeBacktestProfit(runDir, {
|
|
24151
|
+
expectedBacktestId: backtestId,
|
|
24152
|
+
includeSeries: args.includeSeries === true
|
|
24153
|
+
});
|
|
24154
|
+
summary.evidence = {
|
|
24155
|
+
contextAvailable: Boolean(context),
|
|
24156
|
+
requestedBacktestId: backtestId,
|
|
24157
|
+
...summary.backtestId ? { artifactBacktestId: summary.backtestId } : {},
|
|
24158
|
+
runDir,
|
|
24159
|
+
...context?.strategyId ? { strategyId: context.strategyId } : {},
|
|
24160
|
+
...context?.runParams ? { effectiveRunParams: { ...context.runParams } } : {},
|
|
24161
|
+
...context?.sourceSha256 ? { sourceSha256: context.sourceSha256 } : {}
|
|
24162
|
+
};
|
|
23807
24163
|
return toolText({
|
|
23808
24164
|
ErrNo: 0,
|
|
23809
24165
|
ErrMsg: "",
|
|
23810
|
-
Data:
|
|
23811
|
-
expectedBacktestId: backtestId,
|
|
23812
|
-
includeSeries: args.includeSeries === true
|
|
23813
|
-
})
|
|
24166
|
+
Data: summary
|
|
23814
24167
|
});
|
|
23815
24168
|
}
|
|
23816
24169
|
|
|
@@ -23848,7 +24201,7 @@ var RUNTIME_TOOLS = [
|
|
|
23848
24201
|
},
|
|
23849
24202
|
{
|
|
23850
24203
|
name: "zlt-runtime-start",
|
|
23851
|
-
description: "\
|
|
24204
|
+
description: "\u542F\u52A8\u5DF2\u5B89\u88C5\u7684\u667A\u91CF\u901A\u672C\u5730\u56DE\u6D4B runtime\uFF1A\u7ECF\u667A\u80FD\u7BA1\u5BB6\uFF08ZLTHome selfstart\uFF09\u6258\u7BA1\u62C9\u8D77\u5E76\u7B49\u5F85\u5176\u521B\u5EFA\u7684 ZLTAF \u7BA1\u9053\uFF0C\u7EDD\u4E0D\u76F4\u63A5\u542F\u52A8 zltaf.exe\u3002\u672C\u5DE5\u5177\u4E0D\u4F1A\u542F\u52A8 Code.exe \u6216 jsservice\uFF0C\u4E5F\u4E0D\u8BFB\u53D6 backServiceRun.json\u3002\u5B89\u88C5\u5B8C\u6210\u540E\u5982\u679C backtestReady=false\uFF0C\u5E94\u8C03\u7528 zlt-runtime-install \u4FEE\u590D zltaf\u3001Python/Git \u6216 SDK\uFF1B\u4E0D\u8981\u624B\u52A8\u521B\u5EFA zltaf \u76EE\u5F55\u3002",
|
|
23852
24205
|
inputSchema: {
|
|
23853
24206
|
type: "object",
|
|
23854
24207
|
properties: {},
|
|
@@ -23858,7 +24211,7 @@ var RUNTIME_TOOLS = [
|
|
|
23858
24211
|
},
|
|
23859
24212
|
{
|
|
23860
24213
|
name: "zlt-runtime-install",
|
|
23861
|
-
description: "\u4E0B\u8F7D\u5E76\u5B89\u88C5\u667A\u91CF\u901A\u672C\u5730 ZLTAF runtime\uFF0C\u6821\u9A8C\u6295\u7814\u6A21\u5757\u4E0B\u53D1\u7684 Python/MinGit \u5DE5\u5177\u94FE\u4E0E zltquant/zltsdk\uFF0C\u5E76\
|
|
24214
|
+
description: "\u4E0B\u8F7D\u5E76\u5B89\u88C5\u667A\u91CF\u901A\u672C\u5730 ZLTAF runtime\uFF0C\u6821\u9A8C\u6295\u7814\u6A21\u5757\u4E0B\u53D1\u7684 Python/MinGit \u5DE5\u5177\u94FE\u4E0E zltquant/zltsdk\uFF0C\u5E76\u7ECF\u667A\u80FD\u7BA1\u5BB6\u6258\u7BA1\u542F\u52A8\u56DE\u6D4B\u670D\u52A1\u3002Python \u4E0E MinGit \u5F52\u6295\u7814\u6A21\u5757\u4E0B\u53D1\uFF0C\u672C\u5DE5\u5177\u53EA\u6821\u9A8C\u3001\u4E0D\u518D\u81EA\u884C\u4E0B\u8F7D\u6216\u4FEE\u590D\u5B83\u4EEC\uFF1A\u7F3A\u5931\u65F6\u4F1A\u660E\u786E\u62A5\u51FA\u300C\u8BF7\u5728\u667A\u80FD\u7BA1\u5BB6\u4E2D\u5B89\u88C5\u6216\u4FEE\u590D\u6295\u7814\u6A21\u5757\u300D\u3002\u8BE5\u64CD\u4F5C\u4F1A\u5199\u5165\u672C\u673A\u78C1\u76D8\u5E76\u53EF\u80FD\u89E6\u53D1 Windows \u5B89\u88C5/UAC\uFF0C\u8C03\u7528\u524D\u5FC5\u987B\u53D6\u5F97\u7528\u6237\u786E\u8BA4\uFF0C\u5E76\u4F20\u5165 confirm=true\u3002\u5B89\u88C5\u5305\u5FC5\u987B\u81EA\u5E26 zltaf\uFF1B\u672C\u5DE5\u5177\u4E0D\u4F1A\u901A\u8FC7 Assistant IPC\u3001ZLTHome \u6216 ZLTBackService \u8865\u88C5\u6A21\u5757\uFF0C\u4E5F\u4E0D\u4F1A\u542F\u52A8 Code.exe/jsservice\u3002",
|
|
23862
24215
|
inputSchema: {
|
|
23863
24216
|
type: "object",
|
|
23864
24217
|
properties: {
|
|
@@ -23892,14 +24245,7 @@ async function startMcpServer() {
|
|
|
23892
24245
|
...resolveListedRuntimeTools(RUNTIME_TOOLS, toolProfile),
|
|
23893
24246
|
...resolveListedIpcTools(config2.tools, toolProfile)
|
|
23894
24247
|
];
|
|
23895
|
-
const runtimeConfig =
|
|
23896
|
-
...loadAssistantRuntimeConfig(resolveDefaultRuntimeConfigPath()),
|
|
23897
|
-
zltafConfigFile: ZLTAF_CONFIG_FILE_DAY,
|
|
23898
|
-
// Trae/WorkBuddy owns a standalone direct-ZLTAF lane. 智能管家 and its
|
|
23899
|
-
// Assistant-managed services belong to the zlt-quant VSCode runtime.
|
|
23900
|
-
manualServiceIndices: [],
|
|
23901
|
-
startupCheckIndices: []
|
|
23902
|
-
};
|
|
24248
|
+
const runtimeConfig = loadAssistantRuntimeConfig(resolveDefaultRuntimeConfigPath());
|
|
23903
24249
|
let runtimeStartAttempted = false;
|
|
23904
24250
|
let runtimeLease;
|
|
23905
24251
|
let leaseStateUpdate = Promise.resolve();
|
|
@@ -24074,7 +24420,7 @@ async function startMcpServer() {
|
|
|
24074
24420
|
);
|
|
24075
24421
|
if (special) return special;
|
|
24076
24422
|
if (tool.steps && tool.steps.length > 0) {
|
|
24077
|
-
const result = await executeSteps(tool.steps, ipcClient, stripControlParams(toolArgs), timeout, withRuntimeRepairHint);
|
|
24423
|
+
const result = await executeSteps(tool.steps, ipcClient, stripControlParams(toolArgs), timeout, withRuntimeRepairHint, tool.name);
|
|
24078
24424
|
return shapeToolResult(tool, toolArgs, result, session);
|
|
24079
24425
|
}
|
|
24080
24426
|
try {
|
|
@@ -24118,6 +24464,14 @@ async function startMcpServer() {
|
|
|
24118
24464
|
if (runtimeLease) {
|
|
24119
24465
|
const lease = runtimeLease;
|
|
24120
24466
|
runtimeLease = void 0;
|
|
24467
|
+
try {
|
|
24468
|
+
const zltContent = await readZltContent(lease.workRoot, runtimeConfig.temporaryZltFile);
|
|
24469
|
+
if (zltContent) await unregisterRuntimeConsumerPid(zltContent, runtimeConfig);
|
|
24470
|
+
process.stderr.write("[zlt-mcp-proxy] runtime PID \u5DF2\u6CE8\u9500\n");
|
|
24471
|
+
} catch (error2) {
|
|
24472
|
+
process.stderr.write(`[zlt-mcp-proxy] runtime PID \u6CE8\u9500\u5931\u8D25\uFF08\u5FFD\u7565\uFF09: ${error2 instanceof Error ? error2.message : String(error2)}
|
|
24473
|
+
`);
|
|
24474
|
+
}
|
|
24121
24475
|
try {
|
|
24122
24476
|
const released = await releaseRuntimeLease(lease);
|
|
24123
24477
|
process.stderr.write(`[zlt-mcp-proxy] runtime lease released: ${released.reason}
|
|
@@ -24473,7 +24827,7 @@ function getRuntimeRecommendedAction(runtimeReady, backtestReady) {
|
|
|
24473
24827
|
return "call zlt-runtime-install with confirm=true to install the local backtest runtime";
|
|
24474
24828
|
}
|
|
24475
24829
|
if (!backtestReady) {
|
|
24476
|
-
return "if zltaf is missing, call zlt-runtime-install with confirm=true. Python/Git toolchain and SDK packages come from the \u6295\u7814 module: ask the user to install or repair it in \u667A\u80FD\u7BA1\u5BB6. Then start
|
|
24830
|
+
return "if zltaf is missing, call zlt-runtime-install with confirm=true. Python/Git toolchain and SDK packages come from the \u6295\u7814 module: ask the user to install or repair it in \u667A\u80FD\u7BA1\u5BB6. Then start the managed runtime.";
|
|
24477
24831
|
}
|
|
24478
24832
|
return "call zlt-runtime-start before backtest if the ZLTAF pipe is not running";
|
|
24479
24833
|
}
|
|
@@ -24485,10 +24839,10 @@ function getRuntimeStartUserAction(message) {
|
|
|
24485
24839
|
return "\u667A\u91CF\u901A\u672C\u5730 ZLTAF runtime \u4E0D\u5B8C\u6574\uFF0C\u672A\u627E\u5230 C:\\ZLTClient\\zltaf\\zltaf.exe\u3002\u8BF7\u53D6\u5F97\u7528\u6237\u786E\u8BA4\u540E\u8C03\u7528 zlt-runtime-install\uFF0C\u4F7F\u7528\u5305\u542B zltaf \u7684\u5B89\u88C5\u5305\u4FEE\u590D\uFF1B\u4E0D\u8981\u624B\u52A8\u521B\u5EFA zltaf \u76EE\u5F55\u3002";
|
|
24486
24840
|
}
|
|
24487
24841
|
if (/handshake/i.test(message)) {
|
|
24488
|
-
return "\u667A\u91CF\u901A
|
|
24842
|
+
return "\u667A\u91CF\u901A\u6258\u7BA1\u542F\u52A8\uFF08ZLTHome selfstart\uFF09\u63E1\u624B\u5931\u8D25\u3002\u8BF7\u628A ErrMsg \u548C doctor \u7ED3\u679C\u53CD\u9988\u7ED9\u5F00\u53D1\u8005\u6392\u67E5 ZLTAF \u7BA1\u9053\u534F\u8BAE\uFF1B\u4E0D\u8981\u624B\u52A8\u521B\u5EFA zltaf \u76EE\u5F55\uFF0C\u4E5F\u4E0D\u8981\u542F\u52A8 ZLTHome\u3001ZLTBackService\u3001Code.exe \u6216 jsservice\u3002";
|
|
24489
24843
|
}
|
|
24490
24844
|
if (/pipe|管道|ZLTAF/i.test(message)) {
|
|
24491
|
-
return "\u667A\u91CF\u901A ZLTAF \u7BA1\u9053\u4ECD\u4E0D\u53EF\u7528\u3002\u8BF7\u628A ErrMsg\u3001doctor \u7ED3\u679C\u548C zltaf \u65E5\u5FD7\u53CD\u9988\u7ED9\u5F00\u53D1\u8005\u6392\u67E5
|
|
24845
|
+
return "\u667A\u91CF\u901A ZLTAF \u7BA1\u9053\u4ECD\u4E0D\u53EF\u7528\u3002\u8BF7\u628A ErrMsg\u3001doctor \u7ED3\u679C\u548C zltaf \u65E5\u5FD7\u53CD\u9988\u7ED9\u5F00\u53D1\u8005\u6392\u67E5\u6258\u7BA1\u542F\u52A8\u94FE\u8DEF\uFF1B\u4E0D\u8981\u624B\u52A8\u521B\u5EFA zltaf \u76EE\u5F55\uFF0C\u4E5F\u4E0D\u8981\u542F\u52A8 ZLTHome\u3001ZLTBackService\u3001Code.exe \u6216 jsservice\u3002";
|
|
24492
24846
|
}
|
|
24493
24847
|
return "\u667A\u91CF\u901A ZLTAF runtime \u542F\u52A8\u5931\u8D25\u3002\u8BF7\u628A ErrMsg \u548C doctor \u7ED3\u679C\u53CD\u9988\u7ED9\u7528\u6237\u6216\u5F00\u53D1\u8005\u6392\u67E5\uFF1B\u4E0D\u8981\u624B\u52A8\u521B\u5EFA zltaf \u76EE\u5F55\u3001\u6740\u8FDB\u7A0B\u3001\u542F\u52A8 ZLTHome/ZLTBackService/Code.exe/jsservice \u6216\u91CD\u590D\u5B89\u88C5 runtime\u3002";
|
|
24494
24848
|
}
|
|
@@ -24502,7 +24856,7 @@ function getRuntimeInstallUserAction(message) {
|
|
|
24502
24856
|
if (/handshake|pipe|管道|ZLTAF/i.test(message)) {
|
|
24503
24857
|
return getRuntimeStartUserAction(message);
|
|
24504
24858
|
}
|
|
24505
|
-
return "\u667A\u91CF\u901A ZLTAF runtime \u5B89\u88C5/\u4FEE\u590D\u5931\u8D25\u3002\u8BF7\u628A ErrMsg \u548C doctor \u7ED3\u679C\u53CD\u9988\u7ED9\u5F00\u53D1\u8005\u6392\u67E5\u5B89\u88C5\u5668\u6216
|
|
24859
|
+
return "\u667A\u91CF\u901A ZLTAF runtime \u5B89\u88C5/\u4FEE\u590D\u5931\u8D25\u3002\u8BF7\u628A ErrMsg \u548C doctor \u7ED3\u679C\u53CD\u9988\u7ED9\u5F00\u53D1\u8005\u6392\u67E5\u5B89\u88C5\u5668\u6216\u6258\u7BA1\u542F\u52A8\u94FE\u8DEF\uFF1B\u4E0D\u8981\u624B\u52A8\u521B\u5EFA zltaf \u76EE\u5F55\u3001\u6740\u8FDB\u7A0B\u3001\u542F\u52A8 ZLTHome/ZLTBackService/Code.exe/jsservice \u6216\u91CD\u590D\u5B89\u88C5 runtime\u3002";
|
|
24506
24860
|
}
|
|
24507
24861
|
function runtimeRecoveryStopData(message, extra = {}, handler = "runtimeStart") {
|
|
24508
24862
|
return {
|