
AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆【免费下载链接】OperitThe most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent项目地址https://gitcode.com/gh_mirrors/op/Operit点击查看免费下载本文是 OperitAndroid AI Agent / AI 聊天应用中Issue 782 主题编辑器草稿系列的收官章节《Verification》的展开版本。文章围绕主题编辑器在目标草稿target draft改造完成后如何进行验证展开覆盖静态检查清单、六组手动回归场景、已完成检查的结论以及当前已知的数据约束重复角色卡名无法唯一识别主题并补充仓库源码级的实现证据与对应路径帮助读者在阅读或复现该改造时建立先静态、后手动、再确认边界的完整验证思路。验证对象一段需要被证明无副作用的编辑器改造在进入检查清单之前需要先明确这段改造到底改了什么。Issue 782 的目标是让主题编辑器只修改编辑器会话editor session中的内存草稿而不是直接改写持久化的角色/分组主题管理器并让一次显式保存动作原子化地落盘。与之配套的还有三条行为约束切换编辑目标默认角色、任意角色卡、任意分组时激活该角色及其已保存主题但不切换、不创建聊天历史WebChat 的主题请求必须从被请求的那个聊天解析目标而不是从当前激活 prompt解析所有路由变更返回键、抽屉、快捷方式、外部路由请求都必须经过统一的路由离开守卫保证脏草稿得到一致的处理。这些改造的源码证据集中体现在ActivePromptManager.kt ——setActivePrompt只切换激活角色不触碰聊天历史ThemeEditorSession.kt —— 屏幕持有的编辑器会话values / baseline / dirty / staged assetsThemeSettingsContentEditor.kt —— 目标切换、保存、丢弃、取消与离开守卫的编排UserPreferencesManager.kt ——replaceThemeForPrompt/resetVisualThemeForPrompt单事务原子替换WebChatHttpBridge.kt —— 从聊天元数据解析主题快照OperitApp.kt —— 统一的路由过渡门。静态检查清单从写路径到路由的六项审查验证文档给出了六项静态检查它们对应六个不同的边界每一条都需要在源码中逐一对号入座1. 检查每一个主题编辑器写路径确保它只改变编辑器会话而不是持久化管理器对应证据ThemeEditorSession.update/setString/setBoolean/setInt/setFloat系列方法只更新内存中的MutableStateFlowThemePreferenceValues并通过deleteUnreferencedStagedAssets同步清理不再被引用的暂存资源ThemeEditorSession.kt。会话直到beginSave被调用前都不会触达UserPreferencesManager真正落盘只发生在 ThemeSettingsContentEditor.kt 的saveCurrentDraft中调用commitThemeDraft/resetThemeDraft之后。2. 检查保存与重置路径确保在异步工作开始前已捕获唯一目标对应证据saveCurrentDraft的第一步就是val target state.target随后才draft.beginSave(savedValues)并启动协程ThemeSettingsContentEditor.kt。而ThemeEditorSession.markSaved会更新baselineValues、清空inFlightSavedValues保证保存成功后脏状态归零ThemeEditorSession.kt。3. 检查实体清理区分目标删除与视觉主题重置对应证据resetVisualThemeForPrompt只调用clearVisualThemeValues清除目标前缀下的视觉键随后writeThemeTargetMetadata仍会写入 AI 头像与自定义聊天标题UserPreferencesManager.kt而删除角色卡/分组走的是独立的deleteThemeByPrefix它会按类型移除全部 string / boolean / int / float 主题键UserPreferencesManager.kt。这正是文档所述重置只改视觉配置、删除则移除该目标全部数据的边界。4. 检查 WebChat 主题与结构化渲染确保从被请求的聊天解析对应证据resolveThemePreferenceSnapshot(chat: ChatHistory?)优先使用聊天的characterGroupId否则用characterCardName查找角色卡最终回退到默认角色卡WebChatHttpBridge.ktresolveStructuredRenderPreferences同样通过该快照解析showThinkingProcess等渲染开关WebChatHttpBridge.kt。5. 检查每个路由变更都经过路由离开守卫对应证据requestRouteTransition在切换前先调用routeBackGuardRegistry.canLeaveRoute(routeInstanceId)并校验routerState.currentEntry.instanceId仍是同一个实例后才执行onAllowed()OperitApp.kt。抽屉、快捷方式、外部路由请求都统一走requestRouteTransition不再只是返回键。6. 仅在显式请求时才运行格式化与构建验证这是流程约束而非代码约束Gradle、lint、单测、构建以及xmllint独立解析均不在默认验证范围内需要明确请求才执行。手动回归场景六组可直接复现的验证步骤验证文档定义了六组手动场景它们是验证清单的运行时版本覆盖了目标激活、草稿隔离、重置边界、WebChat 隔离与路由守卫一致性。下面逐条展开并给出预期结果与代码依据。场景 1切换另一张角色卡确认其角色与已保存主题被激活而当前聊天 ID 不变操作在主题编辑器顶部的目标选择器中选中另一张角色卡。预期setActivePrompt(ActivePrompt.CharacterCard(...))被调用角色卡管理器写入新激活卡并清空激活分组ActivePromptManager.kt但聊天历史不切换。activateTarget中对失败的兜底Toast 提示与editorReloadToken刷新也在 ThemeSettingsContentEditor.kt 中体现。场景 2编辑一个分组切换到其他目标再丢弃确认其已存主题不变操作进入某分组的主题编辑改动若干项使其脏化随后选择另一目标在确认弹窗中选择丢弃。预期ThemeEditorSession.discard()删除暂存资源并把_values恢复为baselineValuesThemeEditorSession.kt持久化层从未被写入原分组主题保持不变。场景 3重置一张角色卡的主题确认其 AI 头像与自定义聊天标题保留操作对某角色卡执行重置。预期resetThemeDraft→resetVisualThemeForPrompt只清除视觉键集合writeThemeTargetMetadata仍把custom_ai_avatar_uri与custom_chat_title写入同一 DataStore 事务UserPreferencesManager.kt。会话侧的reset()同样在defaultVisual()基础上保留这两个元数据键ThemeEditorSession.kt。场景 4请求两个不同 WebChat 主题确认每次响应都携带各自匹配的目标来源与玻璃设置操作在 WebChat 中打开两个分别绑定到不同角色/分组的聊天分别请求GET /chats/{id}/theme。预期每个响应都来自resolveThemePreferenceSnapshot(当前聊天的 ChatHistory)解析出的快照气泡玻璃liquid/water glass与字体开关等字段都映射自同一个快照互不串扰。会话内setBoolean中 liquid/water glass 互斥的规则ThemeEditorSession.kt保证单目标内部也不会出现两种玻璃同时开启。场景 5编辑一个目标后分别通过抽屉、快捷方式、返回键离开确认每种路由变更都等待同一个对话框操作使草稿脏化后分别尝试a抽屉导航、b快捷方式导航、c返回键离开。预期三条路径最终都汇入requestRouteTransition→canLeaveRoute→ 编辑器注册的RegisterRouteBackGuard弹出保存 / 丢弃 / 取消对话框用户选择结果通过exitContinuation.resume(allowNavigation)回传给路由门ThemeSettingsContentEditor.kt。队列机制保证路由请求串行化最新一次外部目标请求在守卫等待期间被保留OperitApp.kt。场景 6编辑一个目标后选择另一个目标验证保存、丢弃、取消各自在目标激活之前完成操作脏草稿下切换目标。预期pendingAction ThemeEditorPendingAction.SelectTarget(target)被挂起finishPendingAction(allowNavigation)只有用户确认后才调用activateTarget若取消则保持当前编辑器目标并重新加载ThemeSettingsContentEditor.kt。同时targetSwitchesInFlight计数保证并发激活请求被串行化避免旧目标在切换中写入新目标。已完成静态检查的结论汇总验证文档记录了改造后已完成的静态检查结果均与上文源码证据一一对应主题控件只读取一个编辑器会话的 values 流并直接同步更新内存草稿目标捕获、暂存资源清理、目标元数据提交与视觉重置的边界均已核实当外部 prompt 在待确认期间变化时目标/会话配对仍保持正确对应ActiveTargetChanged分支并发激活请求保持串行化过期后台失败不会改写前一个目标mutateActiveThemeForPrompt只在getActivePrompt() target时才写重置提交保留 AI 头像与自定义聊天标题元数据WebChat 在构建主题与结构化渲染响应前解析被请求的聊天OperitApp中的路由变更都进入统一离开守卫已移除的管理器形态编辑器 API、重复的 identity 卡片资源与即时保存包装器在源码中已无任何引用git diff --check通过无空白/补丁格式问题。未执行的验证项与适用前提Gradle、lint、单元测试与构建未运行依据验证约定未显式请求验证命令时一概不执行。需要复现构建验证时应显式运行对应 Gradle 任务如./gradlew lint与测试任务并确认环境已按仓库 README.md 的要求配置好 Android SDK 与本地属性参考 local.properties.example。独立 XML 解析未运行环境缺少xmllint因此不执行独立的 XML 校验相关资源合法性由 lint 阶段显式请求时兜底。已知数据约束重复角色卡名的歧义边界验证文档明确记录了一条当前版本必须接受的约束现有聊天绑定存储的是角色卡名称character-card names。重复的名称无法唯一识别一张卡的主题直到专门的聊天 schema 迁移引入稳定的卡 IDcard ID为止。在源码中的对应表现是resolveThemePreferenceSnapshot通过characterCardManager.findCharacterCardByName(cardName)按名称反查角色卡WebChatHttpBridge.kt因此在存在重名卡的聊天上主题解析可能命中第一个匹配项。这一约束同样适用于角色/分组前缀键的读取方UserPreferencesManager的主题快照均以目标前缀为键themePrefixForPrompt前缀本身由稳定的卡 ID / 分组 ID 派生名称歧义只影响从聊天反查卡这一环节。验证与测试中应把重名卡场景标记为已知限制而不是缺陷。验证建议把静态检查固化为回归测试从仓库的测试布局看Android 端测试分布在 app/src/test/java 与 app/src/androidTest/java均为 Kotlin工具包测试另有 tools/test 目录。针对本改造建议在后续显式构建验证时覆盖以下断言replaceThemeForPrompt与resetVisualThemeForPrompt单事务语义先清除视觉键、再写完整草稿/元数据见 UserPreferencesManager.ktThemeEditorSession的 dirty 判定resetRequested || currentValues ! baselineValuesThemeEditorSession.kt路由门canLeaveRoute在同一路由实例上等待守卫结果的语义OperitApp.kt。小结Issue 782 主题编辑器草稿的验证工作可以归纳为一条主线所有写操作先进内存草稿保存/重置/丢弃三个出口分别走单事务落盘或纯内存回滚所有离开路径统一经过路由守卫。静态检查证明代码结构符合这一契约六组手动场景则从用户视角确认了目标激活不换聊天、草稿隔离、重置保元数据、WebChat 按聊天解析与守卫一致性五个核心行为。唯一需要长期跟进的是重名角色卡的主题解析歧义它依赖未来的聊天 schema 迁移引入稳定卡 ID 才能彻底解决——在此之前验证与测试都必须把该场景当作已知约束处理。赞分享AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆【免费下载链接】OperitThe most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent项目地址https://gitcode.com/gh_mirrors/op/Operit点击查看免费下载相关推荐Zvec索引管理指南create_index、drop_index、optimize全流程详解Zvec索引管理指南create_index、drop_index、optimize全流程详解 Zvec 是一款轻量、极速的进程内嵌入式向量数据库其索引向量数据库数据库嵌入式数据库CANN/asc-devkit本地内存异常检测接口CheckLocalMemoryIA\ ISASI\ a nameZH CN_TOPIC_0000001834740621 /a 产品支持情况 !人工智能深度学习算子库CANNAscendReact Router路由守卫实现登录验证和权限检查的终极指南React Router路由守卫实现登录验证和权限检查的终极指南 在现代Web应用开发中 路由守卫 是保护应用安全的重要机制。React Router作为R前端路由上一篇OpenVMM代码覆盖率分析提升测试质量的方法下一篇SciPy 截断帕累托分布 truncpareto数学定义、源码实现与拟合实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考