资讯动态

Roo Code 3.3.23 补丁深度解析:设置页未保存更改保护与自定义指令文件读取的错误处理

发布时间:2026/9/13 10:34:26 来源:尧图企业网站定制
Roo Code 3.3.23 补丁深度解析设置页未保存更改保护与自定义指令文件读取的错误处理【免费下载链接】Roo-CodeRoo Code gives you a whole dev team of AI agents in your code editor.项目地址: https://gitcode.com/GitHub_Trending/ro/Roo-CodeRoo Code 3.3.23 是一个聚焦于设置管理与指令加载稳定性的补丁版本发布于 2025-02-20集中修复了两类影响日常使用体验的问题设置页面存在未保存更改时点击 Done 的行为异常以及从规则文件读取自定义指令时错误处理不够优雅的问题。本文以该版本的官方发布说明为核心结合仓库中的实现源码与测试用例逐层拆解这两处修复背后的机制、涉及的配置项与验证方式帮助开发者理解设置页变更检测的工作原理以及自定义指令文件的加载链路。版本概览3.3.23 是 3.3.x 系列中紧接 3.3.22 的一个补丁发布。在 CHANGELOG.md 中本次发布记录了两条修复项与发布说明完全对应## [3.3.23] - 2025-02-20 - Handle errors more gracefully when reading custom instructions from files (thanks joemanley201!) - Bug fix to hitting Done on settings page with unsaved changes (thanks System233!)从发布节奏看它位于 3.3.22引入Provider Settings 配置界面增加明确的保存按钮与未保存更改警告与 3.3.24 之间可以视为对设置界面相关功能的一次稳定性收尾。整个修复范围可以概括为两个主题设置页未保存更改保护解决在设置页面修改了配置但未保存时点击 Done 无法正确处理变更的问题自定义指令文件读取的健壮性解决从磁盘读取自定义指令/规则文件时对异常情况的容错问题。下文分别展开。修复一设置页点击 Done 时的未保存更改保护问题场景Roo Code 的设置页是一个包含 Provider、Modes、Skills、Slash Commands、Auto-Approve、MCP、Checkpoints、Notifications、Prompts 等多个分区的单页界面用户可以在多个 Tab 之间切换后统一保存。3.3.23 修复的问题场景是当用户在设置页修改了某些配置此时尚未保存直接点击 Done完成按钮时页面应当正确处理这些未保存的更改——要么弹出确认对话框让用户决定是否放弃要么正常完成流程而不是出现异常或静默丢失状态。变更检测机制的实现该修复的核心逻辑位于 webview-ui/src/components/settings/SettingsView.tsx。整个设置页通过一个isChangeDetected状态来跟踪是否存在未保存更改const [isDiscardDialogShow, setDiscardDialogShow] useState(false) const [isChangeDetected, setChangeDetected] useState(false)页面中每个配置项的 setter 都遵循同一模式只有当新值与当前值不同时才将setChangeDetected(true)避免把没有实际变化的赋值误判为一次更改。例如语言、Debug 开关、图像生成 Provider 等的更新回调都是如此const setDebug useCallback((debug: boolean) { setCachedState((prevState) { if (prevState.debug debug) { return prevState } setChangeDetected(true) return { ...prevState, debug } }) }, [])值得一提的是3.3.23 的修复还覆盖了一个边界场景空字符串不应被当作一次更改。这一点在测试用例 SettingsView.change-detection.spec.tsx 中有明确验证verifies the fix: empty string should not be treated as a change。也就是说用户清空又恢复某个字段或某些自动初始化的字段从空值变为空值不应触发未保存更改的弹窗。点击 Done 时的守卫流程Done 操作通过useImperativeHandle暴露给父组件调用的checkUnsaveChanges方法完成守卫。SettingsViewRef接口定义了该方法export interface SettingsViewRef { checkUnsaveChanges: (then: () void) void }其实现为如果检测到未保存更改就把后续要执行的动作暂存到confirmDialogHandler.current并弹出确认对话框否则直接执行该动作const checkUnsaveChanges useCallback( (then: () void) { if (isChangeDetected) { confirmDialogHandler.current then setDiscardDialogShow(true) } else { then() } }, [isChangeDetected], )当用户在弹出的对话框中做出选择时由onConfirmDialogResult处理const onConfirmDialogResult useCallback( (confirm: boolean) { if (confirm) { // Discard changes: Reset state and flag setCachedState(extensionState) // Revert to original state setChangeDetected(false) // Reset change flag confirmDialogHandler.current?.() // Execute the pending action } // If confirm is false (Cancel), do nothing, dialog closes automatically }, [extensionState], )这里有两个关键细节放弃更改确认后先将cachedState还原为扩展原始的extensionState丢弃用户在设置页上做的所有修改再重置变更标记最后才执行被暂存的动作取消操作选择取消则什么都不做对话框自动关闭用户在设置页上的编辑内容得以保留。对话框的本地化文案弹窗文案通过 i18n 管理在 webview-ui/src/i18n/locales/en/settings.json 中的定义为unsavedChangesDialog: { title: Unsaved Changes, description: Do you want to discard changes and continue?, cancelButton: Cancel, discardButton: Discard changes }对话框组件本身使用 UI 库的AlertDialog实现并渲染在设置页底部SettingsView.tsx第 919-930 行附近由isDiscardDialogShow控制显隐。测试验证仓库中为该机制提供了多组测试覆盖了修复前后的关键行为测试用例位置验证内容点击 Done 且存在未保存更改时显示对话框SettingsView.spec.tsx修改配置后点击 Done出现settings:unsavedChangesDialog.title用户做出实际更改后显示对话框SettingsView.unsaved-changes.spec.tsx真实修改触发弹窗未做任何更改时不显示对话框SettingsView.change-detection.spec.tsx无变更时onDone直接被调用空字符串不算更改SettingsView.change-detection.spec.tsx验证 3.3.23 的边界修复这些测试共同保证了变更检测只在真实修改发生时触发从而避免自动初始化、空值回写等场景弹出误导性的未保存提示。修复二从文件读取自定义指令时的优雅错误处理问题场景Roo Code 支持通过多种来源向系统提示词注入用户自定义指令Prompts 标签页中的文本框、全局规则目录~/.roo/rules/、工作区规则.roo/rules/、模式专属规则.roo/rules-{modeSlug}/以及AGENTS.md、.roorules、.clinerules等规则文件。3.3.23 修复的问题场景是当读取这些文件时如果遇到文件不存在或路径是一个目录等常规磁盘情况Roo Code 不应抛出未处理异常导致整个提示词组装流程中断而应静默跳过并继续。safeReadFile修复的核心该修复的核心体现在 src/core/prompts/sections/custom-instructions.ts 中的safeReadFile函数/** * Safely read a file and return its trimmed content */ async function safeReadFile(filePath: string): Promisestring { try { const content await fs.readFile(filePath, utf-8) return content.trim() } catch (err) { const errorCode (err as NodeJS.ErrnoException).code if (!errorCode || ![ENOENT, EISDIR].includes(errorCode)) { throw err } return } }关键逻辑在于 catch 分支ENOENT文件不存在与EISDIR路径是目录而非文件被视为可预期的常规情况函数返回空字符串上层逻辑据此判定没有可用内容并回退到其他来源除此之外的异常如EACCES权限拒绝、EIO磁盘错误等仍然原样抛出避免掩盖真实故障。这一区分可预期错误与真实错误的处理方式正是发布说明中 Handled errors more gracefully 的具体落地。规则目录的递归读取与容错readTextFilesFromDirectory负责递归读取规则目录中的全部文本文件它的设计同样体现了健壮性通过fs.readdir(dirPath, { withFileTypes: true, recursive: true })递归枚举条目对每个条目调用resolveDirectoryEntry普通文件直接收集符号链接通过resolveSymLink解析目标支持链接到文件、目录乃至嵌套符号链接并设置MAX_DEPTH 5的递归深度上限以杜绝循环链接死循环在读取每个文件前用shouldIncludeRuleFile过滤缓存与系统文件排除.DS_Store、*.bak、*.cache、*.db、*.log、*.tmp、*.swp、Thumbs.db等模式完整列表见 custom-instructions.ts所有异步读取通过Promise.all并发执行单个文件读取失败时只返回null被过滤掉不会中断整体流程最终按文件名不区分大小写进行字母序排序保证同一批规则每次以一致的顺序注入系统提示词。规则加载链路与回退顺序loadRuleFilescustom-instructions.ts展示了通用规则的完整加载链路依次检查全局与工作区的.roo/rules/目录若启用enableSubfolderRules还会递归发现子目录中带.roo的规则目录目录中有内容则直接采用若上述目录均无内容回退到工作区根目录的.roorules再回退到.clinerules兼容旧项目。模式专属规则.roo/rules-{modeSlug}/目录回退到.roorules-{modeSlug}与.clinerules-{modeSlug}文件、AGENTS.md/AGENT.md/AGENTS.local.md通过loadAllAgentRulesFiles加载可通过roo-cline.useAgentRules设置关闭遵循同样的目录优先、文件回退、静默跳过缺失文件的原则。最终所有这些内容由addCustomInstructions汇总进系统提示词形成固定的注入格式分隔的 USERS CUSTOM INSTRUCTIONS 区块完整格式示例参见 apps/docs/docs/features/custom-instructions.md。也就是说3.3.23 的容错修复保障的是这条链路上每一环的稳定执行任何一个可选规则文件缺失或损坏都不应影响整体提示词的成功组装。用户侧的自定义指令来源汇总结合官方特性文档 apps/docs/docs/features/custom-instructions.md 与上述源码3.3.23 版本下用户可用的自定义指令来源包括来源全局所有项目工作区当前项目Prompts 标签页文本全局指令 / 各模式的模式指令跟随模式是否为全局而定通用规则目录~/.roo/rules/.roo/rules/模式专属规则目录~/.roo/rules-{modeSlug}/.roo/rules-{modeSlug}/旧式单文件回退—.roorules、.clinerules、.roorules-{modeSlug}Agent 规则—AGENTS.md回退AGENT.md另有AGENTS.local.md加载顺序为全局规则优先、工作区规则在后冲突时工作区优先每一层级内模式专属规则先于通用规则目录方式存在内容时优先于单文件回退。customInstructions消息经 src/core/webview/webviewMessageHandler.ts 分发最终由 ClineProvider.updateCustomInstructions 写入全局状态并刷新 WebviewPrompts 标签页的修改即通过这一链路生效。相关测试src/core/prompts/tests目录下的测试覆盖了指令组装行为包括add-custom-instructions.spec.ts验证addCustomInstructions对各来源内容的组装与顺序sections.spec.ts、system-prompt.spec.ts验证系统提示词最终是否包含用户自定义指令区块。这些测试与safeReadFile的容错逻辑一起确保了读取自定义指令文件这一功能在异常环境下仍能平稳降级。如何验证本次修复对于普通用户升级到 3.3.23 后可以通过以下方式快速验证两个修复未保存更改保护打开设置页随意修改任一配置如切换语言或修改某个开关在不保存的情况下直接点击 Done应弹出 Unsaved Changes 对话框选择 Discard changes 后设置被还原并退出选择 Cancel 则继续停留在设置页保留修改指令文件容错在工作区根目录放置一个空的.roorules文件或让某个AGENTS.md指向一个无效路径然后发起一次任务系统提示词组装不应报错其他规则来源的内容仍正常注入。若从源码构建或参与贡献可以直接运行webview-ui下SettingsView相关测试如SettingsView.unsaved-changes.spec.tsx与src/core/prompts下的指令组装测试来回归验证这两处行为。小结Roo Code 3.3.23 虽是一个小型补丁版本但其两处修复分别对应了两类典型的稳定性问题一类是交互层——设置页的变更检测与退出守卫通过isChangeDetected状态机、checkUnsaveChanges暂存回调与确认对话框保证了未保存更改不会被静默丢弃另一类是IO 层——规则文件读取的容错通过safeReadFile区分ENOENT/EISDIR等可预期错误并静默跳过配合符号链接解析、深度限制与缓存文件过滤让自定义指令的加载链路在任何磁盘状态下都能稳定运行。理解这两处修复的实现也有助于开发者更安全地使用规则目录组织团队级与个人级指令。【免费下载链接】Roo-CodeRoo Code gives you a whole dev team of AI agents in your code editor.项目地址: https://gitcode.com/GitHub_Trending/ro/Roo-Code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价