资讯详情

JetBrains 插件回滚功能加固实践:快照感知的消息提示、代码去重与端到端测试闭环

📅 2026/9/10 21:13:53 | 华诺云谱 👁 阅读
JetBrains 插件回滚功能加固实践:快照感知的消息提示、代码去重与端到端测试闭环
JetBrains 插件回滚功能加固实践快照感知的消息提示、代码去重与端到端测试闭环【免费下载链接】kilocodeKilo is the all-in-one agentic engineering platform. Build, ship, and iterate faster with the most popular open source coding agent.项目地址: https://gitcode.com/GitHub_Trending/ki/kilocode本指南围绕 Kilo 开源仓库中 JetBrains 插件packages/kilo-jetbrains/的回滚/重做Rollback/Redo功能加固计划展开系统讲解如何在快照被禁用时向用户准确传达仅回滚了会话、未改动文件这一语义并通过代码去重、测试补全与 AGENTS 一致性清理收拢质量缺口。读完本文你将掌握回滚功能的完整调用链前端按钮 → Controller → CLI RPC → SessionUpdated 事件 → Banner 渲染、SessionRevertDto.snapshot的判空信号用法以及一套可落地的 Kotlin/JetBrains 测试与埋点实践。回滚功能现状与加固目标JetBrains 插件已具备按消息回滚Revert与重做Redo能力完整调用链如下用户点击每条消息上的 Rollback 按钮位于MessageToolbar/MessageViewSessionController.revert()先中止忙碌中的回合busy turn再向 CLI 发起POST /session/:id/revertCLI 写入回滚标记revert marker并广播SessionUpdated事件前端SessionModel.setRevert()更新模型RevertBanner展示回滚信息并隐藏被回滚的消息redo()/redoAll()分别驱动/session/:id/revert定位到下一条用户消息与/session/:id/unrevert清除回滚标记。该计划的核心动机是填补四个质量缺口快照语义未传达当服务端因快照被禁用config.snapshot false、非 git 工作区或 ACP 场景而未恢复文件时回滚实际只回退了会话历史但用户界面上没有明确提示后端 DTO 映射存在重复代码KiloBackendSessionManager中有两个几乎一致的revertDto(...)重载测试覆盖不足模型层、控制器层、Banner 接线、前后端契约与 JSON 序列化均缺少针对性用例AGENTS 一致性欠账存在未使用的 bundle key、冗余的透明面板标记以及用户行为埋点缺口。全部改动限定在packages/kilo-jetbrains/内不涉及共享的packages/opencode/代码因此无需引入kilocode_change标记。关键信号SessionRevertDto.snapshot判空即仅历史回滚计划选定的可靠信号来自共享 DTO SessionDto.ktSerializable data class SessionRevertDto( val messageID: String, val partID: String? null, val snapshot: String? null, val diff: String? null, val diffs: ListDiffFileDto emptyList(), )规则简单且可靠snapshot恰好为null时说明服务端没有恢复任何文件快照被禁用、非 git 工作区或 ACP 场景。此时diff/diffs也为空Banner 本就渲染不出文件行。该字段已经过解析并随SessionModel.revert()到达前端因此无需新增任何 API 或共享代码改动即可用model.revert()?.snapshot null判定仅历史回滚。这是贯穿整个计划的基础信号。已确定的设计决策计划明确锁定了四项决策避免在实现中反复摇摆不隐藏、不禁用 Rollback 按钮即使快照关闭。这与 VS Code 行为对齐保持仅历史回滚可用只补充提示文案通过model.revert()?.snapshot null检测文件未恢复不引入新配置或新 API在RevertBanner中用独立本地化文案提示仅在snapshot null时显示在回滚前主动告警需将config.snapshot/vcs暴露给前端超出本期范围明确不做。Phase 1沟通仅历史回滚快照禁用时的用户提示新增本地化文案在 KiloBundle.properties 的revert.banner.*键族旁新增revert.banner.filesNotRestoredSnapshots are off - only the conversation was reverted; your files were not changed.同时必须在所有翻译文件KiloBundle_*.properties中同步该键暂无翻译时复制英文原文与既有revert.banner.*键的播种方式一致确保任何语言包都不会缺键。当前仓库的实际状态印证了这条路径KiloBundle.properties第 77 行已存在该键且KiloBundle_ar.properties、KiloBundle_bs.properties、KiloBundle_da.properties等翻译包中也已同步存在。Banner 中的提示标签在 RevertBanner.kt 中提示标签作为保留字段retainedJBLabel创建一次字体与hint一致JBFont.small()并追加到body中hint之后private val notice JBLabel(KiloBundle.message(revert.banner.filesNotRestored)).apply { font JBFont.small() }在update()中完成revert计算后按信号切换可见性对应源码 L123notice.isVisible revert.snapshot null配色走主题 API在applyStyle()中随hint.foreground一起重估不硬编码颜色当前实现用SessionUiStyle.Text.Secondary.foreground()与次级提示保持一致。原有空 diff 不显示文件行的行为保持不变——提示标签只是补齐缺失的信息而非增加 UI 元素对应resolveDiffs的逻辑L180-L181snapshot null时返回空列表。顺带清理body、files两个Stack上冗余的isOpaque falseStack本身即无背景色面板。Phase 2关闭revertDto代码重复KiloBackendSessionManager.kt 中针对SessionRevert与GlobalSessionRevert两个模型类型存在重复的revertDto(...)映射逻辑。计划要求将其收敛为一个私有辅助函数映射四个字段messageID、partID、snapshot、diffprivate fun revertDto(messageID: String?, partID: String?, snapshot: String?, diff: String?): SessionRevertDto? // messageID 为 null 时返回 null两个调用点各自从模型类型提取字段后复用这是一次纯重构行为保持不变由既有的KiloBackendSessionManagerTest解析断言兜底。从当前源码看仓库已演进为私有四参数辅助函数 面向通用形状的反射兜底的结构说明该去重方向与计划一致。Phase 3填补测试与端到端空白前端模型层测试SessionModelTest.kt针对revertedCount()与isRevertedMessage()补充直接模型测试构造u1,a1,u2,a2四段条目标记位于u1时revertedCount()为 2、位于u2时为 1、标记 id 不存在时为 0isRevertedMessage()对标记消息及其之后的消息返回 true对之前返回 falsesnapshot为 null 的标记仍应得到非零的revertedCount()仅历史回滚场景。前端控制器层测试TurnLifecycleTest.kt 或新增RevertFlowTest.kt使用prompted()基座验证控制器逻辑redo()回滚到下一条用户消息种子u1,a1,u2,a2标记置于u1edt { m.redo() }后 flush断言rpc.reverts最后一次调用目标为u2在最后一条用户消息上redo()应调用 unrevert标记置于u2断言记录了rpc.unreverts且没有新的 revert 调用redoAll()调用 unrevert断言rpc.unreverts包含(ses_test,/test)unrevert()通过 RPC 清除标记断言rpc.unreverts被填充。这些断言依赖 FakeSessionRpcApi已跟踪rpc.reverts与rpc.unreverts和SessionControllerTestBase。Banner → 控制器接线测试SessionMessageListPanelTest.kt按钮点击触发控制器构造RevertBanner(model, redo { redo }, redoAll { all })设置标记后点击 Redo 按钮并断言 lambda 触发revertedCount 1时同样验证 Redo All仅历史回滚提示标记使用SessionRevertDto(u1, snapshot null)断言revert.banner.filesNotRestored标签可见且无文件行快照存在场景标记使用snapshot snap1断言提示标签隐藏。测试通过components(banner)读取组件完成断言。完整前端端到端经SessionControllerTestBase的RevertFlowTest用例种子多轮会话edt { m.revert(userMsgId) }后 flush断言忙碌中止顺序与rpc.revertsemit(SessionUpdated(..., revert SessionRevertDto(userMsgId, snapshot s1)))后断言model.isRevertedMessage(userMsgId)为 true 且回滚视图隐藏通过m.redoAll()驱动emit(SessionUpdated(..., revert null))后断言消息恢复isRevertedMessage为 false且标记清除全部复用既有emit/flush辅助函数不使用超时等待。后端 HTTP 契约测试MockCliServer 扩展MockCliServer.kt既有/session/ses_*正则均为全匹配不会误捕/revert后缀故新增用例安全新增lastRevertPath、lastRevertBody、lastUnrevertPath、lastUnrevertBody四个Volatile var ... : String? null捕获字段在summarize/prompt_async用例旁新增两个 POST 分支bare.matches(Regex(/session/ses_[^/]/revert))与bare.matches(Regex(/session/ses_[^/]/unrevert))分别存储 pathbody 后以respond(output, 200, sessionCreate)响应。ChatManager 测试KiloBackendChatManagerTest.kt镜像既有compact posts summarize request测试的写法revert posts messageID and partID to revert endpoint调用chat.revert(ses_abc, /test/project, msg1, prt1)断言requestCount(/session/ses_abc/revert) 1、路径以/session/ses_abc/revert?directory开头、body 为{messageID:msg1,partID:prt1}revert omits partID when nullbody 为{messageID:msg1}unrevert posts empty body to unrevert endpointbody 为{}且断言路径前缀。对应实现位于 KiloBackendChatManager.kt 的revert/unrevert以及 RPC 入口 KiloSessionRpcApiImpl.kt。CLI JSON 序列化测试KiloCliDataParserTest.kt针对 KiloCliDataParser.kt 的buildRevertJsonbuildRevertJson(m1, null) {messageID:m1}buildRevertJson(m1, p1) {messageID:m1,partID:p1}转义测试id 含引号/反斜杠时被 JSON 转义复用解析器的escape。Phase 4AGENTS 一致性清理移除无用 bundle key删除KiloBundle.properties及各翻译包中的revert.disabled.agentBusygrep 证实 Kotlin 代码中无任何引用。若团队想对齐 VS Code可将其作为 Rollback 按钮的禁用态 tooltip 接入但推荐的低风险动作是直接删除——因为 JetBrains 插件刻意采用中止忙碌回合而非禁用按钮的策略。从当前仓库 bundle 文件看revert.*键族仅剩revert.banner.*系列印证了清理方向清理冗余透明标记移除RevertBanner.kt中body、files两个Stack上冗余的isOpaque false根BorderLayoutPanel的isOpaque false仅在确实覆盖会话表面时保留否则一并移除使用默认值补充用户行为埋点在 SessionController.kt 的revert()成功路径sessions.revert之后调用capture(Session Rollback, sessionProps(id))当前源码 L527 已落地redo()/redoAll()/unrevert()分别位于 L653、L677、L727对应打点Session Redo/Session Redo All。事件命名与既有约定保持一致不携带 PII。范围外事项将config.snapshot/vcs暴露给前端以在回滚前主动告警改变RevertBanner.files的保留 vs 重建策略低频更新维持现状可接受将synchronizeFromDisk中的全项目ACTION_SYNCHRONIZE替换为作用域化 VFS 刷新仅在出现性能问题时再考虑除既有共享 i18n 字符串外的任何 VS Code webview 一致性改动。验证方式在packages/kilo-jetbrains/下执行./gradlew typecheck # 编译全部 Kotlin含生成的客户端 ./gradlew test # 运行前端 后端测试套件需 Java 21仅当 Gradle 报 Java 错误时才排查 Java 版本迭代期间可定向运行受影响的测试类TurnLifecycleTest/RevertFlowTest、SessionMessageListPanelTest、SessionModelTest、KiloBackendChatManagerTest、KiloCliDataParserTest。可选手动冒烟./gradlew runIde在非 git 目录或snapshot: false触发回滚确认 Banner 显示文件未更改提示且无文件行在 git 仓库中触发回滚确认提示隐藏且出现文件行。Changeset 与执行顺序新增.changeset/slug.mdkilocode/kilo-jetbrains: patch描述面向用户的变化例如Clarify in JetBrains rollback that only the conversation was reverted when snapshots are disabled.。纯测试与重构任务无需各自建立 changeset。建议执行顺序Phase 3 的后端测试9–11与模型测试5相互独立可先行落地以锁定行为随后是 Phase 1 的用户可见提示及其 Banner 测试7最后是 Phase 2 重构、Phase 4 清理、控制器测试6、8与 changeset。【免费下载链接】kilocodeKilo is the all-in-one agentic engineering platform. Build, ship, and iterate faster with the most popular open source coding agent.项目地址: https://gitcode.com/GitHub_Trending/ki/kilocode创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。