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-revise-chan

v0.2.4

Published

让 dsh 可以修改 AI 回答内容 + 显示大纲悬浮栏:回答署名、修订分支、悬浮大纲

Readme

dsh-revise-chan(修订酱)

English | 中文

npm version license dsh

让 dsh 可以修改 AI 回答内容 + 显示大纲悬浮栏。

给 DeepSeek Harness(dsh)的对话补上三件「把回答当文稿来管」的事:署名、修订、目录。

悬浮大纲:按钮钉在对话区右上角,点开是贴着右侧的轮次列表,当前轮高亮

  • 署名:每条回答下方的时间行末尾补上 模型 | 提供方,取自这一轮回答的 token 计量归属(turn-tail.tokenUsage.routes,即真正被计费的那次路由;Chat 折叠没有这条时回退到消息自带的 providerMetadata)。
  • 修订:复制按钮右边多一支铅笔。点开一个应用内对话框改回答正文,保存后从这条回答的提问处新建分支——新分支里这条回答就是你改写的正文,而且沿用原标题(你始终待在"同一条对话"里);被取代的旧会话加上 ·<修改时间> 后缀并归档。
  • 目录:对话区右上角有一个悬浮的「大纲」按钮,点开是贴着对话列右侧的悬浮列表:每个已开始的轮次一行(提问 1 行 + 回答 2 行预览,纯图片/纯命令的轮次回落成轮次号),当前轮高亮,点任意一条跳到该轮(未载入的轮次会先按 turnOutline 的 seq 把历史翻页到那一轮)。面板用满对话栏高度、底部停在输入框上方,点面板与其按钮之外的任意处(或 Esc / ✕ / 再点按钮)收起。它是悬浮窗而不是右侧栏页签——不占用列宽、不必打开侧栏,也不会遮挡宿主的悬停刻度条(那个我们一行都没碰)。

安装

从 npm:

dsh plugin --profile web add dsh-revise-chan

直接从 GitHub:

dsh plugin --profile web add github:shellexy/dsh-revise-chan

本地源码(改完即用,无需构建):

git clone https://github.com/shellexy/dsh-revise-chan.git
dsh plugin --profile web add ./dsh-revise-chan

装完重启正在运行的 dsh web(Host 半需要重启才能加载 revise-chan Remote;Browser 半刷新页面即生效)。

兼容性

  • 目标 dsh 0.2.0-rc.2(0.2.x 的 session / surface / slot 契约)。纯 JavaScript、无构建步骤、无 npm 依赖:Host 半不 import 任何包(Remote marker 与 Typert binding 手工安装,见下),Browser 半只 require('react')。
  • 未在 0.1.x 上验证:0.1.x 的 surface 契约与 Remote endpoint 形状不同,revise 依赖 0.2.x 的行为。

功能 2 到底做了什么

dsh 的会话日志是只追加、深度冻结的,而且 assistant/message 不能做 surface replacement(它要求引用被遮蔽的节点,又禁止携带 sourceEventSeqs),所以「改写历史里那条回答」在 0.2.x 上无法字面实现。dsh-revise-chan 改用一条完全申报的路径:

  1. revise-chan/plan 在来源会话的日志里定位这条回答所属轮次的人类提问事件序号(只有 source.kind === 'user' 的 user/message 才算)。
  2. Browser 半在那一格 sessions.fork({ atSeq })——子会话原样继承到提问为止(连标题一起):提问还在,原回答不在,子会话自己的 turn/end 由 fork 合成闭包补上。
  3. revise-chan/revise 往这个还活着的子会话里追加一个完整轮次:turn/start(沿用该轮轮次号)→ step/start → assistant/message(正文=你的修订稿,沿用原消息 id、provider、model,保留思考块与图片,丢弃工具调用)→ step/end → turn/end。

一次真实修订在日志里长这样:

源会话
  0:turn/start(1) 1:user/message 2:step/start 3:assistant/message 4:step/end 5:turn/end
  6:turn/start(2) 7:user/message(提问) 8:step/start 9:assistant/message(原回答) 10:step/end 11:turn/end

fork(atSeq=7) 分支继承
  0:turn/start(1) … 5:turn/end  6:turn/start(2) 7:user/message 8:session/end-seed 9:turn/end(fork 合成闭包)
  → 折叠:[提问1, 回答1, 提问2]

revise 追加
  10:turn/start(2) 11:step/start(2,1) 12:assistant/message(修订稿) 13:step/end 14:turn/end(2)
  → 折叠:[提问1, 回答1, 提问2, 修订后的回答]

结论:模型可见历史(surface 折叠)在分支里读作 …, 提问, 修订后的回答;旧事件一条没动,压缩摘要、token 计量、轨迹视图都照常。沿用同一轮次号还有一个好处:宿主 Agent 在 fork 时就已把下一轮号定为 N+1,分支里继续发消息不会和这条修订回答撞号。

