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

插件性能透视 Nwflower/dsh-perf-lens

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

按插件归因 CPU、内存与磁盘占用,定位拖慢宿主的元凶

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

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · chat
装得上吗
实装验证未通过(runtime_smoke_failed),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 29 天前
档位由哪些信号合成

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

验证判据与等级说明 →
⚠︎ 实装验证未通过(runtime_smoke_failed · 2026/11/4) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 68 处,展示前 67 条)
  • 读取本地文件
    probes/01-esm-builtin-patchability.mjs:20
    readFileSync('C:/Windows/win.ini')
  • 写入本地文件
    probes/03-overhead.mjs:35
    writeFileSync(ioPath, payload)
  • 读取本地文件
    probes/03-overhead.mjs:36
    readFileSync(ioPath)
  • 删除本地文件
    probes/03-overhead.mjs:89
    rmSync(ioPath, { force: true })
  • 删除本地文件递归
    probes/04-ancestor-walk.mjs:21
    rmSync(root, { recursive: true, force: true })
  • 写入本地文件
    probes/04-ancestor-walk.mjs:22
    mkdirSync(join(root, 'shared'), { recursive: true })
  • 写入本地文件
    probes/04-ancestor-walk.mjs:24
    writeFileSync(
  • 写入本地文件
    probes/04-ancestor-walk.mjs:28
    writeFileSync(
  • 写入本地文件
    probes/04-ancestor-walk.mjs:32
    writeFileSync(
  • 删除本地文件递归
    probes/04-ancestor-walk.mjs:103
    rmSync(root, { recursive: true, force: true })
  • 写入本地文件
    probes/05-io-counters.mjs:20
    writeFileSync(ioPath, payload)
  • 读取本地文件
    probes/05-io-counters.mjs:21
    readFileSync(ioPath)
  • 删除本地文件
    probes/05-io-counters.mjs:40
    rmSync(ioPath, { force: true })
  • 写入本地文件
    probes/06-async-hooks-fs.mjs:31
    writeFileSync(ioPath, 'x'.repeat(1024))
  • 读取本地文件
    probes/06-async-hooks-fs.mjs:34
    readFileSync(ioPath)
  • 读取本地文件
    probes/06-async-hooks-fs.mjs:35
    readFileSync(ioPath)
  • 写入本地文件
    probes/06-async-hooks-fs.mjs:44
    writeFileSync(ioPath, 'w')
  • 写入本地文件
    probes/07-runtime-composition.mjs:42
    await writeFile(file, JSON.stringify(big))
  • 读取本地文件
    probes/07-runtime-composition.mjs:43
    await readFile(file, 'utf8')
  • 删除本地文件递归
    probes/07-runtime-composition.mjs:50
    await rm(dir, { recursive: true, force: true })
  • 读取本地文件
    probes/10-heap-snapshot-and-analyzer.mjs:70
    ` file ${mb(statSync(snapshotPath).size)}MB\n`,
  • 读取本地文件
    probes/10-heap-snapshot-and-analyzer.mjs:78
    const raw = readFileSync(snapshotPath, 'utf8')
  • 读取本地文件
    probes/10-heap-snapshot-and-analyzer.mjs:291
    console.log(` file bytes on disk ${mb(statSync(snapshotPath).size)}MB`)
  • 删除本地文件
    probes/10-heap-snapshot-and-analyzer.mjs:293
    rmSync(snapshotPath, { force: true })
  • 发起网络请求
    probes/11-real-host-heap-snapshot.mjs:42
    const res = await fetch('http://127.0.0.1:' + port + '/json/list')
  • 写入本地文件
    probes/11-real-host-heap-snapshot.mjs:97
    stream = createWriteStream(out)
  • 读取本地文件
    probes/11-real-host-heap-snapshot.mjs:107
    const fileMb = statSync(out).size / 1024 / 1024
  • 读取本地文件
    probes/12-history-share-audit.mjs:49
    names = readdirSync(dir).filter((name) => name.endsWith('.jsonl'))
  • 读取本地文件
    probes/12-history-share-audit.mjs:75
    const rl = createInterface({ input: createReadStream(file), crlfDelay: Infinity })
  • 读取本地文件
    probes/13-real-host-anchor-discovery.mjs:25
    console.log('snapshot: ' + file + ' (' + mb(statSync(file).size) + 'MB)')
  • 读取本地文件
    probes/13-real-host-anchor-discovery.mjs:28
    const raw = readFileSync(file, 'utf8')
  • 读取本地文件
    probes/13-real-host-anchor-discovery.mjs:53
    console.log(' nodes/MB ' + (nodeCount / (statSync(file).size / 1024 / 1024)).toFixed(0) + ' (probe 10 synthetic: 15,700 nodes/MB)')
  • 读取本地文件
    probes/14-heap-snapshot-module-owners.mjs:53
    const parsed = JSON.parse(readFileSync(rulesPath, 'utf8'))
  • 读取本地文件
    probes/14-heap-snapshot-module-owners.mjs:63
    const raw = readFileSync(path, 'utf8')
  • 读取本地文件
    probes/14-heap-snapshot-module-owners.mjs:259
    console.log(`file ${mb(statSync(path).size)}MB nodes ${nodeCount.toLocaleString()} edges ${totalEdges.toLocaleString()} reachable ${reachable.toLoc
  • 读取本地文件
    probes/15-empty-window-audit.mjs:33
    names = readdirSync(dir).filter((name) => name.endsWith('.jsonl'))
  • 读取本地文件
    probes/15-empty-window-audit.mjs:46
    for (const line of readFileSync(file, 'utf8').split('\n')) {
  • 读取本地文件
    probes/17-log-line-compaction.mjs:18
    const files = readdirSync(dir)
  • 读取本地文件
    probes/17-log-line-compaction.mjs:27
    const lines = readFileSync(file, 'utf8').split('\n').filter(Boolean)
  • 写入本地文件
    probes/19-mechanism-c.mjs:59
    writeFileSync(harnessPath, HARNESS_SOURCE)
  • 写入本地文件
    probes/19-mechanism-c.mjs:60
    writeFileSync(pluginPath, PLUGIN_SOURCE)
  • 删除本地文件递归
    probes/19-mechanism-c.mjs:166
    rmSync(dir, { recursive: true, force: true })
  • 读取本地文件
    probes/23-loaf-attribution.mjs:40
    const capture = JSON.parse(readFileSync(file, 'utf8'))
  • 读取本地文件
    probes/23-loaf-attribution.mjs:122
    entries = readdirSync(root, { withFileTypes: true })
  • 读取本地文件
    probes/23-loaf-attribution.mjs:134
    for (const inner of readdirSync(join(root, entry.name), { withFileTypes: true })) {
  • 读取本地文件
    probes/23-loaf-attribution.mjs:146
    const manifest = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'))
  • 读取本地文件
    probes/23-loaf-attribution.mjs:150
    return readFileSync(join(dir, entry), 'utf8')
  • 读取密钥环境变量
    probes/23-loaf-attribution.mjs:221
    const token = option('token', process.env.DSH_WEB_TOKEN ?? '')
  • 发起网络请求
    probes/23-loaf-attribution.mjs:230
    const response = await fetch(`${base}/api-perf/vitals${suffix}`)
  • 读取本地文件
    probes/23-loaf-attribution.mjs:274
    files = readdirSync(dir).filter(name => /^metrics-\d{8}\.jsonl$/.test(name))
  • 读取本地文件
    src/host/disk-footprint.ts:41
    lstat(path: string): Promise<{ readonly size: number; isDirectory(): boolean; isFile(): boolean }>
  • 读取本地文件
    src/host/disk-footprint.ts:45
    openDir: (path) => opendir(path),
  • 读取本地文件
    src/host/disk-footprint.ts:46
    lstat: (path) => lstat(path),
  • 写入本地文件
    src/host/history.ts:130
    mkdirSync(path: string): void
  • 写入本地文件
    src/host/history.ts:131
    appendFileSync(path: string, data: string): void
  • 读取本地文件
    src/host/history.ts:132
    readFileSync(path: string): string
  • 读取本地文件
    src/host/history.ts:135
    readdirSync(path: string): string[]
  • 读取本地文件
    src/host/history.ts:136
    statSync(path: string): { readonly size: number; readonly mtimeMs: number }
  • 删除本地文件
    src/host/history.ts:137
    unlinkSync(path: string): void
  • 写入本地文件
    src/host/history.ts:142
    mkdirSync: (path) => { mkdirSync(path, { recursive: true }) },
  • 写入本地文件
    src/host/history.ts:143
    appendFileSync: (path, data) => { appendFileSync(path, data) },
  • 读取本地文件
    src/host/history.ts:144
    readFileSync: (path) => readFileSync(path, 'utf8'),
  • 读取本地文件
    src/host/history.ts:160
    readdirSync: (path) => readdirSync(path),
  • 读取本地文件
    src/host/history.ts:161
    statSync: (path) => statSync(path),
  • 删除本地文件
    src/host/history.ts:162
    unlinkSync: (path) => { unlinkSync(path) },
  • 读取本地文件
    src/host/index.ts:145
    return readFileSync(path, 'utf8')
  • 执行外部命令来自配置/变量
    src/host/process-tree.ts:172
    execFile(file, [...args], { timeout: COMMAND_TIMEOUT_MS, maxBuffer: COMMAND_MAX_BUFFER, windowsHide: true }, (error, stdout) => {
扫描于 2026/11/3(1 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库

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

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

功能亮点

  • 按插件归因资源占用
  • 展示CPU内存磁盘开销

DeepSeek Harness 插件资源开销面板:按插件归因 CPU、内存、磁盘占用。DSH 插件面板,显示哪些插件占用宿主 CPU、内存和磁盘,并按插件归因。

README

由 DeepSeek 最新模型翻译生成
dsh-perf-lens 一个 DeepSeek Harness(DSH)插件,告诉你哪个插件在吃宿主机的 CPU、内存和磁盘,又是哪个插件把浏览器拖卡的。 DSH 宿主的每个插件都跑在同一个 Node 进程里,操作系统只能告诉你整个进程的开销。Perf Lens 从进程内部采样,把每次采样算到引发它的插件头上,再把结果放进 DSH Web GUI 的仪表盘——浏览器端也照此处理,长帧的脚本耗时按插件归属(Long Animation Frames API)。哪里感觉慢了,不用再临时写一堆性能脚本。 状态: 0.1.0 功能已完整(见 CHANGELOG.md);0.2.0 正在 master 上开发——按插件归属的卡顿、子进程视图、监听器 / 磁盘占用两列都已落地。 你能看到什么 在左侧边栏打开 Perf Lens: - 进程总览 —— RSS、堆、事件循环延迟、GC 停顿,以及上一个窗口里有多少时间处于空闲;还有那些只有宿主自己说不清的读数:子进程树(数量、合计 CPU、合计内存)、配置档没能归因的 CPU,以及进程持有的异步资源。 - 开销构成 —— 每个插件占整个进程的比例,CPU 和采样堆各一份。 - 消耗大户 —— 当前最费资源的插件,附平均值和峰值。 - 趋势 —— 最近一小时、一天或一周里每个插件的 CPU。
展开完整文档(README 剩余 1 节)
dsh-perf-lens

一个 DeepSeek Harness(DSH)插件,告诉你哪个插件在吃宿主机的 CPU、内存和磁盘,又是哪个插件把浏览器拖卡的。

DSH 宿主的每个插件都跑在同一个 Node 进程里,操作系统只能告诉你整个进程的开销。Perf Lens 从进程内部采样,把每次采样算到引发它的插件头上,再把结果放进 DSH Web GUI 的仪表盘——浏览器端也照此处理,长帧的脚本耗时按插件归属(Long Animation Frames API)。哪里感觉慢了,不用再临时写一堆性能脚本。

状态: 0.1.0 功能已完整(见 CHANGELOG.md);0.2.0 正在 master 上开发——按插件归属的卡顿、子进程视图、监听器 / 磁盘占用两列都已落地。

你能看到什么

在左侧边栏打开 Perf Lens:

- 进程总览 —— RSS、堆、事件循环延迟、GC 停顿,以及上一个窗口里有多少时间处于空闲;还有那些只有宿主自己说不清的读数:子进程树(数量、合计 CPU、合计内存)、配置档没能归因的 CPU,以及进程持有的异步资源。
- 开销构成 —— 每个插件占整个进程的比例,CPU 和采样堆各一份。
- 消耗大户 —— 当前最费资源的插件,附平均值和峰值。
- 趋势 —— 最近一小时、一天或一周里每个插件的 CPU。
- 累计开销排行 —— 这段时间里谁烧的 CPU 最多。
- 插件详情 —— 所有插件分组、可排序,最重的 harness 包单独列出;深度模式下还能看到每个插件的热点函数。每个插件都带 监听器(精确值,来自 cordis 事件注册表)和 磁盘字节数(精确值,来自对 $DSH_HOME 的目录扫描)。
- 前台卡顿 —— 浏览器里的长任务和掉帧,长帧脚本耗时按插件归属(Long Animation Frames API),旁边对照当时宿主在忙什么。不支持该 API 的浏览器退回普通的时间相关性分析。在 DSH Desktop 窗口里,浏览器不给这份归属数据,改用 卡顿探针 开关来测量:哪些插件调度的回调占着主线程,附每个插件的回调毫秒数、调用次数和单次最长调用。

面板跟随 GUI 语言(中文或英文)。

环境要求

- DeepSeek Harness 0.1.7-alpha.1 或更高版本,使用 Web GUI(dsh web)
- Node.js 22.13 或更高版本(跑你 DSH 宿主的那个)

安装

还没上 npm——从本地检出安装:

git clone https://github.com/Nwflower/dsh-perf-lens.gitbash
cd dsh-perf-lens && pnpm install && pnpm build # produces lib/ (host + single-file client bundle)

然后在 DSH 配置档里注册它。默认 web 配置档要编辑 ~/.dsh/profiles/web/package.json: jsonc {
"dsh": { "profile": { "bundles": [ /* … existing bundles … /, "dsh-perf-lens" ] } },
"dependencies": { "dsh-perf-lens": "link:D:/path/to/dsh-perf-lens" }
}
bash
cd ~/.dsh/profiles/web && pnpm install

服务器启动时会加载 host 那一半,所以要重启 dsh web 才会生效。等包发布到 npm 之后,依赖那一行就变成 "dsh-perf-lens": "^0.1.0",也不需要构建步骤了。如果配置档的 pnpm 供应链策略(minimumReleaseAge)拦住了某个包,临时跑一次 pnpm install --config.minimumReleaseAge=0 就行,别去改配置档的设置。

采样控制

采样从来不是免费的,所以 Perf Lens 只在短窗口里采样,具体查得多勤由你决定。有三个控制项,它们会叠加生效——面板始终显示实际正在运行的组合,而不只是哪几个按钮亮着。

强度(三选一):

| 档位 | 做什么 | 什么时候用 |
| Low(默认) | 每 30 秒或更久采一个 5 秒窗口;host 空闲时退到 2 分钟一次,同时每 10 秒做一次 1 秒的轻量检查,免得漏掉突发 | 一直开着 |
| High | 连续采 2 秒窗口,一个接一个;10 分钟后回落到 low | 你正在盯着某个东西看的时候 |
| Stop | 不再开新窗口 | 想让 host 清静一会儿的时候 |

后台采样(开 / 关)决定强度为 Stop 时怎么办:开着的话,host 每 2 分钟保留一个粗略的 2 秒窗口,这样面板关掉也能留下长期记录。在 Low 或 High 下它没什么可补的,因为前台已经在采样了。

内存采样(开 / 关)给实际运行的窗口加上堆采样——内存归因、每个插件的热点函数,以及插件通过 harness 回调安排的工作也算在它头上。这是最贵的选项,也是唯一在 CPU 采样之外还要额外花钱的选项。

所以 Stop + 后台开* 是便宜的常开记录,Low + 内存开 是常规的性能分析配置,High + 内存开 就是「我现在正盯着看」。每次改动立即生效,三项设置都由 host 上报,所以刷新页面也不会丢。

读懂这些数字

- 占比 vs 绝对开销。 插件的占比是它在窗口内进程实际用掉的 CPU 里占的那一份。host 空闲时分母很小,所以跑了短短几毫秒的东西也可能显示 90%。面板总会在旁边给出绝对开销——每秒 CPU 毫秒数和单核百分比——跨时间或跨机器比较要看的是这个数。
- 算在调用方头上。 每个样本都会沿调用栈往上走到最近的插件栈帧,所以插件调用到的代码(它自己的依赖、Node 内置模块)都算在这个插件头上。
- Harness built-ins 是 DSH 框架本身,合并成一行,下面列出它内部最忙的几个包。Runtime 行(GC、native / syscalls、Node internals、event loop)是没有任何插件栈帧在栈上的工作。This plugin's overhead 是 Perf Lens 自己。
- 估算值都有标记。 凡是采样得来、而非实测的数字都会注明;如果采样覆盖的范围太小,不足以诚实地外推,累计排名就隐藏整段范围的估算值。
- 卡顿归因会带上它的覆盖率。 按插件统计的长帧表总会显示可归因的脚本时间占比;分段读不出来的组合包会落进明确的「Unresolved」行,绝不猜。
限制
- 没有按插件统计的 RSS。 一个进程只有一个 RSS。内存数字是 deep-mode 窗口里采样得到的堆分配量,不是某个插件的占用。
- 子进程只展示,不归因。 概览报告的是宿主的所有后代进程总共花了多少,因为 shell 命令、终端或语言服务器跑在宿主之外,只看宿主会显得很闲。哪个插件拉起了子进程,目前还没测;而且进程树是轮询而非监听,所以两次轮询之间启动又退出的命令看不到——这个读数针对的是长命的后代进程(语言服务器、开发服务器、终端、构建)。在 Windows 上每次轮询大约花 330ms 墙钟时间(启动一次 PowerShell),所以每 30s 跑一次,面板打开时额外立即刷新一次。
- 磁盘字节数没有测。 按插件统计的文件操作次数是精确的,按插件统计的磁盘占用(「On disk」列,扫描 $DSH_HOME 加上每个插件自己的目录)也是精确的;文件的读写字节数不是。扫描不跟随符号链接,所以如果某个插件的文件位于这两个根目录之外、又藏在链接后面,读出来就是空的。
- 定时器和句柄只有进程级。 要按插件统计它们,需要一个常开的 async_hooks 钩子,实测在 promise 密集的工作上会带来 2.3–2.6× 的开销,所以面板只报告进程总数,干脆不显示按插件的列,而不是给出一个假的零。监听器是按插件统计的,而且精确。
- 无法解释的 CPU 是信号,不是答案。 它说明有 CPU 跑在采样线程之外(某个 worker,或 native 代码);它不说明是哪个插件放进去的。
- 短窗口噪声大。 单个窗口适合看「谁在忙」;累计排名才是精确的视角。
- 卡顿归因只覆盖脚本执行。 Long Animation Frames 会指出运行的是哪个脚本、以及它强制触发了哪些样式/布局;绘制、合成和浏览器自身的记账不属于任何脚本,留在帧级总数里。这个 API 需要 Chromium 123 或更高版本(DSH web GUI 满足要求);较旧的引擎会显示关联视图。DSH Desktop 窗口(dsh-app:// 自定义协议)在浏览器层面不提供脚本归属信息,所以长帧表格只会在 dsh web GUI 上出现。

- 卡顿探针测的是注册,不是执行。 它报告页面在某个位置注册的回调里花掉的总时间,统计每一层的嵌套包装器数量,但说不出回调里到底是哪条语句耗掉了时间(该源上的页内分析器已禁用)。插件可以注册另一个插件的回调,所以某一行读作「在此处注册的回调」。它默认关闭;打开后会重新加载页面一次,好让探针在插件注册之前装好,这个选择会被记住。

数据与隐私

- 一切都留在你的机器上。面板只跟你自己的 DSH 主机通信。
- 每个采样窗口会往 $DSH_HOME/perf-lens/metrics-YYYYMMDD.jsonl 追加一行聚合数字(默认 ~/.dsh/perf-lens/)。文件保留 14 天,总量上限 200 MB。
- 只写入开销和计数。调用栈、函数名和文件路径绝不写入磁盘;深度模式开启期间,热点函数只存在内存里。磁盘占用扫描会读取 $DSH_HOME 下的路径,但只写入算出的字节总数;后代进程读取只在内存里保留进程名。
- 后代进程读取每 30 秒跑一次进程表命令(ps,Windows 上是 PowerShell);这是 Perf Lens 启动的唯一外部进程。
- 卸载插件会停止所有采样,以及它拥有的每一个定时器。

故障排查

如果面板是空的,或者数字看着不对,先查诊断端点: powershell Invoke-RestMethod http://127.0.0.1:3081/api-perf/diagnostics | ConvertTo-Json -Depth 4

- sampleCount 为 0 表示上一个窗口没采到样本;lastError 显示采样循环捕获到的异常。
- ownerRules 应该列出真实的包目录(例如 …/node_modules/dsh-context/lib)。如果它是空的,或者指向配置档目录,说明插件路径没能解析,样本会落到「未归属」里。
- listenersMeasured 应该是 true。如果是 false,说明 cordis 事件注册表没有暴露出来,Listeners 这一列就是个缺口,而不是数字。
- processTree.available 应该是 true,且 at 非零。如果是 false,说明进程表命令(ps,Windows 上是 PowerShell)缺失或被拒绝,概览会显示「无法读取」而不是「没有子进程」——这是两件不同的事实。
- diskFootprint 应该非 null,且 scannedAt 是最近的。truncated: true 表示遍历撞到了预算上限,或者打不开某个根目录,所以每一个磁盘上的数字都只是下界。
- 采样控件变灰并带警告。 主机那一半只在 dsh web 时加载一次启动时;面板是页面拉取的 bundle。升级插件后,页面可能比正在运行的主机更新,而早于三块控件的宿主不认识它们发送的字段——点击会被静默忽略。面板会检测到这一点(宿主不上报采样配置),并禁用这些控件。重启 dsh web 以加载新的宿主部分。
- 同样的版本偏差也会影响端点结构:早于 0.1.0 的宿主返回的 /api-perf/snapshot 没有 sampling 字段,早于绝对基准的宿主返回的 /api-perf/trend 没有 cpuMsPerSec。

面板背后的 HTTP API(/api-perf/snapshot、/stats、/trend、/hotspots 等)记录在 docs/design.md §8。

开发 bash
pnpm install # dev toolchain only; the harness peer packages are not installed (see .npmrc)
pnpm test # vitest: host specs in node, client specs in jsdom
pnpm typecheck # tsc --noEmit
pnpm lint # oxlint
pnpm build # tsdown: lib/index.js (host) + lib/client.js (single-file client bundle)

prepublishOnly 会运行以上全部四项。

本地改动后,用 pnpm build 重新构建,然后重新加载页面以加载客户端改动;宿主改动需要重启 dsh web。

harness 客户端类型包没有作为开发依赖安装:它们在 registry 上的 latest 标签指向一条损坏的 0.0.1-rc.1 版本线,依赖一个未发布的包。客户端改为在 src/client/ctx.ts 中声明自己需要的结构化类型,与 dsh-context 的做法一致。

文档

| 文档 | 内容 |
| docs/feasibility.md | 为什么可行:运行时事实、每种机制都经过验证、开销、限制 |
| docs/landscape-survey.md | 还有谁把运行时开销归因到插件:DSH 生态、其他插件宿主、持续分析器,以及可以借鉴什么 |
| docs/roadmap-proposals.md | 调研后提出的功能,按哪些承诺缺口真实存在排序 |
| docs/design.md | 架构:归因、指标契约、采样状态机、持久化、HTTP API、仪表盘布局、决策 |
| docs/evidence.md | 每个结论背后的原始实测输出,以及如何复现 |
| docs/design-overnight-analyzer.md | 关于持续后台分析的研究:采样器开销、堆快照(已否决)、占比开销与绝对开销、检测精度 |
| probes/README.md | 一次性研究脚本,以及每个脚本确立了哪些结论 |
| CHANGELOG.md | 每个版本包含什么 |

生态

同一作者的其他 DSH 插件: dsh-chat-import(把 25+ 个外部智能体的聊天记录迁移到 DSH)· dsh-pilot(契约驱动(主代理/子代理调度)· dsh-file-claim (多会话文件认领)· dsh-claude-style

许可证

MIT
预览分享卡片长什么样 ↓Nwflower/dsh-perf-lens
分享 · DeepSeek Harness Hub
Nwflower/dsh-perf-lens

按插件归因 CPU、内存与磁盘占用,定位拖慢宿主的元凶

这是你的仓库?认领条目

回到顶部