Repository navigation
feat(logging): 声明式插件由执行方代记插件操作事实 - #1720
Merged
Merged
Conversation
没有插件进程的语言服务器、调试适配器和构建命令来源,以前在 plugins/<id>/host 通道没有任何操作事实,和 SDK 插件不统一。 - Core 新增 diagnostics.recordPluginOperation 与贡献映射表 CONTRIBUTIONS: languageServer/start、debugAdapter/start(ProcessStart)与 lithe/build/model、lithe/build/dependencies(CommandRun),失败阶段统一映射到 host.* 码;非法输入统一 -32064。 - macOS 新增 PluginOperationReporter / PluginOperationAttempt:调试适配器启动、 构建模型与依赖命令由宿主记录;语言服务器启动前失败由宿主记录,之后通过 lsp.startServer.startupOperation 交给 Core 记录唯一结果。 - 取消、停止、过期结果与由插件后端提供的构建计划不记录;从不解析错误文本。 - 修复 RustCoreBridge.LogFailure 按 reason 解码 Core 日志域错误。 - 更新事件目录、fixture、Core API 与插件契约、Agent Note 和功能矩阵。
xiaoyumuxi
marked this pull request as ready for review
November 4, 2026 06:43
This was referenced Nov 4, 2026
xiaoyumuxi
marked this pull request as draft
November 4, 2026 06:43
create-lithe-plugin Skill(#1713)规定,宿主替哪些声明式贡献记录结果,以 shared/logging/README.md 和 shared/logging/events/ 为准。这里在“引擎宿主”一节补上 diagnostics.recordPluginOperation 的语义、当前代记的四种贡献表(operation、声明来源、记录方、可能的失败阶段),以及新增声明式贡献时要同步做的事。
xiaoyumuxi
marked this pull request as ready for review
November 4, 2026 06:51
Lithe 运行验收版本: 对照:共同祖先
未覆盖:
工作副本与运行状态已清理;可复用编译缓存按 12 GiB / 7 天预算保留。 |
- LSP:写 initialize 失败记 launch;被新索引策略淘汰的启动放弃 attempt;handoff 携带 pluginId,只在 LanguageServer 角色且会话 身份缺省或一致时接受;plugin API 1 宿主进程启动的服务器也覆盖; 启动前停止会取消 attempt。 - 构建:计划由插件后端提供时,宿主仍记录 provider 工具解析和计划 失败,发请求前再取消。 - 调试:op 用调试会话 ID;托管适配器按到达阶段记录(端口发现失败 launch、发现截止 timeout、连上后断开才是 exit);Core 拒绝建会话 取消不记录;同步 start 抛错即使任务已取消也记失败。 - 调试日志适配器段改用 identity_segment,与插件事实同一映射。 - diagnostics.recordPluginOperation 拒绝可选字段显式 null(-32064)。 - 同步契约、事件目录说明和 Agent Note。
xiaoyumuxi
added a commit
to Mucheen/Lithe-IDEA
that referenced
this pull request
Nov 4, 2026
Resolve the outputPlan conflict with 1lck#1720 plugin operation stages, and record the run's own model load in runTask as a buildModel attempt so captureOutput receives one. Keep the Windows host working after the macOS-only split: an IDE host that sends no toolExposure on open now serves the whole catalog (the preview behavior) instead of being refused, while macOS keeps declaring and enforcing its selection. Contracts updated accordingly.
This was referenced Nov 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概要
纯声明式插件(Go、PHP、LLDB、Gradle 等只在
plugin.json里声明语言服务器、调试适配器或构建命令、没有自己后端进程的插件)以前在结构化日志 v2 里没有任何插件操作事实:它们不能发lithe/log,所以plugins/<id>/host通道是空的,和 Database、Docker、HTTP Client、Cargo、SVN、Maven、Lua 这些 SDK 插件不统一。本 PR 让实际执行声明工作的一方(macOS 宿主或 Core 引擎)替插件写同一组
plugins.operation.finished/plugins.operation.failed事件,写到同一个plugins/<id>/host通道。声明式插件不需要写任何日志代码。只做 macOS 与 Core;Windows 仍是 v1,不在本 PR 范围内。
设计:一个通用结构 + 一张贡献映射表
rust/lithe-core/src/diagnostics/plugin_operations.rs:DeclarativeOperation(插件 ID、贡献、失败阶段、耗时、可选 op)。CONTRIBUTIONS,每行只有操作名和生命周期:languageServer/startlanguageServers[]ProcessStartdebugAdapter/startdebugAdapters[]ProcessStartlithe/build/modelbuildSystems[].model命令来源CommandRunlithe/build/dependenciesbuildSystems[].dependencies命令来源CommandRunhost.*码”表,同一个码在所有贡献里只有一个含义:planhost.planFailedresolvehost.executableUnavailablehost.executableUnavailablelaunchhost.launchFailedhost.launchFailedinitializehost.initializeFailedtimeouthost.timedOuthost.timedOutexithost.exitedEarlyhost.commandFaileddecodehost.outputInvaliddiagnostics.recordPluginOperation:{pluginId,operation,outcome,stage?,durationMs,operationId?},deny_unknown_fields,返回data:{result:{}};任何非法输入(未知操作、生命周期到不了的阶段、finished带 stage、failed缺 stage、非法 op、超范围耗时、多余字段、可选字段显式写null)统一返回新错误码 -32064 Invalid host plugin operation(一码一义,不回显被拒值)。channel.rs抽出identity_segment/digest_segment,宿主代记与 SDK 路径、引擎身份路由共用同一映射,同一插件只会落到同一个通道。谁执行,谁记录
DebugTransportFailed等记录对得上。MacPluginDebugAdapterTransport在解析出命令、即将start时推进到launch,适配器可达后推进到initialize:stdio 进程跑起来即可达;语言服务器托管的适配器要等 socket 连上(Core 传输层第一次进入 ready)才可达,之前端口发现失败记launch,发现截止时间到记timeout。会话进入 ready 记成功;只有可达过的适配器断开才记exit;同步start抛错一律记失败(即使调用方任务已取消);Core 拒绝建会话(如父会话已结束)是宿主结果,取消不记录;用户停止记为取消,不记录。BuildSystemService在 plan / resolve / launch / timeout / exit / decode 处推进阶段。若构建计划实际由插件后端(provider)提供,宿主先记录自己负责的 provider 工具解析(resolve)和计划(plan)失败,请求发给后端前取消自己的 attempt,之后由 SDK 记录,避免重复。结果过期(被新请求取代、输入已变)算取消,不记录。lsp.startServer.startupOperation:{pluginId,operationId,elapsedMs}把 attempt 交给 Core。pluginId放在 handoff 里,因为 API 1 会话本身没有插件身份;会话有身份但与 handoff 不一致时 Core 忽略该 handoff。Core 在 spawn 失败或写 initialize 失败(launch)、初始化前退出(exit)、握手失败(initialize)、初始化超时(timeout)或initialize成功时记录唯一结果,耗时 = 宿主已用 + Core 计时。停止、取消、被新索引策略淘汰的启动都不记录;宿主在启动前停止服务器会取消 attempt,后续启动不会误记。PluginOperationReporter/PluginOperationAttempt(LitheModuleAPI/Logging):第一次终态生效;end(throwing:)遇到CancellationError或任务已取消时按取消处理;handOff()结束宿主侧 attempt 并返回交接数据。其他改动
RustCoreBridge.LogFailure的字段名:Core 日志域错误返回的是{code,reason},旧结构按message解码会导致域错误解析失败。shared/logging/events/plugins.json更新plugin/operation/duration/code字段说明以覆盖声明式代记,重新生成catalog_generated.rs。shared/fixtures/diagnostics/engine-logging-v2.json增加hostOperations:diagnostics.recordPluginOperation输入到事件、通道和host.*码的对照样例(Go 语言服务器、LLDB 调试适配器、Gradle 构建模型)。shared/contracts/rust-core-api.md记录命令、两张表、交接语义与 -32064;shared/contracts/plugins/v1/README.md的日志一节说明声明式插件会得到哪些事实和码。shared/logging/README.md的“引擎宿主”一节列出宿主当前代记的四种声明式贡献(operation、声明来源、记录方、可能的失败阶段),以及新增声明式贡献时要同步做的事。docs(skills): 新增 create-lithe-plugin Skill,规定插件日志接线 #1713 的create-lithe-pluginSkill 规定以这里为准查询“宿主替哪些声明式贡献记录结果”。2026-11-03-structured-logging-channels.md新增“声明式插件:由执行方代记同一组操作事实”,并记录被否方案(单独的监听服务进程、每贡献一个事件或封闭大枚举、解析错误消息判断阶段)。diagnostics-export.json补证据和验证说明;Windows 仍为 missing。评审修复(/code-review)
采纳并修复:
initialize失败现在记launch(原先漏记);被新索引策略淘汰的启动放弃 attempt,不再误记失败;handoff 只在 LanguageServer 角色、且会话pluginId缺省或与 handoff 一致时接受。pluginId;宿主在启动前停止服务器会取消 attempt,后续启动不会误记。resolve)与计划(plan)失败,发请求前才取消 attempt,交给 SDK 记录。launch、发现截止timeout、socket 连上后断开才是exit;stdio 进程跑起来即算可达。start抛错即使调用方任务已取消也记失败。identity_segment,同一 ID 只落一个通道(删掉重复的debug_log_adapter)。diagnostics.recordPluginOperation的可选字段显式写null返回 -32064。经核实未改:
end(throwing:)把Task.isCancelled当取消处理,不会误记。MacServiceContainer始终注入 reporter 的记录函数。create_session总是从Initializing开始,重启一定会经过状态变化。验证
本地(macOS,已 rebase 到 preview 9e1a270):
cargo test --manifest-path rust/Cargo.toml -p lithe-core --lib:1733 通过,0 失败(含plugin_operations的映射表、阶段→码、-32064 拒绝(含显式null)、通道路由测试,以及 LSP 引擎交接、写initialize失败、被索引策略淘汰、身份不一致的交接测试)。DebugModuleTests、LitheLanguageIntelligenceModuleTests、LanguageServerStatusTests、RustLanguageServerLaunchTests、JavaLanguageServerRuntimeTests、DiagnosticsWorkflowTests、CorePayloadDecodingTests、RunConfigurationIntegrationTests、RealJavaDebugIntegrationTests:3 个测试二进制分别 162 / 46 / 162 个通过。PluginDebugAdapterTests、TCPDebugAdapterTests、MacNativeProviderDebugIntegrationTests、BuildSystemServiceTests、PluginLanguageServerLaunchResolverTests、MacBuildProviderSessionsTests、LanguageExtensionProcessLifecycleTests、MacLogStoreTests、LanguageFeatureProviderTests:125 + 86 个通过。./.agents/skills/write-stable-tests/scripts/test-stability-macos.sh -- --filter '<本 PR 新增的 24 个测试>':通过,24 个测试均有单独计时。最慢的是stoppedDeclarativeModelCommandRecordsNothing(534 ms),因为要用 500 ms 的有界窗口证明停止后不会补记,和同文件已有的“不会发布”断言写法一致;其余都在 0.1 s 以内(托管适配器三种结局共 42 ms)。test-stability: allow(swift-unbounded-wait)并写明上界来源,没有真实 sleep。verify-test-stability.sh、generate-log-events.mjs --check、verify-log-usage.mjs、verify-agent-notes.sh、verify-shared-contracts.sh、verify-service-boundaries.sh、verify-platform-feature-matrix.sh、verify-rust-core-comments.sh、verify-windows-boundaries.sh、verify-app-language-localization.mjs、generate-i18n.mjs --check:全部通过。cargo fmt --check仍会报 preview 上已有的格式差异(lithe-agent-host/src/claude_desktop.rs、lithe-core/src/git/mod.rs、dispatcher.rs的两个 Git 命令分支),本 PR 没有动这些代码。未做:完整 macOS 测试套件;在真实应用里用 Go/PHP/LLDB/Gradle 插件逐个查看日志窗口的插件通道。
合并后需要做的
shared/contracts/plugins/v1/README.md,合并后需要在 lithe-plugin-docs 运行node scripts/contract.mjs sync --revision <合并后的 preview commit>并提交。plugin_function.rs等),SDK 无需改动。配套插件 PR(README 改为说明宿主代记的操作与码)
限制
CoreDebugAdapterProtocolSession里,和该会话已有的初始化截止时间、DebugTransportFailed记录在同一层。按“通用逻辑进 Rust Core”的规则,后续应把整个调试启动生命周期(截止时间、传输失败事实、attempt)一起迁到 Core,像 LSP 一样在建会话时交接;只迁 attempt 会把同一个生命周期拆到两层。