已知边界

  • 修订会丢掉原轮次的工具调用链:那些工具确实属于被丢弃的分支,新分支不能替它们认领结果。思考块与图片保留。
  • 压缩摘要已经吞掉该轮时无法修订:宿主返回 message-not-found,对话框照实说明。
  • 会话标题有 UTF-8 80 字节上限(session-title 的 maxTitleBytes),宿主是截断而不是拒绝。所以插件先把原标题按字节裁到 62 字节再补 ·YYYY-MM-DD HH:mm,避免宿主的截断吃掉时间戳后缀;同一会话反复修订时,旧时间戳后缀会先被剥掉再重新加。
  • 大纲的「跳到某轮」「当前轮次高亮」以及悬浮按钮的落位,都依赖宿主为自身锚点发布的 [data-conversation-scroll] / [data-chat-turn] 属性;日后改名只会让这三件事失效(按钮不出现、列表不跟随),大纲数据本身不受影响。
  • 悬浮窗的位置与高度都是量出来的:贴着对话滚动区右上角,高度用满「滚动区减去 composer」(宿主在滚动区上发布 --dsh-composer-height,读不到时退回刻度条同款 152px),所以不会盖住发送按钮。对话视图没挂载(比如切到别的面板或轨迹视图)时它整体消失——大纲本来只服务于对话流。
  • 每行是一行提问 + 两行回答预览(宿主刻度条同款密度),不再占用一行显示「第 N 轮」;只有该轮既无提问也无回答预览时(纯图片、纯命令的轮次),才用轮次号占那一行,轮次号同时留在悬停提示与 aria-label 里。
  • 点面板与按钮以外的任何地方会自动收起(pointerdown 捕获),点面板内部(换一轮跳转)不会收起;Esc 、✕、再点按钮同理。每个会话记得自己上次的开关状态(仅本次页面生命周期内)。

实现说明

| 文件 | 职责 | |---|---| | index.js | Host 半:revise-chan Remote 命名空间(plan / revise)。Remote marker 直接按 @deepseek-ai/dsh-typert-protocol/remote-methods 的描述符安装,因此纯 JavaScript 无需装饰器或 typert 生成物。 | | client.js | Browser 半:署名与编辑按钮(conversation.chat.assistant-actions)、编辑对话框(shell.overlay)、大纲数据桥(conversation.input.dock,只发布不渲染)与悬浮大纲(shell.overlay)。 | | cordis.patch.yml | 把 dsh-revise-chan 这一行插进 profile 的 Loader 配置。 |

Browser 半只 require('react'),不引用任何 Harness Client 包;样式全部走 --dsw-* 主题 token,界面文案走 locale.register 的中英文词典。

为什么 Host 半零 import

dsh plugin add <本地路径> 装进 profile 的是 link:,Node 会从真实路径解析裸包名,于是 @deepseek-ai/dsh-typert-protocol 这类包解析不到(加载时报 "failed to import")。所以 Host 半不 import:

  • Remote 方法标记 = 往原型上装一个 '@deepseek-ai/dsh-typert-protocol/remote-methods' 描述符({ version: 1, methods: [{ method, invocation: { kind: 'direct' } }] });
  • 服务注册 = ctx.provide('revise-chan', instance),实例自挂 typertRemote = { service, serviceKey, namespace }。

网关的 SRC 发现读的就是这两样东西,行为与 TypertRemoteService + @Remote 装饰器等价。

已验证到什么程度

可复跑的部分都在 tools/:三个离线验证(宿主半发现与行为、引擎折叠语义、Browser 半注册与保存事务)和一个端到端验证(启一个一次性 profile,走真实 Typert Gateway)。

bash tools/verify-all.sh          # 离线:不需要模型,不联网
bash tools/verify-all.sh --e2e    # 再启一次性 profile 走真实网关

在 dsh 0.2.0-rc.2 上的结论:

  • 真实网关:ctx.typertGateway.invoke({ namespace: 'revise-chan', method: 'plan' | 'revise', args: { request } }) 可解析并执行;分支折叠为 [提问, 修订后的回答],turnBoundary.lastTurn 保持原轮次号(后续轮次不撞号)。
  • 真实引擎:buildForkSeed + Session.create 复现「提问处 fork + 追加同轮修订回答」,deriveMessages() 与上面一致,且继承前缀逐事件与来源相同。
  • Browser 半:tools/lib/mini-react.mjs 提供带状态与副作用的最小 React 运行时,因此验证覆盖到交互本身——署名文本、铅笔禁用态与交接、对话框草稿、大纲按钮出现、面板展开/列轮次/高亮当前轮/点未载入轮次先翻页再滚动/关闭/会话卸载后撤回;saveRevision 的 RPC 载荷、fork 边界、新标题规则(只给被取代的会话加时间戳)与归档顺序也全部断言。
  • 未验证:真实浏览器里的布局、配色与悬停观感——那部分需要人眼。