Repository navigation
Releases
v0.4.1 - DSH 0.2.1-rc.2, Category Priority & Triple-Gate Extraction
v0.4.1 Release Notes
- DSH 0.2.1-rc.2 Specification & Engines Alignment: Declared
"engines": { "dsh": ">=0.1.2-rc.1" }inpackage.json, adhering to the official priority evaluation ofengines.dsh. - Fixed Volatile Reference Validation Bug: Resolved
ValidationErrorduringinstallSettingsCompatby cleanly unwrapping volatile references withunwrapConfig. - L0 Catalog Category Priority & Anti-Truncation: Enforced stable output priority in
renderIndex(preferences -> entities -> experiences -> events) and expanded defaultindex.maxTokensto 2000, preventing core rules and assets from being dropped by token budgets. - Triple Gate for Background Extraction: Overhauled
extractionSystemwith a strict negative exclusion list, 30-day durability test, and aggressive merge requirement to eliminate over-extraction and memory fragmentation.
v0.3.2 - Fix Volatile Schema Unwrapping on Boot
What's Changed in v0.3.2
Fix Schemastery Volatile Reference Handling in resolveConfig
- Root cause: Schemastery wraps fields marked with
.volatile()inVolatile<T>reference objects ({ get(): T }). When dsh loads a profile entry without an explicit config, Cordis resolves absent volatile fields into reference objects instead of plainundefined. As a result,config.root ?? DEFAULT_MEMORY_ROOTyielded the reference object rather than falling back to default, causingexpandHomePathto throwTypeError: path.startsWith is not a function. - Fix: Added
unwrapConfigrecursive helper to extract primitive values from any volatile reference before runningresolveConfig. - Verification: Tested clean boot under both plain empty and Schemastery-parsed volatile configs (125/125 tests pass).
v0.3.1 - Fix dsh 0.1.7 v4 Catalog Message Source
What's Changed in v0.3.1
dsh 0.1.7 Session Format v4 Message Source Adaptation
- Producer-owned source kind (
src/catalog.ts):- In dsh 0.1.7 (session format v4), the legacy generic
{ kind: 'plugin', plugin: '...' }wrapper was retired and is rejected by v4 source admission (SessionFormatError: format v4 message requires a producer-owned source kind). - Catalog messages are now published with the producer-owned source kind:
source: { kind: 'plugin:dsh-memory-lite', form: 'catalog' }. - Background extraction messages in
src/extract/index.tsupdated tokind: 'plugin:dsh-memory-lite'.
- In dsh 0.1.7 (session format v4), the legacy generic
- Three-generation backward compatibility:
isMemoryCatalogSourceupgraded to recognize all historical representations:- Gen 1 (<0.2.3):
kind === 'memory-catalog' - Gen 2 (0.2.3–0.3.0):
kind === 'plugin' && plugin === 'dsh-memory-lite' - Gen 3 (>=0.3.1):
kind === 'plugin:dsh-memory-lite'
- Gen 1 (<0.2.3):
- Fully backward compatible with dsh 0.1.5 (v3 format).
v0.3.0 - dsh 0.1.7 Dual-Track Compatibility
What's Changed in v0.3.0
dsh 0.1.7 Dual-Track Compatibility Architecture
- Schema volatile declarations (
src/config.ts): Decorated editable configuration fields (root,defaultPeer,index.maxTokens,extraction.*,sharing.*,ui.headerOrder) withasVolatilehelper (calling.volatile()in 3.18.4+ and fallback.extra('volatile', true)), enablingSettingsFormsto persist edits in profile patches without remounting. - Dual-track host settings integration (
src/index.ts):installSettingsCompatautomatically detects runtime capabilities:- In
dsh <= 0.1.5: bindsSettingsProvider.installSection(legacy settings.yaml namespace); - In
dsh >= 0.1.7: disables fallback schema form viaSettingsForms.configure({ auto: false }), points source thunk toentry.options.config, and subscribes toapp-boot/config-reloadevents.
- In
- Universal web client scope resolution (
lib/client.js):- Restricts declared
injectto universal services (['connection', 'slots']) to prevent activation failure on platforms lackingsettingsScope; - Dynamically binds
configForms.get('memory-lite')on 0.1.7 andsettingsScope.bind('dsh-memory-lite')on 0.1.5, with graceful fallback.
- Restricts declared
- Test coverage: Added 0.1.7
FakeSettingsFormsintegration tests and dual client scope tests; total 124/124 tests passing.
v0.2.8 — root/共享挂载恢复生效 + headless 可加载
0.2.8 — 设置里的 root / 跨 peer 共享 恢复生效;headless 可加载
跨 peer 共享从 08-27 起就静默失效了(这次修好)
08-27 的「方案 A」把插件配置从 profile 的 row config 迁到 ~/.dsh/settings.yaml,但 root / sharing.* 仍被钉在迁移前的初始 row config 上 —— 于是设置面板里的「重启生效」是假的:root 改了不生效,共享挂载也从来不发布。
实测时间线:sync 工作区最后一个目录里带 ## shared 的会话是 08-27 18:36,之后全部为空(08-26 的会话还能读到 shared/dsh-test/entities/…)。
现在改为:MemoryStore 首次使用时才构造,启动那一次由设置层提供 root/sharing;运行中再改仍是「重启生效」。所以:
- 你在设置里配的共享挂载(
dsh-test-72572e8b、sync-d1ace078)会真正生效 —— 重启后 sync 工作区的记忆目录里会出现## shared; - 自定义
root也终于生效。
headless profile 不再因缺 connection 而整盘起不来
connection 是 web app 才有的服务。此前它写在硬 inject 里,装进 headless profile 会让整个 profile 启动失败(pending (waiting for service: connection))。现在四个浏览器 RPC 路由改为可选注入:headless 下插件照常加载(工具 + 提取可用),只是没有指示器和设置页。
Tests 120 → 122。
v0.2.7 — 修复新装环境工具调用崩溃(核心包必须 peerDependencies)
0.2.7 — 修复「新装环境一调用工具就崩」
症状:全新安装(尤其是 Linux)后,纯聊天正常,但任何工具调用都整轮失败:
dsh: UNKNOWN: Cannot read properties of undefined (reading 'prepare')
tool/call 已写入但没有配对的 tool/result,错误不落盘栈。
根因:package.json 曾把 dsh-tools / dsh-settings / dsh-atomic-write / dsh-home-paths 写在 dependencies 里并钉死 0.1.2-rc.1。pnpm 会把它们 hoist 进 profile 的 node_modules,于是 profile 里出现第二份物理拷贝;cordis loader 从 profile 目录优先解析内置条目,而 fallback 里的宿主包仍用自己那份 —— dsh-tools 的调度器挂在包内私有 Symbol 上,两份拷贝 = 两个 Symbol,registry[TOOL_RUNTIME_SCHEDULER] 读到 undefined → scheduler.prepare 抛错。
修复:这些 DSH 核心包全部改为 peerDependencies(>=0.1.2-rc.1),插件沿父目录解析到宿主那一份;schemastery 仍为普通依赖。新 profile 里只剩 schemastery + cosmokit。
验证:用只拉旧 dsh-tools 的 shim 包复现了完全相同的崩溃(与插件无关),修复后全新 profile 端到端验证 —— 6/6 工具调用全部有配对结果(含 remember / read_memory)。
升级建议:如果你在全新环境装过旧版本并遇到上述崩溃,升级到 0.2.7 后需要重装 profile 依赖(dsh plugin --profile <p> add @alanzhao/dsh-memory-lite@0.2.7)并重启,让旧的第二份拷贝消失。
另:IMPLEMENTATION.md §19 记录了这条对所有 dsh 插件都适用的依赖政策。
v0.2.6 — 用户文档重写 + 元数据补齐 + messageScope 显示修复
0.2.6
文档与元数据这次是主角,外加一个 UI 修复。
README 重写成用户文档(中文主 + English)
README.md 现在是中文使用指南:安装 → 重启 → 验证三步(含"装完该看到什么")、功能表、成本表、设置速查、记忆目录结构、故障排查、卸载、已知限制;README.en.md 是对应英文版。新增 docs/preview/ 三张截图(标题栏指示器、设置面板)。
旧 README 里 IMPLEMENTATION.md / src/config.ts 两个相对链接在 npm 上是死链(这两个文件不在发布包里),已改成 GitHub 绝对地址。
包与仓库元数据
package.json补repository/homepage/bugs(npm 页面现在能回链 GitHub),关键词扩充,发布文件加入docs与README.en.md。- GitHub 仓库补 description 与 topics(
dsh、dsh-plugin、deepseek-harness、memory、agent-memory)——按 topic 发现插件的工具现在能找到它了。
UI 修复:空 messageScope 的显示一致性
「计入窗口的消息类型」三项全不勾时,面板此前显示"什么都没选",而运行时仍按默认(用户+助手)计数。现在面板按解析后的默认值显示,保存时写 unset 而不是 [],hint 也写明了「三项全不勾 = 用默认」。
Tests 119 → 120。
v0.2.5 — 跟随全局默认也能选推理强度
0.2.5
跟随全局默认时,推理强度不再只有「跟随全局默认」一项。
问题
extraction.llm.route 留空(跟随全局默认)时,面板的「推理强度」下拉只有空选项——不固定提取模型就无法指定具体强度,与字段 hint 的承诺不符。
直接后果:提取继承了 agent-default-model 的 reasoningEffort: max,4096 token 预算被思考吃光,正文为空,每次都要走一次「修复重试」(llmCalls=2、20~85 秒)。
改动
- route 为空时,强度选项按 当前全局默认模型(
agent-default-model活值)读取;换了默认模型自动跟着变。 - 失效值标记同样适用于强度:存的强度不在所选模型声明里时会标
已失效并给出提示。 - 选择变化由 hook 自动重取,移除了手动 re-target 逻辑。
Tests 118 → 119。
v0.2.4 — 失效模型值可见 + provider 错误详情
0.2.4
2026-09-16 提取静默停摆事故的收尾修复(两个可观测性缺陷)。
设置面板不再隐藏失效的模型值
extraction.llm.route(或 reasoningEffort)指向 provider 已改名/删除的模型时,下拉框此前会退化成显示第一项(跟随全局默认)——页面看着完全正常,而提取一直在用那个已死的模型并失败。现在会把存的值作为显式选项显示(已失效 标记 + 红色说明),列表尚未加载时不误标;并补上挂载时按已存 route 拉取一次推理强度选项(此前只有手动重选 route 才会拉)。
提取失败日志带上 provider 原文
终态 error / aborted finish 现在把 finish.failure.message(附 [code status])拼进错误,审计 note 形如:
llm-error: llm stream finished with error: pi-ai provider "huoshan" has no configured model "deepseek-v4-flash" [UNKNOWN_MODEL]
此前只有 llm-error,真因被吞掉。
Tests 116 → 118。
v0.2.3
v0.2.3 — silent extraction failures fixed; catalog moved to the official source
Fixes
- Implicit extraction no longer dies silently after a session-format migration. A released v0→v1→v2→v3 migration renumbers every session event, so a stored extraction checkpoint from the previous numbering sat beyond the log's end and the extraction window was always empty — no run, no log, no error. The plugin now detects the rebase and resumes from the recent window; already-affected sessions recover automatically on their next trigger.
- A failed run keeps its bookmark.
llm-error/parse-error/apply-error/no-routeruns no longer advance the checkpoint past the window they failed to read, so the next trigger retries it instead of dropping the content. - System injections no longer count as conversation. The memory catalog and other injected user messages no longer count toward
windowTurnsor keep re-arming the idle timer; the trigger counter and the window selector now share one predicate. - An empty window clears the pending counter, so an oversized counter cannot re-schedule a full-log scan on every subsequent event.
Compatibility
- The injected catalog now uses the official source vocabulary:
{ kind: 'plugin', plugin: 'dsh-memory-lite', form: 'catalog' }instead of the privatememory-catalogkind. Released session-format migrations audit message sources against a closed, plugin-independent set, so the private kind made old sessions fail to load on dsh 0.1.5. - Sessions written before 0.2.3 keep working: the legacy kind is still recognized, so an existing catalog is never injected twice and no session data is rewritten.
- The official
catalogform carries no payload, so "the published catalog is still current" is now decided by comparing the published message text with the current rendering. - Requires dsh ≥ 0.1.5. No dependency changes.
Docs
- README "How it works" and IMPLEMENTATION §5.1/§5.4 updated for the official source form.