Repository navigation
Releases
v1.11.0
v1.11.0 — 修复「启动后重复镜像」
现象:同一个会话在工作区里出现两次。
根因:jsonl 类应用的 key 是 <app>:<文件相对路径>。这个 key 只有在文件不动时才稳定——应用重写项目目录、恢复备份、或从第二个根目录同步同一份历史,同一段对话就会拿到新 key,于是生成新 mirrorId、把整段历史再追加一遍。旧记录被换 key 后变成孤儿,两份同时出现在列表里。
证据:投影缓存里有 14 组同标题重复,每组恰好一份在 store 里、一份是孤儿(如「分析透视关系是否正确」15b397f6 / 59927928)。
修法:新增前置去重守卫。用内容指纹(app id + 首条用户消息 + 起始时间)代替路径来识别同一场对话;建新镜像前先查已有记录,命中就让它接管新 key,不再新建。
指纹里不含任何路径,所以文件移动不影响;已归档的记录不参与匹配(不会复活用户主动归档的会话)。
新增 test/dedupe.gate.mjs(8 项)已接入 npm test;27 项单测 + 四套 gate 全绿。
v1.10.0
v1.10.0 — 落盘不变量守卫(修「历史加载失败」根因)
问题:镜像会话的历史突然加载失败,报 system/message requires a protected first surface head,任务从列表消失。
根因(DSH v4 会话日志格式铁律):system/message 必须是整个会话第一个 surface 事件(受保护头)。一旦会话已有 user/assistant 内容,之后任何 system/message 都会让整份日志被判 corrupt —— 不是坏一条,是整份读不出来。agent-sync 直接写日志,所以必须在写之前自己守住。
修复(每次 append 前跑两道纯函数守卫):
| 守卫 | 作用 |
|---|---|
assertNoMidSessionSystem |
已有 surface 内容时拒绝追加 system/message,直接抛错并说明后果 |
assertSeqConsecutive |
拒绝 seq 断档/重复,坏批次根本不落盘 |
另:空镜像不再创建无内容的 isSeeded:false 会话。
验证:新增 test/invariants.gate.mjs(9 项,已接入 npm test);27 项单测 + bundle/safety/invariants 三套 gate 全绿。
顺带:/agent-sync/sessions 改为 async(读活投影缓存),engine 测试同步改为 await。
v1.9.3
修复:改名后搜不到镜像任务
根因:本地标题索引从来没读到会话数据 —— normalizeSessions 取 Object.values(snapshot),而快照实际是 { byId, ids, phase },于是活索引恒为空,搜索只能靠 host 侧的镜像记录,那是 agent-sync 建镜像时写的旧标题。
修法:
- 读
snapshot.byId - 标题以活投影为准(host 侧索引改为按真实 persistence header 查投影缓存),镜像记录只做兜底
- 合并时客户端索引优先,避免旧串压掉新名
兼容性与市场显示
exports["."]增加"./package.json":插件市场与插件管理器靠它读 title/description,缺了只能显示包名和路径- 新增
engines.dsh: ">=0.1.0":版本兼容性显式声明,而非隐含
已验证:本地单测覆盖「改名后按新名可搜、旧名不再命中、仅 id 兜底不进索引」;bundle.gate 5 项 + safety.gate 4 项全绿。
v1.9.2 - drop TRAE support
变更
- 移除 TRAE 支持:TRAE 的 IDE 会话存放在加密的本地库(
ModularData/ai-agent/database.db,SQLCipher),既没有可枚举的接口,也没有可用的导出,无法实现会话镜像。删除了应用注册表条目、Markdown 导出解析器与相关文档。 - 支持的应用数:14 → 13。
- 修复服务解析:
ctx.get()取不到服务时回落到直接的上下文属性,避免最小化 harness 下引擎完全不工作(引擎用例曾因此失败)。 - README 增加「不提供 TRAE 支持」的说明与已知限制条目。
测试
node --test:27 通过test/bundle.gate.mjs:5 项通过test/safety.gate.mjs:4 项通过
v1.9.1 - follow account rename
chore: follow the account rename to JiangHuai24 Repository, homepage and issues URLs point at the new account; author stays project-neutral so the published content carries no personal handle.
v1.9.0 - safe config writes
feat: adopt managed-block, atomic patch writes Ports the safe persistence model from kuaiyukuaikuai/dsh-agent-sync: a marked managed section instead of regex surgery, tmp+rename so an interrupted write cannot truncate the file, a one-shot backup, a structural guard before writing, and profile-layer precedence so saves land in the user profile rather than the package directory. test/safety.gate.mjs enforces all of it.
v1.8.1 - graceful degradation
fix: degrade instead of aborting when a service is missing github-flow called ctx.skills.register directly, so an unavailable skills service threw during activation and the host reported 'import failed', aborting the whole web boot. It now resolves via ctx.get and logs instead of throwing. The gate also imports and applies both host halves with zero services, which is the condition that produced the crash.
v1.7.3 - bundle cache notes and combo gate
docs: explain the bundle cache trap and gate combo collisions The served rev is sha1(mtimeMs, ctimeMs, size), not a content hash, so a broken rewrite gets a fresh rev while a content change with unchanged metadata keeps the old one. Documents both shapes and extends the gate with a combo check for top-level identifiers shared across bundles.
v1.7.2 - safe children spreading
fix: spread React children safely Passing a single child gives React the value itself rather than an array, so spreading it threw 'Spread syntax requires ...iterable' and took the whole settings.section slot down. Children are normalised with React.Children.toArray; the bundle gate now renders every slot with single-child and undefined children so this shape is covered.
v1.7.1 - bundle gate
fix: repair the damaged footerButtonStyle and add a bundle gate My earlier patch truncated footerButtonStyle, which turned every later declaration into dead code and left the settings panel blank. The function is restored, and test/bundle.gate.mjs now fails the build when a bundle leaks patch-script source, declares functions after the module return, or throws on render.