首页/新闻资讯/正文详情

Operit 会话破坏性删除与中断收尾的协调:丢弃式取消如何阻止消息写入已删会话

发布时间:2026/9/27 21:47:40 来源:云帆数科 栏目:资讯中心
Operit 会话破坏性删除与中断收尾的协调:丢弃式取消如何阻止消息写入已删会话
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点击查看免费下载导读本文围绕 Operit 中中断回合统计修复issue 741的第二个子问题展开当用户在 Web 端删除一个仍在流式输出的会话时如何保证取消任务先结束、会话删除后执行避免中断收尾把部分消息写入已被删除的数据库会话。文章会从 02-coordinate-destructive-delete.md 这份实现纪要出发结合MessageProcessingDelegate、WebChatHttpBridge与ChatServiceCore的真实源码讲清楚普通取消与丢弃式取消的语义差异、同步等待再删除的调用链以及对应的单元测试与验收标准。一、问题背景为什么取消和删除会打架1.1 上游问题中断回合的统计丢失在进入破坏性删除话题之前需要先了解它的上游背景。根据 issue-741 主文档中断回合统计原本存在一个根本性缺陷取消模型输出之前消息处理层已经读取了当前 Token 与耗时快照取消任务结束之后收尾逻辑会重新从 Room 加载消息并通过只存在于内存中的contentStream字段去查找流式消息但 Room 不持久化contentStreamChatMessage.kt 中该字段被明确注释为不需要序列化因为它是暂时性的重载后查找必然无法命中导致部分回复、Token、耗时和完成时间全部丢失。修复思路是由每个会话的运行态对象持有当前可持久化的流式 AI 消息取消操作在终止任务前取得该消息引用任务停止后直接完成并持久化同一条消息不再从持久化模型反推运行态身份。1.2 本文问题删除活动会话时的竞态02-coordinate-destructive-delete.md 记录的则是这个修复引出的第二个问题——协调删除会话与取消旧实现Web 接口发现目标会话仍在输出时会异步请求取消并立即删除数据库会话。中断收尾开始写入部分消息后这两个操作可能交错造成消息写入已删除会话。也就是说在旧流程里取消是异步发起的fire-and-forget取消收尾把部分回复、Token 快照写回数据库和DELETE语句可能并发执行。一旦删除先落地收尾写入就会指向一个已经不存在的会话行产生脏写或写入失败。二、修复方案先同步丢弃式取消再执行删除文档给出的修正非常明确修正Web 删除接口等待总结与消息处理完成丢弃式取消再执行会话删除。丢弃式取消不持久化部分回复。关键语义有二等待等待取消真正结束——不是异步发请求而是同步阻塞到取消协程全部 join 完成丢弃式不持久化部分回复——既然会话马上要整体删除把半截回复写回数据库毫无意义收尾直接放弃。下面分别看这两点在源码里是如何落实的。三、丢弃式取消的实现cancelMessageForDestructiveMutation3.1 与普通取消的分叉点MessageProcessingDelegate对外暴露了两条取消路径二者共用同一个内部实现仅通过keepPartialResponse参数区分普通取消cancelMessage(chatId)用户手动停止输出keepPartialResponse true保留部分回复并写回统计快照丢弃式取消cancelMessageForDestructiveMutation(chatId)破坏性变更前的取消keepPartialResponse false不持久化任何部分回复。核心实现位于 MessageProcessingDelegate.ktsuspend fun cancelMessageForDestructiveMutation(chatId: String) { cancelMessageInternal(chatId, keepPartialResponse false) }在cancelMessageInternal内部keepPartialResponse直接决定两个动作val activeTurn if (keepPartialResponse) chatRuntime.activeStreamingTurn else null val cancellationSnapshot if (keepPartialResponse) readCurrentTurnCancellationSnapshot(chatId) else null当keepPartialResponse false时activeTurn与cancellationSnapshot均为 null取消流程只做三件事通过AIMessageManager.cancelOperation(chatId)向底层 AI 服务发出取消对sendJob、stateCollectionJob、streamCollectionJob逐个cancel()并join()等待其真正结束在finally中清理运行态置空sendJob/responseStream/activeStreamingTurn/currentTurnOptions重置requestSentAt、requestStartElapsed、firstResponseElapsed并把isLoading置为false、输入状态恢复Idle。注意第 2 步的join()正是等待取消结束的语义来源——cancelMessageInternal整体被cancellationMutex保护删除流程在拿到返回值之前所有流收集与状态收集协程都已被确认停止。3.2 对比普通取消的保留路径不受删除影响而普通取消keepPartialResponse true在join()之后还会走detachStreamingAiMessage把部分内容与统计快照写回数据库if (activeTurn ! null) { detachStreamingAiMessage( chatId chatId, activeTurn activeTurn, snapshot cancellationSnapshot, ) }这正是文档验收标准第二条中断统计的普通保存路径不参与破坏性删除的落点两条路径在keepPartialResponse处分叉丢弃式删除绝不会触发detachStreamingAiMessage因此统计保存逻辑与删除操作在代码层面就是互斥的不存在交错可能。四、中断收尾的运行态持有为什么必须用activeStreamingTurn4.1 Room 不保存contentStream修复的关键约束在 ChatRuntime 的注释里写得非常直白// 取消收尾必须持有运行态对象Room 不保存 contentStream重载后无法识别当前流消息。 var activeStreamingTurn: ActiveStreamingTurn? null,ActiveStreamingTurn持有两部分数据private data class ActiveStreamingTurn( val message: ChatMessage, val segmentedMessages: MutableListChatMessage? null, )message当前正在流式输出的 AI 消息持有contentStream共享流引用segmentedMessagesWaifu 模式下已经形成的分段消息列表用于中断时给每段补齐同样的回合统计。ChatRuntime以chatId为 key 存放在chatRuntimes: ConcurrentHashMap中activeStreamingTurn在每次sendUserMessage创建流时写入MessageProcessingDelegate.kt在取消收尾或回合结束后清理。4.2 中断消息的完成与指标快照detachStreamingAiMessageMessageProcessingDelegate.kt是普通取消路径的收尾函数它做四件事resolveFinalContent从contentStream的replayCache或TextStreamEventCarrier事件通道中拼出最终内容内存中的流引用是唯一数据来源completeInterruptedMessage生成完成态消息——套用统计快照、把content设为最终内容、清空contentStream、写入completedAt通过sentAt回匹配用户消息把 Token/耗时指标同步到用户消息上withTurnMetricsWaifu 模式下把同一组指标复制给每一段已发出的分段消息。统计快照TurnCancellationSnapshotMessageProcessingDelegate.kt包含六个字段字段含义inputTokens取消时刻的输入 Token 数outputTokens取消时刻的输出 Token 数cachedInputTokens缓存命中 Token 数sentAt请求发出时间outputDurationMs从首个响应块到取消时刻的输出耗时waitDurationMs从请求发出到首个响应块的等待耗时其中两个耗时由运行态时间戳推算waitDurationMs firstResponseElapsed - requestStartElapsedoutputDurationMs messageTimingNow() - firstResponseElapsedreadCurrentTurnCancellationSnapshot。五、Web 删除接口先取消后删除的同步顺序5.1handleDeleteChat的调用链Web 侧删除会话的入口是 WebChatHttpBridge.handleDeleteChat修复后的执行顺序为chatHistoryManager.chatExists(chatId)——会话不存在直接返回 404chatHistoryManager.canDeleteChatHistory(chatId)——会话被锁定则返回 CONFLICTChat is locked and cannot be deleted若core.activeStreamingChatIds.value.contains(chatId)目标会话仍在流式输出执行runBlocking { core.cancelMessageForDestructiveMutation(chatId) }——注意这里是runBlocking同步等待丢弃式取消彻底结束后才继续最后才执行chatHistoryManager.deleteChatHistory(chatId)真正删除数据库会话。顺序上的关键点正是文档修正案的第一条验收标准删除活动会话时取消任务先结束随后删除聊天记录。5.2 不止 Web全路径的破坏性变更前置钩子这条取消逻辑并不仅限于 Web 接口。ChatServiceCore在初始化时通过ChatHistoryDelegate注册了一个全局的破坏性历史变更前置钩子ChatServiceCore.ktchatHistoryDelegate.setBeforeDestructiveHistoryMutation { chatId - messageCoordinationDelegate.cancelSummaryForDestructiveMutation(chatId) messageProcessingDelegate.cancelMessageForDestructiveMutation(chatId) }ChatHistoryDelegate.deleteChatHistoryChatHistoryDelegate.kt在真正删除之前会先调用prepareChatForDestructiveMutation(chatId)从而触发上面的钩子。这意味着任何删除路径——Web 删除、App 内删除、分组删除、删除当前会话——都会先同步完成两件事MessageCoordinationDelegate.cancelSummaryForDestructiveMutationMessageCoordinationDelegate.kt取消进行中的异步总结任务MessageProcessingDelegate.cancelMessageForDestructiveMutation丢弃式取消流式输出。删除完成后还有afterDestructiveHistoryMutation钩子负责refreshStableContextWindow刷新上下文窗口保证删除后的上下文计算不残留已删会话的数据。5.3 为什么是丢弃式而不是保留式从删除语义上讲会话即将被整体删除此时把半截回复与 Token 快照写回数据库属于纯粹的浪费甚至可能触发外键/索引层面的写入失败。因此破坏性删除场景特意绕开detachStreamingAiMessage只求干净、快速地终止所有协程不做任何持久化写入——这就是丢弃式取消不持久化部分回复的实现本质。六、测试验证MessageProcessingDelegateTest针对消息完成规则仓库新增了 MessageProcessingDelegateTest.kt其中completeInterruptedMessage_appliesTurnSnapshotAndCompletesPartialContent直接覆盖completeInterruptedMessage的纯函数行为构造一个content stale、带emptyStream()的流式消息以及一份含inputTokens 120、outputTokens 34、cachedInputTokens 56、sentAt 30、outputDurationMs 4_000、waitDurationMs 500的TurnCancellationSnapshot断言完成后的消息content partial response部分内容被保留、contentStream null流引用被清理、六个统计字段全部按快照写入、completedAt 5_000。这组断言与 index.md 的验证记录一致覆盖中断消息载荷中的部分内容、Token、耗时、发送时间、完成时间和流引用清理。七、验收标准对照与结论验收标准实现依据删除活动会话时取消任务先结束随后删除聊天记录handleDeleteChat 先runBlocking执行cancelMessageForDestructiveMutation再deleteChatHistory内部对所有协程cancel()join()中断统计的普通保存路径不参与破坏性删除cancelMessageInternal中keepPartialResponsefalse使activeTurn与cancellationSnapshot为 nulldetachStreamingAiMessage不会执行统计快照只在普通取消路径keepPartialResponsetrue写回删除路径统一ChatServiceCore.kt 的beforeDestructiveHistoryMutation钩子让 App 内删除、Web 删除、分组删除共享同一套取消前置逻辑总结下来issue 741 的第二个子问题用一条清晰的代码纪律解决取消要么保留收尾用户主动停止要么丢弃收尾即将删除二者通过keepPartialResponse参数严格分叉而删除动作永远排在被确认终止的取消之后。这条纪律既堵住了消息写入已删除会话的竞态又让中断统计的普通保存路径与破坏性删除在代码层面彻底隔离为会话数据的完整性和一致性提供了可测试的保障。赞分享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点击查看免费下载相关推荐ChatGPT桌面应用会话删除确认防止意外删除对话ChatGPT桌面应用会话删除确认防止意外删除对话 在日常使用ChatGPT桌面应用时我们经常需要管理大量对话记录。但误删重要会话可能导致信息丢失影响工作桌面应用AI 应用Cherry Studio 消息删除行为变更保留会话分支与多模型回复组的精准删除Cherry Studio 消息删除行为变更保留会话分支与多模型回复组的精准删除 导读 本技术指南围绕 Cherry Studio 的一次消息删除行为变更展开人工智能大模型AI 应用交互助手本地部署如何在Angular项目中快速集成ngx-moment5分钟上手教程如何在Angular项目中快速集成ngx moment5分钟上手教程 ngx moment是一个专为Angular应用打造的时间处理库它基于Moment.j上一篇N_m3u8DL-RE 完整指南从安装到选流、解密3 条命令下好 MPD/M3U8/ISM 流媒体下一篇Sunshine终极指南打造完美自托管游戏串流服务器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

