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

后台任务统计 kahomesl/dsh-client-ui-job-stats

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

在侧边栏累计记录本会话跑过的每个任务

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

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:待复验
是什么
dsh 原生插件 · ui
装得上吗
曾在 dsh 0.2.0-rc.2 下真实安装成功,但当前 dsh 已更新至 0.2.1-rc.5,本站尚未在新版下复验
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 36 天前
档位由哪些信号合成

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

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

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

读写/删除本地文件发起外部网络请求
查看扫描证据(共 12 处,展示前 12 条)
  • 发起网络请求
    client/client.js:1084
    response = await fetch(outcomesUrl(sessionId), { headers: { accept: 'application/json' } });
  • 写入本地文件
    lib/recorder.js:199
    mkdirSync(dirname(path), { recursive: true });
  • 写入本地文件
    lib/recorder.js:202
    writeFileSync(temporary, body);
  • 写入本地文件
    lib/recorder.js:203
    renameSync(temporary, path);
  • 读取本地文件
    lib/recorder.js:214
    parsed = JSON.parse(readFileSync(file, 'utf8'));
  • 删除本地文件
    lib/recorder.js:263
    rmSync(`${path}.tmp`, { force: true });
  • 写入本地文件
    lib/recorder.js:278
    renameSync(`${path}.tmp`, path);
  • 读取本地文件
    lib/recorder.js:310
    if (!existsSync(path)) return undefined;
  • 读取本地文件
    lib/recorder.js:313
    if (statSync(path).size > 24 * 1024 * 1024) throw new Error('legacy import exceeds 24 MiB');
  • 读取本地文件
    lib/recorder.js:314
    const body = JSON.parse(readFileSync(path, 'utf8'));
  • 读取本地文件
    lib/recorder.js:548
    if (!existsSync(importPath)) return;
  • 删除本地文件
    lib/recorder.js:565
    rmSync(importPath);
