WASD258-jpg/dsh-context-surgery
Surgical rewriting of the model-visible conversation history of a DSH session (surface replacement). Edit reply vs reasoning chain separately.
これは DeepSeek Harness(DSH)プラグインです。当サイトは GitHub README、インストール情報、メンテナンス状況、公開セキュリティシグナルをまとめています。
dsh-context-surgery
English | 中文
强制改写 DSH 会话的模型可见历史(surface 替换)。剧情扮演 AI 跑偏(OOC)时把回复改成没跑偏的 版本、retcon 整场戏、修正措辞——模型下一轮请求读到的就是改后的历史,仿佛从未发生过。 回复正文与思考链(reasoning)分开编辑。
社区插件——非 DeepSeek 官方组件,不代表 DeepSeek 背书。
功能
- 每条 AI 消息下方的操作按钮——聊天视图中每条 AI 消息的操作行(插槽
conversation.chat.assistant-actions,order 20):✏️ 改回复、💡 改思考链、🗑️ 删除。 💡 仅在消息确实带 reasoning 块时出现。 - 回复与思考链分开编辑——
part=reply只改 text 块(保留思考链与工具调用);part=thinking只改 reasoning 块(留空 = 全部移除);part=all整条重写为纯文本。 /context命令全家桶——list / edit / think / clear-think / rewrite / delete / replace, 聊天输入框即可完成一切操作。- 模型可调用工具——
context_list/context_edit/context_delete/context_replace, 把同样的能力交给 agent 本身(可用于自我纠错循环)。 - HTTP API——
/api/dsh-context-surgery下的GET /list、GET /message、POST /edit|/delete|/replace,供客户端编辑条使用。 - 立即生效——模型下一轮请求读到改后的历史,GUI 对话视图重新折叠显示改后的版本。
- 日志 append-only——原始文本从不被抹除;每次改写都是影蔽旧节点的新日志事件, 随时可从日志还原。
- 仅限顶层会话——子代理一律拒绝(
requireRootAgent)。
安装
需要 DSH web profile(@deepseek-ai/dsh-web-app)与 Node >= 22.19.0。
-
克隆或下载本仓库:
git clone https://github.com/WASD258-jpg/dsh-context-surgery.git -
安装到 DSH profile 依赖目录(二选一):
方式 A:npm 安装(推荐)
cd "$env:USERPROFILE\.dsh\profiles" npm install @wasd258/dsh-context-surgery --no-save方式 B:从源码复制
$src = '.\dsh-context-surgery' $dst = "$env:USERPROFILE\.dsh\profiles\node_modules\@wasd258\dsh-context-surgery" New-Item -ItemType Directory -Force -Path "$dst\lib" | Out-Null Copy-Item "$src\package.json" $dst -Force Copy-Item "$src\lib\index.js","$src\lib\client.js" "$dst\lib" -Force Copy-Item "$src\LICENSE","$src\NOTICE" $dst -ForceLinux/macOS 用
~/.dsh(或$DSH_HOME)代替$env:USERPROFILE\.dsh。 -
把包名追加到 profile 的
package.json的dsh.profile.bundles数组,注册为 bundle:{ "name": "dsh-profile-web", "private": true, "dependencies": {}, "dsh": { "profile": { "bundles": [ "@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "@wasd258/dsh-context-surgery" ] } } } -
重启一次 DSH web(或运行时热装配 bundle),然后刷新浏览器页面以加载客户端模块 (
lib/client.js)。
使用
UI:每条消息的操作
- 在 DSH web 打开一个运行中的顶层会话。
- 悬停某条 AI 消息的操作行:✏️ 改回复、💡 改思考(仅当存在 reasoning 块)、🗑️ 删除。
- 点 ✏️ 展开内联文本框(预填当前回复正文);修改后点保存 → “回复已改写 ✓”。 思考链与工具调用不受影响。
- 点 💡 在文本框里编辑思考链;留空保存 = 移除 → “思考链已改写 ✓”。
- 点 🗑️ 弹出确认(“删除这条消息(模型视角消失,原始文本仍在日志)?”)→ “已删除 ✓”。
/context 命令
/context(或 /context list、ls、?)列出当前模型可见历史——最后 10 条带 seq:
模型可见上下文共 10 条(显示最后 10 条):
[1] YOU 你好,来扮演图书馆管理员吧。
[2] AI 好的,欢迎光临。今天想找什么书?
[3] YOU 讲讲那本被禁的书。
[4] AI [reasoning] 主角不该知道这本书……那本书只是传说。
[5] TOOL [tool-call toolu_01ABC…]
[6] TOOL [tool-result] {"found": false}
[7] AI 抱歉,馆里没有这本书的记载。
[8] YOU 你刚才不是这么说的。
[9] AI 我记错了,请您原谅。
[10] YOU 继续吧。
行格式 [seq] AI|TOOL|YOU <预览>(预览截断到 120 字符;AI=assistant,TOOL=tool/result,YOU=user)。
| 命令 | 作用 |
|---|---|
/context edit <seq> <文本> | 只改回复正文(保留思考链)。→ 已改写 [7] 的回复正文(思考链保留):下一轮模型请求将看到新文本。 |
/context think <seq> <文本> | 只改思考链(保留回复正文)。→ 已改写 [7] 的思考链(回复正文保留)。 |
/context clear-think <seq> | 移除思考链。→ 已移除 [7] 的思考链。 |
/context rewrite <seq> <user|assistant> <文本> | 整条重写为纯文本(part=all)。→ 已整条重写 [7] 为 user 消息:下一轮模型请求将看到新文本。 |
/context delete <seq> | 删除该节点(以空 assistant 消息影蔽)。→ 已删除 [7](assistant/message):从模型视角消失。 |
/context replace <start> <end> <user|assistant> <文本> | 整段连续节点替换为一条新消息。→ 已整段替换 [3,4] 为一条 assistant 消息。 |
错误以 操作失败:<原因> 或 未知子命令:<op> 返回;seq 必须是整数(否则
seq 必须是整数:<值>)。
part 语义
| part | text 块 | reasoning 块 | 其他块(tool-call 等) | 适用 |
|---|---|---|---|---|
reply(默认) | 替换 | 保留 | 保留 | user、assistant |
thinking | 保留 | 替换;留空 = 全部移除 | 保留 | 仅 assistant(用户消息没有思考链,会被拒绝) |
all | 整条变成单一 text 块 | 丢弃 | 丢弃 | user、assistant |
工具
| 工具 | 参数 | 说明 |
|---|---|---|
context_list | limit? | 按顺序列出全部 surface 节点(或最后 N 条),含 seq/role/text |
context_edit | seq、text、role?、part? | part 默认 reply;role 缺省沿用原节点角色 |
context_delete | seq | 以空 assistant 节点影蔽 |
context_replace | start、end、role、text | start/end 含端点;都必须是当前 surface 节点 |
示例:context_edit { "seq": 7, "part": "reply", "text": "…" } →
{ "ok": true, "replacementSeq": 11, "shadowedSeq": 7, "role": "assistant", "part": "reply", "text": "…" }。
失败返回 { "ok": false, "error": "…" }。
HTTP API
路由统一挂在 /api/dsh-context-surgery 下:
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /list | surface 节点;?sessionId=&limit=(limit = 最后 N 条;省略或 0 = 全部) |
| GET | /message | 单条消息拆分为 reply / reasoning;?sessionId=&messageId= |
| POST | /edit | 改写单条;body { sessionId, seq|messageId, part?, role?, text } |
| POST | /delete | 删除单条;body { sessionId, seq|messageId } |
| POST | /replace | 整段替换;body { sessionId, start, end, role, text } |
/edit 与 /delete 接受 seq 或 messageId(/edit 的 part 仅 thinking/all 生效,
其余回退为 reply)。
GET /list?sessionId=abc&limit=3 →
{ "ok": true, "sessionId": "abc", "total": 12, "rows": [
{ "seq": 10, "type": "user/message", "role": "user", "text": "…" },
{ "seq": 11, "type": "assistant/message", "role": "assistant", "text": "…", "messageId": "msg_…" }
] }
GET /message?sessionId=abc&messageId=msg_… →
{ "ok": true, "sessionId": "abc", "seq": 11, "messageId": "msg_…",
"type": "assistant/message", "role": "assistant",
"reply": "回复正文", "reasoning": "思考链", "hasReasoning": true }
POST /edit,body { "sessionId": "abc", "seq": 11, "part": "thinking", "text": "…" } →
{ "ok": true, "replacementSeq": 15, "shadowedSeq": 11, "role": "assistant", "part": "thinking", "text": "…" }
错误情况:
| 状态码 | 条件 |
|---|---|
| 403 | 非回环源地址(context-surgery API is loopback-only) |
| 403 | Host 头不是回环主机名/当前端口(invalid host header,防 DNS rebinding,GET/POST 一视同仁) |
| 403 | 跨源页面发来的 POST(cross-origin request rejected) |
| 404 | 会话不在运行(会话 X 不在运行中)/ messageId 不在 surface / 未知路由 |
| 415 | POST 未带 Content-Type: application/json |
| 400 | JSON 无效,或请求体超过 256 KiB |
200 + ok:false | 操作级失败(seq 已被影蔽、tool/result 节点、对用户消息用 thinking 等) |
| 500 | 服务器内部错误 |
工作原理
lib/index.js(host 端)注册/context命令、四个context_*工具与 HTTP 路由;lib/client.js(web 端)通过conversation.chat.assistant-actions插槽注入每条消息的操作按钮。- 模型的消息列表由会话日志的 surface 折叠而来(
Session.deriveMessages()→ 请求组装)。 日志 append-only,但 surface 支持位置替换:append 一个带surfaceOp: { op: "replace", start, end }+sourceEventSeqs(覆盖全部被影蔽节点)的新事件, 即可替换该段 surface——compaction 压缩总结用的正是同一条缝。 - 改写后:模型下一轮请求读到改后的历史;GUI 对话视图重新折叠;原始文本仍完整保留在事件日志里, 可查可还原。
- 只能改写运行中的顶层会话;子代理一律拒绝。
- 影蔽区间若包含工具调用,后续轮次引用旧记录可能对不上——优先单条改写;
tool/result节点不可改写(请改用户消息或 AI 回复)。
隐私与安全
- HTTP API 仅限本机回环且设计上无鉴权:任何本地进程都能读取会话内容(含思考链)并驱动 历史改写。请在可信的本机环境运行 DSH。
- Host 头 + 同源校验防 DNS rebinding 与跨站请求;写路由额外要求
Content-Type: application/json。 context_*工具把“改写自身历史”的能力交给了模型——仅在信任模型及其输入不会被 prompt injection 控制时启用(被注入的模型可能被诱导隐藏或篡改历史)。- 无遥测、无外部网络请求、不读写凭据。
兼容性
- 需要 DSH web profile;在 DeepSeek Harness
47f9438时代实测。 - Node >= 22.19.0;版本 0.1.1;MIT。
- 历史改写走会话 surface 替换缝(与 compaction 同机制);事件日志本身从不被修改。
官方生态要求
按 DeepSeek 当前建议,社区插件发布在各自的 GitHub 仓库并添加
dsh-plugin topic 以便被发现。官方仓库不接受外部 PR,
也不强制社区插件模板。参见
CONTRIBUTING.zh.md。
许可
セキュリティとインストールエビデンス
このスコアは公開リポジトリメタデータと当サイトに登録されたインストールエビデンスのみに基づくもので、コードセキュリティ監査とは異なります。
公開プラグインカタログから取得し、公開 GitHub リポジトリにリンクしています。
GitHub メタデータにライセンスが検出されませんでした。
過去180日以内にコードの更新があります。
再現可能な正確なインストールメタデータはまだ登録されていません。リポジトリの説明に従って手動で確認してください。
確認したパッケージメタデータにインストールライフサイクルスクリプトは宣言されていません。
missing-license