Puma 7.0 升级指南:从 keepalive 长尾优化到 fiber-per-request 的完整迁移路线
Puma 7.0 升级指南:从 keepalive 长尾优化到 fiber-per-request 的完整迁移路线

后端网络 【免费下载链接】puma A Ruby/Rack web server built for parallelism 项目地址: https://gitcode.com/gh_mirrors/pu/puma 点击查看 免费下载 Puma 7(代号 "Romantic Warrior")是一次以请求生命周期为核心的里程碑版本&… · 2026/9/27 21:47:21

PX4 电调遥测消息 EscReport 详解:字段定义、故障位掩码与源码级应用分析
PX4 电调遥测消息 EscReport 详解:字段定义、故障位掩码与源码级应用分析

嵌入式物联网机器人自动驾驶智能硬件 【免费下载链接】PX4-Autopilot PX4 Autopilot Software 项目地址: https://gitcode.com/gh_mirrors/px/PX4-Autopilot 点击查看 免费下载 本文以 PX4-Autopilot 仓库中 EscReport 消息文档 为核心,系统拆解 esc_re… · 2026/9/27 21:47:21

TVA具身智能系统(2):从数字内容生成到物理世界行动的能力边界重构
TVA具身智能系统(2):从数字内容生成到物理世界行动的能力边界重构

