🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

回答耗时拆解 liuzhihao-min/dsh-answer-timing

DeepSeek Harness
liuzhihao-min10 天前有提交已提供中文文档扫描:含敏感能力

拆解每次回答的模型、工具与等待耗时

29.8/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/27 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add liuzhihao-min/dsh-answer-timing
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
dsh 原生插件 · tool
暂无时间戳·判据 →
装得上吗[实装验证]—
本站尚未做安装检查
暂无时间戳·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 10 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件
查看扫描证据(共 21 处,展示前 16 条)
  • 读取本地文件
    lib/store.mjs:30
    if (!existsSync(this.file)) return;
  • 读取本地文件
    lib/store.mjs:33
    for (const line of readFileSync(this.file, "utf8").split(/ ? /)) {
  • 写入本地文件
    lib/store.mjs:78
    mkdirSync(this.dir, { recursive: true });
  • 写入本地文件
    lib/store.mjs:79
    appendFileSync(this.file, JSON.stringify(rec) + "\n", "utf8");
  • 读取本地文件
    install.mjs:69
    console.log(readFileSync(fileURLToPath(import.meta.url), 'utf8').split('*/')[0].replace(/^ ?/, ''));
  • 读取本地文件
    install.mjs:75
    const pkg = JSON.parse(readFileSync(join(PLUGIN_ROOT, 'package.json'), 'utf8'));
  • 读取本地文件
    install.mjs:81
    if (!existsSync(join(PLUGIN_ROOT, pkg.main || 'index.js'))) {
  • 读取本地文件
    install.mjs:91
    if (!existsSync(PROFILE_PKG)) {
  • 读取本地文件
    install.mjs:93
    const found = existsSync(profilesRoot)
  • 读取本地文件
    install.mjs:94
    ? readdirSync(profilesRoot).filter((n) => {
  • 删除本地文件
    install.mjs:121
    unlinkSync(linkPath);
  • 写入本地文件
    install.mjs:137
    if (O.dryRun) { info(`将把真实目录改名为 ${bak}`); } else { renameSync(linkPath, bak); warn(`原目录已备份为 ${bak}`); }
  • 写入本地文件
    install.mjs:141
    mkdirSync(dirname(linkPath), { recursive: true });
  • 删除本地文件
    install.mjs:153
    unlinkSync(linkPath);
  • 写入本地文件
    install.mjs:236
    writeFileSync(bak, readFileSync(PROFILE_PKG));
  • 写入本地文件
    install.mjs:238
    writeFileSync(PROFILE_PKG, JSON.stringify(profile, null, 2) + '\n');
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-tools@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DSH 的答案级耗时拆解:模型思考、首 token、解码时间、每个工具的开销,以及其他全部。

README

由 DeepSeek 最新模型翻译生成
dsh-answer-timing 把「这次回答到底花了多少时间、花在哪」变成可查的数据。 给 DeepSeek Harness(DSH)用的耗时统计插件。 纯 host 端:不注入任何 client 代码、不改 UI,只旁听会话事件流。 输出长什么样 每次回答结束,末尾一行: ⚡ 本次 1m23s = 模型 58s(首字 1.2s · 生成 41s)+ 工具 19s(pwsh 12s · read 4s · grep 3s)+ 其它 6s 需要明细时(detail: true),给三张表:阶段构成 / 工具累计 / 逐步骤。 它算什么 对每一次回答(turn),拆成三段: | 段 | 含义 | 来源 | | 模型 | 思考 + 生成的总时间;内部再分「首字」和「生成」 | step/start → assistant/message | | 工具 | 每个工具的实际执行时间,按工具名累加 | tool/call → tool/result(按 callId 配对) | | 其它 | 总时长减去上面两项:调度、审批等待、排队 | turn 起止差 − 模型 − 工具 | - 首字(ttft):从 step/start 到这个 step 第一个推理/文本 chunk 的时间(读 stream 里的 time0)。
展开完整文档(README 剩余 1 节)
dsh-answer-timing

把「这次回答到底花了多少时间、花在哪」变成可查的数据。

给 DeepSeek Harness(DSH)用的耗时统计插件。
纯 host 端:不注入任何 client 代码、不改 UI,只旁听会话事件流。

输出长什么样

每次回答结束,末尾一行:

⚡ 本次 1m23s = 模型 58s(首字 1.2s · 生成 41s)+ 工具 19s(pwsh 12s · read 4s · grep 3s)+ 其它 6s

需要明细时(detail: true),给三张表:阶段构成 / 工具累计 / 逐步骤。

它算什么

对每一次回答(turn),拆成三段:

| 段 | 含义 | 来源 |
| 模型 | 思考 + 生成的总时间;内部再分「首字」和「生成」 | step/start → assistant/message |
| 工具 | 每个工具的实际执行时间,按工具名累加 | tool/call → tool/result(按 callId 配对) |
| 其它 | 总时长减去上面两项:调度、审批等待、排队 | turn 起止差 − 模型 − 工具 |

- 首字(ttft):从 step/start 到这个 step 第一个推理/文本 chunk 的时间(读 stream 里的 time0)。
- 生成(decode):首个 chunk 到 assistant/message 落定的时间。
- 总时长:这一轮第一个带 data.turn 的事件到最后一个事件的时间差。

安装

前置

- DSH >=0.2.1-rc.2 <0.3.0
- Node.js >=24

最快:一条命令

dsh plugin --profile <你的 profile> add dsh-answer-timing

或者直接把仓库地址给它:

dsh plugin --profile <你的 profile> add https://github.com/liuzhihao-min/dsh-answer-timing

两种写法都实测过(DSH 0.2.1-rc.2 / pnpm 11):dsh plugin add 底层是 pnpm,装完会读取包里的 dsh.bundle 清单,自动把包写进 dsh.profile.bundles——不需要手动改 package.json,也不需要建 junction。

然后完全退出 DSH 再启动。

桌面版 profile 名一般是 desktop,Web 版是 web。国内的网络环境推荐用上面第一种(走 npm),第二种要连 github.com。

从源码(想改代码时)

git clone https://github.com/liuzhihao-min/dsh-answer-timing
cd dsh-answer-timing
node install.mjs

脚本会做四件事(全部可重复执行,幂等):

1. <profile>/.dsh-answer-timing-source → 本仓库(Windows 用 junction,macOS/Linux 用 symlink)
2. <profile>/node_modules/dsh-answer-timing → 本仓库
3. dependencies["dsh-answer-timing"] = "link:.dsh-answer-timing-source"
4. dsh.profile.bundles 末尾追加 dsh-answer-timing

写 package.json 前会自动备份成 package.json.bak-<时间戳>。然后完全退出 DSH 再启动(改 profile 不热加载)。

常用参数:

| 参数 | 作用 |
| --dry-run | 只打印将要做什么,不写文件 |
| --profile web | 指定其它 profile(默认 desktop) |
| --dsh-home D:\x | 指定 DSH 目录(默认 ~/.dsh 或 $DSH_HOME) |
| --force | 目标位置是真实目录时,改名备份后继续 |
| --uninstall | 卸载:摘掉 bundles / 依赖 / 两个链接 |

卸载时 DSH 必须先退出。 否则 node_modules 里的链接被占用删不掉(脚本会警告并跳过,注册信息仍会清干净,退出后再跑一次即可)。

从 npm 手动安装(不用 dsh plugin add 时)

一般用上面的「最快:一条命令」就够了。只有在 CLI 用不了、要自己控制依赖版本时才走这一节。

包已发布:dsh-answer-timing

在当前 profile 目录(桌面版一般是 ~/.dsh/profiles/desktop)里装:

cd ~/.dsh/profiles/desktop
npm install dsh-answer-timing

然后在同一个 package.json 里补两处:

{
"dependencies": {
"dsh-answer-timing": "^1.0.0" // ① 依赖 },
"dsh": {
"profile": {
"bundles": [
"dsh-answer-timing" // ② 末尾追加这一项 ] } } } 从 npm 装的不用建 junction —— 包已经在 node_modules 里了。install.mjs 是给源码目录用的。

改完同样要完全退出 DSH 再启动。

两种来源的区别

| 来源 | 命令 | 要 junction 吗 | 适合 |
| npm | npm install dsh-answer-timing | 不用 | 只想用,不打算改代码 |
| 源码 | git clone + node install.mjs | 要(脚本自动建) | 想改代码、跟着仓库更新 |

手动注册(不想跑脚本时)

1. 目录联接(换成你自己的实际路径) cmd /c mklink /J "$env:USERPROFILE\.dsh\profiles\desktop\.dsh-answer-timing-source" "D:\plugins\dsh-answer-timing" cmd /c mklink /J "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-answer-timing" "D:\plugins\dsh-answer-timing"

// 2. package.json → dependencies 里加一行 "dsh-answer-timing": "link:.dsh-answer-timing-source"

// 3. package.json → dsh.profile.bundles 末尾追加 "dsh-answer-timing"

然后完全退出 DSH 再启动(改 profile 不会热加载)。

验证

对话里问一句「刚才那轮花了多久」,或直接调用 timing_report。
工具存在即安装成功;~/.dsh/timing/turns.jsonl 会在第一轮结束后出现。

使用

工具:timing_report

| 参数 | 说明 |
| scope | last(默认)/ turn / session / turns |
| turn | 指定轮次(配合 scope: "turn") |
| limit | scope: "turns" 取最近几条,默认 10 |
| detail | true 时给「阶段构成 / 工具累计 / 逐步骤」三张表 |

配套技能 answer-timing 会让智能体在每次回答末尾自动附上那一行。

落盘与隐私

- 路径:$DSH_HOME/timing/turns.jsonl(未设 DSH_HOME 时用 ~/.dsh/timing/turns.jsonl)
- 一行一个 turn,按 sessionId + turn 去重
- 只存:时间戳、各段毫秒数、输出 tokens、工具名、模型名
- 不存:提示词、回答正文、工具参数、任何对话内容
- 默认保留 30 天(读取时按 retentionDays 过滤,不改写文件)

配置

| 键 | 默认 | 说明 |
| dataDir | 空 | 自定义落盘目录 |
| retentionDays | 30 | 历史保留天数 |
| maxTurnsInMemory | 200 | 每会话内存里保留多少轮 |

口径与限制

- 一个 step 若产生多条 assistant/message(重试/多次 attempt),只记最后一次,其余不累加。
- 没有 step/start 锚点的 step 不臆造耗时,只计入 untimedSteps,这样能和官方 sessionStats 的口径对上。
- 工具审批等待发生在 tool/call 与 tool/result 之间,因此算进「工具」而不是「其它」。
- 子代理是独立会话,各自统计;主会话里子代理调用的等待算在主会话的「工具」。
- 宿主重启后,内存里的逐轮状态从零开始;历史请用 scope: "turns" 读落盘账本。
- 这是观测插件:不改变任何调度、超时或重试行为。

目录结构

.
├── index.js # 插件入口:订阅事件 + 注册工具 ├── install.mjs # 安装/卸载脚本(幂等,自动备份 package.json) ├── cordis.patch.yml # bundle 插入声明 ├── lib/ │ ├── fold.mjs # 纯函数:事件流 → 逐轮耗时 │ ├── format.mjs # 单行摘要 + 三张明细表 │ └── store.mjs # JSONL 账本(去重、保留期) ├── test/ │ └── fold.test.mjs # node:test,9 个用例 └── .github/workflows/ └── test.yml # CI:ubuntu + windows × node 24

开发与测试

node test/fold.test.mjs

用 node --test 在某些受限沙箱里会因子进程 spawn EPERM 失败,直接执行测试文件即可(node:test 在进程内跑)。
调试插件加载:设 DSH_ANSWER_TIMING_DEBUG=1,启动时会往 stderr 打一行 [answer-timing] loaded。

兼容性

依赖 DSH 的会话事件字段(step/start、assistant/message、tool/call、tool/result、turn/end)。
这些是 DSH 的内部接口,随版本可能变动;升级 DSH 后若数字异常,先在这里排查字段名。

许可

MIT
预览分享卡片长什么样 ↓liuzhihao-min/dsh-answer-timing
分享 · DeepSeek Harness Hub
liuzhihao-min/dsh-answer-timing

拆解每次回答的模型、工具与等待耗时

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部