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
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