Skills Plugins MCP Prompt Model 导航 博客 资讯 我的中心
工具与能力 #deepseek-harness#deepseek-harness-plugin#deepseek-harness-plugins#llm-cost#observability#token-usage

dsh-turn-tokens

Per-turn token usage, request composition and cost breakdown panel for the DeepSeek Harness Web GUI.

d0cx0011 @d0cx0011 ⬇ 1 ★ 0 main

安装

dsh plugin --profile web add github:d0cx0011/dsh-turn-tokens
下载安装清单

需要可复现安装时,可在仓库后追加 #commit 固定提交。

Per-turn token usage, request composition and cost breakdown panel for the DeepSeek Harness Web GUI.

该插件未提供要点说明,请参考仓库 README。

deepseek-harnessdeepseek-harness-plugindeepseek-harness-pluginsllm-costobservabilitytoken-usage
  1. 安装并启动 DeepSeek Harness:npx @deepseek-ai/dsh web
  2. 在终端执行上面的安装命令(CLI 会解析插件并核验来源)
  3. 用 dsh plugins list 确认已安装,必要时重启 Harness 生效

插件以当前 dsh 进程的权限运行,安装时可能执行代码。请先通读仓库源码与许可证,确认无破坏性命令与越权访问;本站只做索引,不对第三方插件安全性作担保。

代码仓库github.com/d0cx0011/dsh-turn-tokens
许可证MIT
主要语言main
下载量1
GitHub 星标0
最近推送2026-09-16
收录日期2026-09-19
分类工具与能力

事实信息来自公开插件目录快照(2026-10-01),介绍文案由本站再加工。

以下为插件仓库 README 全文(原始内容,由公开目录抓取整理)。

# dsh-turn-tokens

> 在 DeepSeek Harness 的 Web 界面里看清**每一轮对话花了多少 token、钱花在哪、一次请求由什么组成**。

一个 host + client 双半边的 Web 插件。它只读本机的会话日志与官方会话投影:**不联网、不需要 API Key、不上传任何数据**。

**中文** | [English](README.en.md)

