DeepSeek Harness 插件

dsh-conversation-rail

对话左缘的导航轨:一根杠一轮对话,杠长按该轮文字体量,悬停出提问与回答预览,点击跳转;杠来自 host 侧读整份会话日志折出的大纲,未加载进窗口的轮次也画得出来,点击时再翻页补历史。

跳到安装方式

来源信息

GitHub 仓库
dingyi580/dsh-conversation-rail
最近更新
2026年8月18日
分类
界面增强
GitHub stars
0

安装

默认先复制一段 Prompt,让 Agent 读页面和仓库;需要自己装时再切到命令。

复制这段 Prompt,发给 DSH、Codex 或其他 Agent,让它先读页面和仓库。

请先不要安装。阅读这个 DeepSeek Harness 插件,说明它解决什么问题、会访问哪些文件、网络或密钥,以及如何安装和卸载。

插件页面:https://deepseekplugins.org/zh/plugins/dingyi580/dsh-conversation-rail
GitHub:https://github.com/dingyi580/dsh-conversation-rail
插件名:dsh-conversation-rail
作者:dingyi580
安装命令:dsh plugin --profile web add github:dingyi580/dsh-conversation-rail

确认前不要执行安装命令。

检查来源文件

安装前先看这个插件目录里的 README 和其他文件。

文件资源管理器3 个文件
README.md来源说明 · 只读预览

dsh-conversation-rail · session minimap

English | [中文](README.zh.md)

A locator for long conversations in DSH Web. A vertical rail sits along the left edge of the conversation, one bar per turn; hover a bar for a preview card, click it to jump to that turn.

  ▏─────                 ┌──────────────────────────────┐
  ▏───────────           │ Can you patch this without…  │  ← question (one line, dark)
  ▏━━━━━━━━━━━━━━  ◀━━━━━┤ CRLF is already ruled out…   │
  ▏──────                │ only the legal re-encodes…   │  ← answer (up to four lines, dimmed)
  ▏────────              └──────────────────────────────┘
  • Bar length = how much text that turn holds (square-root compressed, 10–34px).
  • The bold bar = the turn currently at the top of the scroll area.
  • The preview card carries prose only: your question plus the assistant's plain

text. Fenced code blocks, tool calls, shell commands, reasoning traces and injected context never reach the card — you cannot skim JSON.

It draws the whole session, not the loaded window

Conversation history is paginated: the front-end snapshot usually holds only the most recent stretch, so an 8-turn session may have 1 turn in the window. The rail is not bound by that:

  • The skeleton comes from the host's outline endpoint

(GET /dsh-conversation-rail/api/outline?sessionId=). The host reads the full log with ctx.sessionQuery.readSession(), folds it into a table of contents of roughly a hundred bytes per turn, and returns that — the history itself never crosses the network.

  • The live snapshot overrides the part that is loaded: it carries jumpable DOM

anchors, and for a turn that is still streaming it is the only current source. The two are aligned by the user/message event seq, live winning over outline.

  • Clicking a bar that isn't loaded yet calls session.loadOlder() repeatedly

until that turn enters the window, then jumps. The bar pulses while paging, with a ceiling of 40 pages — better to not reach a turn than to page through an entire log because of one click.

The outline uses readSession rather than the lighter filterEvents because the latter does not return source. The user/message event type carries both real questions and context injected by agent.inject() (file-change notices, AGENTS.md, skill bodies…); the official docs state all three project content verbatim and are told apart by source. Without that field, injected context would be drawn as turns.

How it attaches

It takes one seat: conversation.session.header.utilities. Not to draw anything in the header — that slot is session-scoped, so the component receives the framework's useSession snapshot hook and sessionId, and its lifetime follows the session. The component renders null in the header; the actual rail is a fixed overlay on body, aligned to the measured rectangle of [data-conversation-scroll]. It stays out of the host layout, so switching skins, collapsing the sidebar or changing the grid cannot squeeze it.

Turn data comes from ConversationSnapshot.chat: walk order, open a turn on a user node, attribute the following assistant-step text blocks to it. Jumping uses the host's own anchors ([data-chat-anchor-key]), the same path its internal scroll positioning takes.

Known boundaries

  • The outline is fetched once per session. New turns arrive through the live

snapshot and do not trigger a refetch; only leaving and returning to the session refetches (a 5-second host-side cache absorbs the back-and-forth).

  • Jumping to a very early turn loads every page between it and the window.

That is what pagination means: to show turn 1, everything from there up to the loaded window has to come in. Jumping to recent turns pages almost not at all.

  • If the outline endpoint fails, the rail degrades to drawing only the loaded

stretch rather than disappearing.

  • Previews are rendered as plain text, not markdown: leading #, -, 1. and

emphasis marks are stripped, fenced code is removed entirely.

Install

dsh plugin --profile web add github:dingyi580/dsh-conversation-rail

Then restart dsh web (a newly assembled plugin needs a restart; later code changes can be hot-reloaded with dev_reload_package).

<details> <summary>Installing from a local checkout</summary>

Put the plugin at ~/.dsh/plugins/dsh-conversation-rail, then add two entries to ~/.dsh/profiles/web/package.json:

{
  "dsh": { "profile": { "bundles": ["…", "dsh-conversation-rail"] } },
  "dependencies": {
    "dsh-conversation-rail": "link:/Users/<you>/.dsh/plugins/dsh-conversation-rail"
  }
}

and link it into the profile's node_modules:

ln -sfn ../../../plugins/dsh-conversation-rail ~/.dsh/profiles/web/node_modules/dsh-conversation-rail

</details>

Build

npm run build       # tsc for the host entry + tsdown for src/client → lib/client.js
npm run typecheck   # type check only

lib/ is committed so the plugin installs from GitHub without a build step. Assembly goes through cordis.patch.yml plus the profile's dsh.profile.bundles.

License

BSD-3-Clause