npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-session-title

v0.1.0

Published

DeepSeek Harness 插件:给模型一个按使用者自定义规则设置会话标题的工具,规则在设置页「会话标题」里配置

Readme

dsh-session-title

简体中文 | English

DeepSeek Harness 插件:给模型一个按你自己定义的规则设置会话标题的工具。

装上后,模型可以主动把当前会话标题改成你要的格式(比如 0924 | v0.1.0 | 修复登录跳转),并钉住它——之后不会再被自动生成的标题覆盖。

默认是关闭的。 插件会往模型的工具目录里增加一个工具,属于对模型上下文的改动,所以装上不会立刻生效。安装后在 设置 → 会话标题 里勾选「启用」并保存即可(详见安装)。

安装

dsh plugin --profile web add dsh-session-title

装完重启 dsh 进程——bundle 集合变化不会热加载。

然后:

  1. 打开 Web 界面 设置 → 会话标题;
  2. 按需修改「标题正则」(不会写就让 LLM 帮你写);
  3. 勾选「启用」并保存。

想省掉第 3 步、装上即用,就在 profile 的 config: 里写 enabled: true(见用配置文件预设)。

手动安装

如果 dsh 不在 PATH,或用的是 DSH Desktop / 源码检出,也可以直接编辑 profile 的 ~/.dsh/profiles/web/package.json:

{
  "dsh": { "profile": { "bundles": [ /* …, */ "dsh-session-title" ] } },
  "dependencies": { "dsh-session-title": "^0.1.0" }
}

然后在 profile 目录执行 pnpm install(或 npm install)、重启。

不需要任何构建步骤:client 侧产物 lib/client.js 已随包提供。

它解决什么

DSH 本体把会话重命名做成了 Host 能力(ctx.sessionTitle 服务 / session/rename Remote),但面向模型的工具目录里没有改名工具,所以过去只能由人在侧栏手动改。本插件补上这一个工具:set_session_title。

命名规则不写死在代码里,由你在设置里配置,因此可以适配任意仓库、任意团队的约定。

行为

| 项 | 说明 | |---|---| | 工具名 | set_session_title,参数 title(完整标题) | | 生效 | 调 ctx.sessionTitle.rename(agent.session, title);校验通过即写入并钉住标题 | | 副作用 | 钉住后该会话不再自动生成标题 | | 不做的 | 不读写会话文件、不碰工作区、不做归档/删除 |

不合规的标题会作为工具错误返回明确原因,模型据此改写后重试。

配置规则

配置有两条途径:设置页(推荐,改完即时生效)或 profile 的 config:。两者写的是同一份配置,都无需重启。

| 配置项 | 类型 | 默认 | 说明 | |---|---|---|---| | enabled | boolean | false | 是否启用;关闭后模型看不到这个工具(运行中切换即时生效) | | pattern | string | ^(\d{4}) \| ([^\|]+) \| ([^\|]+)$ | 标题必须匹配的正则(JS 语法,不带动界符) | | patternMode | match / search / none | match | match 全串匹配;search 允许包含;none 关闭正则校验 | | patternHint | string | "" | 正则不匹配时给模型看的提示,留空用默认提示 | | maxTitleBytes | number | 80 | 整标题的 UTF-8 字节上限 | | forbidTrailingPunctuation | boolean | true | 禁止以句末标点结尾 | | forbidControlCharacters | boolean | true | 禁止换行、制表符等控制字符 | | normalizeSeparatorSpacing | boolean | true | 把 \| 前后的空白规范化为单空格 | | caseInsensitive | boolean | false | 正则忽略大小写 |

默认规则是 MMDD | 版本或 tag | 描述,只是个开箱即用的示例——改成你自己的约定即可。

未启用时设置页会明确提示「当前未启用:模型看不到 set_session_title 工具」,不会让人误以为插件坏了。正则字段始终会预填当前值,所以你可以先把规则调好、再打开开关。

改动规则后,工具说明会自动重写:模型看到的描述里会带上当前生效的正则和字节上限,因此它不必盲猜格式。

不会写正则?让 LLM 帮你写

设置页说明文字下方有个折叠块「示例提示词:让 LLM 帮你写一条正则」,点开是一段可直接复制的提示词,末尾留了「我的命名需求」让你填。复制后发给任意 LLM,把返回的正则粘进「标题正则」字段即可。

提示词里刻意写死了几条输出约束(不带 / 定界符、不带 flags、不要代码块、不要解释、用 ^/$ 锚定整串、段内不含竖线用 [^|]+),否则模型经常返回没法直接粘贴的东西。它也明确说了「句末标点、字节长度、换行不用你管」——那些是本插件另外的开关,不需要塞进正则。

完整提示词(与插件内一致):

我在用 DeepSeek Harness 的 dsh-session-title 插件管理会话标题,需要你帮我写一条校验标题的正则。

请只输出正则本身:一行、不带 / 定界符、不带 flags、不要代码块、不要解释。并且:
1. 用 ^ 和 $ 锚定整串;
2. 需要单独校验的分段用括号 () 捕获;
3. 某段不允许出现竖线 | 时,用 [^|]+ 表示(| 是分段分隔符);
4. 不要处理句末标点、字节长度、换行 —— 这些插件会另外校验。

我的命名需求:<在这里描述你的规则,例如「以 BUG- 或 FEAT- 开头,接一个数字,然后一个空格加简短中文描述」>

参考:插件当前的默认正则是 ^(\d{4}) \| ([^|]+) \| ([^|]+)$ ,含义是「四位日期 | 版本或 tag | 描述」。

用配置文件预设

想跳过设置页、直接预设初值,就编辑 profile 的 cordis.patch.yml(这是 schema 默认值的覆盖):

