资讯动态

弱网不再掉线:CC Pocket离线重发与流式恢复机制深度解析

发布时间:2026/10/17 21:47:27 来源:尧图企业网站定制
人工智能代码智能体交互助手工具调用【免费下载链接】ccpocketMobile client for Codex and Claude — control coding agents from your phone via WebSocket bridge项目地址https://gitcode.com/gh_mirrors/cc/ccpocket点击查看免费下载 CC Pocket 是一款运行在 iPhone / Android 上的移动端客户端让你通过 WebSocket 桥接Bridge在手机上远程控制电脑上的 Codex 和 Claude 编码代理。地铁里、通勤路上信号随时可能断掉——这篇文章将带你完整拆解 CC Pocket 的离线重发与流式恢复机制断网时输入不丢失、重连后自动补发、流式会话历史无缝续接弱网环境下也能安心指挥 AI 写代码。为什么手机上的编码代理最容易掉线CC Pocket 的架构是手机 App ⇄ WebSocket ⇄ 桌面 Bridge 服务。Bridge 运行在你的电脑上负责真正驱动 Codex / Claude 执行编码任务手机只负责展示与输入。这意味着一次对话往往持续几十分钟而移动网络恰恰是最不稳定的介质——电梯、地铁、地下车库都会让 WebSocket 随时断开。传统的处理方式是断了就白屏、输入就丢失而 CC Pocket 在设计之初就为弱网场景做了系统性的容错设计核心目标写在官方设计文档 docs/design/network-resilience-sync.md 中断网期间可以继续预约输入不阻塞用户网络恢复后只把 Bridge 能安全受理的操作真正发出去与其他终端的冲突要能被发现而不是静默覆盖下面分四个层次来看这套机制的实现。一、离线消息队列断网时的输入保险箱 所有出站消息都经过BridgeService的统一入口send()其逻辑非常清晰bridge_service.dart#L1582-L1619连接正常→ 消息直接通过 WebSocket 发出未连接或发送抛错→ 消息转入内存队列_messageQueue等待重连后批量补发Finder 即时操作如reveal_file这类本地 UI 命令会被直接丢弃不做重放——因为它对旧连接补发毫无意义。去重防止同一句话发两遍每条可重发的消息都会计算一个去重键bridge_service.dart#L1947-L1957input消息以clientMessageId客户端生成的 UUID为键同一条输入无论重发多少次队列里永远只有一份resume_session、start消息则按会话 / 规范化 JSON 去重。这保证了重试不会变成重复执行。关键操作落盘持久化杀 App 也不丢内存队列有个隐患App 被系统杀掉队列就没了。CC Pocket 的解法是只把值得保留的操作持久化到 SharedPreferencesbridge_service.dart#L1935-L1945消息类型是否持久化原因input发送输入✅用户核心操作start新建会话✅会话尚未创建丢了就回不来了resume_session恢复会话✅同上rename_session重命名✅低风险元数据操作update_queued_input/cancel_queued_input✅Codex 排队输入的修改/取消approve/reject/answer审批类❌强时间依赖自动补发反而危险注意最后一条审批类操作刻意不重放。你五分钟前点的允许运行等网络恢复后对应的工具调用可能早已结束盲目补发会造成误操作。这是宁可不发、不可乱发的保守设计。App 重启后_restoreOfflinePendingMessages()会从本地存储还原这些消息并做去重合并bridge_service.dart#L2288-L2353用户甚至意识不到刚才 App 其实重启过。二、指数退避自动重连不打扰、不轰炸 连接断开后_scheduleReconnect()会启动指数退避重连bridge_service.dart#L1565-L1580等待时间 min(2^第N次尝试, 最大延迟)即 2 秒 → 4 秒 → 8 秒……逐步拉长既避免弱网环境下疯狂重试拖垮电池又保证网络一恢复就能快速接上。同时服务内还内置了健康探测即使 TCP 连接看起来还活着如果心跳已失效也会主动断开并触发重连防止假连接。重连成功后的补发流程_flushMessageQueueAsyncbridge_service.dart#L1889-L1929同样考虑了中途再次断网的情况先恢复持久化的离线队列再整体取出待发消息逐条重新send()若发送中途网络再次中断未发完的消息自动回到队列并重新落盘等待下一轮重连。换句话说队列刷新本身也是幂等且可中断的——无论断网多少次消息只会迟到不会丢失更不会多发。三、流式恢复重连后如何续上断掉的会话 ⚡比补发消息更难的问题是断网期间服务器那边其实一直在跑。你盯着手机等回复网络抖了一下期间 Bridge 可能已经流式推来几百个 token。重连后如何不丢、不重、不乱序地补齐本地时间线缓存再进会话秒开客户端为每个会话维护一份运行时缓存SessionRuntimeStoresession_runtime_store.dart只保留每个会话最近200 条消息内存占用可控为每条消息记录历史序号 seq并维护historySeq已知的最新序号与cachedHistorySeq本地已连续覆盖到的序号两个水位线按 seq 去重合并upsert即使乱序到达也能自动排正。所以再次进入会话时屏幕先立即画出缓存里的最后对话不会白屏转圈再向 Bridge 请求增量补齐。增量同步 全量兜底这是弱网体验优化的核心。相比每次进会话都拉取全量历史get_history新协议支持get_history_delta只请求我上次看到的 seq 之后的增量消息流量和等待时间骤降history_snapshot当本地 seq 太旧超出 Bridge 保留窗口时Bridge 会回退为快照全量返回旧版 Bridge 兼容老版本 Bridge 不认识 delta 消息会返回unsupported_messageApp 自动降级回get_history全量拉取。三种协议形态新 App 旧 Bridge / 旧 App 新 Bridge / 双新都能正常工作——这是设计文档中optional field 渐进演进原则的直接体现network-resilience-sync.md。审批状态的事后追认断线期间如果 Bridge 那边弹出了权限审批请求permission_request重连后 App 会调用refreshHistory()重新拉取历史与上下文chat_session_cubit.dart#L2235-L2243把断网期间错过的审批状态完整恢复出来——你回到手机前该点的允许按钮已经摆好了。而正在流式输出的气泡由StreamingStateCubit驱动在消息流中断时会安全地定格为部分输出状态等assistant完整消息或历史补齐后自然对齐不会出现半句话永久卡住的问题。四、冲突检测别人先说话了怎么办多设备场景下最危险的不是没发出去而是发错了。CC Pocket 给input消息附带两个字段clientMessageId让 Bridge 的应答input_ack/input_rejected能精确对回具体某条气泡而不是按顺序猜测baseSeq发送时我看到的最后一个历史序号。重连补发前先做冲突预检用baseSeq之后的增量里如果出现了别的终端发来的用户输入、会话回合已结束result、或 rewind / 会话切换等改变前提的事件这条预约输入会被标记为failed_conflict——App 会保留你写好的内容提供编辑后重发而不是悄悄发到错误的上下文中。最终裁决权在 Bridge即使客户端预检通过Bridge 端发现baseSeq与当前 revision 不符仍会返回input_rejected(reason: conflict)。客户端预检只是优化体验服务端校验才是底线。五、用户能看到的离线状态 整套机制在 UI 上呈现为一条清晰的消息生命周期offline_pending_action.dartqueued已排队断网中 → sending重连后发送中 → sentBridge 已受理 ↘ failed冲突/失败可编辑重发离线时点击发送输入气泡立即显示为已排队不阻塞继续编辑下一条离线预约的新建会话 / 恢复会话会以待处理卡片出现在会话列表网络恢复后自动执行并迁移为真实会话长时间停留在发送中的消息会自动显示为待处理状态用户可随时取消。机制速览一次断网到底发生了什么阶段客户端行为对应实现断开瞬间标记 disconnected在途消息回收到队列_requeueInFlightInputMessages断网期间输入排入队列关键操作落盘指数退避重连_messageQueue SharedPreferences重连成功恢复持久化队列去重后逐条补发_flushMessageQueueAsync补发校验预检 baseSeq 冲突冲突则标记 failedinput_rejected会话画面缓存秒开 → delta 增量补齐 → 全量兜底SessionRuntimeStore相关源码与文档 弱网同步总体设计五阶段规划docs/design/network-resilience-sync.md客户端桥接服务队列、重连、持久化apps/mobile/lib/services/bridge_service.dart会话运行时缓存apps/mobile/lib/services/session_runtime_store.dart离线待处理动作模型apps/mobile/lib/models/offline_pending_action.dart会话状态机与历史刷新apps/mobile/lib/features/chat_session/state/chat_session_cubit.dart桌面端 Bridge WebSocket 服务packages/bridge/src/websocket.ts会话与历史管理packages/bridge/src/session.ts端到端行为测试apps/mobile/test/session_runtime_store_test.dart、apps/mobile/test/bridge_endpoint_probe_test.dart小结CC Pocket 的离线重发与流式恢复可以浓缩为一句话消息会迟到但绝不丢失、绝不发错。内存队列 选择性持久化保证断网不丢输入指数退避重连保证恢复不轰炸seq 水位线 增量同步保证续接不重复baseSeq冲突检测保证补发不越界。对于需要长时间远程看护 AI 编码代理的手机用户来说这套机制让在地铁上发一条指令回到公司发现代码已经写好成为可靠体验而不是靠运气。✨赞分享人工智能代码智能体交互助手工具调用【免费下载链接】ccpocketMobile client for Codex and Claude — control coding agents from your phone via WebSocket bridge项目地址https://gitcode.com/gh_mirrors/cc/ccpocket点击查看免费下载相关推荐Upsonic Agent 执行流水线深度剖析24 步 Direct Pipeline、22 步流式管线与 HITL 恢复机制Upsonic Agent 执行流水线深度剖析24 步 Direct Pipeline、22 步流式管线与 HITL 恢复机制 本文基于 Upsonic 框架人工智能大模型AI AgentAgent 框架自主智能体工具调用RAGAgent 记忆Agent 编排老旧 Mac 装不上新版 macOSOpenCore Legacy Patcher 四步免费装好老旧 Mac 装不上新版 macOSOpenCore Legacy Patcher 四步免费装好 能装吗只要是 2008 年及以后发布的 Intel 版 M操作系统固件驱动开发Omni离线数据同步重新联网后恢复操作的机制Omni离线数据同步重新联网后恢复操作的机制 你是否遇到过这样的情况在没有网络连接时使用Omni全功能生产力工具执行了一系列操作担心这些操作会丢失O开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

免费获取报价 →
↑