Skip to content

feat(plugins): 独立编辑器高亮与动作 API,复用普通函数调用 - #1617

Merged
xiaoyumuxi merged 6 commits into
previewfrom
feat/570-plugin-grammar-run-markers
Oct 31, 2026
Merged

xiaoyumuxi merged 6 commits into
previewfrom
feat/570-plugin-grammar-run-markers

Conversation

@xiaoyumuxi

@xiaoyumuxi xiaoyumuxi commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

概述

重写本 PR 的插件编辑器接入方案:普通工具插件可以独立贡献高亮、编辑配置和文本位置动作,不要求实现 LSP、Build、Run、Test 或 Debug Provider。

原方案的 runMarkers[] / requires.runMarkers 和 commands/didRun.runMarker 已移除。 点击位置动作复用既有插件函数调用,原命令通知与领域协议保持不变。

Refs #570;原 Issue 的 Windows 产品能力不由本 PR 完成。

设计边界与评审依据

  • 功能领域契约用于统一同一领域的事实和流程,不是所有插件的强制入口。播放图标只是展示,不代表接入 Run 工作流。
  • 独立扩展点有自己的最小类型化输入输出、权限和生命周期;身份、会话、JSON-RPC、超时、取消和进度继续复用基础设施。
  • HTTP/SQL 解析与执行属于插件;宿主只理解范围、标题、图标和函数绑定,不按工具名、配置格式、固定任务 ID 或私有错误码特判。
  • 真正参与原生 Build/Test/Debug 的插件仍使用对应统一模型,不能用私有函数绕过领域校验。
  • 总结并引用维护者在 #1581 的方案评论、#1581 后续评论、#1558 的正式评审 中提出的边界。

功能点

1. 独立的静态高亮与编辑配置

  • 保留 languages:2 的包内 Monarch grammar 和注释、括号、自动配对配置,不需要语言服务器、后端或激活事件;仅配置贡献也生效。
  • 静态编辑器模块参与启用、停用和隔离;纯静态贡献可即时安装、撤回,不抢占已有语言的服务器、运行和调试所有权。
  • Rust Core 校验语法大小、状态、规则、动作等,并拒绝 include 环与展开后超出 4096 条规则的语法。
  • 插件正则仅在可终止 worker 中编译和执行,不运行在编辑器 UI 主线程;本地期限超时后停止并保留普通文本编辑。
  • 复用当前工作树生成的 textmate-worker.js 和固定 Monaco 引擎;不新增下载,不把“项目还没有 TextMate/WASM”当作选型前提。
  • 有界、只读读取包内文件;改进拒绝结果缓存、配置变更身份、活跃扩展名匹配和语言别名身份;撤回释放 tokenizer/configuration。

2. 独立 editor/registerActions 宿主 API

  • 在函数协议 3 内增量增加 lithe/host/editor/registerActions,通过 getCapabilities 发现,不提高顶层 pluginAPIVersion 或函数协议版本。
  • 需要 backend:2、documents.read 和明确的 editor.actions 权限;新增中英权限说明。旧宿主不认识新权限时明确拒绝,不能宣称同一包无条件降级。
  • 后端注册上下文、文件名/扩展名选择器和已注册的收集函数;返回既有 subscriptionID,使用原订阅释放机制。
  • 注册只记录绑定,稍后才收集,避免宿主处理注册请求时反向调用等待中的后端。
  • 收集函数接收公开 documentID、contentVersion、相对路径和当前脏缓冲,不再使用 WebView 桥接 revision 作为公开文档版本。
  • 返回 {actions:[{id,range,title,icon,invoke:{functionID,params}}]}。共享 Core 校验一基 UTF-16 范围、代理对边界、重复 ID、数量及字节预算;HTTP/SQL 业务数据保持不透明。
  • 同一行的多个动作共用菜单,不静默覆盖;点击只传宿主生成的批次与动作键,不能由编辑器伪造函数或业务参数。
  • 宿主在点击时重新检查文档版本、上下文、注册租约和同插件会话函数,再通过普通 invocation 执行。原 commands/didRun {commandID,context?} 不变。

