dsh-session-title-cold
Cold-session title backfill for DeepSeek Harness: rows in
session.listthat come from persisted cold sessions (never opened, especially subagent children) have no projection cache, so the sidebar falls back to the workspace directory name — a screen full of "dsh" with no way to tell sessions apart. This plugin scans persisted sessions in the background, folds each registered projection unit (title / sessionStats / sessionListMetadata …) down to the latest event, and writes the title back into the projection cache.DSH 冷会话标题回填:后台扫描持久化会话,把投影单元折叠到最新事件并写回缓存,会话列表显示真实标题而不是工作区目录名。
English
Problem
session.list rows backed by persisted cold sessions (never opened, especially subagent children) have no projection cache, so the sidebar falls back to the workspace directory name (e.g. dsh) — you cannot tell sessions apart.
What it does
On startup (and then incrementally), scans all persisted sessions, folds each registered projection unit (title / sessionStats / sessionListMetadata …) down to the latest event, and writes the title back into the projection cache. Afterwards every session.list row carries projections.values.title, and the frontend shows the real title (fallback: first message, or the LLM/user rename).
Features
- Zero intrusion: no dsh source changes; a pure server-side plugin using the official projection registration/cache extension points
- Incremental: sessions that already have cache rows only read the event tail (
restoreFloor → readFrom), refreshed every 10 minutes; new renames are absorbed automatically - Fail-soft: a single session failure logs at debug level and never blocks the batch; live sessions are skipped (their cache is maintained by the runtime persistence path, avoiding overwriting fresh state)
Install
- Plugin directory:
~/.dsh/plugins/dsh-session-title-cold/ - Profile registration (
cordis.patch.yml):
- insert:
- id: session-title-cold
name: dsh-session-title-cold
Restart dsh web — backfill starts 5 seconds after boot (log [title-cold] 回填完成:N 个会话), refresh the web sidebar to see real titles.
Config (optional)
- id: session-title-cold
name: dsh-session-title-cold
config:
backfillDelayMs: 5000 # delay before backfill after boot
refreshIntervalMs: 600000 # incremental refresh period
concurrency: 3 # concurrent disk reads
How it works
sessionProjections.restoreFloor(checkpoint)→ incremental read floorsessionPersistence.readFrom(id, floor)→ read the tail events (with seq)sessionProjections.restore(checkpoint, events, floor)→ fold all unit snapshots (includingtitlefromsession/titleevents: fallback / user rename)- Merge only the
titlerow into the cache and write back viasessionProjectionCache.putSoft(other units of a cold session may hold non-pure-JSON state — skipped to avoidnot losslessly JSON-serializablerejections of the whole row) - The next
session.listcarriesprojections.values.title;displayTitleOfno longer falls back to the directory name
中文
问题
session.list 的行若来自持久化冷会话(从未打开过、尤其 subagent 子会话),projection 缓存里没有它们的行,列表拿不到标题,侧边栏只能 fallback 显示工作区目录名(如 dsh),一屏全是 "dsh" 分不清谁是谁。
功能
启动后后台扫描全部持久化会话,把每个已注册 projection unit(title / sessionStats / sessionListMetadata 等)折叠到最新事件并写回 projection 缓存;之后 session.list 每行都带 projections.values.title,前端列表直接显示真实标题(fallback 自首条消息,或 LLM/用户重命名)。
特性
- 零侵入:不改 dsh 源码,纯服务端插件,利用官方 projection 注册/缓存扩展点
- 增量:已有缓存行的会话只读事件尾部(restoreFloor → readFrom),每 10 分钟刷新一次,rename 等新标题变化自动吸收
- fail-soft:单个会话失败只记 debug 日志,不阻断批次;live 会话自动跳过(它们的缓存由运行时落盘路径维护,避免覆盖新状态)
安装
- 插件目录:
~/.dsh/plugins/dsh-session-title-cold/ - profile 注册(cordis.patch.yml):
- insert:
- id: session-title-cold
name: dsh-session-title-cold
重启 dsh-web 后,启动 5 秒后台回填(日志 [title-cold] 回填完成:N 个会话),刷新网页侧边栏即可看到全部真实标题。
配置(可选)
- id: session-title-cold
name: dsh-session-title-cold
config:
backfillDelayMs: 5000 # 启动后多久开始回填
refreshIntervalMs: 600000 # 增量刷新周期
concurrency: 3 # 并发读盘数
工作原理
sessionProjections.restoreFloor(checkpoint)得出增量读起点sessionPersistence.readFrom(id, floor)读尾部事件(带 seq)sessionProjections.restore(checkpoint, events, floor)折叠出全部 unit 快照(含title,来自session/title事件,如 fallback/用户重命名)- 只把
title行合并进缓存并sessionProjectionCache.putSoft写回(cold 会话其余 unit 的 state 可能含非纯 JSON 值,跳过不写,避免not losslessly JSON-serializable拒绝整行) - 前端下一次
session.list即带projections.values.title,displayTitleOf不再 fallback 到目录名
License
MIT
No comments yet. Be the first to write one.