# dsh-chat-history

<img width="920" height="864" alt="image" src="https://github.com/user-attachments/assets/7d27294b-37f9-4fcf-b276-63bd1bfb5e14" />


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

ChatGPT-style conversation-history rail for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) web GUI. A thin strip of horizontal bars sits at the transcript's right edge, one bar per user message; hovering it opens a panel listing every user message, and clicking a row scrolls the transcript to that message. The active bar follows the scroll position until the panel takes over (click-lock), matching the familiar ChatGPT sidebar.

## Features

- **Rail**: one horizontal bar per user message on the transcript's right edge, always visible while the session holds at least two user messages.
- **Hover panel**: lists every user message as a numbered, single-line preview; click to jump.
- **Scroll sync**: the active bar tracks the first user message at or below the scrollport's top edge; the highlight follows the reader and pins after a jump.
- **Click-lock**: while the panel is open, auto-sync pauses; closing the panel resumes following.
- **Bar-press jump**: pressing the rail itself jumps to the nearest bar, so the gaps between dots still navigate.
- Derived entirely from the session's chat snapshot (`user`/`steering` nodes), styled with design tokens only.

## Requirements

- A DeepSeek Harness **web profile** (the GUI). The rail registers into the `conversation.session.header.actions` seat — a long-standing session-header action slot that every released `@deepseek-ai/dsh-client-ui-conversation` ships — so the plugin works with any published ui-conversation and needs no upstream slot changes. The rail itself renders `position: fixed` against the transcript scrollport, so it does not occupy the header's layout.

## Install

In the profile you run the GUI from (e.g. `~/.dsh/profiles/web`), add the bundle and install it:

```sh
# from the profile directory, from the npm registry
pnpm add @ttmouse/dsh-chat-history
```

or, as a GitHub-source dependency:

```sh
pnpm add @ttmouse/dsh-chat-history@github:ttmouse/dsh-chat-history
```

or, using the dsh plugin channel once available:

```sh
dsh plugin --profile web add @ttmouse/dsh-chat-history
```

Then list the bundle in `dsh.profile.bundles` (the `dsh plugin add` flow does this for you):

```json
{
  "dsh": {
    "profile": {
      "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "@ttmouse/dsh-chat-history"]
    }
  }
}
```

Restart `dsh web` and refresh the browser. The rail appears at the right edge of the active conversation.

## Development

```sh
pnpm install
pnpm build     # tsc (lib/types + node half) + tsdown (lib/client.js browser bundle)
pnpm test      # vitest, jsdom
```

The browser bundle is a `window.__ModuleLoader__.load` handoff with CSS Modules inlined as a plugin-tagged `<style>`; externals (`react`, `@deepseek-ai/dsh-client-runtime/client`, …) resolve through the DSH loader module table.

## License

MIT