3. 生命周期、安全与独立后端

  • 编辑立即撤销旧动作并取消旧收集,防抖后重新解析;拒绝旧文档、改名、关闭或已撤回贡献的迟到结果。
  • 收集与用户执行任务分开管理:重新解析不误停用户操作;注册/会话/上下文撤销、文档关闭和编辑器销毁时取消所属任务,不自动重试副作用。
  • 只读预览不收集/执行动作;明确限制文档大小、动作数量、注册数量与并发执行。
  • 没有 UI 的工具后端获得独立的应用级启用模块,能通过真实插件 catalog 接纳,不需要虚构网页或 LSP 模块;停用、安全模式与隔离可阻止启动。
  • 语法、tokens、注册租约和动作列表均为内存状态。发行目录与插件包只读,更新资源复用排除清单、拒绝路由、回归测试和 docs/ci-builds.md。

4. Skill、契约和文档

  • develop-lithe 新增“同领域统一模型,不把独立能力硬塞进领域”,审查规则同步检查工具名特判、封闭格式枚举、固定 ID、第二工具复用和临时迁移退出条件。
  • 新增中文架构决策,修正旧笔记中过宽的“宿主理解就是领域能力”判断,更新静态贡献热激活说明。
  • 同步正式 README/schema/fixture、Core 命令文档、实施计划、中英词条和生成结果。
  • 功能矩阵拆为 plugin-editor-grammars 与 plugin-editor-actions,分别描述可独立验收的能力;未做的 Windows 与完整产品验收没有标为通过。

验证

  • Rust Core 逐项计时:1458 项通过。
  • Swift 相关 suite 逐项计时:69 项通过;使用固定 Swift 6.3.3 与本机 SDK 26.5。默认 SDK 27.2 与该工具链不兼容,未调整仓库工具链要求。
  • 共享编辑器:38 项通过。
  • 真实 WebKit workbench 集成:116 项通过,新增 worker 高亮、编辑保持、同一行多动作、明确点击、过期批次菜单拒绝场景。
  • 在 lithe-plugin-docs 运行官方 node scripts/sdk-e2e.mjs --source <本地工作树> --ref <精确验证快照>:Node、Java、Rust 示例 E2E 全部通过;未修改 SDK 源码或直接改契约副本。
  • 新模块严格 TypeScript 检查通过;完整 workbench 与未修改基线均为 55 条既有诊断,无新增诊断;不宣称全量 typecheck 无错误。
  • Core fixture verifier、契约、服务/编辑器/Windows 静态边界、Rust 注释/布局/格式、i18n 35 项、资源复用 28 项、Skill、184 篇笔记和 228 项矩阵校验通过。
  • 推送前对精确 base/head 运行矩阵变更门禁与矩阵验证、bundle 只读和 i18n 检查。最终源码树与已验证改写 a75cb52a4 逐字节相同。
  • 测试/预览/SDK 后端进程已清理;未运行 Windows 原生构建或完整安装验收。

已知边界与后续

  • 仅 macOS 接线;Windows 产品实现缺失。
  • 后端仍按启动登记,安装需要重启;第一版复用 onWorkspaceOpen,未实现按文件懒启动或后端热安装。
  • 位置动作暂不服务远程工作区或只读预览;快照上限 128 KiB。
  • 插件高亮的 worker 路径对超过 128 Ki UTF-16 单位或 10,000 行的文档保持普通文本;嵌入语言暂按普通文本处理。
  • 仍需打包后安装真实工具插件的完整产品与界面验收,矩阵保持 partial/pending。
  • 合并后在 lithe-plugin-docs 用最终 preview commit 执行 node scripts/contract.mjs sync --revision <commit> 并提交;对外使用指南与 SDK helper 属于该仓库,不在这里另存 SDK。

提交说明

本次保留 PR 原提交及其 preview 合并历史,合入重写后的已验证源码,不强推、不恢复旧 runMarker 方案。保留当前 ready 状态,没有反复 push 触发完整 CI。

- languages 2:插件语言可带 Monarch 语法和编辑器配置,Core 校验,纯语法插件免重启
- runMarkers 1:backend 2 插件函数回答可运行行,编辑器画运行按钮,点击经 commands/didRun 带 runMarker
- 契约、fixture、Agent Note、计划文档与功能矩阵同步更新;Windows 暂不支持

Refs #570
@ghfind-review ghfind-review Bot added the review: medium ghfind author score; see https://ghfind.com label Oct 31, 2026
@xiaoyumuxi
xiaoyumuxi marked this pull request as ready for review October 31, 2026 04:35
@lithe-code-review

lithe-code-review Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Lithe Review