- insert:
    - id: session-title-tool
      name: dsh-session-title
      config:
        enabled: true
        # 用 [BUG]/[FEAT] 前缀
        pattern: '^\[(BUG|FEAT)\] .+$'
        maxTitleBytes: 60
      config:
        enabled: true
        # 完全不校验格式,只保留字节上限与标点规则
        patternMode: none
        maxTitleBytes: 120

关于 maxTitleBytes

宿主 session-title 服务的 maxTitleBytes 是硬上限:rename() 会按它做归一化和截断。本插件的 maxTitleBytes 是前置校验,应设置为小于或等于宿主配值,否则模型会拿到一个通过了本插件校验、却被宿主截断的标题。

base 组合里宿主配值是 80(packages/bundle/base/cordis.patch.yml),所以这里默认也取 80。

设置页

插件由两部分组成,设置页注册为 Web 设置面板里的一个独立分区:设置 → 会话标题。

| 侧 | 入口 | 作用 | |---|---|---| | host 侧 | index.js | 注册 set_session_title 工具、校验规则、接入 settings 命名空间 | | client 侧 | lib/client.js | 注册 settings.section 分区,渲染规则表单 |

工作机制:

  • 命名空间就是插件在 profile 里的条目 id,即 session-title-tool(见 cordis.patch.yml)。client 侧读不到 host 侧的条目 id,所以这个字符串在 lib/client.js 里也写了一份——改名要同时改两处(有测试锁住这条)。
  • 读写通道:ctx.configForms(ui-settings 提供的 client 服务,背后是 settings Remote),与官方 ui-settings-subagent 等设置页同款,不需要自建 HTTP 路由。
  • 门控:configForms.whileServed([ns], …),宿主确实提供该命名空间时才注册分区,避免出现空页面。
  • 即时生效:写入的是同一份配置引用,无需重启;工具说明也会同步刷新。

client 侧是手写 bundle(零构建)

lib/client.js 是手写的 CJS bundle,刻意不引入 TypeScript / tsdown / JSX 构建链:

  • 产物格式与 DSH 内部 packages/client/tsdown.client.ts 的 banner/footer 一致:window.__ModuleLoader__.load({ id, factory });
  • 运行期只 require('react')(来自平台模块表 packages/client/web/src/platform.ts),组件用 React.createElement、样式用内联对象;
  • 所以本地 link: 安装时改完即生效,不需要 build。

package.json 里的声明是加载器的发现入口,任何一处不对都会表现为「设置页静默不出现」:

"exports": { "./client": "./lib/client.js" },
"dsh": { "client": { "platform": "web", "inject": [ /* … */ ] } }

卸载

dsh plugin --profile web remove dsh-session-title

或从 profile 的 dependencies 与 dsh.profile.bundles 里移除,重装依赖后重启。已经钉住的标题不受影响。

自测

npm test

host 侧(test/smoke.test.mjs):Config 字段与 volatile 标记、可配置规则(正则/上限/开关)的行为、非法正则的加载期报错、注册形态契约、execute 成功与失败路径、出厂默认关闭、enabled 运行时增删工具、工具说明随规则刷新、插件卸载时注销工具、最小宿主兼容性。

client 侧(test/client.test.mjs):bundle 形态符合 __ModuleLoader__ 契约、dsh.client 声明满足加载器扫描规则、分区注册到正确的命名空间、组件用真实 React 渲染出全部字段、示例提示词与「未启用」提示确实渲染、以及真实 DOM 交互(改字段 → 保存 → 断言写入收到正确的字段与类型)。

几条值得注意的回归测试:

  • 用 output.schema 校验 execute 的返回值——这正是不依赖 Harness 包的测试最容易漏、却唯一能捕获「返回值与输出契约不符」的地方;
  • client 侧表单字段名与 host 侧 Config 字段逐一对应——错一个就会被 host 侧校验拒绝;
  • enabled 的 schema 默认值与 resolveRule() 的兜底值必须一致,否则「默认关闭」会有两种答案;
  • 有一项用 DSH 检出里真实的 volatileForm 投影验证设置表单确实能生成;找不到检出时自动跳过(DSH_CHECKOUT 可指定路径),因此单独克隆本仓库也能跑通。

实现备注

host 侧(index.js)

  • 运行期只依赖三个宿主接口:ctx.tools.register、ctx.sessionTitle.rename、ctx.on('loader/volatile-update')。唯一依赖是声明 Config 所必需的 @deepseek-ai/schemastery。
  • parameters 使用原始 JSON Schema,与 DSH 内置的 MCP 客户端桥接做法一致:ctx.tools.register() 只校验 output.schema,parameters 原样投影给模型。
  • output.schema 是 { type: 'string' },execute 返回标题字符串(从 rename() 的 snapshot 上取 .title)。注册表会用该 schema 校验返回值,返回 snapshot 对象会直接抛 ToolOutputError——副作用已经写入却报失败。
  • 注册返回的注销函数必须自己挂到 ctx.effect 上:ctx.tools.register() 内部用的是 ToolRuntime 自己的 context,插件卸载时不会自动清掉本次注册。
  • 规则读取走 Volatile.get();enabled 和 pattern 的改动经 loader/volatile-update 触发同步重注册,所以对运行中的实例立即生效,工具说明也始终反映当前规则。

client 侧(lib/client.js)

  • 手写 CJS bundle,零构建;只 require('react'),组件用 React.createElement、样式用内联对象。
  • 用 useSyncExternalStore 订阅 ctx.configForms 的 ConfigForm,并传第三个参数 getServerSnapshot,让组件在 SSR / 预渲染路径下同样成立。
  • 本地编辑层叠加在 host 侧值之上({...hostValue, ...edits}),所以别处的写入不会覆盖用户正在改的内容;保存时逐字段 form.set(),由 host 侧的 Config 整份校验把关。