关于 Versions-LE
Versions-LE 用于比较仓库清单文件和 CI 工作流中的依赖及工具链约束,适合检查单体仓库、发布准备和依赖更新。对于不支持的语法,它会明确拒绝比较,而不会猜测。
主要功能
- 01比较多个清单中的约束
- 02检测无法同时满足的版本范围
- 03检查 Rust 最低版本与 CI 偏差
- 04报告问题及其来源位置
- 05拒绝处理不支持的约束语法
适用场景
- 01查找单体仓库中的依赖冲突
- 02发布前核对 CI 工具链
- 03检查依赖更新后的约束一致性
MCP 相关
MCP 服务向 MCP 客户端提供 `compare_versions` 和 `versions_le_check`。它通过参数接收文件路径和内容并返回比较数据,不访问文件系统或网络。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
1收录的工具列表 · 更新于 3 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| files | array | 是 | 要比较的清单。 |
| maxResults | integer | 否 | 返回的问题数上限(默认 500)。meta.truncated 报告是否有结果被省略。 |
详细介绍
Versions-LE:两个版本约束,一个依赖项
查找仓库清单文件中同一依赖项约束不一致的位置,以及没有任何版本能同时满足这些约束的情况
package.json · Cargo.toml · pyproject.toml · go.mod · GitHub 工作流
觉得有用? 点赞或评分能帮助其他开发者发现它 — ★ GitHub · ★ Open VSX · ★ Marketplace
功能介绍
构建失败了,因为 api 要求 regex = "1",而 web 要求 regex = "2",没有任何一个版本能同时满足两者。也可能构建还没失败,但迟早会失败:自 3 月以来,CI 一直使用 Rust 1.80 构建,而 rust-version 却写着 1.88。
运行 Versions-LE: Compare Versions,即可将工作区中的所有清单文件作为一个整体进行比较;也可以在资源管理器中比较某个文件夹下的所有清单文件。报告会在编辑器旁打开:按严重程度列出每个问题,并展示导致问题的所有文件、键和约束,随后说明哪些内容被有意排除在比较之外及其原因。可在 VS Code 以及 Cursor、VSCodium 等基于 VS Code 的编辑器中使用(可从 Open VSX 安装)。
- 在单体仓库中 — 某个 crate 固定使用
serde 0.9,而其他部分已升级到1.0 - 发布前 — CI 使用的工具链比你发布所要求的最低版本还旧
- 审查依赖项升级时 — 找出那个没有和其他依赖项一起升级的包
它绝不会修改清单文件,也绝不猜测:任何不在其模型范围内的约束都会被明确指出,并从所有比较中排除。
安装
| 位置 | 可获得的内容 | 安装 |
|---|---|---|
| VS Code | 在编辑器中通过一次按键完成比较 | Marketplace |
| Cursor、VSCodium、Windsurf | 同一扩展 | Open VSX |
| 终端或 CI 步骤 | 整棵依赖树,并返回退出代码 | cargo install versions-le · crates.io |
| 通过 Node 使用终端 | 与 Rust 版逐字节保持一致的同一命令行 | npx versions-le · npm |
| 任何 MCP Agent,通过 Node 使用 | 通过 stdio 调用 compare_versions | npx versions-le-mcp · npm |
六项检查
| 代码 | 严重性 | 含义 |
|---|---|---|
disjoint-constraint | 错误 | 同一依赖的两个约束,不存在任何一个版本能同时满足。这是此工具作出的最强判定。 |
malformed-constraint | 错误 | 形式上符合其所属生态系统的约束语法,但内容有误。 |
constraint-conflict | 警告 | 同一依赖在多个位置存在两个或更多不同要求。 |
msrv-mismatch | 警告 | 不同清单中的 rust-version 不一致,或 CI 工具链固定版本低于声明的最低版本。 |
prerelease-in-production | 警告 | 在开发或构建依赖之外出现 -rc 或 -alpha 约束。 |
floating-pin | 信息 | latest、*、针对 0.x 版本的插入符,或未固定版本的 CI 工具。 |
不同与无法满足是两种发现。 constraint-conflict
表示可疑之处;disjoint-constraint 则表示构建无法解析。二者
绝不会混为一谈。
是否互斥由模型化范围上的区间运算决定,而非字符串比较——
这也是为什么 >=20 和 >=20.0.0 不会被报告为冲突。它们是
以两种写法表达的同一项要求。
每个存在版本偏差的依赖只报告一项发现,并列出所有位置。一个依赖 有四种约束时,就是一个问题、四个位置;若报告四项发现, 看起来就像是四个问题。
四种拒绝判定
绝不猜测。 对于此工具未建模语法中的约束,会在报告的
refusals 中列出,且不参与任何比较——
绝不会将其近似转换为范围。
| 原因 | 情况 |
|---|---|
unknown_grammar | 该值是此工具未建模语法中的约束:PEP 440 的 ~=, !=, ===, ==1.2.*;npm 的 workspace:, npm:, file:, link:、git 或 https URL、owner/repo 简写、发行标签;不含 version 的 Cargo 依赖表;提交 SHA 或分支形式的 action 引用;CI 通道名称(stable、latest、lts/*)。 |
cross_ecosystem | 同一名称出现在两个生态系统中。只命名一次,每个生态系统各列出一个位置,且绝不比较二者。 |
ambiguous_version_string | 工作流中的 <tool>-version: 值显然不是版本,例如 ${{ matrix.node }}、列表或文件名。根本不会创建条目:没有可比较的内容,也没有虚构任何内容。 |
per_job_tool_version | 同一 CI 工具安装了两个版本——测试任务中的 python-version: 3.9,发布任务中的 3.12。工具版本属于安装它的任务,因此绝不比较二者。 |
malformed-constraint 是一项发现,而非拒绝判定;这种区别
是有意的:它是更严格的结论,表示该值形式上符合其所属生态系统的约束语法,
但内容有误。只有确信时,工具才会归咎于清单;其他情况则由工具
自行承担责任。^^1.0.0 格式错误。latest 则不是——它是一种
此工具选择不建模的语法,且有其含义。
比较绝不会跨越生态系统。 npm 的 semver 与 Cargo 的
semver 是两个毫不相关、仅共享同一名称的包——而裸值
"1.0.200" 在 npm 中表示恰好为 1.0.200,在
Cargo 中则表示小于 2.0.0 的任何版本。只有一种桥接情形:msrv-mismatch;
它通过同时指定两个键来建立,而非通过匹配名称。
它会读取什么
| 清单 | 键 |
|---|---|
package.json | 四个依赖项部分、engines.*、packageManager |
Cargo.toml | 依赖项、开发依赖项、构建依赖项、工作区和目标变体、rust-version |
pyproject.toml | PEP 621 dependencies、optional-dependencies、requires-python |
go.mod | require(单行和块形式)、go 指令 |
.github/workflows/*.yml | uses: 操作引用、<tool>-version: 输入、toolchain: |
最后一行和第一行一样,都是本工具存在的原因:CI 工具链偏离清单声明的最低版本,正是那种没人会注意到、直到发布时才暴露的故障。
它永远不会读取 node_modules、vendor 和 .git。它始终会读取 .github——工作流按定义就位于隐藏目录中。
它不会做什么
- 它绝不会编辑清单。 没有
--fix、--pin或--update。依赖项偏离时该使用哪个版本,需要作出决定,而不是推导出来。 - 它绝不会解析依赖关系图。 它读取清单写明的内容,而不是解析器会选出的内容——不读取锁文件,也不做传递依赖分析。
- 它绝不会访问网络。 它不知道哪些版本存在、哪些已被撤回,或哪些是最新版本;它只会检查两个已声明的要求能否同时满足。
- 它不会检查代码风格。 清单的排序、引号和格式由其他工具负责。
在 AI Agent 中使用
同一个引擎也可以作为 MCP 服务运行,因此 Agent 可以直接调用它,而不是用肉眼比较清单。
| 编辑器 | 方法 |
|---|---|
| VS Code 1.101+ | 无需安装——该扩展会向 Agent 模式注册 compare_versions |
| Claude Code | claude mcp add versions-le -- npx -y versions-le-mcp |
| Cursor、Windsurf 及其他工具 | 将其指向 npx versions-le-mcp |
compare_versions(files: [{ path, content }], maxResults?)
它会以数据形式返回编辑器所呈现的报告——默认最多包含 500 条发现,并附带 meta.truncated。它不读取文件,也不发起网络请求。该工具以 versions-le-mcp 的名称发布在 npm 上,并以 io.github.nolindnaidoo/versions-le 的名称发布在 MCP 注册表中。它的回答与 Rust CLI 的服务完全一致:两者运行同一套语料库,并通过差分测试向两者输入数千组生成的清单(包括格式错误的 JSON 和 TOML),然后比较每个回答。
手动配置——任何带有 MCP 配置文件的宿主
{
"mcpServers": {
"versions-le": {
"command": "npx",
"args": ["-y", "versions-le-mcp"]
}
}
}
也可以通过 npm install -g versions-le-mcp 一次性安装,然后将其指向 versions-le-mcp。它不需要环境变量、API 密钥,也不需要单独配置。检查方法如下:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | npx -y versions-le-mcp
同一项比较也可以通过终端或 CI 步骤对目录树运行:Rust 命令行工具位于 crate/,并与扩展共用同一套测试语料 — crate/fixtures/ — 因此二者绝不会以不同方式读取约束。同一命令行工具也以 versions-le 的形式发布到 npm,供装有 Node、但未安装 Rust 的机器使用;CI 会在三种操作系统上逐字节验证它与 crate 的一致性。
从 npm 安装 (versions-le) 或从 crates.io 安装 (versions-le)。两种方式都会安装同一个 versions-le 命令。
npm install -g versions-le # or run it once: npx versions-le
cargo install versions-le
versions-le . # every manifest in the tree; one JSON report on stdout when piped
versions-le --ecosystem cargo . # one ecosystem
versions-le --fail-on any . # floating pins fail the build too
versions-le --strict . # an unanalysed corner exits 2
versions-le mcp # compare_versions and versions_le_check over MCP on stdio
退出代码就是结果 — 0 表示没有高于 info 级别的问题,1 表示发现问题,2 表示问题格式错误。完全没有清单时返回 0:没有东西就不会发生冲突。
命令
| 命令 | 描述 |
|---|---|
Versions-LE: Compare Versions | 比较工作区中的所有清单,或 Explorer 中选定文件夹下的所有清单 |
Versions-LE: Open Settings | 打开 Versions-LE 设置 |
Versions-LE: Help & Troubleshooting | 内置文档 |
默认情况下,没有命令绑定快捷键。可在编辑器的 键盘快捷键 中为任意命令设置快捷键。
设置
| 设置 | 默认值 | 描述 |
|---|---|---|
versions-le.exclude | [] | 要排除的清单的 Glob 模式;始终排除 node_modules、.git 和 vendor |
versions-le.openResultsSideBySide | true | 在当前编辑器旁打开报告 |
versions-le.showPositions | true | 显示每条约束所在的行 |
versions-le.copyToClipboardEnabled | false | 同时将报告复制到剪贴板 |
versions-le.clipboardIncludesPositions | true | 在复制内容中包含行号 |
versions-le.notificationsLevel | silent | all = 所有通知,important = 警告 + 错误,silent = 仅错误 |
versions-le.statusBar.enabled | true | 显示状态栏项目 |
versions-le.telemetryEnabled | false | 仅限本地的事件日志(参见“隐私”) |
语言
除英语外,支持 12 种语言:
德语 · 西班牙语 · 法语 · 印度尼西亚语 · 意大利语 · 日语 · 韩语 · 葡萄牙语(巴西)· 俄语 · 乌克兰语 · 越南语 · 简体中文
两个部分都已覆盖 — 清单(命令标题、设置名称和说明),以及扩展运行时显示的所有内容(通知、状态栏和报告标题)。发现问题的消息使用引擎的英文,与命令行工具完全一致。
隐私与安全
- 不访问网络。 此扩展不会向任何地方发送数据;它不知道有哪些版本,只知道两个给定的要求能否同时满足。
telemetryEnabled设置仅会将事件写入本地输出通道,供你查看(Versions-LE)。 - 只读取清单,不读取其他内容,也绝不会写入清单。
- MCP 服务同样遵守这一原则。 它接收内容作为参数并返回数据:不访问文件系统、不进行网络调用,也不收集遥测数据。
- 错误通知会对主目录和类似凭据的片段进行脱敏。
- 评分提示最多出现两次。 第 3 次成功使用时,扩展会询问你是否愿意评分;如果你选择了 稍后 或关闭提示,则会在第 20 次使用时再询问一次。选择 不再询问 后,提示便会停止。你自行将
notificationsLevel设置为important或silent也会关闭提示。计数保存在 VS Code 的扩展存储中,不会发送到任何地方;点击 评分 会在浏览器中打开你安装扩展时使用的列表页面——VS Code Marketplace 或 Open VSX。
文档
| 内容 | 位置 |
|---|---|
| 此工具可以声明什么——检查、拒绝、输出约定、非目标 | crate/SPEC.md |
| 扩展的构建与内部结构——架构、不变量、工具链、发布 | AGENTS.md |
| CLI 的构建与内部结构 | crate/AGENTS.md |
| 变更内容 | CHANGELOG.md · crate/CHANGELOG.md |
| 此工具的页面及其他 15 个工具 | letools.dev/tools/versions-le |
性能
| 输入 | 大小 | 找到 | 耗时 | 速率 | 扫描速度 |
|---|---|---|---|---|---|
| 50 个 crate,50 个 package | 0.01 MB | 450 | 2.38 ms | 188,722/秒 | 6.1 MB/s |
| 500 个 crate,500 个 package | 0.15 MB | 4,500 | 27.13 ms | 165,892/秒 | 5.4 MB/s |
| 2,000 个 crate,2,000 个 package | 0.58 MB | 18,000 | 486.79 ms | 36,977/秒 | 1.2 MB/s |
数据取自预热后的 7 次运行的中位数,测试设备为 Apple M5 Pro、24 GB RAM,运行 Node 24.3.0。输入由 scripts/benchmark.ts 生成,而非检入仓库,因此上面的大小就是实际测得的大小。运行 bun run benchmark 可复现。
这些数据因机器而异,CI 不会断言它们——以基准测试作为构建门槛,只能说明运行器当时有多忙。
测试
| 指标 | 覆盖率 |
|---|---|
| 语句 | 79.30% |
| 分支 | 72.41% |
| 函数 | 82.44% |
| 行 | 82.58% |
24 个文件中共有 381 个测试用例,此外还有一个在真实 VS Code 扩展宿主中运行的集成测试套件,以及一个将构建好的 .vsix 安装到干净配置文件中的端到端测试。
数据由 scripts/coverage-readme.js 根据真实运行生成——来源文件为 coverage/coverage-summary.json 和 coverage/test-results.json;如果本节内容与实际不符,CI 会失败。运行 bun run test:coverage 可复现;用例数以 vitest 打印的数字为准。
LE 系列的更多工具
为每个模型眼前的工作打造的 16 款单一用途工具。每款都附带一个 Rust CLI 和一个 MCP 服务。一页尽览:letools.dev
提取
- String-LE — 提取代码库中的所有字符串,方便人工阅读
- Numbers-LE — 提取代码库中所有硬编码数字,方便人工检查
- Units-LE — 提取所有带单位的数量并统一格式,遇到含义不明确的数量时会按名称拒绝处理
- Dates-LE — 提取所有日期和时间戳,并给出每个日期和时间戳解析出的确切时刻
- IDs-LE — 提取所有 UUID、ULID、NanoID、ObjectId 和 Snowflake,并解码其中的时间
- IPs-LE — 提取所有 IP 地址、CIDR 网段和 MAC 地址,统一格式并按范围分类
- URLs-LE — 提取代码库中的所有 URL,并给出协议和确切位置
- Paths-LE — 提取代码库中的所有文件路径,并说明它们是否仍指向实际内容
- Colors-LE — 提取代码库中的所有颜色,并指出哪些颜色不在你的调色板中
检查
- Regex-LE — 查找代码库中的所有正则表达式,并报告哪些可能导致灾难性回溯
- Versions-LE — 查找某个依赖项在仓库的各个清单文件中受到不同约束的位置
- i18n-LE — 识别项目使用的 i18n 库,然后依据该库的规则审查其目录
- Scrape-LE — 在编写抓取器之前检查网页能否抓取,并说明何时无法判断
防护
- Secrets-LE — 查找代码库中的硬编码凭据,绝不在报告中打印凭据
- EnvSync-LE — 比较目录树中的 dotenv 文件,并指出哪些文件缺少哪些键
- Unicode-LE — 查找那些隐藏含义的 Unicode 字符——双向控制字符、不可见字符、同形异义字符、混合文字系统
每款工具都独立运行:没有共享的 crate,也没有发布的核心库。若有两款工具得出相同结论,那是因为这个答案经得起两次验证。
联系 — nolindnaidoo.com · GitHub · LinkedIn
nolindnaidoo 的其他项目
Rust — pixelcoords 和 pixelactions 构成一个工作循环:pixelcoords 回答 位置,pixelactions 在那里执行操作。它们有各自的工具、各自的风格——不属于 LE 系列。
- pixelcoords — 冻结屏幕,标记区域,获取像素级精确的坐标和裁剪图像 pixelcoords.dev · crates.io · docs.rs
- pixelactions — 使用经过人工验证的坐标执行交互,并确认操作已生效 pixelactions.dev · crates.io · docs.rs
许可证
MIT © nolindnaidoo
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。