结论: ⛔ 有阻塞
范围: preview ← feat/570-plugin-grammar-run-markers · head: 4a38fcd

Findings

  1. [P1] 将新贡献接入语言模块归属校验,否则示例插件无法加载

    macos/Sources/LitheCoreContracts/Plugins/DeclarativePluginContracts.swift:815

    • 实际影响:本次两个示例插件都无法通过 macOS 插件接纳流程,高亮和运行标记不会生效。
    • 触发条件:语言只贡献 grammar 或 backend/UI/runMarkers,没有语言服务器、执行或调试模块。
    • 复现路径:用新增的 language-grammar.plugin.json 或 run-markers.plugin.json 构造 descriptor,再交给 ValidatedPluginCatalog。LanguageSupportDeclaration.moduleIDs 仍只收集 server/execution/testing/debug 四类模块,因此为空;PluginManifestValidator.swift:255 明确拒绝空列表。MacPluginStartupLoader.accept 和实时注册表都会经过该校验。现有新测试直接注入 package,绕过了接纳流程。
    • 来源:本次引入。
  2. [P1] 运行标记使用公开文档版本,而非桥接 revision

    macos/Sources/Lithe/Platform/MacOS/MonacoWorkbenchEditor.swift:1285

    • 实际影响:按新契约通过 documents/getSnapshot 检查版本的插件,会把当前运行标记误判为过期,拒绝执行。
    • 触发条件:插件比较 Provider 参数或 commands/didRun.runMarker.version 与公开文档快照的版本。
    • 复现路径:打开未编辑的新文档,桥接 register 将 revision 初始化为 0,而 EditorDocument.contentVersion 初始为 1;EditorDocumentService.swift:179 返回后者。这里发送 0,点击时第 1331 行再次发送桥接 revision。两者也不能简单加一换算,因为批量编辑和编辑器重新登记会使计数进一步分离。
    • 来源:本次引入。
  3. [P2] 保留 Provider 的原始语言 ID

    frontend/editor/src/workbench.ts:225

    • 实际影响:使用语言别名的合法 Provider 不会收到请求,也不会显示运行按钮。
    • 触发条件:插件语言 ID 与 Monaco 着色 ID 不同,例如 properties → ini 或 bash → shell。
    • 复现路径:安装声明 properties、语言服务器及运行标记的插件,打开其文件。macOS 激活载荷只传文件名;languageForFilename 返回 Monaco 注册 ID,entry.languageID 因此是 ini,而 pluginRunMarkerLanguages 保存的是 properties。这里匹配失败;语法注册同样经过了 toMonacoLanguageId,无法保留原始身份。
    • 来源:本次引入。
  4. [P2] 新请求和文档关闭时应取消旧 Provider 调用

    macos/Sources/Lithe/Platform/MacOS/MonacoWorkbenchEditor.swift:1295

    • 实际影响:旧版本请求持续占用后端执行资源,关闭文档后也会继续运行至返回或超时。
    • 触发条件:Provider 响应较慢,用户持续编辑,每次停顿超过 180 ms。
    • 复现路径:让 Provider 延迟数秒返回,连续修改文档。宿主每次只替换请求 UUID,并创建未保存句柄的 Task;旧调用没有收到取消。返回后的 UUID 校验只丢弃结果。底层 LanguageServerSession.invokeFunction 已支持通过 Task 取消传播操作取消,但此处未使用。
    • 来源:本次引入。

Scope Check

  • [Feature] 支持.http文件,实现发送http/https请求 #570 的 Windows HTTP 客户端尚未实现;本 PR 是前置 API,不能视为完成该 Issue。
  • 本次覆盖语法、运行标记、点击通知、契约、测试、笔记和矩阵;Windows 与真机验收明确留待后续。
  • 复用了 Monaco Monarch、现有运行按钮和插件函数协议,未发现新增平行语言语义引擎。
  • 四项 Finding 均由本次新增行为触发,属于当前改动职责范围;前两项阻塞合并,后两项为非阻塞建议。

Suggestions

  1. 为语法和运行标记补齐明确的语言贡献归属,并同步接纳校验;增加两个 fixture 经过真实启动加载器及实时注册表的测试。
  2. 单独保存 Provider 计算时的 document.contentVersion,在请求和点击通知中使用;桥接 revision 继续用于编辑器同步。覆盖初始文档、批量编辑和重新登记。
  3. 将插件语言身份与 Monaco 着色 ID 分开传递和匹配,覆盖别名语言及没有 grammar 的自定义语言。
  4. 按文档持有请求 Task,在编辑、新请求、Provider 撤回和关闭时取消;用可控 Provider 验证取消传播与清理。

