dsh-ai-session-title
Verifieddsh-ai-session-title · v0.4.6 · MIT · Web UI
AI-generated session titles for DeepSeek Harness: one-click generation inside the session rename dialog.
Install
dsh plugin add dsh-ai-session-title Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Creators
Readme
AI 会话标题
为 DeepSeek Harness(DSH)的会话重命名对话框加一个 AI 生成按钮:读取真实对话内容(以及你已经输入的草稿),让当前会话所用的模型写一个短标题,填进输入框——你确认后按「重命名」,不满意就继续改。
English | 中文
要求:dsh ≥ 0.2.1-rc.3、Node ≥ 20。
效果

- 打开任意会话自带的「重命名会话」对话框(侧栏
···→ 重命名会话)。 - 输入框内右侧、同一条边框里多一个星标按钮——不是新弹窗,就是原生那个框。
- 点一下:读取该会话的对话记录,连同你已输入的草稿一起作为参考,生成标题并填回输入框。
- 底部仍然是原生的「取消 / 重命名」;生成不会自己改名,必须你点确认。
安装
从 npm 安装(推荐)
dsh plugin --profile <你的 profile> add dsh-ai-session-title
然后重启 dsh web 并刷新页面。
自带
dsh的桌面版请在 App 内 设置 → 插件 里安装,不要用命令行——App 运行期间不会让 CLI 改写它自己的 profile。
从本仓库安装
plugin_manager install_bundle target = <本目录的绝对路径>
或者让 agent 用 plugin_manager 工具装。装完刷新 Web 界面。
从插件市场安装
市场读取的是 awesome-dsh-plugin 这份目录,而不是本仓库。目录收录之后,在 插件 → 发现 里搜索安装即可。
工作原理
一个包,两半:
| 半边 | 文件 | 作用 |
|---|---|---|
| Host | index.js |
注册全局命令 /ai-title。读会话事件日志、按下一次请求要用的路由(session.requestHeader().config,取不到时回退到最新一条助手消息)选模型,用 ctx.llm 以 purpose: 'session-title' 流式生成一条,清洗后返回。命令名后面的文本视为用户的草稿标题。 |
| Client | client.js |
监听原生对话框的会话名输入框,就地装饰一个星标按钮;点击后调用 ctx.remote.commands.execute(sessionId, '/ai-title <草稿>', []),把返回的标题用原生 input 事件写回该输入框。 |
两个实现细节值得说明:
- 为什么装饰 DOM 而不是注册插槽:原生对话框把目标会话存在组件内部 state 里,通过
shell.overlay渲染,内部没有暴露任何插槽,所以插件拿不到插入点,只能就地装饰它;会话 id 则通过输入框预填的标题在 Workspace Service 的会话列表里反查。 - 为什么走命令:客户端到 host 的 RPC 接口是构建期生成的,第三方 bundle 无法新增方法,命令是唯一稳定的调用通道。代价是每次生成会在会话流里留下一条
command/run+command/done记录——这也是生成过程中唯一的可见反馈。
配置(可选)
装好之后打开 更多 → 设置,左侧导航里会多出一项 「AI 会话标题」,改完点保存即可:
| 字段 | 说明 |
|---|---|
style |
标题结构,决定生成出来的标题长什么样,见下表 |
datePrefix |
是否在标题前加「月-日」前缀,默认关 |
prompt |
自定义结构提示词,只在 style 选“自定义”时生效;留空按“主题”处理 |
maxTitleChars |
标题字符上限,默认 30 |
四种结构对应四种“以后怎么把会话找回来”的方式:
style |
名称 | 示例 | 适合 |
|---|---|---|---|
concise |
主题 | 登录超时排查 |
默认。3~8 字名词短语,侧栏最窄时也能一眼扫过去 |
descriptive |
动作 | 重构登录状态管理 |
动词开头,回看时知道这次做了什么 |
outcome |
主题 + 结论 | 分页错位 · 定位到索引边界 |
先主题再产出,复盘时最能看出这次值不值 |
custom |
自定义 | 由提示词决定 | 用 prompt 描述你自己想要的格式 |
日期单独是一个开关,不是第五种结构:打开 datePrefix,上面任何一种结构都会多出 10-30 前缀,所以「日期 + 主题」「日期 + 主题 + 结论」都是两次点击的事,不用为每种组合再列一张卡片。
datePrefix 的日期不是模型编的:插件读会话第一条消息的时间,自己补 MM-DD ,并且先从前缀里扣掉 6 个字符再要求模型写正文,所以总长度仍然守得住 maxTitleChars。
不管选哪种结构,硬性要求都不变:只输出一行纯文本,不加引号、前缀或 Markdown,语言跟随对话。结构只换措辞,不会把生成结果弄脏。
早先版本里的 english / dated 两个结构值仍然被接受:english 照旧输出英文标题,dated 等价于「主题 + 打开 datePrefix」,所以旧配置升级后不会挂。
这一页由插件自己注册(settings.section),读写的就是插件自己的配置项 ai-session-title,和下面手写 cordis.patch.yml 完全等价。
少数高级项不放在设置页里,需要时写进 profile 的 cordis.patch.yml:
- id: ai-session-title
name: dsh-ai-session-title
config:
provider: deepseek
model: deepseek-chat
maxOutputTokens: 1024
| 键 | 含义 |
|---|---|
provider / model |
强制指定路由。要么都配、要么都不配;默认按下一次请求的路由,取不到再用最新一条助手消息的路由。 |
timeoutMs |
生成超时,默认 60000。 |
maxOutputTokens |
单次调用的输出预算,默认 1024。思考型模型如果先思考、把预算耗光才轮到你看到的标题,会报 max-tokens,把它调大即可。 |
兼容性
engines.dsh 声明为 ^0.2.1-rc.3。DSH 只按 engines.dsh 判断兼容性(没有该字段时才回退到 @deepseek-ai/dsh-* 的 peer 范围),插件市场的卡片上也会显示这个要求。
这个插件在运行时只导入一个 @deepseek-ai/* 包:host 半边用 @deepseek-ai/schemastery 声明 Config(harness 自带),其余只用 ctx.commands / ctx.llm;client 半边只用 ctx.remote 和 DOM API。好处是任何 profile 都不需要额外装依赖就能加载;代价是如果上游改了这些服务的签名或重命名对话框的结构,就需要跟着发新版本。
开发
npm test # host 半边的冒烟测试,不需要 harness、也不需要模型
client 半边没有构建步骤:client.js 按原样被加载。改完刷新 Web 界面即可(profile 里是 link: 安装,不用重装)。
目录结构
cordis.patch.yml 把行 id `ai-session-title` 插入为本包
index.js host 半边(命令 + 生成)
client.js client 半边(就地装饰 + 远程调用)
test/host.smoke.mjs host 半边冒烟测试(npm test)
locale/*.json 插件展示信息(标题 / 描述)
icon.svg 插件图标
screenshots.json 市场卡片用的截图声明
docs/screenshot.png 截图
常见问题
按钮没出现? 确认插件已启用、刷新过页面,且 dsh 版本满足 ^0.2.1-rc.3。
报「模型没有返回可用的标题」? 多数是思考型模型把输出预算全用在推理上,调大 maxOutputTokens。
报「无法确定要命名的会话」? 说明输入框里的标题在会话列表里匹配不到(例如同名的会话刚被改名)。先在侧栏打开该会话再试一次。
License
MIT,见 LICENSE。