@mingozhou/dsh-replay 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +164 -0
- package/README.zh.md +164 -0
- package/cordis.patch.yml +6 -0
- package/lib/client.js +2478 -0
- package/lib/core.js +720 -0
- package/lib/index.js +111 -0
- package/lib/types/demo/main.d.ts +1 -0
- package/lib/types/demo/samples.d.ts +21 -0
- package/lib/types/src/client/api.d.ts +43 -0
- package/lib/types/src/client/components/AuditView.d.ts +8 -0
- package/lib/types/src/client/components/CompareView.d.ts +9 -0
- package/lib/types/src/client/components/ForkTreeView.d.ts +7 -0
- package/lib/types/src/client/components/ItemDetail.d.ts +6 -0
- package/lib/types/src/client/components/OverviewView.d.ts +8 -0
- package/lib/types/src/client/components/ReplayApp.d.ts +12 -0
- package/lib/types/src/client/components/ReplayModal.d.ts +8 -0
- package/lib/types/src/client/components/SessionPicker.d.ts +6 -0
- package/lib/types/src/client/components/TimelineView.d.ts +6 -0
- package/lib/types/src/client/export.d.ts +13 -0
- package/lib/types/src/client/i18n.d.ts +24 -0
- package/lib/types/src/client/index.d.ts +12 -0
- package/lib/types/src/client/mascot-image.d.ts +1 -0
- package/lib/types/src/client/mascot.d.ts +17 -0
- package/lib/types/src/client/viewer-entry.d.ts +1 -0
- package/lib/types/src/core/audit.d.ts +39 -0
- package/lib/types/src/core/compare.d.ts +31 -0
- package/lib/types/src/core/cost.d.ts +30 -0
- package/lib/types/src/core/decode.d.ts +25 -0
- package/lib/types/src/core/forktree.d.ts +33 -0
- package/lib/types/src/core/index.d.ts +7 -0
- package/lib/types/src/core/timeline.d.ts +96 -0
- package/lib/types/src/core/types.d.ts +88 -0
- package/lib/types/src/index.d.ts +20 -0
- package/lib/viewer.js +812 -0
- package/package.json +107 -0
- package/scripts/build.mjs +131 -0
- package/src/client/api.ts +119 -0
- package/src/client/components/AuditView.tsx +57 -0
- package/src/client/components/CompareView.tsx +186 -0
- package/src/client/components/ForkTreeView.tsx +123 -0
- package/src/client/components/ItemDetail.tsx +117 -0
- package/src/client/components/OverviewView.tsx +258 -0
- package/src/client/components/ReplayApp.tsx +205 -0
- package/src/client/components/ReplayModal.tsx +53 -0
- package/src/client/components/SessionPicker.tsx +60 -0
- package/src/client/components/TimelineView.tsx +296 -0
- package/src/client/export.ts +43 -0
- package/src/client/i18n.ts +360 -0
- package/src/client/index.ts +146 -0
- package/src/client/mascot-image.ts +1 -0
- package/src/client/mascot.tsx +192 -0
- package/src/client/styles.css +719 -0
- package/src/client/viewer-entry.tsx +66 -0
- package/src/core/audit.ts +227 -0
- package/src/core/compare.ts +0 -0
- package/src/core/cost.ts +61 -0
- package/src/core/decode.ts +125 -0
- package/src/core/forktree.ts +104 -0
- package/src/core/index.ts +7 -0
- package/src/core/timeline.ts +396 -0
- package/src/core/types.ts +90 -0
- package/src/index.ts +157 -0
- package/tsconfig.json +18 -0
- package/types.d.ts +15 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-replay MingoZhou
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="./assets/jingxiaoshen.png" width="150" alt="Jing Xiaoshen (鲸小深), the dsh-replay mascot" />
|
|
4
|
+
|
|
5
|
+
# dsh-replay
|
|
6
|
+
|
|
7
|
+
**Time machine for your agent sessions.**<br/>
|
|
8
|
+
Replay · Audit · Cost · Fork tree · Compare — inside the DeepSeek Harness web UI.
|
|
9
|
+
|
|
10
|
+
[](https://github.com/MingoZhou/dsh-replay/actions/workflows/ci.yml)
|
|
11
|
+
[](./LICENSE)
|
|
12
|
+
[](https://github.com/topics/dsh-plugin)
|
|
13
|
+
[](https://github.com/MingoZhou/dsh-replay/pulls)
|
|
14
|
+
|
|
15
|
+
**[🎮 Live demo](https://mingozhou.github.io/dsh-replay/)** · [中文文档](./README.zh.md) · [Install](#-quick-start) · [FAQ](#-faq--troubleshooting)
|
|
16
|
+
|
|
17
|
+
<img src="./assets/start.png" width="880" alt="overview dashboard" />
|
|
18
|
+
<img src="./assets/demo.gif" width="880" alt="dsh‑replay operation demo" />
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
## 😫 Sound familiar?
|
|
23
|
+
|
|
24
|
+
You kick off an agent task, come back after dinner, and:
|
|
25
|
+
|
|
26
|
+
- *"It ran for **5 hours** and burned **18M tokens** — on WHAT?"*
|
|
27
|
+
- *"Which tool call ate all that wall-clock time? Was it stuck?"*
|
|
28
|
+
- *"Did it touch my `.env`? Did it `rm -rf` anything? Who approved that?"*
|
|
29
|
+
- *"How much did this session actually **cost** me?"*
|
|
30
|
+
- *"I forked the session yesterday — where exactly did the two histories diverge?"*
|
|
31
|
+
- *"I want to show a teammate this hilarious failure — do they need to install the whole harness?"*
|
|
32
|
+
|
|
33
|
+
DeepSeek Harness keeps a beautiful append-only log where *everything that reached the model is reconstructible* — but ships no viewer for it. **dsh-replay is that viewer.** One plugin, and every question above becomes one click.
|
|
34
|
+
|
|
35
|
+
## ✨ What you get
|
|
36
|
+
|
|
37
|
+
| | |
|
|
38
|
+
|---|---|
|
|
39
|
+
| ⏪ **Timeline replay** | Scrub through every turn, step, message and tool call; play back at 1–16×; click any event for raw prompt/args/results/durations |
|
|
40
|
+
| 📊 **Overview dashboard** | Hero stats, cumulative token chart with crosshair, tool-time ranking — where the time and tokens actually went |
|
|
41
|
+
| 💰 **Cost estimate** | ≈ dollar cost from disjoint token accounting (cache-aware); editable pricing table, DeepSeek / Claude / OpenAI / Gemini defaults |
|
|
42
|
+
| 🛡️ **Security audit** | Rules-based scan: dangerous shell (`rm -rf`, `sudo`, curl-pipe…), sensitive paths (`.env`, `~/.ssh`…), sandbox/permission changes, denied approvals — ranked, clickable, extensible |
|
|
43
|
+
| 🌿 **Fork tree** | The whole session lineage as a clickable tree, fork boundaries labeled, subagents marked |
|
|
44
|
+
| ⚖️ **Compare** | Any two sessions side by side: stats, tool mix, token deltas, exact divergence seq for forks |
|
|
45
|
+
| 📤 **One-click HTML export** | Bake a session into a single offline `.html` — attach it to a bug report or send to a teammate; they get the full interactive replay with **zero installs** |
|
|
46
|
+
| 🔍 **Filter & search** | Free-text search across messages/args/results + kind filters, right in the playback bar |
|
|
47
|
+
| 🌏 **EN / 中文** | Whole UI switches language (findings and meta labels included); auto-detected, one-click toggle |
|
|
48
|
+
|
|
49
|
+
<div align="center">
|
|
50
|
+
<img src="./assets/overview-light.png" width="880" alt="overview dashboard" />
|
|
51
|
+
<img src="./assets/timeline-light.png" width="880" alt="timeline replay" />
|
|
52
|
+
<img src="./assets/audit-light.png" width="880" alt="security audit" />
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
Dark mode follows the harness theme. Loading and empty states are hosted by **Jing Xiaoshen (鲸小深)**, our original whale-catgirl mascot (hide her with `.dshr-mascot { display: none }`).
|
|
56
|
+
|
|
57
|
+
## 🚀 Quick start
|
|
58
|
+
|
|
59
|
+
### Try it first (zero install)
|
|
60
|
+
|
|
61
|
+
**Online demo:** https://mingozhou.github.io/dsh-replay/ — or locally:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
git clone https://github.com/MingoZhou/dsh-replay.git
|
|
65
|
+
cd dsh-replay
|
|
66
|
+
npm install && npm run build
|
|
67
|
+
npm run demo # → http://localhost:4173
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Install into DeepSeek Harness
|
|
71
|
+
|
|
72
|
+
**Case A — you use the released CLI** (`npm i -g @deepseek-ai/dsh`):
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
# build the plugin once
|
|
76
|
+
cd <path-to>/dsh-replay && npm install && npm run build
|
|
77
|
+
|
|
78
|
+
# add it to the profile you actually use (list them: ls ~/.dsh/profiles)
|
|
79
|
+
dsh plugin --profile <your-profile> add <absolute-path-to>/dsh-replay
|
|
80
|
+
dsh --profile <your-profile> --dump-config # expect a "# == dsh-replay" section
|
|
81
|
+
dsh web --profile <your-profile>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Case B — you run the harness from a source checkout** (`pnpm dsh web`):
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
# build the plugin once
|
|
88
|
+
cd <path-to>/dsh-replay && npm install && npm run build
|
|
89
|
+
|
|
90
|
+
# note: `pnpm dsh web` boots the profile named "web"
|
|
91
|
+
cd <path-to>/deepseek-harness
|
|
92
|
+
pnpm dsh plugin --profile web add <absolute-path-to>/dsh-replay
|
|
93
|
+
pnpm dsh --profile web --dump-config # expect a "# == dsh-replay" section
|
|
94
|
+
pnpm dsh web
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Open http://127.0.0.1:3080 — you now have **two entries**:
|
|
98
|
+
|
|
99
|
+
1. the **Session Replay** button at the bottom-left of the sidebar (opens a full-screen modal with a session picker), and
|
|
100
|
+
2. a **Replay** tab inside every open conversation.
|
|
101
|
+
|
|
102
|
+
Installing from npm (`dsh plugin --profile <p> add dsh-replay`, once published) or from a git URL also works; git installs run the package's `prepare` build, which the harness requires you to allowlist in the profile's `pnpm-workspace.yaml`:
|
|
103
|
+
|
|
104
|
+
```yaml
|
|
105
|
+
allowBuilds:
|
|
106
|
+
dsh-replay: true
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## 🧹 Uninstall
|
|
110
|
+
|
|
111
|
+
The official way (works **even when the harness fails to boot**, since it only runs pnpm in the profile directory):
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
dsh plugin --profile <your-profile> remove dsh-replay # released CLI
|
|
115
|
+
# or, from a harness source checkout:
|
|
116
|
+
pnpm dsh plugin --profile web remove dsh-replay
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Then restart the harness. Manual fallback if the command itself misbehaves: open the profile directory (`~/.dsh/profiles/<your-profile>` — on Windows `C:\Users\<you>\.dsh\profiles\<your-profile>`), remove `dsh-replay` from `package.json` → `dependencies` **and** from `dsh.profile.bundles`, run `pnpm install` there, restart. Nothing else is written anywhere — the plugin keeps no state outside its own package.
|
|
120
|
+
|
|
121
|
+
## 🔧 FAQ / Troubleshooting
|
|
122
|
+
|
|
123
|
+
**`GET /replay/api/sessions` returns 404** — the config layer didn't land. The harness fails *silently* on an unresolvable plugin name: re-run the `dsh plugin add` step and check `--dump-config` for the `# == dsh-replay` section.
|
|
124
|
+
|
|
125
|
+
**`Cannot find module '…\dsh-replay\lib\index.js'` at boot** — the profile links to your plugin folder, and `lib/` is a build artifact that ships neither in git nor in release archives. Run `npm install && npm run build` inside the plugin folder (required after every fresh clone/unzip), then start the harness again.
|
|
126
|
+
|
|
127
|
+
**API works but no sidebar button / Replay tab** — the browser half didn't load. Confirm `lib/client.js` exists (run `npm run build` in the plugin), then fully restart the harness: client plugin sets are only scanned at boot, and negative results are cached.
|
|
128
|
+
|
|
129
|
+
**`EADDRINUSE: 127.0.0.1:3080`** — a previous harness instance is still running; stop it first.
|
|
130
|
+
|
|
131
|
+
**`npm install` fails on `@deepseek-ai/*` packages** — you're on an old checkout of this plugin. All harness packages are optional peers since v0.2.0; pull the latest.
|
|
132
|
+
|
|
133
|
+
**The harness updated and something broke** — the preview-phase plugin API moves. Everything hard lives in the dependency-free `core/`; fixes land in two thin adapter files. `npm run demo` always works.
|
|
134
|
+
|
|
135
|
+
## 🏗️ Architecture
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
src/core dependency-free analysis: JSONL + chunk-row decoding, timeline
|
|
139
|
+
folding, audit rules, fork forest, cost model, session diff ← 27 unit tests
|
|
140
|
+
src/index.ts host half: read-only HTTP API on the harness web server
|
|
141
|
+
(GET /replay/api/sessions | /session/<id> | /viewer.js)
|
|
142
|
+
src/client browser half: React components + three slot registrations
|
|
143
|
+
(conversation.view · sidebar.footer.action · shell.overlay)
|
|
144
|
+
demo/ the same components over sample logs, zero harness deps
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The split is deliberate: a preview-phase API break means fixing an adapter, not the product. `core` is importable on its own (`dsh-replay/core`) if you want to build your own tooling over session logs — it understands the wire format including packed chunk rows, torn crash tails, seed boundaries, and compaction shadowing.
|
|
148
|
+
|
|
149
|
+
<details>
|
|
150
|
+
<summary><b>Wire-format notes (for fellow plugin authors)</b></summary>
|
|
151
|
+
|
|
152
|
+
`seq` is contiguous and gapless; streaming chunks may arrive packed as `text-chunks` / `reasoning-chunks` / `tool-call-chunks` rows (`seq0` + `dt[]` deltas); token usage rides `assistant/message` (and early `usage` chunks) and **replaces** rather than accumulates per turn/step; cache token counts are disjoint from `inputTokens` (billed input = input + cacheRead + cacheWrite); session titles are log-only `session/title` events — take the *last*; `session/end-seed` marks the fork/resume boundary; a final line without a newline is an uncommitted crash tail, not corruption.
|
|
153
|
+
|
|
154
|
+
</details>
|
|
155
|
+
|
|
156
|
+
## 🗺️ Roadmap
|
|
157
|
+
|
|
158
|
+
Live mode (follow a running session over the events websocket) · file-diff reconstruction from edit-tool calls · audit rule packs · replay annotations & sharing links.
|
|
159
|
+
|
|
160
|
+
Issues and PRs welcome. If you build something on `dsh-replay/core`, open a discussion — happy to link it here.
|
|
161
|
+
|
|
162
|
+
## 📜 License & credits
|
|
163
|
+
|
|
164
|
+
MIT. Jing Xiaoshen (鲸小深) is an original character created for this project — she is not the official DeepSeek logo nor third-party fan art. Mascot artwork lives at `assets/jingxiaoshen.png`; replace it (≤400 KB) and `npm run build` embeds your version everywhere in the UI.
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="./assets/jingxiaoshen.png" width="150" alt="鲸小深 — dsh-replay 吉祥物" />
|
|
4
|
+
|
|
5
|
+
# dsh-replay
|
|
6
|
+
|
|
7
|
+
**Agent 会话的时光机。**<br/>
|
|
8
|
+
回放 · 审计 · 成本 · 分支树 · 对比 —— 全部内嵌在 DeepSeek Harness Web UI 里。
|
|
9
|
+
|
|
10
|
+
[](https://github.com/MingoZhou/dsh-replay/actions/workflows/ci.yml)
|
|
11
|
+
[](./LICENSE)
|
|
12
|
+
[](https://github.com/topics/dsh-plugin)
|
|
13
|
+
[](https://github.com/MingoZhou/dsh-replay/pulls)
|
|
14
|
+
|
|
15
|
+
**[🎮 在线 Demo](https://mingozhou.github.io/dsh-replay/)** · [English](./README.md) · [安装](#-快速上手) · [常见问题](#-常见问题排查)
|
|
16
|
+
|
|
17
|
+
<img src="./assets/overview-light.png" width="880" alt="概览仪表盘" />
|
|
18
|
+
<img src="./assets/demo.gif" width="880" alt="dsh‑replay operation demo" />
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
## 😫 这些场景你熟不熟
|
|
23
|
+
|
|
24
|
+
你把任务丢给 Agent,吃个晚饭回来——
|
|
25
|
+
|
|
26
|
+
- *"它跑了 **5 个小时**、烧了 **1800 万 token**,到底干了啥?"*
|
|
27
|
+
- *"哪个工具调用吃掉了大头时间?是不是卡死过?"*
|
|
28
|
+
- *"它有没有碰我的 `.env`?有没有 `rm -rf` 过什么?谁批准的?"*
|
|
29
|
+
- *"这一次会话到底**花了多少钱**?"*
|
|
30
|
+
- *"昨天 fork 过一次会话,两条历史到底从哪个事件开始分岔的?"*
|
|
31
|
+
- *"想把这次搞笑的翻车现场发给同事围观——难道要他装一整套 Harness?"*
|
|
32
|
+
|
|
33
|
+
DeepSeek Harness 有一套优雅的 append-only 日志,官方承诺"到达模型的一切都可从日志重建"——但它没有配查看器。**dsh-replay 就是那个查看器。** 装一个插件,上面每个问题都变成一次点击。
|
|
34
|
+
|
|
35
|
+
## ✨ 你会得到什么
|
|
36
|
+
|
|
37
|
+
| | |
|
|
38
|
+
|---|---|
|
|
39
|
+
| ⏪ **时间线回放** | 逐事件拖动每个 turn/step/消息/工具调用;1–16 倍速播放;点击任意事件看原始提示词/参数/结果/耗时 |
|
|
40
|
+
| 📊 **概览仪表盘** | 核心指标大数字、带十字线的累计 token 曲线、各工具耗时排行 —— 时间和 token 到底去哪了 |
|
|
41
|
+
| 💰 **成本估算** | 按不相交 token 口径(缓存感知)估算 ≈ 美元成本;估价表可编辑,内置 DeepSeek / Claude / OpenAI / Gemini 默认价 |
|
|
42
|
+
| 🛡️ **安全审计** | 规则化扫描:危险 shell(`rm -rf`、`sudo`、curl 管道执行…)、敏感路径(`.env`、`~/.ssh`…)、沙箱/权限变更、被拒审批 —— 分级排序、点击直达、规则可扩展 |
|
|
43
|
+
| 🌿 **分支树** | 完整会话血缘画成可点击的树,fork 边界带标注,子 Agent 有标记 |
|
|
44
|
+
| ⚖️ **会话对比** | 任意两个会话并排:指标、工具分布、token 差值,fork 会话给出精确分岔 seq |
|
|
45
|
+
| 📤 **一键导出 HTML** | 把会话烤进单个离线 `.html`:附到 bug report、发给同事,对方**零安装**看到完整可交互回放 |
|
|
46
|
+
| 🔍 **搜索过滤** | 播放条上直接全文搜索(消息/参数/结果)+ 按类型一键过滤 |
|
|
47
|
+
| 🌏 **中英双语** | 整个 UI 可切换语言(审计发现、元事件标签都翻译);自动检测,一键切换 |
|
|
48
|
+
|
|
49
|
+
<div align="center">
|
|
50
|
+
<img src="./assets/overview-light.png" width="880" alt="overview dashboard" />
|
|
51
|
+
<img src="./assets/timeline-light.png" width="880" alt="时间线回放" />
|
|
52
|
+
<img src="./assets/audit-light.png" width="880" alt="安全审计" />
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
深色模式跟随 Harness 主题。加载与空状态由原创鲸猫娘吉祥物 **鲸小深** 值班(不喜欢可一行 CSS 隐藏:`.dshr-mascot { display: none }`)。
|
|
56
|
+
|
|
57
|
+
## 🚀 快速上手
|
|
58
|
+
|
|
59
|
+
### 先试试(零安装)
|
|
60
|
+
|
|
61
|
+
**在线 Demo:** https://mingozhou.github.io/dsh-replay/ ,或本地跑:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
git clone https://github.com/MingoZhou/dsh-replay.git
|
|
65
|
+
cd dsh-replay
|
|
66
|
+
npm install && npm run build
|
|
67
|
+
npm run demo # → http://localhost:4173
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 装进 DeepSeek Harness
|
|
71
|
+
|
|
72
|
+
**情况 A —— 你用的是发行版 CLI**(`npm i -g @deepseek-ai/dsh`):
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
# 先构建插件(一次即可)
|
|
76
|
+
cd <插件路径>/dsh-replay && npm install && npm run build
|
|
77
|
+
|
|
78
|
+
# 加进你实际在用的 profile(列出所有 profile:ls ~/.dsh/profiles)
|
|
79
|
+
dsh plugin --profile <你的profile> add <插件绝对路径>/dsh-replay
|
|
80
|
+
dsh --profile <你的profile> --dump-config # 应出现 "# == dsh-replay" 一段
|
|
81
|
+
dsh web --profile <你的profile>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**情况 B —— 你从源码仓库跑 Harness**(`pnpm dsh web`):
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
# 先构建插件(一次即可)
|
|
88
|
+
cd <插件路径>/dsh-replay && npm install && npm run build
|
|
89
|
+
|
|
90
|
+
# 注意:`pnpm dsh web` 实际挂载的是名为 "web" 的 profile
|
|
91
|
+
cd <Harness源码路径>/deepseek-harness
|
|
92
|
+
pnpm dsh plugin --profile web add <插件绝对路径>/dsh-replay
|
|
93
|
+
pnpm dsh --profile web --dump-config # 应出现 "# == dsh-replay" 一段
|
|
94
|
+
pnpm dsh web
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
打开 http://127.0.0.1:3080 ,你会得到**两个入口**:
|
|
98
|
+
|
|
99
|
+
1. 侧栏左下角的 **会话回放** 按钮(弹出带会话选择器的全屏弹窗);
|
|
100
|
+
2. 每个会话视图里的 **Replay** 标签页。
|
|
101
|
+
|
|
102
|
+
从 npm(发布后 `dsh plugin --profile <p> add dsh-replay`)或 git URL 安装也可以;git 安装会执行包的 `prepare` 构建,Harness 要求在 profile 的 `pnpm-workspace.yaml` 里显式放行:
|
|
103
|
+
|
|
104
|
+
```yaml
|
|
105
|
+
allowBuilds:
|
|
106
|
+
dsh-replay: true
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## 🧹 卸载
|
|
110
|
+
|
|
111
|
+
官方姿势(**即使 Harness 启动不了也能用**,因为它只是在 profile 目录里跑 pnpm):
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
dsh plugin --profile <你的profile> remove dsh-replay # 发行版 CLI
|
|
115
|
+
# 源码模式:
|
|
116
|
+
pnpm dsh plugin --profile web remove dsh-replay
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
然后重启 Harness。手动兜底:打开 profile 目录(`~/.dsh/profiles/<你的profile>`,Windows 下是 `C:\Users\<用户名>\.dsh\profiles\<你的profile>`),在 `package.json` 里把 `dsh-replay` 从 `dependencies` **和** `dsh.profile.bundles` 两处删掉,在该目录 `pnpm install`,重启即可。插件不在其他任何地方写入状态。
|
|
120
|
+
|
|
121
|
+
## 🔧 常见问题排查
|
|
122
|
+
|
|
123
|
+
**`GET /replay/api/sessions` 返回 404** —— 配置层没生效。Harness 对无法解析的插件名是**静默失败**:重跑 `dsh plugin add`,并用 `--dump-config` 确认有 `# == dsh-replay` 一段。
|
|
124
|
+
|
|
125
|
+
**启动报 `Cannot find module '…\dsh-replay\lib\index.js'`** —— profile 链接的是你的插件文件夹,而 `lib/` 是构建产物,git 和压缩包里都不带。进插件目录跑 `npm install && npm run build`(每次重新 clone/解压后都要),再启动 Harness。
|
|
126
|
+
|
|
127
|
+
**API 正常但没有侧栏按钮 / Replay 标签页** —— 浏览器半没加载。确认插件目录下 `lib/client.js` 存在(跑 `npm run build`),然后**完全重启** Harness:客户端插件集合只在启动时扫描,负面结果还会被缓存。
|
|
128
|
+
|
|
129
|
+
**`EADDRINUSE: 127.0.0.1:3080`** —— 上一个 Harness 实例还开着,先关掉。
|
|
130
|
+
|
|
131
|
+
**`npm install` 在 `@deepseek-ai/*` 包上报错** —— 你用的是旧版插件代码。v0.2.0 起所有 Harness 包都是 optional peer,拉最新代码即可。
|
|
132
|
+
|
|
133
|
+
**Harness 升级后坏了** —— preview 阶段插件 API 会变。所有核心逻辑都在零依赖的 `core/` 里,修复只落在两个薄适配文件;`npm run demo` 永远可用。
|
|
134
|
+
|
|
135
|
+
## 🏗️ 架构
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
src/core 零依赖分析层:JSONL + chunk-row 解码、时间线折叠、审计规则、
|
|
139
|
+
分支森林、成本模型、会话 diff ← 27 个单元测试
|
|
140
|
+
src/index.ts 宿主侧:在 Harness web server 上注册只读 HTTP API
|
|
141
|
+
(GET /replay/api/sessions | /session/<id> | /viewer.js)
|
|
142
|
+
src/client 浏览器侧:React 组件 + 三个插槽注册
|
|
143
|
+
(conversation.view · sidebar.footer.action · shell.overlay)
|
|
144
|
+
demo/ 同一套组件跑在示例日志上,不依赖 Harness
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
这个拆分是刻意的:preview 阶段 API 变了,改适配层就行,产品不动。`core` 可单独引入(`dsh-replay/core`),想基于会话日志做自己的工具直接用——它理解完整线上格式:打包 chunk row、崩溃残尾、seed 边界、压缩遮蔽。
|
|
148
|
+
|
|
149
|
+
<details>
|
|
150
|
+
<summary><b>线上格式笔记(写给同行插件作者)</b></summary>
|
|
151
|
+
|
|
152
|
+
`seq` 连续无空洞;流式 chunk 可能打包为 `text-chunks` / `reasoning-chunks` / `tool-call-chunks` 行(`seq0` + `dt[]` 增量);token 用量随 `assistant/message`(及提前的 `usage` chunk)记录,同 turn/step 内**替换**而非累加;缓存 token 与 `inputTokens` 不相交(计费输入 = input + cacheRead + cacheWrite);会话标题是 log-only 的 `session/title` 事件——取**最后**一个;`session/end-seed` 标记 fork/resume 边界;末行无换行是未提交的崩溃残尾,不是损坏。
|
|
153
|
+
|
|
154
|
+
</details>
|
|
155
|
+
|
|
156
|
+
## 🗺️ 路线图
|
|
157
|
+
|
|
158
|
+
Live 模式(事件 websocket 跟随运行中会话) · 从编辑类工具调用重建文件 diff · 审计规则包 · 回放标注与分享链接。
|
|
159
|
+
|
|
160
|
+
欢迎 Issue 和 PR。基于 `dsh-replay/core` 做了新东西,开个 discussion,乐意在这里放链接。
|
|
161
|
+
|
|
162
|
+
## 📜 许可与致谢
|
|
163
|
+
|
|
164
|
+
MIT。鲸小深是为本项目创作的原创角色 —— 不是 DeepSeek 官方 logo,也不是第三方同人作品。吉祥物图片在 `assets/jingxiaoshen.png`,替换成你自己的版本(≤400 KB)后 `npm run build` 会自动嵌入 UI 各处。
|