Repository navigation
v2026.09.21.1
v2026.09.21.1 — 按会话暂停 / 恢复同步(Web 多选 · 服务端冻结 · 客户端补推)
服务端 + 客户端发布:
CLIENT_VERSION2026.09.13.4 → 2026.09.21.1(mcp/updater.py与server/client_update.py同步),各端经/api/client/manifest自动更新、Agent 重启后生效。schema 变更:sessions新增sync_paused/sync_paused_at两列,由启动时的init_db()幂等ALTER TABLE ... ADD COLUMN IF NOT EXISTS创建,无需人工迁移。
Added(Web 端可多选:暂停 / 恢复会话同步)
- 选定会话暂停 / 恢复同步:工作空间详情页与「全部会话」页每行带勾选框,批量栏一次暂停或恢复所选会话;每行另有单行按钮,会话查看器页也有同一按钮。暂停的会话在列表里带「已暂停同步」徽标。
- 语义是服务端冻结上行,不是把会话从共享池里摘掉:
/push(以及 Web 导入)对这些会话零写入 —— 会话元数据、消息、rev/field_rev、last_synced_at全部不动。闸门放在push_sync最前面,所以配额闸门、消息去重快照与 rev 记账都看不到被暂停的会话:整会话冻结,不是部分合并。/pull照旧下发冻结版本。否则其它设备会认为"服务端没有这个会话",触发「本地删除不是删除信号」的补回逻辑,或让用户以为会话被删。暂停只断上行。
/push新增响应字段paused_ids:本次被冻结跳过的会话 id。客户端据此不记录 push 指纹 —— 指纹的含义是"服务端已持有这份内容",记了它,暂停期间的内容在恢复后将永远补不上去(本地无变化 → 指纹命中 → 跳过)。不记指纹 = 每轮重发,恢复后下一轮自动补齐。- 路由:
POST /web/sync/pause/POST /web/sync/resume,表单字段sel可重复,值"<ws_id>:<session_id>"(会话 id 自身可含冒号,只按第一个冒号切分);只更新调用者自己的 workspace(workspaces.user_id校验),返回路径next限同源。行内已有各自的删除表单,所以每行勾选框用form="sync-bulk"关联到行外表单(HTML 不允许嵌套 form),两个提交按钮用formaction区分。 - Web 导入(
/web/workspace/{id}/import)跳过暂停会话并在 flash 中报数(与/push同规则,不静默丢弃)。
Changed(客户端与文档)
mcp/server.py::push_sessions识别paused_ids:不计入processed、不写指纹,日志与返回体给出paused/paused_ids计数(多 chunk 合并计数)。- 新增词条
sync_pause_*/sync_bulk_*/ws_import_paused(zh-CN + en);_macros.html新增sync_paused_chip()。 - 文档:
docs/ARCHITECTURE.md新增「暂停/恢复同步」决策记录(含混合版本窗口与回归防线)、sessions 表两列、路由表、pull 过滤段说明;docs/server-deployment.md路由表 //push响应字段 / sessions 列表同步;docs/OPERATIONS.md数据保留章节补条目;README(中英)功能要点同步。
混合版本窗口(实测确认)
- 未更新的客户端照常自动同步:旧客户端(2026.09.13.4)对新服务端实测 —— 普通会话推送行为一字未变;推送被暂停会话时返回计数 0、无 error,同步循环不中断,同批次其它会话照常入库。
- 代价:旧客户端会把那次"被跳过"的推送当作成功并写入指纹,于是暂停期间的内容要等该会话本地内容再变化一次、或清一次指纹 sidecar(
<mcp目录>/.hermes-sync-field-meta-push-fingerprint.json)才会补上。实测清掉 sidecar 后下一轮即补齐。客户端自动更新后该窗口自然消失。
测试与验证
- 单元测试:
server/tests/test_sync.py(PushTest新增 sync pause 用例:冻结零写入、同批次其它会话照常落库、响应带paused_ids、暂停会话不再进入配额闸门)、server/tests/test_sync_pause_ui.py(sel解析含冒号 id、端点、多选、属主校验、空选择提示、next同源校验、导入跳过并计数、zh/en 词条齐备)、mcp/tests/test_push_pause.py(不写指纹、下一轮重发、混合版本窗口、多 chunk 合并计数)。全量:server + mcp 477 passed / 2 skipped。 - 线上(236)20 项检查全 PASS:两列由
init_db()建出;匿名POST /web/sync/pause→ 307/web/login;Web 暂停后/push返回paused_ids且该会话标题/消息数原封不动、/pull仍下发冻结版本;列表页渲染徽标与批量栏;恢复后同一次推送补齐暂停期间的 2 条消息;/api/client/manifest?agent=hermes&v=2026.09.13.4返回 version 2026.09.21.1 +update_available=true,下载包内manifest.json版本一致、mcp/server.py的 sha256 与清单相符且含paused_ids。
生产状态:236 已部署(提交 9531474)—— 11 个文件(6 个 .py + 4 个模板 + mcp/ 客户端 2 个)对上次部署提交 cab5a8a 逐文件 LF 归一化 sha256 预检通过、上传后回读一致、py_compile 通过,重启后 systemctl is-active = active、journal 无 error;check_drift_236.py / check_drift_mcp_236.py 复核 server/ 50 个文件、mcp/ 15 个文件 drift=0。线上 /api/client/manifest 已服务 2026.09.21.1。
仓库说明:v2026.09.19.2 的历史重写(清除部署细节 + 提交身份统一为 noreply)保持不变;本次发布起,新提交与 tag 使用维护者身份 道荣 <westsource@126.com>。