feat: bootstrap portable Node runtimes
CI / Client installer (macos-latest) (push) Canceled after 0s
CI / Client installer (ubuntu-latest) (push) Canceled after 0s
CI / Client installer (windows-latest) (push) Canceled after 0s
CI / test (22) (push) Canceled after 0s
CI / test (24) (push) Canceled after 0s
CI / release-smoke (push) Canceled after 0s
CI / Client installer (macos-latest) (push) Canceled after 0s
CI / Client installer (ubuntu-latest) (push) Canceled after 0s
CI / Client installer (windows-latest) (push) Canceled after 0s
CI / test (22) (push) Canceled after 0s
CI / test (24) (push) Canceled after 0s
CI / release-smoke (push) Canceled after 0s
This commit is contained in:
@@ -15,7 +15,11 @@
|
||||
- 签名清单:`{{MANIFEST_URL}}`
|
||||
- 清单签名:`{{MANIFEST_SIGNATURE_URL}}`
|
||||
- 统一网关:`{{GATEWAY_URL}}`
|
||||
- Node.js:`>=22.13.0`
|
||||
- Windows 安装引导:`{{BOOTSTRAP_WINDOWS_URL}}`
|
||||
- Windows 安装引导 SHA-256:`{{BOOTSTRAP_WINDOWS_SHA256}}`
|
||||
- Linux/macOS 安装引导:`{{BOOTSTRAP_POSIX_URL}}`
|
||||
- Linux/macOS 安装引导 SHA-256:`{{BOOTSTRAP_POSIX_SHA256}}`
|
||||
- 私有 Node.js:`{{NODE_VERSION}}`(最低兼容版本 `{{NODE_MINIMUM_VERSION}}`)
|
||||
|
||||
首次安装通过上述 HTTPS 地址和固定 SHA-256 建立信任;安装器随后必须使用固定公钥验证 Ed25519 清单签名和全部发布物哈希。URL、TLS、签名或哈希任一不匹配都必须停止。不得索取 AppKey、AppSecret、AuthoritySecret、CorpId、userId、员工号、Cookie 或 Token。
|
||||
|
||||
@@ -23,7 +27,7 @@
|
||||
|
||||
只有以下条件全部成立,才能告诉用户“安装完成,可以使用”:
|
||||
|
||||
1. Node.js 版本满足要求,安装器与公钥 SHA-256 均正确;
|
||||
1. 对应平台安装引导的 SHA-256 正确,并已选用兼容的系统 Node 或经过官方哈希校验的私有 Node;
|
||||
2. 安装器 JSON 返回 `ok: true`;
|
||||
3. 已按当前 Agent 的官方方式安装返回的 `skillPath`;
|
||||
4. 已原样使用返回的 `mcpConfig` 注册并信任本地 stdio MCP;
|
||||
@@ -31,73 +35,79 @@
|
||||
6. `approval_list_todos` 的双来源验证中,钉钉 OA 与薪福通都为 `ok`;
|
||||
7. 未执行任何审批写操作。
|
||||
|
||||
## 步骤 1:检查运行环境
|
||||
## 步骤 1:确认操作系统与架构
|
||||
|
||||
在当前用户权限下运行:
|
||||
支持以下当前用户环境:
|
||||
|
||||
```text
|
||||
node --version
|
||||
npm --version
|
||||
```
|
||||
- Windows 10/11:x64 或 ARM64;
|
||||
- Linux:x64 或 ARM64;
|
||||
- macOS:Intel x64 或 Apple Silicon ARM64。
|
||||
|
||||
Node.js 必须为 `22.13.0` 或更高版本,npm 必须可用。不要使用管理员权限、`sudo`、全局 npm 安装、DWS 或浏览器自动化。若刚安装或升级 Node.js,先打开一个新的终端,再重新执行版本检查。
|
||||
系统无需预装 Node.js。安装引导会优先复用版本不低于 `{{NODE_MINIMUM_VERSION}}` 且 npm 可用的系统 Node;否则自动准备只属于本插件的 Node `{{NODE_VERSION}}`。不要让用户安装全局 Node,不要使用管理员权限、`sudo`、全局 npm 安装、DWS 或浏览器自动化。
|
||||
|
||||
## 步骤 2:下载并校验首次安装文件
|
||||
## 步骤 2:下载、校验并执行平台安装引导
|
||||
|
||||
不要在浏览器中复制下载内容,不要对 URL 解码、重新编码或手工拼接。原样使用上面的 HTTPS URL。
|
||||
不要在浏览器中复制脚本内容,不要对 URL 解码、重新编码或手工拼接。必须先校验安装引导 SHA-256,再执行它。
|
||||
|
||||
### Windows(PowerShell)
|
||||
|
||||
在普通 PowerShell 中逐行运行:
|
||||
|
||||
```powershell
|
||||
$dingInstallDir = Join-Path ([System.IO.Path]::GetTempPath()) ("dingmcp-install-" + [guid]::NewGuid().ToString("N"))
|
||||
New-Item -ItemType Directory -Path $dingInstallDir -Force | Out-Null
|
||||
$dingInstaller = Join-Path $dingInstallDir "installer.mjs"
|
||||
$dingPublicKey = Join-Path $dingInstallDir "release-signing-public.pem"
|
||||
Invoke-WebRequest -Uri "{{INSTALLER_URL}}" -OutFile $dingInstaller
|
||||
Invoke-WebRequest -Uri "{{PUBLIC_KEY_URL}}" -OutFile $dingPublicKey
|
||||
$dingInstallerHash = (Get-FileHash -Algorithm SHA256 $dingInstaller).Hash.ToLowerInvariant()
|
||||
$dingPublicKeyHash = (Get-FileHash -Algorithm SHA256 $dingPublicKey).Hash.ToLowerInvariant()
|
||||
if ($dingInstallerHash -ne "{{INSTALLER_SHA256}}") { throw "安装器 SHA-256 不匹配,停止安装" }
|
||||
if ($dingPublicKeyHash -ne "{{PUBLIC_KEY_SHA256}}") { throw "发布公钥 SHA-256 不匹配,停止安装" }
|
||||
```
|
||||
|
||||
任一 `Invoke-WebRequest` 或哈希检查失败都必须停止,不能忽略错误继续。
|
||||
|
||||
### Linux / macOS(POSIX shell)
|
||||
|
||||
```bash
|
||||
ding_install_dir="$(mktemp -d)"
|
||||
curl --fail --location --output "$ding_install_dir/installer.mjs" "{{INSTALLER_URL}}"
|
||||
curl --fail --location --output "$ding_install_dir/release-signing-public.pem" "{{PUBLIC_KEY_URL}}"
|
||||
printf '%s %s\n' '{{INSTALLER_SHA256}}' "$ding_install_dir/installer.mjs" | sha256sum --check --strict
|
||||
printf '%s %s\n' '{{PUBLIC_KEY_SHA256}}' "$ding_install_dir/release-signing-public.pem" | sha256sum --check --strict
|
||||
```
|
||||
|
||||
macOS 没有 `sha256sum` 时,使用 `shasum -a 256` 分别计算并精确比较,不得跳过校验。
|
||||
|
||||
## 步骤 3:执行唯一通用安装入口
|
||||
|
||||
### Windows(PowerShell)
|
||||
|
||||
继续使用步骤 2 的同一个 PowerShell:
|
||||
|
||||
```powershell
|
||||
$dingInstallJson = & node $dingInstaller install --manifest-url "{{MANIFEST_URL}}" --public-key $dingPublicKey --json
|
||||
if ($LASTEXITCODE -ne 0) { throw "钉钉审批安装器执行失败:$dingInstallJson" }
|
||||
$dingBootstrapDir = Join-Path ([System.IO.Path]::GetTempPath()) ("dingmcp-bootstrap-" + [guid]::NewGuid().ToString("N"))
|
||||
New-Item -ItemType Directory -Path $dingBootstrapDir -Force | Out-Null
|
||||
$dingBootstrap = Join-Path $dingBootstrapDir "dingtalk-approval-bootstrap.ps1"
|
||||
Invoke-WebRequest -UseBasicParsing -Uri "{{BOOTSTRAP_WINDOWS_URL}}" -OutFile $dingBootstrap
|
||||
$dingBootstrapHash = (Get-FileHash -Algorithm SHA256 $dingBootstrap).Hash.ToLowerInvariant()
|
||||
if ($dingBootstrapHash -ne "{{BOOTSTRAP_WINDOWS_SHA256}}") { throw "Windows 安装引导 SHA-256 不匹配,停止安装" }
|
||||
$dingInstallJson = & powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File $dingBootstrap
|
||||
if ($LASTEXITCODE -ne 0) { throw "钉钉审批安装引导执行失败:$dingInstallJson" }
|
||||
$dingInstall = $dingInstallJson | ConvertFrom-Json
|
||||
if ($dingInstall.ok -ne $true) { throw "钉钉审批安装失败:$($dingInstall.error)" }
|
||||
$dingInstall | ConvertTo-Json -Depth 20
|
||||
```
|
||||
|
||||
### Linux / macOS
|
||||
完成后可删除 `$dingBootstrapDir`。任一下载或哈希检查失败都不能忽略。
|
||||
|
||||
### Linux / macOS(POSIX shell)
|
||||
|
||||
```bash
|
||||
node "$ding_install_dir/installer.mjs" install --manifest-url "{{MANIFEST_URL}}" --public-key "$ding_install_dir/release-signing-public.pem" --json
|
||||
ding_bootstrap_dir="$(mktemp -d)"
|
||||
ding_bootstrap="$ding_bootstrap_dir/dingtalk-approval-bootstrap.sh"
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
curl --fail --location --output "$ding_bootstrap" "{{BOOTSTRAP_POSIX_URL}}"
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget --https-only --output-document="$ding_bootstrap" "{{BOOTSTRAP_POSIX_URL}}"
|
||||
else
|
||||
echo '缺少 curl 或 wget,无法下载安装引导' >&2
|
||||
exit 1
|
||||
fi
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
ding_bootstrap_hash="$(sha256sum "$ding_bootstrap" | awk '{print $1}')"
|
||||
else
|
||||
ding_bootstrap_hash="$(shasum -a 256 "$ding_bootstrap" | awk '{print $1}')"
|
||||
fi
|
||||
if [ "$ding_bootstrap_hash" != '{{BOOTSTRAP_POSIX_SHA256}}' ]; then
|
||||
echo 'Linux/macOS 安装引导 SHA-256 不匹配,停止安装' >&2
|
||||
exit 1
|
||||
fi
|
||||
ding_install_json="$(sh "$ding_bootstrap")"
|
||||
printf '%s\n' "$ding_install_json"
|
||||
```
|
||||
|
||||
这是唯一通用安装入口。安装器会在稳定的当前用户数据目录安装客户端与 Skill,不会全局安装 npm 包,也不会修改 Agent 私有配置。保留完整 JSON 结果,后续只使用其中的真实字段,不要猜路径。
|
||||
完成后可删除 `$ding_bootstrap_dir`。如果 `sha256sum` 与 `shasum` 都不存在,必须停止,不能跳过校验。
|
||||
|
||||
## 步骤 3:验收安装结果
|
||||
|
||||
步骤 2 的平台引导是唯一通用安装入口。它会:
|
||||
|
||||
1. 检查系统 Node;缺失或版本不兼容时,根据当前操作系统和 CPU 架构选择私有 Node;
|
||||
2. 按“阿里云精确版本 → npmmirror 精确版本 → Node 官方精确版本”的顺序下载。只有网络失败、超时或 404 才切换来源;任一已下载文件的 SHA-256 不匹配都会立即终止;
|
||||
3. 把私有 Node 放在插件自己的当前用户数据目录,不修改系统 PATH,不要求管理员权限;
|
||||
4. 下载并校验首次安装器和发布公钥,再由安装器验证 Ed25519 清单签名与全部客户端发布物;
|
||||
5. 返回一份 JSON 安装结果。
|
||||
|
||||
安装器会在稳定的当前用户数据目录安装客户端与 Skill,不会全局安装 npm 包,也不会修改 Agent 私有配置。保留完整 JSON 结果,后续只使用其中的真实字段,不要猜路径。
|
||||
|
||||
安装结果至少必须包含:
|
||||
|
||||
@@ -106,6 +116,7 @@ node "$ding_install_dir/installer.mjs" install --manifest-url "{{MANIFEST_URL}}"
|
||||
- `loginCommand`;
|
||||
- `mcpConfig.mcpServers.dingtalk-approval`;
|
||||
- `postInstall`。
|
||||
- `nodeRuntime`,其中 `managed: true` 表示正在使用插件私有 Node。
|
||||
|
||||
Windows 的 `bridgePath` 和 `mcpConfig...command` 正常应以 `dingtalk-approval-bridge.cmd` 结尾。路径中可能包含空格;保留完整字符串,不要拆分,不要去掉 `.cmd`,不要改为 `node`、`npx` 或远程 URL。
|
||||
|
||||
@@ -155,7 +166,7 @@ $dingLogin | ConvertTo-Json -Depth 20
|
||||
1. 如果当前 Agent 要求信任本地连接器,按其官方界面或命令确认名称为 `dingtalk-approval` 的连接器。
|
||||
2. 如果不能热加载,完整退出并重新启动 Agent,或新建一个确定会重新读取 MCP 配置的会话;只刷新聊天内容通常不够。
|
||||
3. 重启后确认能发现 `approval_login`、`approval_list_todos` 等钉钉审批工具。当前版本应发现 13 个工具。
|
||||
4. 若连接器进程退出、显示 302 或无法启动,先执行步骤 9 的 Windows 排障,不要把连接器改成远程 HTTP MCP。
|
||||
4. 若连接器进程退出、显示 302 或无法启动,先执行步骤 9 的故障排查,不要把连接器改成远程 HTTP MCP。
|
||||
|
||||
## 步骤 7:确认登录并验证两个审批来源
|
||||
|
||||
@@ -173,17 +184,18 @@ $dingLogin | ConvertTo-Json -Depth 20
|
||||
|
||||
安装阶段不得处理审批,也不得在登录和双来源验证完成前声称“已可使用”。
|
||||
|
||||
## 步骤 9:Windows 常见故障排查
|
||||
## 步骤 9:常见故障排查
|
||||
|
||||
按顺序排查,不要跳到重装:
|
||||
|
||||
1. **显示 302 或启动后立即退出**:检查连接器是否被错误配置成 `{{GATEWAY_URL}}` 或其他 HTTP URL。正确配置必须是 `type: "stdio"`,`command` 为本机 `dingtalk-approval-bridge.cmd`,`args: []`。重新复制安装结果中的 `mcpConfig`。
|
||||
2. **路径不存在或 Node 升级后失效**:不要引用 Node/NVM 的版本目录。执行安装结果中的 `cliPath`,或运行 `dingtalk-approval print-config --format mcp-json` 重新取得稳定配置。
|
||||
3. **Bridge 仍无法启动**:执行 `<cliPath> doctor --json`。只有所有 `checks` 都为 `ok: true` 才继续;把失败检查和错误原文报告给维护者,不要提供 Token 或会话文件。
|
||||
4. **提示找不到 npm-cli.js**:当前 Node 安装不完整。安装带 npm 的 Node.js 22.13+,打开新 PowerShell,重新检查 `node --version` 和 `npm --version` 后再运行安装器。
|
||||
4. **提示找不到 npm-cli.js 或 Node 运行时损坏**:重新执行步骤 2 中已经过哈希校验的平台引导,让它修复插件私有 Node;不要安装全局 npm。
|
||||
5. **路径包含空格**:不要手写命令行字符串。把安装器返回的整个 `mcpConfig` 作为 JSON 对象交给 Agent;在 PowerShell 中执行 CLI 时用调用运算符 `&` 和独立参数。
|
||||
6. **连接器一直未出现**:确认已信任本地连接器并完整重启 Agent。不要通过反复重装刷新连接器。
|
||||
7. **授权链接过期**:MCP 已加载就再次调用 `approval_login`;否则执行保存的 `loginCommand`。不要重装。
|
||||
8. **Linux/macOS 缺少下载或校验命令**:必须先具备 `curl` 或 `wget`,以及 `sha256sum` 或 `shasum`;不能绕过 SHA-256 校验。系统 `tar` 必须支持 gzip 归档。
|
||||
|
||||
## 更新
|
||||
|
||||
|
||||
Reference in New Issue
Block a user