前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”)是依托Transformer架构与“因式智能体”理论构建的新型工业视觉系统,也是当前最具代表性的具身视觉技术之一。它有机融合深度强化学习&… · 2026/9/27 21:47:02

Hermes Agent 浏览器自动化实战:用 TaoToken 统一 Key 搭建可追溯研究链路
Hermes Agent 浏览器自动化实战:用 TaoToken 统一 Key 搭建可追溯研究链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 22:23:16

C++ STL 算法库深度解析:从 <algorithm> 全景到工程级避坑
C++ STL 算法库深度解析:从 <algorithm> 全景到工程级避坑

1. 背景:为什么还要专门研究算法库1.1 STL 六大部分,算法是灵魂STL(Standard Template Library)由六大组件构成:容器(Container)、迭代器(Iterator)、算法(Al… · 2026/9/27 22:23:16

无人机避障实战:2D栅格地图pgm文件解析与路径规划代码详解(含TaoToken配置)
无人机避障实战:2D栅格地图pgm文件解析与路径规划代码详解(含TaoToken配置)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 22:23:16

通用Coding Agent不可能好用?用TaoToken统一Key打通Code Review工作流,35岁程序员的春天来了
通用Coding Agent不可能好用?用TaoToken统一Key打通Code Review工作流,35岁程序员的春天来了

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 22:23:10

Claude Code 装上这 10 个 Skills,直接起飞!TaoToken 统一 Key 配置实战
Claude Code 装上这 10 个 Skills,直接起飞!TaoToken 统一 Key 配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 22:23:10

01Linux中断机制:从硬件到内核
01Linux中断机制:从硬件到内核

Linux 内核体系结构(运维视角精讲)先纠偏:3 个表述修正驱动不属于硬件层,属于内核层 硬件层就是物理设备本身,驱动是内核里操控硬件的代码,是内核的核心组成部分,不是硬件自带的。没有独立的 “… · 2026/9/27 22:23:10

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码