扫描于 2026/10/31(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

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

功能亮点

  • 侧边栏标签页
  • 累计记录会话任务

DeepSeek Harness 的会话后台任务统计:右侧边栏的一个标签页,累计记录本会话跑过的每一个任务。

README

由 DeepSeek 最新模型翻译生成
dsh-client-ui-job-stats CI License: MIT DeepSeek Harness DeepSeek Harness 的会话后台任务统计:右侧边栏的一个标签页,累计记录本会话跑过的每一个任务。 后台任务统计面板点开一行后显示完整命令 这两张图由 pnpm preview 用插件自己的组件渲染而成 —— 与宿主实际提供的 client/client.js 是同一个文件,按渲染器组装的 props 挂载、配色取应用真实深色主题的 token 值,只有任务行是示例数据(真实会话的截图会暴露那个会话跑过什么)。它们声明在 screenshots.json 里,插件市场读的就是它。 它是什么 Harness 自带的会话头部「后台任务」列表是一张实时名册:只列会话当前还看得到的任务,而前台命令一旦被调用方取走输出,它的记录就会从名册里消失。所以它适合看"现在在跑什么",不适合当统计 —— 任务会闪一下就没了。 本插件在右侧边栏里补了一个统计席位: - 在哪 —— 展开右侧边栏(会话头部的「打开侧边栏」按钮 / Ctrl+Alt+B),栏内「开始」页会多出第 4 张卡片 「后台任务统计」,与随附的「工作区文件 / 新建终端 / 浏览器」并列;点开即在栏内以标签页形式显示面板。
展开完整文档(README 剩余 1 节)
dsh-client-ui-job-stats

CI
License: MIT
DeepSeek Harness

DeepSeek Harness 的会话后台任务统计:右侧边栏的一个标签页,累计记录本会话跑过的每一个任务。

后台任务统计面板点开一行后显示完整命令

这两张图由 pnpm preview 用插件自己的组件渲染而成 —— 与宿主实际提供的 client/client.js 是同一个文件,按渲染器组装的 props 挂载、配色取应用真实深色主题的 token 值,只有任务行是示例数据(真实会话的截图会暴露那个会话跑过什么)。它们声明在 screenshots.json 里,插件市场读的就是它。

它是什么

Harness 自带的会话头部「后台任务」列表是一张实时名册:只列会话当前还看得到的任务,而前台命令一旦被调用方取走输出,它的记录就会从名册里消失。所以它适合看"现在在跑什么",不适合当统计 —— 任务会闪一下就没了。

本插件在右侧边栏里补了一个统计席位:

- 在哪 —— 展开右侧边栏(会话头部的「打开侧边栏」按钮 / Ctrl+Alt+B),栏内「开始」页会多出第 4 张卡片 「后台任务统计」,与随附的「工作区文件 / 新建终端 / 浏览器」并列;点开即在栏内以标签页形式显示面板。
- 显示什么 —— 各状态计数、完成率、累计耗时、最长耗时、保留输出,以及每个任务的明细(状态、类型、耗时、结束原因);排序为"运行中在前,已结束按结束时间倒序"。
- 范围 —— 一个会话一个标签页:面板只统计它是从哪个会话打开的。
- 语言 —— 简体中文与英文,跟随宿主语言。
- 累计 —— 面板记住它见过的每个任务,因此任务结束后仍留在统计里,而不是随名册消失。

功能

| 计数 | 合计 / 运行中 / 已完成 / 已失败 / 已取消 / 已结束 |
| 指标 | 完成率(只统计已上报结果的任务)、累计耗时、最长耗时、保留输出字节数 |
| 明细 | 每任务一行:状态点、概述、类型 · 状态 · 原因、耗时;列表自身可滚动(表头固定) |
| 说人话 | 能识别的命令显示"在干什么"—— 等待 75 秒 / 提交代码 / 跑测试 / 安装依赖 —— 而不是把代码原样贴出来 |
| 点击展开 | 点一下任务行展开:完整命令、任务 ID、类型、状态、开始/结束时刻、结束原因、保留输出 |
| 实时 | 有任务在跑时,耗时每秒刷新 |
| 台账 | 按会话分开、按 job id 合并、写入浏览器存储(上限 300 条,超出先淘汰最早已结束的) |
| 健壮 | 未知状态、缺 id、字段异常、台账损坏都不会抛错,也不会让面板变空 |

安装

插件就是一个普通的 Harness 组合包(bundle),从源码目录以 link 方式装进某个 profile:

git clone https://github.com/kahomesl/dsh-client-ui-job-stats.git

1. 在该 profile 目录(package.json 里列着 dsh.profile.bundles 的那个,例如 ~/.dsh/profiles/desktop)中,把它加为本地依赖并选为组合包:

{
"dependencies": {
"dsh-client-ui-job-stats": "link:/本机绝对路径/dsh-client-ui-job-stats" },
"dsh": {
"profile": {
"bundles": [
// …原有的组合包…
"dsh-client-ui-job-stats"
]
}
}
}

2. 安装:

pnpm install

3. 展开右侧边栏,「开始」页上就有 「后台任务统计」 卡片。宿主会自行重新读取变更过的客户端 bundle,面板本身不需要重启。
4. 重启一次 DSH。 宿主侧半成品(终态记录器)是一条 Loader 行,而 bundle patch 里的行是在启动时组合的;重启之前面板照常工作,但只能讲名册自己知道的故事(见"已知限制")。每次安装需要重启一次,之后的更新不需要。

包内的 cordis.patch.yml 只做两件事:向组合插入两条 Loader 行 —— job-stats → 本包(由它发布浏览器半侧)与 job-stats-recorder → 本包的 ./recorder 子路径(宿主半侧);不改动 profile 里的其它任何东西。

停用 / 卸载 —— 从 dsh.profile.bundles 里删掉包名即可停用(保留依赖随时可再打开);两处都删掉再 pnpm install 即卸载。

依赖 组合里需要有 @deepseek-ai/dsh-client-ui-sidebar-right 与 @deepseek-ai/dsh-api-job-controller。没有它们时插件保持"未激活",不会激活失败。

数字是怎么来的

面板读 ctx.jobs(@deepseek-ai/dsh-api-job-controller 暴露给浏览器的任务名册镜像),并在其之上加了一层台账:

1. 标签页挂载期间保持该会话的名册流打开(ctx.jobs.watchRows(sessionId));流的首帧就是完整事实。
2. 名册刚看见任务时以 live::: 为临时身份;宿主结算时以该 recorder 实例的 UUID、owner 与原始 id 组成唯一 bootId:owner:id,按 session + id + startedAt 升级同一任务而不显示两条。原始 pwsh-1 仍只用于 UI 的「任务 ID」,跨 Host 重启复用不再覆盖历史。
3. 统计与明细都从台账算出,所以任务被宿主移除后仍留在面板里。浏览器台账升级到 dsh-job-stats/v3/,首次读取会把 v2 仍存在的历史转换成不与未来 Host ID 撞号的 legacy identity,成功写入 v3 才不再依赖 v2;迁移失败不会清掉 v2。只有终态记录会被读回,刷新页面不会复活假的"运行中"。旧版已经覆盖掉的历史不能凭空恢复。
4. 终态来自宿主并落盘:记录器行订阅注册表的 settled 事件(前台命令终态的唯一见证者),把它们持久化在 profile 内的 .job-stats/ledger.json。面板每 2 秒轮询该路由(按 document.baseURI 相对解析)并合并:名册抛弃的行会变成真实的 已完成/已失败/已取消(带结束原因),标签页没见过运行过程的任务也会带着结局补进来。因为台账在宿主侧,重启后再打开面板仍能看到上一次运行结算的任务 —— 这条链路不依赖浏览器存储。

台账文件

| 路径 | 按宿主真正拥有的事实逐级判定:DSH_PROFILE_DIR → DSH_HOME/DSH_PROFILE → 启动器在命令行里传的 profile 目录(dsh-desktop-host 一定会传,形如 C:\Users\你\.dsh\profiles\desktop)→ 最后退回 harness home($DSH_HOME,没有则 ~/.dsh,即框架自己的默认值)。桌面版宿主不导出 DSH_HOME/DSH_PROFILE,所以这一条 argv 规则就是它在用的那条;用的是哪条规则会在路由的 recorder.pathSource 里说明 |
| 条数 | 每会话最多 200 条,超出先淘汰最早的结算;最多 32 个会话,超出先淘汰最久没结算的 |
| 体积 | 200 条真实命令 ≈ 53 KB;最坏情况(每条命令都到 2000 字符上限)≈ 420 KB |
| 写入 | 窗口(1 秒)外立即写;窗口内的多次结算合并成一次尾部写,窗口结束时一定落盘 —— 因此"最后一批"不会因为崩溃/强杀而留在内存里。写的是当下的完整台账(迟到的定时器不会写出旧数据),只有写入成功才清 dirty,写失败按有上限的退避重试。行卸载时立即 flush 并取消定时器;先写临时文件再改名,崩溃不会留下半个文件 |
| 读回 | dsh-job-stats/ledger/v2 以 key 作 Map 键,旧 v1 的幸存记录可升级;其他 schema 不读。写临时文件后被杀会在下次启动恢复 .tmp |
| 删除 | 任何时候都可以删:它只是已结算任务的记录,后续结算会重新建立 |

恢复旧 Host 内存记录:重启前在仓库外备份未过滤的 /dsh-job-stats/outcomes 与 SHA-256、Host PID/启动时间;升级重启后由仓库外一次性脚本校验备份、先备份新的 ledger、检查 200/32 容量与 24 MiB 上限,再把阶段文件写到 profile 内。recorder 从本机阶段文件导入,成功落盘后才移除;没有永久 HTTP 写接口。同名 pwsh-1 用 bootId:owner:id 分开。容量满额时脚本拒绝导入、不悄悄裁掉记录。

出问题时怎么定位

宿主路由的响应里除了 outcomes 还有一个 recorder 块:台账路径与判定来源、装载结果(正常/忽略别的 schema/从临时文件恢复)、持久化状态(dirty、pending、writes、failures、lastError)与订阅健康(state、attempts、lastError)。面板侧同理:outcomes 轮询会记录 lastOkAt/lastErrorAt/consecutiveFailures/lastStatusCode/lastError,第一次失败 warn,之后只在次数翻倍时再报,恢复时打一条 info 说明失败了几次;名册流打不开会按有上限的退避重试(卸载即停),浏览器台账在窗口结束时补写、页面 pagehide 或插件卸载时立即落盘。这样"中间少了一段"能直接看出是哪条链断的,而不是又一次静默失败。

任务概述从哪来

任务行的第一行是"这个任务在干什么",由面板本地从 label(shell 任务的 label 就是命令本身)归纳:先把命令拆成语句、跳过准备动作(cd …、变量赋值、重定向),再识别真正的动作 —— git commit → 提交代码、pnpm install → 安装依赖、Start-Sleep -Seconds 75 → 等待 75 秒、Get-Content → 读取文件、vitest → 跑测试;git、包管理器、解释器、PowerShell cmdlet、容器与构建工具都有覆盖。

识别在两个方向上都刻意保守:认不出来的命令原样显示;label 本身就是描述的任务(有些 producer 会这么写)不会被改写 —— 归纳错了比显示原文更糟。完整命令永远只差一次点击,也保留在行的悬浮提示里。

已知限制

- 台账记录标签页开着时看到过的任务,外加宿主记录器上报的终态。若某任务在标签页关闭期间开始并结束、且已经从记录器环形缓冲里被淘汰,则无法统计。
- 宿主半侧尚未组合时(还没重启,或组合里没有 web server),前台命令的结局不可观测:工具在调用方取走输出时就把记录从名册删掉了,而名册流是合并后再读列表的,所以"已结算"这一帧读不到 —— 面板只看到它"运行中",随后就不见了。这类记录只显示为已结束 —— 不算运行中,也不硬猜成已完成或已失败;此时「完成率」只覆盖已上报结果的结算任务。
- 还在等待结局的「已结束」记录,耗时 = 从开始到最后一次被看到(宿主把它撤下名册的时刻,误差约一秒内)。
- 宿主台账记录的是它亲眼看过的结算;在记录器行加载之前就已结束的任务无法补回(它们的终态只存在于那个已经消失的进程里)。两本台账并存:宿主那本持久(每会话 200 条、跨重启),标签页自己那本在浏览器存储里(每会话 300 条,路由不可达时也保住你看到过的行)。
- 面板是只读统计;停止任务仍由会话头部的任务列表负责。

实现方式

两侧、零构建:

| 文件 | 作用 |
| package.json | 清单:dsh.bundle.patch(组合补丁)+ dsh.client(浏览器半侧,platform web) |
| cordis.patch.yml | 插入两条 Loader 行:job-stats → 本包(发布浏览器半侧)、job-stats-recorder → ./recorder 子路径(宿主半侧) |
| lib/index.js | 宿主半侧:Loaders 可见的空实现;界面在浏览器侧 |
| lib/recorder.js | 宿主半侧:从注册表事件流记录任务终态,并在 /dsh-job-stats/outcomes 上提供 |
| client/client.js | 浏览器半侧:标签类型、开始页卡片、统计面板 |

三处注册,全部走公开契约:

| 注册 | 席位 | 效果 |
| ctx.sidebarRightTabs.register({ id, kind: 'job-stats', title, guide }) | 右侧边栏标签注册表 | 标签类型、标签条标题、开始页卡片 |
| sidebar.right.pane.tab(以类型 id 为键) | 栏内面板(session 作用域) | 面板正文;sessionId 由宿主从标签页传入 |
| sidebar.right.pane.tab.title(以类型 id 为键) | 标签条 | 类型标签前的自定义图标 |

实现遵守的几条规则:

- 不导入任何 Harness 客户端包:React 来自浏览器模块表(require('react')),面板自绘控件,宿主升级不会让入口变空。
- 只用主题 token(--dsw-*,附字面量兜底),亮/暗色自动适配。
- 可选服务作用域:整个贡献放在 ctx.inject(['sidebarRightTabs'], …) 内,没有右侧边栏的组合只是不激活,而不是抛错。
- 模块工厂无副作用:注册与拆卸都由 ctx.effect 持有,卸载后注册表干净。

开发与测试

pnpm install
pnpm test # 34 个用例:包清单、标签类型与席位注册、面板行为、台账

规格刻意用真实实现而不是桩:浏览器半侧按页面加载它的方式载入(一段经典脚本向 window.__ModuleLoader__ 注册一个惰性 factory),slot 注册表是 @deepseek-ai/dsh-client-ui-slots 里生产的 SlotCore,面板由真实 React 以渲染器组装的 props 渲染。于是"清单写错""注册了外壳寻址不到的席位"这类问题会在 CI 里失败,而不是在运行中的页面里翻车。

改动前的验证清单见 CONTRIBUTING.md。

兼容性

已在 DeepSeek Harness 0.1.7-rc.2(DSH Desktop,Windows 11,125% 显示缩放)验证:Loader 行能组合、宿主按匹配的 revision 提供浏览器半侧、开始页卡片与栏内面板均正常渲染。

许可

MIT
预览分享卡片长什么样 ↓kahomesl/dsh-client-ui-job-stats
分享 · DeepSeek Harness Hub
kahomesl/dsh-client-ui-job-stats

在侧边栏累计记录本会话跑过的每个任务

回到顶部