- [它解决什么](#它解决什么)
- [功能](#功能)
- [安装](#安装)
- [指标口径](#指标口径)
- [价格口径](#价格口径)
- [数据来源与隐私](#数据来源与隐私)
- [兼容性与版本要求](#兼容性与版本要求)
- [维护](#维护)
- [已知限制](#已知限制)
- [许可](#许可)

## 它解决什么

内置的统计只给一个总数。这个插件回答三个更具体的问题:

1. **每一轮(turn)实际消耗了多少** —— 未缓存输入 / 缓存读 / 输出 / 推理,来自 provider 上报的用量,是精确值;并给出该轮金额。
2. **一次请求由什么组成** —— 系统提示逐段、工具 schema 逐项、消息体分类,各自多少 token。
3. **这些内容从哪来** —— 每段系统提示来自哪个提示节或哪个文件(含绝对路径);user 角色里那些不是你打的字的注入消息各自来自哪里。

## 功能

### 输入框右侧的指示器

一个紧凑控件,显示 `● 上下文 N%`。圆点颜色即状态:**绿**(<50%)/ **黄**(50–80%)/ **红**(≥80%)。悬停看绝对值与窗口长度,点击展开面板。

它挂在输入框右侧按钮区,**不占用额外行高**。

### 面板

| 区块 | 内容 |
|---|---|
| **最近一轮**(最前面一行) | 刚结束那一轮的调用次数、三部分 `tokens/¥金额` 与该轮合计金额。它排在最前面,一眼就能看到"刚这轮花了多少、钱花在哪"。悬停可看该轮开始时间、峰谷档位与该轮的用户输入 |
| **会话累计用量** | 未缓存输入 / 缓存读 / 缓存写 / 输出,附占比条 |
| **上下文压力** | 最近一次请求的实际 prompt 大小、下一次请求预估、窗口上限、占用百分比 |
| **上下文组成** | 系统提示 / 工具 schema / 消息体 三分类占比 |
| **最近一次请求的明细** | system 分段逐段成本、工具 schema 逐项成本、消息体按类别拆分 |
| **每轮明细** | 每轮的调用次数、四项用量与金额,底部合计 |
| **注入的上下文消息** | 运行时上下文 / 技能目录 / 工作区指令各自被注入了什么、来自哪里、当前是否生效 |

**逐段与逐项都可以点开看完整原文**(保留换行、可滚动),并标注来源的判定方式。

### 来源归因

系统提示的每一段都按三级顺序归因,命中即止,**拿不到就不猜**:

| 级别 | 依据 | 可信度 |
|---|---|---|
| 1 | 宿主提示装配接口返回的**节名** | 权威 |
| 2 | **候选文件的内容比对**(人设卡、设置文件、会话目录下的工作区指令文件) | 高(去空白后逐字匹配) |
| 3 | 段落文本特征 → 对应官方包的路径 | 中(且**只有包路径真实存在才采信**) |

注入的 user 角色消息单独识别:正文里自带来源标识的(如 `Instructions from: <路径>`)会被解析成**绝对路径**,相对路径用会话工作目录拼接。同一来源经历的「注入 → 更新 → 移除」按来源分组,折叠行显示**最新状态**。

## 安装

profile 名因发行版而异,三种方式对两者都适用:

| 发行版 | profile 名 |
|---|---|
| 原生 `dsh` | `web`(`dsh web` 就是 `dsh --profile web`) |
| EAC 桌面客户端 | `web-desktop` |

| 前置 | 说明 |
|---|---|
| Node | 随 DSH 提供,无需另装 |
| pnpm | **只有方式一需要**,且必须在 `PATH` 上 |

### 方式一:`dsh plugin`(原生 DSH 推荐)

本包**尚未发布到 npm**,因此用仓库地址或本地路径安装:

```sh
# A. 从 GitHub 直接安装
dsh plugin --profile web add github:D0cx0011/dsh-turn-tokens

# B. 先克隆,再从本地路径安装(本仓库开发时用的就是这条)
git clone https://github.com/D0cx0011/dsh-turn-tokens.git
dsh plugin --profile web add file:./dsh-turn-tokens
```

`dsh plugin` 是官方 CLI,它把剩余参数转发给 profile 目录下的 `pnpm`。本包在 `package.json` 里声明了 `dsh.bundle.patch`,所以命令跑完后 DSH 会**按已安装状态核对**:声明了 `dsh.bundle` 的依赖被自动追加进 profile 的 `dsh.profile.bundles`,本包自带的 `cordis.patch.yml` 随之作为一层 bundle patch 生效——**无需手工编辑任何配置文件**。

两个已知前置与坑:

- **必须先有 pnpm。** `dsh plugin` 只是 pnpm 的转发器;`PATH` 上没有 pnpm 时它会报 `pnpm not found on PATH` 并返回退出码 127。
- **用 git 规格安装要留意构建授权。** pnpm 会为 git 依赖执行 `prepare` 脚本,默认被拦截并导致安装失败;若遇到,按提示把打印出的 key 加进 `/pnpm-workspace.yaml` 的 `allowBuilds` 再重试。本包是纯 JS、**没有** `prepare` 脚本,通常不会触发;**上面的 B(`file:` 规格)不走这条路径,最稳**。

### 方式二:本仓库附脚本(无 pnpm / 离线 / EAC 环境)

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/install.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/install.ps1 -Uninstall
```

脚本自动探测 profile(依次尝试 `web-desktop`、`web`,再退回到唯一存在的那个),也可显式指定:

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/install.ps1 -Profile web
```

落点:把包复制到 `\node_modules\dsh-turn-tokens\`,并把挂载行追加到同 profile 的 `cordis.patch.yml`(**改动前自动生成带时间戳的备份**)。

> 这里用 `powershell` 而不是 `pwsh`:Windows PowerShell 5.1 一定存在,`pwsh`(PowerShell 7)通常没有。脚本刻意只用 ASCII 编写,以避开 5.1 读中文脚本时的编码陷阱。

### 方式三:完全手工(不依赖任何脚本)

等价于方式二,适合想自己控制每一步的情况:

1. 把本包的 `package.json`、`lib\`、`cordis.patch.yml` 复制到
   `%DSH_HOME%\profiles\\node_modules\dsh-turn-tokens\`
2. 在 `%DSH_HOME%\profiles\\cordis.patch.yml` 末尾追加:

   ```yaml
   - insert:
       - id: turn-tokens
         name: 'dsh-turn-tokens'
   ```

profile 根目录的 `cordis.yml` 里写着 "Edit `cordis.patch.yml`, not this file"——要改的一直是 `cordis.patch.yml`。

### 三种方式不要混用

方式一把包登记为 **bundle 层**,方式二/三往 **用户 patch 层**写同一条挂载行。两者引用同一个 `id: turn-tokens`,同时使用会让同一个入口被插入两次。已经手工装过就先别用方式一;要改走方式一,先用 `-Uninstall` 清掉那条挂载行。

### 安装后自检

**推荐先跑这条**——它不需要 pnpm,也不需要插件本身跑起来:

```sh
dsh --profile web --dump-config     # 打印合成后的配置树,找 turn-tokens 行
```

配置树里出现下面两行,就说明挂载成功(本机实测输出):

```
- id: turn-tokens
  name: dsh-turn-tokens
```

其余可选手段:

- 用方式一安装、且 pnpm 可用时,可确认依赖:`dsh plugin --profile web why dsh-turn-tokens`
- 本仓库的 `node scripts/verify-install.mjs` 会检查 `package.json` 契约、挂载行与 client 半边是否齐备,**同样不需要 pnpm**,适合 EAC 环境。
- profile 名按上面的表替换(原生 `web` / EAC `web-desktop`)。

### 生效规则(重要)

| 改动位置 | 生效方式 |
|---|---|
| **client 半边**(`lib/client.js`,界面与价格) | 宿主会重新打包前端 bundle,**刷新页面即生效** |
| **host 半边**(`lib/index.js`,日志解析与路由) | 模块被 loader 缓存,**必须重启 DSH Web 服务** |

安装后请**刷新页面**;若指示器未出现,再重启服务。

### 依赖的官方契约

本插件只使用 DSH 的公开契约,**不依赖任何对 DSH 源码的修改,也不依赖 EAC 的任何专有功能**:

| 契约 | 用途 |
|---|---|
| `dsh plugin --profile  …` | 官方 CLI,安装入口 |
| `package.json` 的 `dsh.bundle.patch` | 由 `@deepseek-ai/dsh-app-boot` 读取,决定本包的 patch 层 |
| profile 的 `cordis.patch.yml` | 官方指定的用户 patch 层 |
| 客户端槽位 `conversation.input.right` | 由官方 `@deepseek-ai/dsh-client-ui-conversation` 定义 |
| `tokenUsage` / `contextPressure` / `contextBreakdown` 投影 | 官方会话投影 |

如果你改过 DSH 源码、而指示器始终不出现,请先按上面的自检命令确认挂载行与包是否真的进入了配置树——**"没挂上"和"挂上了但没渲染"是两类不同的问题**,先分清再排查。

## 指标口径

### 会话累计用量与每轮明细(精确)

来自 provider 每次调用上报的用量,逐轮累加。实测关系:

```
合计 = 未缓存输入 + 缓存读 + 输出          (不含推理)
```

| 指标 | 含义 |
|---|---|
| **未缓存输入** | 未命中前缀缓存的输入 token,最贵的一项 |
| **缓存读** | 命中缓存被复用的输入 token。**是所有调用的累计读入量,不等于上下文大小** |
| **缓存写** | 写入缓存的部分;部分 provider 不上报,通常为 0 |
| **输出** | 模型生成的 token |
| **推理** | 思考 token。它**含在输出的计费里**,因此**不单独计价**,表内标为「含于输出」 |
| **调用** | 该轮的 API 调用次数 ≈ 步数(一次工具调用 ≈ 一次额外调用) |

> **为什么缓存读能远超上下文窗口**:一轮里常有几十次 API 调用,每次都要重发整段前缀,每次都计入缓存读。它是累计读入量,不是上下文大小。

### 上下文压力与组成(宿主投影)

| 指标 | 精度 |
|---|---|
| 当前 prompt / 窗口上限 | 精确(provider 上报) |
| 下次请求预估 | 估算 |
| 系统提示 / 工具 schema / 消息体 | 启发式 |

### 分段与逐项(本插件解析)

system 分段按空行切分;工具 schema 逐项、消息体分类均按字符估算。**估算口径:ASCII ≈ 4 字符/token,中文 ≈ 1.5 字符/token**,只用于相对比较与排序,**不要当作账单**。

「上下文组成」的三分类合计**不会**等于上面的精确用量——一个算"组成",一个算"计费"。

## 价格口径

每轮明细的每一格显示为 `tokens/¥金额`,合计列给出该轮总价;**底部的合计行也逐列给出金额**。

**定价以官方页面为准**:

| 项(元/百万 tokens) | deepseek-flash 空闲 | 高峰 | deepseek-v4-pro 空闲 | 高峰 |
|---|---|---|---|---|
| 输入(缓存命中) | 0.02 | 0.04 | 0.15 | 0.30 |
| 输入(缓存未命中) | 1 | 2 | 4.5 | 9.0 |
| 输出 | 4 | 8 | 13.5 | 27.0 |

- **峰谷规则**:高峰 = 北京时间周一至周五 9:00-12:00、14:00-18:00,其余空闲(空闲价 = 高峰价的一半)。**每轮按它自己开始时刻的档位计价**。
- **模型名映射**:官方说明旧模型名 `deepseek-v4-flash`、`deepseek-v4-flash-vision-exp` 仍可调用,但**按 Flash 价格计费**。
- **推理不单独计价**,理由见上文。
- **未匹配到价目表就只显示 token,不显示价格** —— 不猜。
- **合计行各列的金额是逐轮累加出来的**:各轮时段可能不同,所以未缓存输入 / 缓存读 / 输出 三列都按「这一轮的用量 × 这一轮自己的单价」分别算完再相加,三列之和恰好等于最后一列的总价。悬停合计行可以看到这条口径说明。

价格是**估算**,不等于官方账单;官方保留调价权利,请定期核对上面的定价页。

## 数据来源与隐私

- **只读**:仅读取本机的会话日志、设置文件与少量候选文本文件,**不写入、不删除**任何被统计的数据。
- **不联网**:插件自身不发起任何网络请求;面板里的官方定价链接只是文本。
- **不上传**:无遥测、无第三方运行时依赖;host 半边只使用 Node 内置模块。
- **面板会显示提示内容**:为了给出"来源"与"完整原文",面板会展示系统提示段落与注入消息的正文。这些内容本来就在你的会话里,插件只是把它们显示出来。

## 兼容性与版本要求

**验证环境**:DSH `0.1.2-alpha.1`(日志格式 v0)与 `0.1.5-rc.1`(日志格式 v3),
均在 `web-desktop` profile、Windows / PowerShell 5.1 下实测。

**两代日志格式都支持**:0.1.5 起 DSH 把会话日志从 v0 推到 v3 —— 文件名从 `session.jsonl.zstd`
变成 `session.v3.jsonl.zstd`,system prompt 也从 `request/header.header.system` 改成了
`system/message` 事件流。本插件两代都认(实现上是"两代都试、谁有内容用谁"),你不需要切换任何开关。
报告里的 `log.format` 与 `systemSource` 会显示实际读到的是哪一代。

本插件的实现依赖宿主契约,下列契约变动即可能出问题。**按症状排查最快**:

| 依赖的契约 | 失效症状 | 现有兜底 |
|---|---|---|
| 会话日志路径 `$DSH_HOME/sessions//session-/session[.vN].jsonl[.zstd]` | 提示"找不到会话日志" | 按 `session-*` 目录扫描;文件名两代都认(v0 无版本段、vN 带版本段),取版本最高 |
| 日志是**多帧** zstd | 只读到最早的一部分,轮次缺失 | 按 zstd magic 切帧逐帧解压,单帧失败不影响其余 |
| 记录类型 `session` / `turn/start` / `request/header` / `request/context` / `system/message` / `assistant/message` / `user/message` / `tool/result` | 对应区块为空 | 所有字段访问都带保护,缺失即跳过 |
| 用量字段名 `inputTokens` / `cacheReadTokens` / `outputTokens` / `reasoningTokens` / `totalTokens` | **每轮用量静默显示为 0**(最危险) | ⚠️ 无兜底:改名不会报错,只会变 0(v3 实测未改名) |
| system prompt 的载体:v0/v1 在 `request/header.header.system`,v2/v3 在 `system/message` 事件流 | system 段为空或大面积"未识别" | 两代都试、谁有内容用谁;`systemSource` 显示实际用了哪一代;事件流按 surface 语义重放 |
| `request/header` 的 `tools` / `config` | 工具列表或模型信息为空 | 有存在性检查(两代都在,v3 只退休了 `system`) |
| 会话投影名 `tokenUsage` / `contextPressure` / `contextBreakdown` | 面板顶部对应数字消失(显示 —) | 有类型检查,缺失即不渲染 |
| 槽位名 `conversation.input.right` | **指示器完全不显示** | ⚠️ 无兜底:槽位不存在时控件被静默丢弃(该槽位是官方契约,定义见官方 Web Client Slots 文档) |
| 客户端模块契约 `window.__ModuleLoader__.load` / `require("react")` / `exports.inject` / `ctx.slots.register` | 前端 bundle 报错或控件不出现 | ⚠️ 无兜底 |
| 提示装配接口返回 `{ sections: [{ name, text }] }` | 节名归因失效 | ✅ 退化为文件比对与文本特征规则 |
| `agent/created` 事件载荷 | 只能用全局作用域的提示节 | ✅ 退回全局上下文 |
| 日志里的会话 `cwd` 字段 | 相对路径无法拼成绝对路径 | ✅ 只显示声明的相对路径 |
| 官方定价与模型名 | 价格不显示(token 照常) | ✅ 未匹配即不显示,不猜 |
| React 主版本 | 组件渲染异常 | peer 范围已放宽到 `^18 \|\| ^19` |

**排查顺序建议**:

1. 指示器不显示 → 先刷新页面,再确认槽位名是否仍存在
2. 面板能开但数字为空 → 检查会话投影名
3. **每轮全是 0** → 优先怀疑用量字段名变了(这类变化不报错)
4. 轮次缺几轮 → 检查日志是否仍是多帧 zstd
5. 来源大面积"未识别" → 检查提示装配接口的返回结构,以及候选文件是否可读

**升级适配提示**:若宿主整体重构了会话日志或投影语义(例如把用量移到新的记录类型),需要同步修改 `lib/index.js` 的解析段;界面与价格部分通常不受影响。

**已经适配过的一次**:0.1.5 把日志格式推到 v3(`header.system` 被退休、文件名带版本段)。
改动集中在 host 半边 —— `locateSession()` 的文件名扫描与 `system/message` 的 surface 重放;
client 半边与官方投影契约未受影响。`scripts/formattest.mjs` 就是为这类升级准备的:
它在临时目录里合成两代日志,**不碰真实会话**,升级 DSH 后先跑它,再用 `selftest.mjs` 对真实数据。

## 维护

### 价格维护

以官方定价页为准(见上)。修改点集中在 `lib/client.js`:

| 位置 | 作用 |
|---|---|
| `PRICING` | 三档单价表(按模型 × 峰谷) |
| `PRICING_ALIAS` | 旧模型名 → 价目表键 |
| `periodNow()` | 峰谷判定(北京时间) |
| `cost()` / `money()` | 计价与金额格式化 |

改完刷新页面即可生效(价格表在 client 半边)。

### 验证脚本

```powershell
node scripts/selftest.mjs         # host:模拟宿主上下文跑通路由,输出真实的每轮与归因结果
node scripts/formattest.mjs       # 日志格式两代(v0/v3):system 载体、文件名、surface 重放
node scripts/clienttest.mjs       # client:模拟模块加载器与槽位,真渲染指示器、面板与价格列
node scripts/verify-install.mjs   # 安装后必跑:配置 YAML 合法性 + 包解析 + 模块加载
```

第 4 个尤其重要:**profile 配置语法错误会让整个 Web 界面起不来**,不只是本插件。
`formattest.mjs` 全程使用临时 `DSH_HOME`,**不读也不写任何真实会话数据**,升级宿主后可放心先跑它。

### 目录结构

```
dsh-turn-tokens/
├── package.json            插件清单(dsh.bundle / dsh.client 声明)
├── cordis.patch.yml        自注册补丁(安装机制读它)
├── lib/
│   ├── index.js            host 半边:日志解析 + 来源归因 + HTTP 路由
│   └── client.js           client 半边:指示器 + 面板 + 价格计算
├── scripts/
│   ├── install.ps1         安装 / 卸载(纯 ASCII,避免编码问题)
│   ├── sync-profile.ps1    同步到已装 profile 的副本(hard link 断裂时用,纯 ASCII)
│   ├── selftest.mjs        host 自测(真实会话)
│   ├── formattest.mjs      日志格式两代自测(合成日志,不碰真实数据)
│   ├── clienttest.mjs      client 自测
│   └── verify-install.mjs  安装校验
├── docs/DEVELOPMENT.md     开发记录:踩坑、契约细节、验证方法
├── README.md / README.en.md
└── LICENSE
```

改代码前请先读 `docs/DEVELOPMENT.md`,踩坑与"为什么这么做"都在里面。

## 已知限制

- 只覆盖**当前会话**:不做跨会话账本、余额、账单与预算。
- 面板为表格与条形,不含趋势图。
- 每轮明细依赖已落盘的日志:**正在进行中的那一轮**要等该轮结束才完整。
- 不传会话标识时按"最近修改的会话"取,多会话并发时以最后动过的为准。
- system 分段按空行切分,是近似结构,不等于宿主内部的提示节边界。
- 消息体估算统计的是日志里全部消息文本,**不等于本次请求实际携带**(压缩与替换后会有偏差)。
- 价格按官方刊例价估算,不等于官方账单。

## 许可

[MIT](LICENSE)

数据来源:公开的 DeepSeek Harness 插件目录与各插件 GitHub 仓库。本站为独立第三方目录,与 DeepSeek、幻方(High-Flyer)及插件作者均无隶属或背书关系。

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。