Repository navigation
feat(plugins): 插件注入的工具链框架与 macOS 只读环境设置页 - #1581
FxRayHughes wants to merge 9 commits into
Conversation
技术方案评审:
|
| 贡献 | 回答什么 | 形式 | 谁提供 |
|---|---|---|---|
| 工具定义 | 工具是什么:怎么识别、探测版本、导出环境、启动 | 清单里的静态声明 | 任何插件 |
| 提供方 | 装了什么、项目要什么、全局要什么 | 插件通过 API 返回事实 | 版本管理器插件 |
| 使用方 | 谁需要这个工具 | 已有(通过 tool ID 引用) |
语言服务器、构建系统、运行配置 |
1. 工具定义(示意)
"toolDefinitions": [
{ "id": "java", "displayName": "JDK",
"executables": ["bin/java"], "commands": ["java"],
"version": { "arguments": ["-version"], "pattern": "(?:1\\.)?(\\d+(?:\\.\\d+)*)" },
"exports": [{"name": "JAVA_HOME", "value": "${home}"},
{"name": "LITHE_JAVA_PATH", "value": "${executable}"}],
"pathPrepend": ["${home}/bin"],
"launch": ["${executable}", "${runtimeArguments}", "-jar", "${entry}", "${arguments}"] },
{ "id": "maven", "displayName": "Maven",
"executables": ["bin/mvn"], "commands": ["mvn"],
"projectExecutables": ["mvnw"],
"version": { "arguments": ["-v"] },
"pathPrepend": ["${home}/bin"] }
]这张“工具 ID 到宿主用途”的映射表就是适配层里本来要写死的东西,改成插件贡献。它取代的是:java 当 JDK home 的特判、maven → mvn 的文件名巧合、契约里写死的版本探测参数和 LITHE_<TOOL>_PATH 导出规则、launch.kind: runtime 里 tool 只能是 java 或 node 的限制,以及选择链里专门给 mvnw、gradlew 写的分支。
- ID 归属。 插件自己的工具用
插件id:工具;不带前缀的短名(java、node、go、maven)是保留名,只有宿主内置或官方签名插件能定义。同一 ID 被重复定义时拒绝后来者,不允许覆盖。 - 宿主内置的那几个用同一种格式的数据文件表达,放在
shared/下,各平台随应用打包,作为第一个贡献者注册。适配层里不出现任何工具名,以后各插件可以逐个接管自己的定义。 - 安全校验由 Core 统一做,与具体工具无关。 环境变量值只能是
${home}、${executable}模板;禁止PATH、DYLD_*、LD_*;pathPrepend只能在${home}之内;探测参数必须是-x/--xx形状。安装审查里列出每个定义会运行的程序和参数。
2. 提供方 API
清单只声明“我能回答哪些工具”,不描述目录结构和文件格式:
"toolchainProviders": [{ "id": "mise", "displayName": "mise",
"tools": ["java", "node", "maven", "pnpm", "go"] }],
"permissions": ["toolchains.provide"]宿主向插件发 toolchains/query({operationID, workspace, tools},workspace 为空表示只问全局),插件返回:
{ "installations": [
{"tool": "java", "version": "21.0.2", "home": "/…/installs/java/21.0.2"} ],
"statements": [
{"tool": "java", "scope": "project", "source": "/proj/mise.toml",
"request": "21", "installation": "/…/java/21.0.2"},
{"tool": "java", "scope": "global", "source": "~/.config/mise/config.toml",
"request": "17", "installation": "/…/java/17.0.9"},
{"tool": "node", "scope": "project", "source": "/proj/.tool-versions",
"request": "lts", "installation": null} ],
"watch": ["/proj/mise.toml", "/proj/.tool-versions", "…/installs/java"] }- 插件只能回答自己在
tools里声明过的、且有已启用插件定义的 ID,其余丢弃。这样“任意同名文件被注入”的口子就堵上了。 - 版本语义(哪个文件优先、
lts对应哪个目录)归插件,宿主不解释request。 installation: null表示项目要求了但没装。watch沿用 PR 里“缓存到输入变化”的思路:宿主只做stat指纹比较,没变就不再调用插件。- 沿用现有的
operationID、取消、超时和过期结果规则。 - 返回的路径由 Core 统一校验:绝对路径、存在、可执行、不落在工作区内(保留 PR 现有的这条安全规则)、数量有上限。
.tool-versions、mise.toml这类通用解析函数放进 lithe-plugin-docs 的 Node/Java SDK,不放进宿主。
3. 统一的选择规则
所有工具共用一条规则,按层从上到下取第一个有值的:
| 层 | 内容 | 范围 |
|---|---|---|
| 1 固定 | 用户在 Lithe 里为这个项目选的 | 项目 |
| 2 项目要求 | 提供方上报的 scope: project,以及 mvnw、gradlew 等项目自带的包装脚本 |
项目 |
| 3 全局默认 | Lithe 里的全局默认 → 提供方上报的 scope: global → JAVA_HOME/PATH |
全局 |
| 4 自动检测 | 满足最低版本的已安装最新版(现有的 Core 规则) | — |
- 没装任何插件时,第 2 层为空,行为与现在完全一致。
- Lithe 里固定的值失效:报错,不回落(与调试适配器那篇 Note 的做法一致)。
- 项目要求了但没装:回落到下一层继续工作,但状态标成“未满足”,界面明确提示。
- 界面上每个工具一行,显示“JDK 21 · 来自项目要求(mise.toml)”,展开后列出每层的值,被盖住的划掉。
对这个 PR 的建议
可以保留: 工作区内路径拒绝、按输入缓存、只读原则、i18n 词条、功能矩阵条目、RuntimeChoiceSource 的“来自 %@”展示。
需要重做: Core 里的 toolchain_sources.rs(管理器专属解析与选择语义)、清单 schema 里的目录与格式描述、ProjectRuntimeService 里三条各自的链。
建议拆分:
- 契约(工具定义、提供方、校验)加 Agent Note,先定契约再写代码;
- 适配层的查询客户端(缓存、取消、过期);
- 统一选择规则加运行时设置界面;
- mise 插件加 SDK 帮手,再写一个 SDKMAN 插件当验收,并把
MacRuntimeDiscovery里写死的 SDKMAN 位置迁出去。
契约在 shared/contracts/plugins/v1/,合并后要在 lithe-plugin-docs 运行 node scripts/contract.mjs sync 同步。
待讨论
- API 方向。 上面是“宿主请求、插件返回事实”,不是“插件主动推送”。推送需要插件进程为每个打开的项目常驻;请求式有明确的超时和取消。需要时可以在同一协议上加
toolchains/changed通知。 - 规则细节。 “固定 > 项目要求 > 全局默认”,以及“要求没装就回落并警告”,是建议值,欢迎提出不同意见。
- 保留名。 只允许官方签名的插件或宿主内置定义不带前缀的短名;若允许社区插件定义,冲突处理会复杂很多。
- 自举和免重启。
- 提供运行时的插件,它自己的后端不能依赖它要发现的运行时,否则循环依赖。后端必须自带运行时或是单文件可执行程序(契约已有
packagedRuntime)。 - PR 的
canActivateWithoutRestart只放行“无后端”的插件,这个条件需要放宽。 - 这两点我们还没有原型验证过。
- 提供运行时的插件,它自己的后端不能依赖它要发现的运行时,否则循环依赖。后端必须自带运行时或是单文件可执行程序(契约已有
- Core 的一次性改动。 加定义的校验,以及把
checkRuntimeVersion里 Java 8 的1.x特例改成定义里的正则。之后新增工具或管理器都不再改 Core。
|
这个具体的先后顺序啥的我记得构建工具里面我之前就提过一个方案,按照优先级去维护一个顺序,你可以去看看,具体细节我记不清楚了哎 |
|
感谢这么细的评审。结论先说:同意按「工具定义 / 提供方 / 使用方」重做,本 PR 不再往下推。 我对照代码核对了几处问题,都成立:
你说的「按优先级维护顺序」,我找到的是你在 #1420 的评审(#1420 (comment)):
如果是这条,我打算把新方案的选择规则直接建在它上面,不再写第二套分层逻辑。下面是调整方案,请看方向对不对。 1. 选择规则:写成每个工具定义的默认候选数组四层规则不再写成
示意(Maven;Java 结构相同,把 { "id": "maven", "displayName": "Maven", "commands": ["mvn"],
"version": { "arguments": ["-v"] },
"executables": [
{ "id": "pinned", "kind": "setting", "settingID": "executable", "layer": "project" },
{ "id": "wrapper", "kind": "projectFile", "path": "mvnw" },
{ "id": "projectRequest", "kind": "toolchain", "scope": "project" },
{ "id": "default", "kind": "setting", "settingID": "executable", "layer": "global" },
{ "id": "globalRequest", "kind": "toolchain", "scope": "global" },
{ "id": "home", "kind": "environment", "variable": "MAVEN_HOME", "path": "bin/mvn" },
{ "id": "path", "kind": "command", "command": "mvn" },
{ "id": "detected", "kind": "toolchain", "scope": "installed" }
] }各层在 resolver 里的语义:
这样三条链变成一条。Provider、模型加载和实际执行用同一个结果,#1420 已经保证了这一点。没装版本管理器插件时,所有 2. 提供方:mise 的语义交还给 mise同意「宿主请求,插件返回事实」。mise 插件改成带后端,后端直接调用 mise 自己的机器可读输出,任何一方都不再重写 mise 的规则:
本机验证(mise 2026.9.8):用
自举:后端做成单文件原生程序(Rust,按 darwin-arm64 / x64 分包,Store 已支持按架构下载),不依赖它要发现的 node 或 java。mise 本身的位置用 #1420 的候选声明:设置 → SDKMAN 适合做第二个验收插件: 3. 对待讨论各点的意见
4. 拆分按你的建议,先契约后代码,拆成 4 个 PR:
你列的可以保留的部分(工作区内路径拒绝、按输入缓存、只读原则、i18n 词条、功能矩阵、「来自 %@」展示)会分别带进第 2、3 个 PR。第 1 个提案 PR 提交后关闭本 PR,分支保留作参考;配套的 Store 收录 PR(Lithe-IDEA/Lithe-store#32)同时关闭,等新契约落地后重新提交。 如果方向没问题,我先提第 1 个提案 PR。 |
|
剩下的没啥问题了,你大胆去做吧 |
|
@FxRayHughes 这个可能需要催一下进度,因为有一个 PR 里面我要求使用你这个 PR 的版本管理方案来处理了,如果你没有空的话可以跟我说我来接手 |
改写后的计划:工具全部由插件注入上面几张截图换成了一个可交互的 HTML 原型(链接和用法在最后),以原型和这条评论为准。你 4 个 PR 的拆分和 #1420 候选数组的思路都保留;主要改动是下面这条原则。另外,#1558 的 Maven 迁移要用这里的工具定义来声明 Maven,所以第 1 个提案 PR 请优先提。 0. 原则:宿主不认识任何工具
1. 三类贡献:界面上每一块由谁注入
2. 选择规则:四层,建在 #1420 的候选数组上你在第 1 节给的
3. 按目录(模块)拆分和固定
4. 手动添加
5. 紧凑展示
6. 查询模块和文件监听
7. 拆分(改写后)
你第 3 节里的其余几点照原样进行:免重启第一阶段不放宽, 8. 现有代码里要清掉的写死
9. 原型怎么用
|
* feat(plugins): 声明式语法高亮与运行标记(API-25/27/29) - languages 2:插件语言可带 Monarch 语法和编辑器配置,Core 校验,纯语法插件免重启 - runMarkers 1:backend 2 插件函数回答可运行行,编辑器画运行按钮,点击经 commands/didRun 带 runMarker - 契约、fixture、Agent Note、计划文档与功能矩阵同步更新;Windows 暂不支持 Refs #570 * feat(plugins): 独立编辑器高亮与动作扩展 - languages 2 提供静态语法和独立编辑配置,插件正则在可终止 worker 中运行\n- editor/registerActions 运行期注册文本动作,点击复用普通函数调用,不扩张 Run/LSP/Build/Debug 领域契约\n- 补齐文档版本、动作租约、取消与清理、独立工具后端启用及安全模式边界\n- 更新 Skill、审查规则与决策笔记,总结 #1581/#1558 的架构边界\n- 同步契约、fixtures、中英词条、功能矩阵与资源复用说明\n\nRefs #570\nReworks #1617 * docs(plugins): 明确 API-25 JSON 贡献的支持范围与局限 区分包内静态 JSON 贡献与尚未开放的运行期 Provider 注册、替换和释放;说明独立语义 Provider、新引擎适配及平台、SDK 和验收限制。同步计划、架构笔记、正式契约与功能矩阵。 * fix(plugins): 修复编辑器扩展审查中的生命周期与高亮问题 动作刷新立即确认调度并隔离非致命失败,整批收集共享八秒期限并在撤销时清理计时任务。 Core 保留校验后的 grammar 原始文本,worker 按源顺序解析 cases 并显式默认 root;配置-only 别名借用既有 tokenizer,重映射 token 语言身份以保留独立注释配置。 模块状态观察弱引用 runtime,补齐有界、确定性的 Swift/Rust/WebKit 回归与测试文档模型清理,同步契约、Agent Note 和功能矩阵。 验证:57 项 Swift、1459 项 Rust、39 项编辑器和 119 项真实 WebKit 测试通过;静态边界、i18n、只读 bundle、资源复用与矩阵门禁通过。未执行 Windows 原生构建或打包安装验收。 Refs #1617, #570
27852b0 to
71f9f65
Compare
按 1lck#1581 评审后的改写计划重做:宿主不认识任何工具,工具定义、版本管理器 (提供方)全部由插件声明;Core 只做校验和四层解析,不解析 mise 等管理器 的私有格式。 - 契约:新增 toolDefinitions 1、toolchainProviders 1,executableResolution 增加 v2(只用于工具定义候选);同步 schema、README、toolchains.md、 fixture 和 rust-core-api.md;proposals/toolchains/ 放完整方案草案 - Rust Core:新领域模块 rust/lithe-core/src/toolchain/(定义注册表、 提供方答复校验、目录固定、固定/项目文件/全局/自动四层解析、版本匹配、 扫描计划)和六个 toolchains.* 命令,全部只处理宿主快照,不启动进程、 不扫描、不写文件 - macOS:设置 › 构建新增「运行环境」「环境来源」两页,内容来自已启用 插件的声明和磁盘上的真实文件;未实现的添加、切换、保存、查询入口不显示 - 登录 Shell:新增只读 inspect,来源页显示读取状态、变量数、耗时和 PATH 各目录来源;重新读取不改变本进程 PATH - Debug 预览入口 --toolchain-settings-demo / --toolchain-sources-demo - Agent Note、设置层级 Note、功能矩阵和中英词条同步 Refs 1lck#1514
Lithe Review结论: 未发现需要阻塞合并的问题。 Findings
Scope Check
Suggestions
Summary整体分层与延期边界清晰。建议在后续原生接入前修复上述两处解析不一致,避免设置展示与实际选择产生分歧。 Verification
|
按 1lck#1581 评审后的改写计划重做:宿主不认识任何工具,工具定义、版本管理器 (提供方)全部由插件声明;Core 只做校验和四层解析,不解析 mise 等管理器 的私有格式。 - 契约:新增 toolDefinitions 1、toolchainProviders 1,executableResolution 增加 v2(只用于工具定义候选);同步 schema、README、toolchains.md、 fixture 和 rust-core-api.md;proposals/toolchains/ 放完整方案草案 - Rust Core:新领域模块 rust/lithe-core/src/toolchain/(定义注册表、 提供方答复校验、目录固定、固定/项目文件/全局/自动四层解析、版本匹配、 扫描计划)和六个 toolchains.* 命令,全部只处理宿主快照,不启动进程、 不扫描、不写文件 - macOS:设置 › 构建新增「运行环境」「环境来源」两页,内容来自已启用 插件的声明和磁盘上的真实文件;未实现的添加、切换、保存、查询入口不显示 - 登录 Shell:新增只读 inspect,来源页显示读取状态、变量数、耗时和 PATH 各目录来源;重新读取不改变本进程 PATH - Debug 预览入口 --toolchain-settings-demo / --toolchain-sources-demo - Agent Note、设置层级 Note、功能矩阵和中英词条同步 Refs 1lck#1514
工具的已安装版本有两条途径,可以只用其一或同时使用: - 声明式扫描:工具定义的 discovery/homeLayouts/version 由宿主展开,不运行 插件代码;可用的根和通配写法固定,新的安装形态交给提供方回答。 - 提供方查询:toolchainProviders 通过 toolchains/query 返回安装和要求。 - watchFiles 改为可选:不声明的提供方只报告安装,答复里带版本要求会被拒绝; 定义工具的插件也可以作为自己工具的提供方。 - 自动层把两条途径合成一个候选集合:同一规范化目录只算一次,来源标注优先 提供方、其次 host:system,只用于显示;不同目录同版本仍报冲突。 - discoveryPlan 对每个工具同时列出 scans 和 providers。 - macOS 环境来源页对只报告安装的提供方显示「只报告已安装的版本」。 同时修复评审的两个 P2: - 符号链接安装在解码时已规范化,解析时却按原始路径查证据而误判 unsafePath; 现在文件证据同时证明其规范化目标,证据互相矛盾时拒绝快照。 - 环境变量候选声明的 path 布局被忽略、总取第一个布局;现在按声明的布局选择。
- Core 新增 toolchains.candidates:列出一个工具的登录 Shell home 变量、扫描到的安装、跳过原因和自动层的选择;和 resolve 共用事实校验,宿主分两轮调用完成版本探测,工作区内的目录在探测前拒绝 - toolchains.discoveryPlan 增加 pathPrepend 模板和各平台适用的 home 变量 - 新增 MacToolchainDiscovery:按插件声明展开扫描,只探测 Core 返回的可执行文件;扫描根、条目、文件事实、安装数、探测数、并发和总时长都有上限,超出时给出诊断 - 运行环境页:全局卡片显示 home 变量和探测到的版本,PATH 命令标为版本未验证;自动卡片列出真实安装、选中项、同版本冲突和跳过数,路径显示扫描到的条目名 - 加载器只把登记在官方目录、并经内置或插件市场安装的插件标为官方来源 - 预览改用完整的样例清单,扫描本机真实安装 - 更新契约 toolchains.md、rust-core-api.md、Agent Note、功能矩阵和中英词条
78e696e to
06337dc
Compare
运行环境、环境来源两页插在项目页和运行配置之间,使 SettingsCategory 声明顺序(搜索结果顺序)与侧栏构建分组顺序不一致, settingsCategoryPlacesProjectAndRunBetweenKeymapAndTerminal 在 CI 失败。 把两页的 case 移到项目页之前,测试改为断言 Keymap 与 Terminal 之间 恰好是构建分组,且分组以项目页、运行配置结尾。
test(macos): 设置页声明顺序与构建分组保持一致(修复 1lck#1581 的 macOS CI)
- Core: lsp.toolchainRequest 与 litheToolchains 协商,原样回传回复交 toolchains.decodeReply - Core: candidates 接受 providerInstallations 并保留提供方归属 - 修复别名链接 home 只有链接路径事实时被判 unsafePath(机器人 P2) - macOS: 启动或复用插件后端查询,全局+逐目录独立 operationID/代次,超时与取消 - macOS: watchFiles 与回复 watch 变化整份重查,短时间事件合并 - 设置页显示提供方要求、版本与查询结果;文案走 shared/i18n - 更新契约、功能矩阵与 Agent Note
feat(plugins): macOS 设置页接入工具链提供方查询 (1lck#1581)
|
按上次的分工,补齐了框架剩下的部分。每一项都在单独分支上做,经 fork 内 PR 合入本分支,当前 head 为
本地验证
还没做到的
框架合入后,我再向 Store 重新提交 mise 的索引 PR。 |
- 每个查询过的目录、每个工具调用一次 toolchains.resolve,摘要、徽标和 “第几层生效”都读它的结果,视图不再自己按固定 → 项目 → 全局 → 自动排序 - 解析与提供方查询共用同一份文件事实;同一轮查询的提供方共享代次, 每次查询仍有独立 operationID - 固定值交给 Core 校验:只有固定值的目录只解析它固定的工具(每次加载 最多 256 个),固定的 home 经 toolchains.candidates 检查后探测, 不会出现在自动检测列表;不可用时终止失败,不回落 - 未安装的项目要求记为 unmet 并退到下一层;Core 无法给出结果时给出诊断 - 已知限制写入提案 Note 并建 Issue:冲突选择与写入 1lck#1639、 项目 wrapper 1lck#1640、PATH 命令 commandHomes 1lck#1641 - 新增文案走 shared/i18n 并重新生成




关联
toolchainSources提交(27852b0)已经从分支上移除。那个提交在 Core 里解析 mise 的版本文件,以及lts、prefix:这类写法;评审时原作者已同意改成「工具定义 / 提供方 / 使用方」三类贡献重做(见 评审讨论)。现在分支基于最新的 preview,共三个提交:框架本身、「两条安装途径 + 评审修复」,以及 macOS 设置页接入声明式扫描。原则
宿主不内置任何工具:Java、Maven、Node 等工具由插件定义,mise、nvm、SDKMAN 这类版本管理器由插件作为提供方接入。Core 只负责校验和按四层解析,不解释任何版本管理器的私有格式。
改动
插件契约(
shared/contracts/plugins/v1/)toolDefinitions: 1(工具定义)和toolchainProviders: 1(提供方声明,需要权限toolchains.provide)。executableResolution增加 v2,只用于工具定义的候选,不改变现有 Build 的候选集合。rust-core-api.md。新增toolchains.md,以及两个 fixture(tool-definition.plugin.json、toolchain-provider.plugin.json)。proposals/toolchains/存放完整方案草案,包括查询协议、local.json、清单贡献和解析结果的 schema 与用例。这些只用于评审,不是可以安装的清单。java、node等)只能由宿主验证过的官方插件定义;<pluginID>:<tool>;toolchains.md新增「Two installation routes」一节):discovery、homeLayouts、version,由宿主展开扫描,不运行插件代码。适合目录结构固定的安装位置。可用的写法固定为三种根(用户目录、环境变量、绝对路径)加单层*通配,以后不再扩充;新的安装形态改由提供方回答,宿主不加新的解析器。toolchainProviders通过toolchains/query返回安装和版本要求,适合注册表、管理器数据库、命令输出这类声明式写法表达不了的位置。watchFiles改为可选。不声明时这个提供方只报告已安装的版本,答复里带版本要求会被拒绝。定义工具的插件也可以同时作为这个工具的提供方,但提供方后端不能依赖它要发现的工具运行。Rust Core(
rust/lithe-core/src/toolchain/)工具链是一个独立的领域。插件清单模块只在准入时调用它做校验。
definitions.rsquery.rspins.rs.lithe/toolchains/local.json的pins,找出最近祖先目录上的固定值resolution.rspaths.rshost:system);多个提供方之间取限定 ID 较小的。这个标注只用于显示,不参与选择。toolchains.discoveryPlan现在对每个工具同时列出scans(要展开的扫描)和providers(声明了该工具的提供方)。toolchains.registry、toolchains.decodeReply、toolchains.resolvePins、toolchains.resolve、toolchains.checkVersion、toolchains.discoveryPlan、toolchains.candidates。它们只处理宿主传入的快照,不启动进程、不扫描目录,也不写文件。toolchains.candidates(第三个提交新增):给设置页用,列出一个工具的全局层和自动层,不解析具体目录。resolve相同(注册表、平台、工作区根、文件事实、probes、systemInstallations、environment等),校验也共用同一段代码(prepare)。{tool, shell, installations, skipped, selected, conflicts}:shell是登录 Shell 里声明过的 home 变量及其版本,installations是通过检查的扫描结果(按版本从高到低、目录已规范化),skipped带稳定的原因码(unsafePath、probeFailed、versionUnsatisfied等),selected是自动层的选择,同版本不同目录时为空并报冲突。probes,可执行文件都报probeFailed;宿主只探测这些可执行文件,再带上{executable, output, exitCode}调第二次。工作区内的目录在探测前就被拒绝,项目里的程序不会被运行。toolchains.discoveryPlan还会带上定义的pathPrepend模板,以及各平台适用的登录 Shell home 变量(environment: [{variable, path}]),宿主不用自己解析可执行文件候选。backend.rs:backend 2 的插件可以由已准入的工具链查询触发启动。unsafePath。现在一条非 missing 的文件证据同时证明它的规范化目标;同一目标的证据互相矛盾时拒绝整个快照。版本探测按解析结果中的规范化可执行文件路径对应。JAVA_HOME)声明的path布局之前被忽略,总是取第一个布局。现在只按声明的布局查找,和 macOS 设置页的行为一致。declarative.rs:清单中的toolDefinitions(最多 32 个)和toolchainProviders(最多 8 个)必须非空,能力声明要精确对应。macOS
watchFiles的提供方显示「只报告已安装的版本」,不检查项目文件。MacLoginShellEnvironment新增只读的inspect,供来源页使用。重新读取只更新缓存和页面显示,不会改变当前进程的PATH。MacToolchainDiscovery):toolchains.discoveryPlan展开三种根(用户目录、环境变量、绝对路径)和单层*通配,跳过隐藏条目,按homeLayouts取第一个匹配的 home,收集文件事实,然后交给toolchains.candidates检查。MacToolchainSettingsLoader)注入扫描器;只有登记在官方插件目录、并通过内置或插件市场安装的插件才标记为官方来源,Core 只对这类插件开放java这样的短 ID。$JAVA_HOME)和探测到的版本;PATH 上找到的命令显示路径,但标为「版本未验证」,不会被运行。卡片太窄时变量和版本自动换成两行。jdk-21.jdk,而不是每个都一样的Contents/Home),悬停显示完整 home。另外还会显示同版本冲突和跳过的数量。--toolchain-settings-demo和--toolchain-sources-demo。预览里只有插件清单是样例(java、maven、node、python 的完整清单,以及 nvm、uv、mise 提供方),工作区文件、固定值、登录 Shell 和本机安装的扫描结果都是真实的。可以用以下参数指定初始状态:--toolchain-demo-directory <目录>--toolchain-demo-expand <工具,…>--toolchain-demo-size <宽>x<高>--toolchain-demo-workspace <路径>文档与其他
2026-10-31-plugin-injected-toolchains.md;在设置层级 Note 里补充这两页属于哪个分组。plugin-injected-toolchains,macOS 和 Windows 都标为 partial / pending;macOS 的证据里加上了声明式扫描和对应的测试。toolchains.md更新状态说明,新增「Settings candidates」一节;rust-core-api.md增加toolchains.candidates一行。Agent Note 补充扫描器的工作方式、上限和设置页的显示方式。尚未完成
以下内容这次都没做,页面上也不显示:
验证
verify-rust-core-comments.sh、verify-rust-core.sh、cargo fmt -p lithe-core --check都通过。toolchain 相关 71 个测试通过,其中新增:watchFiles的提供方只能报告安装;定义插件可以作为自己工具的提供方;toolchains.candidates:第一轮没有探测结果时返回要探测的可执行文件;带上探测结果后列出版本,选择结果和resolve一致;同版本不同目录时报冲突。discoveryPlan带上pathPrepend和各平台的 home 变量。test-stability-macos共 67 个测试,0 个失败,没有超过 1 秒的。MacToolchainDiscoveryTests(新增):用真实的临时目录和真实的 Core,只替换用户目录和探测函数,不运行本机装的任何工具。覆盖:homeLayouts取第一个匹配、隐藏和不匹配的条目不扫描、链接到工作区的条目不探测、只探测 Core 返回的可执行文件、显示扫描到的条目名、同版本冲突、被拒的声明不扫描不探测、通配规则和 Core 一致,以及预览用的样例清单能通过 Core 准入。ToolchainSettingsLoaderTests、ToolchainSettingsFeatureTests、ToolchainSettingsLayoutTestsMacLoginShellEnvironmentTests(13 个)SettingsSearchVocabulary、SettingsSidebarToolchainSettingsLoaderTests新增:只报告安装的提供方会列出、不检查版本文件;watchFiles不是数组时仍然报声明无效。verify-runtime-bundle-immutability.sh、verify-service-boundaries.sh、verify-shared-contracts.shverify-platform-feature-matrix.sh、verify-agent-notes.sh、verify-test-stability.sh/Library/Java)、17.0.19 和 11.0.31(SDKMAN);Node 26.12.1(Homebrew,被选中)和 24.14.0(nvm);全局层$JAVA_HOME为 17.0.19。指向不存在目录的openjdk-*.jdk链接被正确跳过。1180×820 和 1000×760 两种窗口下卡片都不溢出、不折断版本号。