另外,请补充本次高亮及运行按钮的界面截图,已有界面提供前后对比;合并前提供两个官方 SDK 的 sdk-e2e 结果,合并后按约定同步契约副本。

Summary

共享校验与平台适配的边界清晰,但真实插件加载链和公开文档版本存在阻塞问题。当前测试主要覆盖解析与直接注入的贡献集合,尚未覆盖这些完整用户路径。

Verification

  • 静态检查了指定范围内全部 43 个变更文件,并追踪插件接纳、语言归属、文档快照、Monaco 语言识别和函数取消调用链。
  • PR 正文报告 Rust 158、编辑器 39、Swift 53 项测试通过,以及契约、i18n、笔记、稳定性、矩阵和 bundle 不变性检查通过;这些结果未在本次独立复核。
  • 已提供的 head Check Run 中,Rust、Swift 和插件测试为 skipped;平台 gate 成功不能替代这些测试的实际执行结果。
  • 本次严格只读,未运行仓库代码、测试或检查脚本,未访问网络或发布评论。
  • 尚缺真机验收、当前改动截图及 SDK E2E 结果;视觉效果未验证。Issue 中的参考图片不构成本 PR 的界面验证证据。

- languages 2 提供静态语法和独立编辑配置,插件正则在可终止 worker 中运行\n- editor/registerActions 运行期注册文本动作,点击复用普通函数调用,不扩张 Run/LSP/Build/Debug 领域契约\n- 补齐文档版本、动作租约、取消与清理、独立工具后端启用及安全模式边界\n- 更新 Skill、审查规则与决策笔记,总结 #1581/#1558 的架构边界\n- 同步契约、fixtures、中英词条、功能矩阵与资源复用说明\n\nRefs #570\nReworks #1617
保留 PR 原实现及 preview 合并历史;最终源码沿用已通过本地验证的 a75cb52,不恢复 runMarkers 专用协议。
@xiaoyumuxi xiaoyumuxi changed the title feat(plugins): 声明式语法高亮与运行标记(API-25/27/29) feat(plugins): 独立编辑器高亮与动作 API,复用普通函数调用 Oct 31, 2026
区分包内静态 JSON 贡献与尚未开放的运行期 Provider 注册、替换和释放;说明独立语义 Provider、新引擎适配及平台、SDK 和验收限制。同步计划、架构笔记、正式契约与功能矩阵。
动作刷新立即确认调度并隔离非致命失败,整批收集共享八秒期限并在撤销时清理计时任务。

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
@xiaoyumuxi
xiaoyumuxi merged commit e2e7f5c into preview Oct 31, 2026
9 of 17 checks passed
1lck added a commit that referenced this pull request Nov 1, 2026
* feat(workspace): enforce directory indexing exclusions (#958)

* fix(workspace): honor indexing ownership across Windows roots

Fix attached-root LSP gates and reevaluate documents when workspace roots change. Carry request-local ownership through inventory, search, replacement and incremental index caches; preserve scoped search when unrelated roots are unavailable.

Disable unsupported remote indexing settings, localize settings failures, normalize both Java exclusion test expectations, and register regressions in Windows CI.

* fix(workspace): 修复索引租约生命周期与跨窗口同步

* docs(workspace): 记录复审修复与 macOS 原生验收证据

* fix(lsp): 保留 Windows 冷启动索引策略的原生路径身份

* fix(macos): 保持打开身份并修复索引回归验证

将会话打开代次与资源投影代次分开,保留立即 Run 的等待意图及同根重开隔离。
避免无待确认 Java 决策时重复发布空值,并使设置与混合规则夹具等待真实生命周期边界。
为 Git 观察 CI 补齐逐项报告,按原始输出活性检测 Swift 停顿,保留既有断言与预算。
记录通过的 126 条受影响 Swift 及 116 条身份消费者验证。

* feat(plugins): 独立编辑器高亮与动作 API,复用普通函数调用 (#1617)

* 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

* fix(indexing): preserve scan ownership and snapshot publication

Retry current-workspace indexing cancellation without retiring another owner, publish only the latest complete inventory, and restore saved sessions once per workspace. Apply scoped search before caps and cursors, preserve dotted provider configuration siblings, and normalize Windows mark identity and localized read failures.

* docs(indexing): record final macOS native acceptance evidence

* fix(search): localize indexing failures and synchronize deferred Run tests

* test(macos): synchronize every initial Run inventory release

* fix: preserve excluded history and validate indexing marks

* fix(macos): 修复分支列表悬停长分支名时触控板无法滚动 (#1621) (#1625)

* fix(macos): 修复分支列表悬停长分支名时触控板无法滚动 (#1621)

触控板手势绑定在开始时的窗口上。悬停扩展面板收到首个滚动事件就关闭,
导致同一手势的后续事件全部丢失。手势期间改为隐藏面板并继续转发给列表,
手势结束后再关闭。鼠标滚轮行为不变。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(matrix): 记录分支列表触控板滚动的验证要求 (#1621)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(macos): 手指停顿时保留滚动手势,点击立即回收隐藏面板 (#1621)

手势进行中的回收超时从 1 秒放宽到 10 秒,避免停顿后继续滚动时丢失手势。
隐藏面板收到点击时立即回收,并在功能矩阵补充对应验收步骤。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(macos): remove push dialog file request ordering race

---------

Co-authored-by: ZJUSCODE <ZengJun326@outlook.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Yao Jingxi <23722032@bjtu.edu.cn>

* fix(macos): forward hidden branch expansion clicks and clean up on close (#1629)

* fix(workspace): preserve directory roles and indexing watcher ownership

* test(windows): use canonical roots in indexing lifecycle fixtures

* test(windows): identify the owned Run fixture descendant explicitly

* feat(macos): 状态栏内存只显示图标,帧率去掉图标并收紧间距 (#1630)

- 内存指示器只保留内存芯片图标,不再常驻显示“总计 / Lithe”数值;
  悬停提示仍给出总计、Lithe、LSP、服务内存,点击打开原有的托管内存详情,
  VoiceOver 读出“托管内存”和当前总计。
- 帧率只显示“60 FPS”文字,去掉速度表图标。
- 新增 18pt 的状态栏紧凑图标按钮样式,只读锁和内存图标改用它,
  不再沿用 28pt 工具窗口按钮留出的大块空白。
- 删除不再使用的 "Total %@" 词条并重新生成本地化资源。
- 更新 memory-monitor 功能矩阵的 macOS 证据与验收说明。

* fix(macos): 虚拟化后台服务退出列表并补充滚动性能规范 (#1627) (#1633)

* fix(macos): virtualize background service exit selection (#1627)

* fix(macos): keep background service accessibility selection live

* fix(agent): 修复 Codex 会话启动与历史漏查,新增供应商筛选 (#1632)

* fix(agent): restore Codex history and add provider filtering

* fix(agent): honor manual archive collapse under provider filters

* feat(macos): 彩色 LSP 状态菜单与普通日志标签页 (#1631)

* feat(macos): 增加彩色 LSP 状态菜单与普通日志标签页

* fix(macos): LSP 入口常驻并仅由启用插件注入服务器

* fix(lsp): 等待重启关闭完成并保留局部索引重置状态

* fix(markdown): preserve inline HTML image layout and alignment (#1623) (#1635)

* feat(markdown): render PlantUML diagrams offline on macOS (#1637)

* feat(markdown): add offline chemistry formulas and subscripts on macOS (#1636)

* feat(macos): 终端标签任意拖拽分屏并保留 PTY (#1638)

* feat(macos): 终端标签任意拖拽分屏并保留 PTY

- 终端标签改用 AppKit 拖拽会话与私有 pasteboard,避免 Monaco 接收文本拖放
- 工具窗终端可拖入编辑器边缘或空编辑器,编辑器终端可拖回工具窗
- 抽出 EditorGroupLayout.splitting 复用分屏几何,补充模型、拖拽与 PTY 测试

Refs #1622

* fix(macos): preserve terminal drop order and deduplicate split previews

- Limit the native tool-window drop overlay to the canvas so tab-strip
  before/after insertion remains available for terminals dragged from editors.
- Publish editor-group preview targets only when they change, including
  repeated clearing and drag lifecycle cleanup.
- Add focused native overlay geometry and preview publication regressions.
- Update the docking Agent Note and terminal capability matrix evidence and
  verification steps without claiming unperformed runtime verification.

Validation: six focused Swift tests passed on Swift 6.3.3 with macOS 26.5 SDK;
runtime bundle, architecture, i18n, Agent Notes and matrix static gates passed.
The exact PR-based push tree also passed the static gates.

Refs #1638

---------

Co-authored-by: Yao Jingxi <23722032@bjtu.edu.cn>

* fix: align project JDK, isolate application sessions, and improve search (#1642) [skip ci]

Use the selected project JDK in JDT configuration on both platforms. Give Windows applications independent cancellable sessions across Run, IDE API and Debug, with isolated failure output. Avoid blocking cold file/text search on content index warmup and improve macOS search sizing and result layout. Include shared fixtures, regression coverage and architecture notes.

* feat(plugins): 插件注入的工具链框架与 macOS 只读环境设置页 (#1581)

* feat(plugins): 插件注入的工具链框架与 macOS 只读环境设置页 (#1581)

按 #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 #1514

* feat(plugins): 工具链安装同时支持声明式扫描与提供方查询 (#1581)

工具的已安装版本有两条途径,可以只用其一或同时使用:
- 声明式扫描:工具定义的 discovery/homeLayouts/version 由宿主展开,不运行
  插件代码;可用的根和通配写法固定,新的安装形态交给提供方回答。
- 提供方查询:toolchainProviders 通过 toolchains/query 返回安装和要求。

- watchFiles 改为可选:不声明的提供方只报告安装,答复里带版本要求会被拒绝;
  定义工具的插件也可以作为自己工具的提供方。
- 自动层把两条途径合成一个候选集合:同一规范化目录只算一次,来源标注优先
  提供方、其次 host:system,只用于显示;不同目录同版本仍报冲突。
- discoveryPlan 对每个工具同时列出 scans 和 providers。
- macOS 环境来源页对只报告安装的提供方显示「只报告已安装的版本」。

同时修复评审的两个 P2:
- 符号链接安装在解码时已规范化,解析时却按原始路径查证据而误判 unsafePath;
  现在文件证据同时证明其规范化目标,证据互相矛盾时拒绝快照。
- 环境变量候选声明的 path 布局被忽略、总取第一个布局;现在按声明的布局选择。

* feat(plugins): macOS 设置页接入声明式扫描与版本探测 (#1581)

- Core 新增 toolchains.candidates:列出一个工具的登录 Shell home 变量、扫描到的安装、跳过原因和自动层的选择;和 resolve 共用事实校验,宿主分两轮调用完成版本探测,工作区内的目录在探测前拒绝
- toolchains.discoveryPlan 增加 pathPrepend 模板和各平台适用的 home 变量
- 新增 MacToolchainDiscovery:按插件声明展开扫描,只探测 Core 返回的可执行文件;扫描根、条目、文件事实、安装数、探测数、并发和总时长都有上限,超出时给出诊断
- 运行环境页:全局卡片显示 home 变量和探测到的版本,PATH 命令标为版本未验证;自动卡片列出真实安装、选中项、同版本冲突和跳过数,路径显示扫描到的条目名
- 加载器只把登记在官方目录、并经内置或插件市场安装的插件标为官方来源
- 预览改用完整的样例清单,扫描本机真实安装
- 更新契约 toolchains.md、rust-core-api.md、Agent Note、功能矩阵和中英词条

* test(macos): 设置页声明顺序与构建分组保持一致 (#1581)

运行环境、环境来源两页插在项目页和运行配置之间,使 SettingsCategory
声明顺序(搜索结果顺序)与侧栏构建分组顺序不一致,
settingsCategoryPlacesProjectAndRunBetweenKeymapAndTerminal 在 CI 失败。
把两页的 case 移到项目页之前,测试改为断言 Keymap 与 Terminal 之间
恰好是构建分组,且分组以项目页、运行配置结尾。

* feat(plugins): macOS 设置页接入工具链提供方查询 (#1581)

- Core: lsp.toolchainRequest 与 litheToolchains 协商,原样回传回复交 toolchains.decodeReply
- Core: candidates 接受 providerInstallations 并保留提供方归属
- 修复别名链接 home 只有链接路径事实时被判 unsafePath(机器人 P2)
- macOS: 启动或复用插件后端查询,全局+逐目录独立 operationID/代次,超时与取消
- macOS: watchFiles 与回复 watch 变化整份重查,短时间事件合并
- 设置页显示提供方要求、版本与查询结果;文案走 shared/i18n
- 更新契约、功能矩阵与 Agent Note

* feat(plugins): 运行环境页每行生效来源改由 Core toolchains.resolve 决定 (#1581)

- 每个查询过的目录、每个工具调用一次 toolchains.resolve,摘要、徽标和
  “第几层生效”都读它的结果,视图不再自己按固定 → 项目 → 全局 → 自动排序
- 解析与提供方查询共用同一份文件事实;同一轮查询的提供方共享代次,
  每次查询仍有独立 operationID
- 固定值交给 Core 校验:只有固定值的目录只解析它固定的工具(每次加载
  最多 256 个),固定的 home 经 toolchains.candidates 检查后探测,
  不会出现在自动检测列表;不可用时终止失败,不回落
- 未安装的项目要求记为 unmet 并退到下一层;Core 无法给出结果时给出诊断
- 已知限制写入提案 Note 并建 Issue:冲突选择与写入 #1639、
  项目 wrapper #1640、PATH 命令 commandHomes #1641
- 新增文案走 shared/i18n 并重新生成

* fix(plugins): 加载途中 context 变化的回复不再显示项目要求 (#1581)

- 同一目录一轮查询里,context 与本轮不一致的提供方回复不会进入 toolchains.resolve,
  但它的项目要求仍被写进页面的 requirements,导致页面显示的要求和 Core 的生效结果来自
  两个不同的 context;现在只记录进入本轮的回复的项目要求,全局要求和安装列表不变。
- 新增 aReplyUnderAChangedContextIsLeftOutOfItsDirectory 测试:两个提供方在加载途中拿到
  不同代次的 context,断言只有进入本轮的提供方要求被显示、Core 用它解析;修复前该测试失败。
- 测试夹具 providerSource 支持声明多个提供方,原有用例行为不变。
- Agent Note 更正“每个路径只读一次”的说法:查询阶段和解析阶段分两次读取事实,单次解析
  内部一致;并补充 context 变化时回复不进本轮的取舍。

* feat(plugins): 提供方超时或不可用交给 Core 记为 providerUnavailable,工具行区分未响应与不可用 (#1581)

- Core 新增 toolchains.failureReply:查询超过 15 秒没有回复,或后端起不来、断开、没有协商这个提供方时,宿主用它生成标准错误回复(plugin.toolchain.timeout / plugin.toolchain.providerUnavailable),再交给 decodeReply,错误码映射只在 Core 维护一份
- toolchains.resolve 只为问过这个工具的查询记 providerUnavailable,并带上 cause 区分超时和不可用;修复一个提供方失败时把它没被问到的工具也记为缺失的问题
- macOS 接线层把 Core 的 requestTimeout 转成 MacToolchainDiscovery.QueryTimeout;取消不生成回复
- 这类回复照常进入目录轮次,下一层来源继续决定;提供方状态显示“15 秒内未响应”或后端原因
- 运行环境页工具行在结果旁写出“mise 未响应 / mise 不可用”,第 2 步在版本文件存在但提供方没回答时显示同样原因,不再显示“版本未查询”;固定值失效时不显示
- 新增中英词条三条;契约 toolchains.md、rust-core-api.md、Agent Note 与功能矩阵同步更新
- 测试:Rust 覆盖两种原因的回复往返、下一层决定、只记被问到的工具、非法输入拒绝;Swift 覆盖超时与后端停止两种提供方并存时的结果与状态

---------

Co-authored-by: Yao Jingxi <23722032@bjtu.edu.cn>
Co-authored-by: FxRayHughes <25192142+FxRayHughes@users.noreply.github.com>

---------

Co-authored-by: Xiaoyumuxi <23722032@bjtu.edu.cn>
Co-authored-by: ZJUSCODE <152275506+ZJUSCODE@users.noreply.github.com>
Co-authored-by: ZJUSCODE <ZengJun326@outlook.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: 十二翼堕落天使 <61737634+icefery@users.noreply.github.com>
Co-authored-by: Lichenkang <2188718831@qq.com>
Co-authored-by: 枫溪 <bushuaichen@yeah.net>
Co-authored-by: FxRayHughes <25192142+FxRayHughes@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review: medium ghfind author score; see https://ghfind.com

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant