dsh-session-title-stamp
Verifieddsh-session-title-stamp · v0.7.1 · MIT · Web UI
DSH session titles in a DATE | CATEGORY | NAME template, with turn-aware auto-generation, a settings page, and hover duration/cost/token stats.
Install
dsh plugin add dsh-session-title-stamp Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Creators
Readme
dsh-session-title-stamp
English | 中文
给 DSH 会话一个稳定的「日期 | 分类 | 名称」标题。除了自动命名,还包括:
- 自动重算:回答完成后更新,2 分钟冷却,超过 100 条消息后冻结;fork、子代理和手动固定的标题跳过。
- 生成标题:会话头 ↻ 按钮、会话行
···菜单「自动生成标题」、或/retitle。 - 复制标题:会话行
···菜单多一项复制完整标题。 - 设置页:可视化调整格式、emoji 和重算节奏,带实时预览,不用改 YAML。
- 可选 emoji 分类:
categoryEmoji: true后标题形如1027 | ⚡ 优化 | ...。 - 悬停统计:不打开面板,一眼看到耗时、估算 CNY 成本、token 数。
- 分类语言:
categoryPreset: zh | en,也可以用categories自定义。 - 失败保护:重算失败保留当前标题,不被兜底标题覆盖。
- 零构建:纯 Host 逻辑 + 小型手写浏览器半边。
标题告诉你这个会话在做什么,悬停卡片告诉你它花了多少。 耗时、估算 CNY 成本和 token 数,悬停即见,不需要打开面板。
默认格式:
日期 | 分类 | 名称
例如:
1028 | 分析 | 绿洲短剧平台验证
1027 | 修复 | 四台设备第十题验收返修
1026 | 发布 | Ubuntu 环境初始化
1025 | 优化 | 降低渲染器内存占用
日期由插件从会话创建时间计算,不交给模型;分类只能从可配置词表中选择,并在本地校验;模型只负责提出分类和名称,最终格式由模板决定。
为什么
工作区里的会话一多,侧栏标题要么是首条消息的前几个字,要么是容易漂移的自动摘要。固定成 日期 | 分类 | 名称 后,跨项目扫侧栏会快很多,也和其它 coding agent 的命名习惯一致。
要求
- DeepSeek Harness
>=0.2.1-rc.3 <0.3.0。 - 会话有可用的模型路由;标题请求默认跟随会话当前的 provider/model,也可用
provider/model单独指定。
安装
DSH Desktop / Web(Discover)
在 插件 → 发现(Discover)→ 索引源 添加:
https://cdn.jsdelivr.net/gh/xuedipiaofei/[email protected]/market/index.json
然后在列表里安装 Session title stamp / 会话标题印章。插件以 profile bundle 的形式安装,之后可在插件页启停。
CLI
从 GitHub 安装:
dsh plugin --profile <profile> add github:xuedipiaofei/dsh-session-title-stamp
从 npm 安装:
dsh plugin --profile <profile> add dsh-session-title-stamp
本地 checkout:
dsh plugin --profile <profile> add ./dsh-session-title-stamp
Electron Desktop 的 profile 由应用管理,请在应用的插件页安装,不要用 dsh plugin --profile desktop。
bundle 的 patch 会禁用内置的 session-title-llm 行并插入本插件。不要同时启用官方的 @deepseek-ai/dsh-experimental-session-titles-bundle:两者替换的是同一个 provider 槽位,标题服务只接受一个 provider。如果别的插件先注册成功,本插件只打一条 warn 并保持 inactive,不会让启动失败。
实现方式
cordis.patch.yml关闭session-title-llm,插入本包的session-title-stamp行。lib/index.js通过ctx.sessionTitle.register()注册提供者,并复用官方的@deepseek-ai/dsh-session-title-llm处理路由、超时、取消、token 上限和请求日志。client.js是手写的浏览器模块:会话头刷新按钮 + 悬停卡片成本/耗时行。
插件从 session.header.createdAt 按本机时区计算日期,让模型返回
{"category":"...","name":"..."},校验分类,再按模板拼装。{type} 或 {topic} 为空时,相邻分隔符会一起消失,不会留下 ||。
重算节奏
provider 注册为 first-prompt,首条消息由标题服务自动命名。之后插件在**每次 turn/end(回答完成)**时判断,并有两道闸:
- 冷却:距上次自动刷新不足
refreshMinIntervalMs(默认 2 分钟)就跳过; - 冻结:用户消息数超过
refreshMaxTurns(默认 100)后停止自动刷新;/retitle仍可用。
fork 子会话、子代理会话,以及用户手动改名固定的标题都会跳过。refreshOnTurnEnd: false 时回退到旧的「每 N 条消息」模式(retitleEvery)。
会话头按钮与悬停统计
0.7.0 增加了一个很小的浏览器半边:
- 会话头有一个刷新图标,效果等同输入
/retitle,会话运行中禁用;

- 鼠标悬停会话行时,在原生相对时间下面多一行:
耗时 1h 51m · 估算 ≈¥4.11 · 131.7M tokens; - 会话行
···菜单最上面多一项「自动生成标题」,下面多一项「复制标题」; 两者都不新开弹窗。
数字来自 sessionStats / tokenUsage 投影,按 DeepSeek 当前 CNY 价格估算,并标注「估算」。只在悬停时向宿主请求,不会为了显示数字去恢复未加载的会话。DSH 原生已经有运行中/待交互/完成未读的状态点与 loader,所以本插件不再加一层状态颜色。
悬停卡片字段说明
| 字段 | 含义 |
|---|---|
耗时 1h 51m |
来自 sessionStats 的模型 + 工具累计执行时间,不是墙钟耗时 |
估算 ≈¥4.11 |
tokenUsage × DeepSeek 当前 CNY 价格表,是粗略估算,不是账单 |
131.7M tokens |
输入、输出、缓存读、缓存写的 token 合计 |
空闲 / 定时任务行 |
DSH 原生状态内容,本插件不添加或替换 |
混合模型的会话按“最近使用的模型”估算,成本可能和实际账单不同。宿主没有该会话统计时,这一行会刻意不显示。
如果悬停行不显示,说明浏览器半边没连上宿主统计路由;刷新按钮和自动标题不受影响。
设置页

0.7.0 增加 设置 → 插件设置 → 会话标题:
- 顶部实时预览当前模板会生成的标题;
- 分类语言(中文/English)、可选分类 emoji、日期格式、标题模板;
- 自动重算开关、最小间隔、消息数冻结、启动补刷,并把额外模型成本写在说明里;
- 高级项只放名称长度和最近消息数;超时、预算、模型路由仍在配置文件里。
保存会写入当前 profile 的插件配置,对下一次生成的标题生效,不需要重启;已有标题不会被改写。
失败时
- 已经有标题时,重算失败会保留旧标题:provider 抛错,标题服务据此不提交新修订。
- 只有还没有标题的会话才用本地兜底:日期 + 推断分类 + 首条消息开头。
- 模型以
max-tokens结束时,只要还能解析出可用文本就继续用;只有完全不可用才算失败。
配置
在 profile 的 cordis.patch.yml 里覆盖:
- id: session-title-stamp
config:
refreshOnTurnEnd: true
refreshMinIntervalMs: 120000
refreshMaxTurns: 100
categoryPreset: zh
template: '{date} | {type} | {topic}'
timeZone: Asia/Shanghai
maxNameChars: 20
| 字段 | 默认 | 说明 |
|---|---|---|
refreshOnTurnEnd |
true |
回答完成后刷新;false 时回退到 retitleEvery |
refreshMinIntervalMs |
120000 |
自动刷新最小间隔;0 关闭冷却 |
refreshMaxTurns |
100 |
超过多少条用户消息后冻结自动刷新;0 不冻结 |
retitleEvery |
10 |
旧的按消息条数模式,仅在 refreshOnTurnEnd: false 时使用 |
backfillOnStart |
false |
启动时对仍是 fallback 标题的 live 会话逐个补刷 |
backfillMaxSessions |
30 |
单次回填最多处理多少个会话 |
backfillIntervalMs |
2000 |
回填两次刷新之间的间隔 |
template |
{date} | {type} | {topic} |
标题模板,占位符见下 |
dateFormat |
MMDD |
{date} 使用:MMDD(1028)/ YYMM(2610)/ YYYYMMDD |
timeZone |
本机时区 | 日期/时间占位符使用的 IANA 时区 |
categoryPreset |
zh |
内置分类语言:zh 或 en |
categories |
预设 | 显式分类词表,优先级高于 categoryPreset |
categoryEmoji |
false |
给分类加 emoji 前缀(⚡ 优化、🐛 修复……) |
maxNameChars |
20 |
名称字符上限(最终还受字节上限约束) |
maxTitleBytes |
标题服务上限(80) |
实际取它与 session-title 的较小值 |
recentMessages |
8 |
发送首条消息 + 最近 N 条消息 |
maxInputBytes |
4096 |
单次标题请求输入上限 |
maxOutputTokens |
4096 |
输出上限(含推理 token) |
timeoutMs |
90000 |
标题请求超时 |
provider / model |
跟随会话 | 可选,成对设置时用独立模型生成标题 |
模板占位符
| 占位符 | 含义 |
|---|---|
{date} |
按 dateFormat 渲染的日期(1028、2610、20261028) |
{YYYY} {YY} {MM} {DD} {HH} {mm} {ss} |
日期/时间部件,可任意拼接({YYYYMMDD}、{HHmm}) |
{type} |
分类;为空时整段及相邻分隔符一起消失 |
{topic} |
名称;为空时整段及相邻分隔符一起消失 |
不认识的占位符会原样保留({MMDD} {bogus} 会保留 {bogus}),方便一眼看出模板写错,而不是悄悄消失。最终仍受 maxTitleBytes 截断。
设置页覆盖常用字段;下面的 YAML 表仍用于自动化和高级配置。默认分类是中文。categoryPreset: en 可切到
Analysis / Build / Fix / Optimize / Debug / QA / Release / Docs / Other;categories
可以覆盖任意预设。提示词使用配置的标签,本地兜底也会把常见中英文关键词映射过去。
隐私与成本
- 发送首条有效用户消息,加上最多
recentMessages - 1条最近消息。消息以 JSON 包裹,避免用户文本破坏分隔符。 - 请求使用会话当前的 provider/model,或可选的
provider/model覆盖。插件没有其它网络请求,也不收集遥测。 - 首条标题一次辅助请求,之后每个完成的 turn 最多一次(受冷却/冻结约束)。标题生成是异步的,不会阻塞主回复;
maxOutputTokens、maxInputBytes、timeoutMs都会约束它。 - 标题作为普通
session/title事件写入会话日志。用户手动重命名后标题会被固定,后续自动命名不会覆盖。
兼容性
- 本包面向 DSH 0.2 线;
engines.dsh会在 0.3+ 上拒绝安装,直到按新 API 更新。 - bundle 依赖内置行 id
session-title-llm。如果已有其它标题 provider 先注册,本插件会打 warn 并保持 inactive;先停用另一个再重载。 llm、commands、sessions、sessionProjections、connection都采用延迟注入;缺少哪个只损失对应能力,不影响插件加载。- 浏览器半边依赖 Web 组合的
sidebar.session.row.hover和conversation.session.header.actions座位;没有这两个座位的 shell 不会显示按钮/悬停行。 - 插件动态 import
@deepseek-ai/dsh-session-title-llm。执行器缺失或不兼容时会降级为本地命名;如果ctx.sessionTitleAPI 本身变化,则可能无法注册。
开发
仓库没有运行时依赖,也不需要构建。
npm test # 格式测试、带 stub 执行器的 provider 测试、元数据/索引检查
npm run validate:index # 可选:用官方校验器校验 market/index.json(需先安装该包)
npm run pack:check # 查看 npm tarball 内容
provider 测试用 Node 的 module.registerHooks 把
@deepseek-ai/dsh-session-title-llm 重定向到
test/support/stub-executor.mjs,因此不需要安装 DSH 或模型凭据。
发布步骤见 PUBLISHING.md。
许可证
MIT © 2026 xuedipiaofei