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

小鲸鱼助手 LengMu-Cloud/dsh-whale-assistant

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

在界面角落播报任务进度、用量与提醒

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

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

该插件未发布到 npm,按作者文档从 GitHub 源安装即可(静态检查只覆盖 npm 路径,不代表插件不可用)。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add LengMu-Cloud/dsh-whale-assistant
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么[目录]—
dsh 原生插件 · other
暂无时间戳·判据 →
装得上吗[实装验证]!
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
数据截至 2026/11/03·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 52 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

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

验证判据与等级说明 →

可信度证据

⚠︎ 实装验证未通过(unknown · 2026/11/3) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
安装兼容性检查需源码安装

仓库 package.json 标记 private,未发布到 npm,需从源码安装;安装清单取自 whale-assistant/package.json

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包@lengmu-cloud/dsh-whale-assistant(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/11 22:18:30

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 82 处,展示前 76 条)
  • 读取本地文件
    build-whale.js:33
    out += fs.readFileSync(path.join(ROOT, mod.file), 'utf8');
  • 读取本地文件
    build-whale.js:43
    const ORIG = fs.existsSync(ORIG_PATH) ? fs.readFileSync(ORIG_PATH, 'utf8') : null;
  • 读取本地文件
    build-whale.js:71
    const PENDING = MANIFEST.filter((m) => !m.inline && !fs.existsSync(path.join(ROOT, m.file)));
  • 读取本地文件
    build-whale.js:118
    const menuSrc = fs.readFileSync(path.join(ROOT, 'src/ui/menu.js'), 'utf8');
  • 读取本地文件
    build-whale.js:132
    const ls = fs.readFileSync(path.join(ROOT, mod.file), 'utf8').split('\n');
  • 写入本地文件
    build-whale.js:148
    fs.writeFileSync(path.join(ROOT, 'whale.js'), finalOut);
  • 写入本地文件
    build-whale.js:157
    fs.mkdirSync(path.join(libDir, 'parts'), { recursive: true });
  • 写入本地文件
    build-whale.js:158
    fs.writeFileSync(path.join(libDir, 'whale.js'), fs.readFileSync(path.join(ROOT, 'whale.js'), 'utf8'));
  • 写入本地文件
    build-whale.js:159
    fs.writeFileSync(path.join(libDir, 'parts', 'style.css'), fs.readFileSync(path.join(ROOT, 'parts', 'style.css'), 'utf8'));
  • 写入本地文件
    build-whale.js:160
    fs.writeFileSync(path.join(libDir, 'whale-logo.svg'), fs.readFileSync(path.join(ROOT, 'whale-logo.svg'), 'utf8'));
  • 读取本地文件
    build-whale.js:172
    out2 += fs.readFileSync(path.join(ROOT, mod.file), 'utf8');
  • 读取本地文件
    check-dsh-compat.js:55
    if (!fs.existsSync(abs) || !fs.statSync(abs).isDirectory()) {
  • 读取本地文件
    check-dsh-compat.js:62
    for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
  • 读取本地文件
    check-dsh-compat.js:71
    try { sz = fs.statSync(p).size; } catch (err) { continue; }
  • 读取本地文件
    check-dsh-compat.js:78
    try { return fs.readFileSync(f, 'utf8'); } catch (e) { return ''; }
  • 发起网络请求
    check-dsh-compat.js:95
    const r = http.request({ host: '127.0.0.1', port, method: 'GET', path: urlPath, timeout: 5000 }, (res) => {
  • 读取密钥环境变量
    check-dsh-compat.js:159
    else if (has('--live')) scanLive(Number(flag('--port')) || 3080, flag('--token') || process.env.DSH_TOKEN || '', has('--cdp'));
  • 读取本地文件
    e2e-whale.js:11
    const SCRIPT = fs.readFileSync(path.join(__dirname, 'whale.js'), 'utf8');
  • 发起网络请求
    e2e-whale.js:60
    const browserFetch = (url, init) => fetch(new URL(url, 'http://127.0.0.1:3080'), init);
  • 发起网络请求
    live-e2e-test.js:16
    const r = http.request({
  • 读取密钥环境变量
    live-e2e-test.js:37
    const token = process.env.DSH_TOKEN || '';
  • 写入本地文件
    shell/main.js:32
    fs.appendFileSync(logFile, `[${new Date().toISOString()}] ${msg}\n`);
  • 读取本地文件
    shell/main.js:55
    try { if (fs.statSync(cand).isFile()) return cand; } catch (_) {}
  • 读取本地文件
    shell/main.js:61
    if (fs.statSync(p).isFile()) return p;
  • 读取本地文件
    shell/main.js:76
    try { if (fs.statSync(c).isFile()) return c; } catch (_) {}
  • 读取本地文件
    shell/main.js:82
    if (fs.statSync(p).isFile()) return p;
  • 读取本地文件
    shell/main.js:90
    try { if (fs.statSync(cand).isFile()) return cand; } catch (_) {}
  • 执行外部命令来自配置/变量
    shell/main.js:119
    child = spawn(nodeExe, ['--', binJs, 'web', '--port', String(DSH_PORT), '--no-open'], {
  • 执行外部命令固定命令
    shell/main.js:136
    child = spawn('cmd.exe', ['/c', `${dshCmd} web --port ${DSH_PORT} --no-open`], {
  • 读取本地文件
    shell/main.js:159
    const text = fs.readFileSync(serverLog, 'utf8');
  • 发起网络请求
    shell/main.js:183
    const req = http.get(url, { timeout: 2500 }, (res) => {
  • 发起网络请求
    src/core/alpha-adapter.js:301
    fetch('/api/whale-assistant/state').then(function (r) {
  • 发起网络请求
    src/core/alpha-adapter.js:306
    return fetch('/api/whale-assistant/save', {
  • 发起网络请求
    src/core/frames.js:209
    fetch('/api/session.history', {
  • 发起网络请求
    src/core/history.js:72
    fetch('/api/whale-assistant/save', {
  • 发起网络请求
    src/core/history.js:85
    fetch('/api/whale-assistant/state').then(function (response) {
  • 发起网络请求
    src/core/server-events.js:271
    fetch('/api/whale-assistant/state').then(function (r) {
  • 发起网络请求
    src/core/server-events.js:287
    fetch('/api/whale-assistant/debug', { method: 'POST', headers: { 'content-type': 'application/json' },
  • 发起网络请求
    src/core/server-events.js:292
    fetch('/api/whale-assistant/debug', { method: 'POST', headers: { 'content-type': 'application/json' },
  • 发起网络请求
    src/core/server-events.js:403
    fetch('/api/whale-assistant/events').then(function (r) {
  • 写入剪贴板
    src/ui/drawers.js:404
    navigator.clipboard.writeText(md).then(function () { uiSay('Markdown 已复制 📋', 2200); }, function () { uiSay('复制失败 🥲', 2000); });
  • 读取本地文件
    test-host-store.js:31
    ok(readdirSync(dir).length === 1, 'no .tmp leftover after rename');
  • 读取本地文件
    test-host-store.js:36
    ok(readdirSync(dir).length === 1, 'still exactly one file');
  • 写入本地文件
    test-host-store.js:40
    writeFileSync(storePath(dir), garbage, 'utf8');
  • 读取本地文件
    test-host-store.js:42
    const leftovers = readdirSync(dir).filter((f) => f.includes('.corrupt-'));
  • 读取本地文件
    test-host-store.js:44
    ok(readFileSync(join(dir, leftovers[0]), 'utf8') === garbage, 'quarantined bytes intact');
  • 删除本地文件递归
    test-host-store.js:124
    rmSync(dir, { recursive: true, force: true });
  • 读取本地文件
    test-whale.js:22
    const SCRIPT = fs.readFileSync(path.join(__dirname, 'whale.js'), 'utf8');
  • 发起网络请求
    test-whale.js:311
    fetch(url, init) {
  • 读取本地文件
    test-whale.js:2827
    const src = fs.readFileSync(path.join(__dirname, 'whale.js'), 'utf8');
  • 读取本地文件
    verify-mute.js:15
    const SCRIPT = fs.readFileSync(path.join(__dirname, 'whale.js'), 'utf8');
  • 发起网络请求
    whale-assistant/client.js:15
    fetch('/api/whale-assistant/whale.js').then((r) => (r.ok ? r.text() : Promise.reject(new Error('whale.js http ' + r.status)))),
  • 发起网络请求
    whale-assistant/client.js:16
    fetch('/api/whale-assistant/assets').then((r) => (r.ok ? r.json() : Promise.reject(new Error('assets http ' + r.status)))),
  • 读取本地文件
    whale-assistant/lib/index.js:55
    return readFileSync(candidate, 'utf8');
  • 读取本地文件
    whale-assistant/lib/index.js:439
    code = readFileSync(candidate, 'utf8');
  • 读取本地文件
    whale-assistant/lib/store.js:31
    raw = readFileSync(storePath(dir), 'utf8');
  • 写入本地文件
    whale-assistant/lib/store.js:48
    renameSync(storePath(dir), quarantined);
  • 写入本地文件
    whale-assistant/lib/store.js:57
    mkdirSync(dirname(file), { recursive: true });
  • 写入本地文件
    whale-assistant/lib/store.js:59
    writeFileSync(tmp, text, 'utf8');
  • 写入本地文件
    whale-assistant/lib/store.js:61
    renameSync(tmp, file);
  • 写入本地文件
    whale-assistant/lib/store.js:63
    writeFileSync(file, text, 'utf8');
  • 删除本地文件
    whale-assistant/lib/store.js:64
    try { unlinkSync(tmp); } catch (e2) { }
  • 发起网络请求
    whale-assistant/lib/whale.js:448
    fetch('/api/whale-assistant/save', {
  • 发起网络请求
    whale-assistant/lib/whale.js:461
    fetch('/api/whale-assistant/state').then(function (response) {
  • 发起网络请求
    whale-assistant/lib/whale.js:1089
    fetch('/api/whale-assistant/state').then(function (r) {
  • 发起网络请求
    whale-assistant/lib/whale.js:1094
    return fetch('/api/whale-assistant/save', {
  • 发起网络请求
    whale-assistant/lib/whale.js:1857
    fetch('/api/whale-assistant/state').then(function (r) {
  • 发起网络请求
    whale-assistant/lib/whale.js:1873
    fetch('/api/whale-assistant/debug', { method: 'POST', headers: { 'content-type': 'application/json' },
  • 写入剪贴板
    whale-assistant/lib/whale.js:6201
    navigator.clipboard.writeText(md).then(function () { uiSay('Markdown 已复制 📋', 2200); }, function () { uiSay('复制失败 🥲', 2000); });
  • 发起网络请求
    whale.js:448
    fetch('/api/whale-assistant/save', {
  • 发起网络请求
    whale.js:461
    fetch('/api/whale-assistant/state').then(function (response) {
  • 发起网络请求
    whale.js:1089
    fetch('/api/whale-assistant/state').then(function (r) {
  • 发起网络请求
    whale.js:1094
    return fetch('/api/whale-assistant/save', {
  • 发起网络请求
    whale.js:1857
    fetch('/api/whale-assistant/state').then(function (r) {
  • 发起网络请求
    whale.js:1873
    fetch('/api/whale-assistant/debug', { method: 'POST', headers: { 'content-type': 'application/json' },
  • 写入剪贴板
    whale.js:6201
    navigator.clipboard.writeText(md).then(function () { uiSay('Markdown 已复制 📋', 2200); }, function () { uiSay('复制失败 🥲', 2000); });
扫描于 2026/11/4(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库

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

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 后台播报任务进度
  • tokens用量面板
  • 定时提醒与周报
展开完整介绍(187 字)↓

🐋住在 DeepSeek Harness(DSH)界面右下角的打工小鲸鱼:跨对话后台通知(集成任务开工/完成/失败/提问or审核播报、 每轮 tokens 用量面板、工具调用情况、长任务计时)、历史任务(搜索/范围清空、跳转至对应任务节点)与周报、 定时提醒(倒计时或指定到时分秒)、双击通知跳转会话、装扮养成、鲸鱼好感度等功能。 只读事件流,不拦截、不修改任何任务行为。

README

由 DeepSeek 最新模型翻译生成
🐋 dsh-whale-assistant — DeepSeek Harness 的小鲸鱼助手插件 住在 DeepSeek Harness(DSH)Web 界面右下角的打工小鲸鱼,功能包括: ①实时任务通知(开工/完成/失败/中止/截断/提问/审核,每种独立音效); ②Token 用量报告(每轮任务消耗 + 全对话累计 + 上下文压力百分比); ③跨会话后台通知(切换对话后仍能收到任务状态;0.4.0 起网页版同样实时推送); ④长任务计时(>2 分钟自动显示运行时长); ⑤历史记录搜索、范围清空(全部/仅7天前/仅30天前),历史条目支持单击跳转到对应对话节点; ⑥任务周报(近7天按日统计 + Markdown/CSV导出); ⑦定时提醒(倒计时或指定时刻到点响铃); ⑧陪伴系统(摸摸头好感度、爱心特效、班味情绪); ⑨每日装饰成就(咖啡杯/红色安全帽); ⑩内置完整使用说明手册(支持搜索过滤)。 只读事件流,不拦截、不修改任何任务行为。 定位一句话:本仓库的核心交付物是 DSH 的 Web UI 插件(src/ + whale-assistant/); shell/ 里的桌面壳是可选的DSH桌面封装——插件只要求 DSH web 在跑,用浏览器直开、你自制的 Electron 封装、PWA 或本仓库的壳,装上都能用。
展开完整文档(README 剩余 1 节)
🐋 dsh-whale-assistant — DeepSeek Harness 的小鲸鱼助手插件

住在 DeepSeek Harness(DSH)Web 界面右下角的打工小鲸鱼,功能包括: ①实时任务通知(开工/完成/失败/中止/截断/提问/审核,每种独立音效); ②Token 用量报告(每轮任务消耗 + 全对话累计 + 上下文压力百分比); ③跨会话后台通知(切换对话后仍能收到任务状态;0.4.0 起网页版同样实时推送); ④长任务计时(>2 分钟自动显示运行时长); ⑤历史记录搜索、范围清空(全部/仅7天前/仅30天前),历史条目支持单击跳转到对应对话节点; ⑥任务周报(近7天按日统计 + Markdown/CSV导出); ⑦定时提醒(倒计时或指定时刻到点响铃); ⑧陪伴系统(摸摸头好感度、爱心特效、班味情绪); ⑨每日装饰成就(咖啡杯/红色安全帽); ⑩内置完整使用说明手册(支持搜索过滤)。
只读事件流,不拦截、不修改任何任务行为。

定位一句话:本仓库的核心交付物是 DSH 的 Web UI 插件(src/ + whale-assistant/); shell/ 里的桌面壳是可选的DSH桌面封装——插件只要求 DSH web 在跑,用浏览器直开、你自制的 Electron 封装、PWA 或本仓库的壳,装上都能用。

前提:本插件只对已经在运行 DeepSeek Harness(DSH)的环境有意义——DSH 本身的获取与安装不在本仓库范围内;还没有 DSH 的话,装上本插件不会有任何效果。

组件关系(插件 / 壳 / 补丁——谁依赖谁)

| 组件 | 必需? | 是什么 | 与小鲸鱼的关系 |
| 插件本体(whale-assistant/ + src/) | ✅ 必需 | DSH cordis 插件:宿主半区(服务端路由 + 事件/投影订阅)+ 页面半区(whale.js) | 全部功能所在,完全自包含——加载走官方模块清单,跳转走官方 sessions 服务,实时推送走自有路由 |
| 桌面壳(shell/) | 可选 | DSH 的 Electron 桌面封装 | 插件不依赖壳;壳的增量只有两点:黑屏防护/崩溃自恢复、独立进程(无标签页被丢弃问题) |
| 壳补丁(scripts/fix-shell.ps1,属于壳) | 装壳时需要 | 写入壳 asar 的稳定性修复 | 只改壳自己的文件,与插件功能零关系;DSH 升级后重跑的是它 |
| 跳转补丁(已退役) | — | 0.3.x 时代的跳转靠一个手动注入脚本(从未随本仓库分发) | 0.4.0 起退役:跳转已内置。若曾打过它,残留无害,下次 DSH 升级时自然消失 |

依赖方向一句话:壳可以没有,跳转补丁已成历史,插件自己就是全部。

环境要求

| 组件 | 要求 |
| DeepSeek Harness | 实测版本 0.1.5-rc.2(2026-09-11,由 0.1.2-rc.1 升级);兼容下限见 whale-assistant/package.json 的 dsh.engines;插件只走公开插件接口与 HTTP 路由。0.1.5 起「上下文已用 N%」由内联文字改为发送按钮旁的环形件;插件压力数据 0.3.3 起改由 DSH 的 token-meter 服务端投影供给,报告压力行/压力色/提醒不受官方 UI 改版影响 |
| Node.js | 跟随 DSH 自身要求即可(开发机 v24 实测);仅改源码/构建/跑测试时需要 |
| 操作系统 | 插件本体为纯 JS,跨平台;自动化脚本为 PowerShell(Windows),macOS/Linux 按下文手动步骤 |
| 运行载体 | 任意现代浏览器;Electron 桌面壳为可选增强 |

能力矩阵(先看这个再安装)

| 能力 | 网页版(浏览器访问 dsh web) | 桌面封装版(Electron 壳) |
| 任务通知 / 用量面板 / 运行计时 / 历史(搜索·范围清空·单击跳转对话) / 周报 / 提醒 | ✅ 开箱即用 | ✅ 开箱即用 |
| 陪伴系统(摸头好感 / 爱心 / 班味情绪 / 装饰成就 / 使用手册) | ✅ | ✅ |
| 多窗口/多端历史同步(同一台机器) | ✅ 服务端镜像,自动合并 | ✅ 同左 |
| 后台任务通知实时性 | ✅ SSE 实时推送(0.4.0 起);标签页被浏览器「内存节省」丢弃时例外 | ✅ 实时(SSE + 独立进程,无标签页丢弃问题) |
| 冷启动黑屏防护 / 崩溃自恢复 | 不适用(浏览器自己管) | ✅ 壳提供(装壳时由 fix-shell.ps1 写入,与插件无关) |
| 跨机器同步 | ❌ 明确不支持(历史存在各自机器的 ~/.dsh/whale-assistant.json) | ❌ 同左 |

插件功能两版完全一致,完整清单见 FEATURES.md;壳的增量只有上面最后两行(独立进程兜底 + 稳定性防护)。组件之间的依赖关系见「组件关系」一节。

安装(网页版 / 桌面版通用第一步)

插件以 DSH cordis 插件形式安装到 DSH 服务(不是 npm 公共包,当前为开发版分发)。
DSH 的 profile 目录默认在 ~/.dsh/profiles/web(DSH 首次运行后生成),注册共三件套: package.json 依赖 + node_modules 实体 + cordis.patch.yml 注册行,缺一不可。

1. 把本仓库放到任意固定目录(下称 ;路径含空格也可以,但后续命令里给含空格的路径加英文引号)。
2. 注册插件到 profile(Windows 推荐用自带脚本,幂等可重复执行):

powershell -ExecutionPolicy Bypass -File \ensure-whale-assistant.ps1

脚本自动完成其中两件:profile package.json 写入 link: 依赖、cordis.patch.yml 追加注册行。剩下一件是把插件实体挂进 profile 的 node_modules(Windows junction):

New-Item -ItemType Directory -Force ~\.dsh\profiles\web\node_modules\@lengmu-cloud | Out-Nulltext
New-Item -ItemType Junction -Force -Path ~\.dsh\profiles\web\node_modules\@lengmu-cloud\dsh-whale-assistant -Target \whale-assistant

macOS / Linux(手动等价操作):

bash
profile package.json 的 dependencies 里加一行: "@lengmu-cloud/dsh-whale-assistant": "link:/whale-assistant"
mkdir -p ~/.dsh/profiles/web/node_modules/@lengmu-cloud
ln -s /whale-assistant ~/.dsh/profiles/web/node_modules/@lengmu-cloud/dsh-whale-assistant

注册行(由脚本自动写入,手动编辑 ~/.dsh/cordis.patch.yml 时照此格式——注意是顶层 FLAT 数组,不要包在 patch: 里):

yaml
- insert:
- id: ui-whale-assistant # 唯一注册点;不要重复注册(会双鲸鱼双通知) name: '@lengmu-cloud/dsh-whale-assistant'

3. 构建产物已随仓库提供(whale.js);自行改源码后重建:

text
node build-whale.js # 产出 whale.js + whale-map.md(函数导航)

4. 重启 DSH 服务让插件挂载:最稳妥是重启电脑;或用任务管理器结束 DSH 的后台服务进程(node,监听 3080 端口)后再开壳。⚠️ 只关壳重开是不够的——服务是壳派生的独立后台进程,关壳它并不退出。首次安装时若 DSH 服务尚未运行过,直接开壳即可。浏览器 F5 即可看到鲸鱼。
5. 验证安装:右下角出现鲸鱼、控制台(F12)有 [dsh-whale-assistant] whale loaded from plugin routes 即成功;一切正常时健康自检零痕迹(鲸鱼旁无 ⚠️)。有问题先看下方「常见问题」。

⚠️ 包名必须带 scope(alpha client 的模块清单只聚合带 scope 的包,scope 用谁家的都行)。
⚠️ 不要把插件同时注册进包内 dsh.bundle.patch 和 profile patch —— 双注册 = 双鲸鱼 = 双份通知。

桌面封装版第二步(可选增强)

如果你已有自己喜欢的封装方式(自制 Electron 壳、Edge/Chrome PWA、或干脆浏览器直开),本节整节跳过——上面的安装完成后插件即已完整可用。

如果你想把 DSH 封装成 Electron 桌面应用(任何壳都行),鲸鱼照常工作;但壳需要自己处理两件事:认证 URL 的读取(dsh web 启动时打印一次性 token URL)与后台限流关闭(backgroundThrottling: false)。

- 使用与我们同款瘦壳:运行 scripts/fix-shell.ps1(见 docs/shell-setup.md)。
- macOS / Linux:暂无自动脚本,请按 docs/shell-setup.md 手动操作。

升级与卸载

升级: text
git pull # 拉最新代码
node build-whale.js # 仅当改了 src/ 源码才需要(构建产物 whale.js 已随仓库提供)

按改动面生效:

- 只动页面半区(src/、whale.js):浏览器 F5 即生效
- 动了宿主半区(whale-assistant/lib/index.js):重启 DSH 服务——⚠️ 关壳重开不会重启它(服务是壳派生的独立后台进程):结束 node 服务进程(监听 3080 端口)或重启电脑

换机迁移(数据不跨机器同步,搬家前手动备份两处):

- 历史:~/.dsh/whale-assistant.json(服务端镜像文件,拷到新机同路径即可)
- 设置/通讯录/提醒/好感度:浏览器 localStorage 里 dsh-whale: 开头的全部键(DevTools → Application → Local Storage 逐条导出再导入;dsh-whale:evseq/ clearAt 拷过去也无害——bootId 不匹配会自动全量重同步)

卸载(删干净三处即完全移除;历史数据 ~/.dsh/whale-assistant.json 与浏览器 localStorage 可留可删):

1. profile cordis.patch.yml 里的 ui-whale-assistant 注册行
2. profile package.json 里的 @lengmu-cloud/dsh-whale-assistant 依赖行
3. profile node_modules 里的 junction / 软链

工作原理(为什么说它是"只读"的)

插件分两半:

- 宿主半区 whale-assistant/lib/index.js:以 cordis 插件挂在 DSH 服务上,新增 8 条仅本机回环的 HTTP 路由(状态 / 历史存取 / 事件轮询 / SSE 实时推送 / 静态资源,外加开发诊断用的 dev-say),从 DSH 自身事件总线与投影订阅任务事件、镜像任务历史——不拦截、不修改任何任务行为。
- 页面半区 src/(33 模块构建为 whale.js):在 Web 页面里消费事件流(SSE 实时 + 轮询兜底)并渲染鲸鱼 UI,DOM 只读采集用量数据;会话跳转经 DSH 官方 sessions 服务完成(0.4.0 起,见「组件关系」)。

全部数据落在你本机(~/.dsh/whale-assistant.json + 浏览器 localStorage),插件自身不发起任何外部网络请求。

开发与测试 text bash
node build-whale.js # 重建 whale.js + whale-map.md,并同步发布副本到 whale-assistant/lib/
构建时强制:顶层声明重复断言 / menu 热点 guard / KNOWN-COUPLING 登记表
node test-whale.js # vm 沙箱单元测试,670+ 断言
node test-chip-gate.js # 芯片闸门纯函数测试,19 断言
node scripts/audit-deps.js # 静态架构审计(作用域/依赖边/缝清单/时序契约 lint,自检前置)
node check-dsh-compat.js --static "" # DSH 升级前:对新版包扫耦合点特征
node check-dsh-compat.js --live [--cdp] # DSH 升级后:对运行实例探活(接口/调试口)
node scripts/run-e2e.js # CDP 端到端四场景(桌面壳调试口 9222 不可达时自动跳过)

调试与测试用的导出缝清单见 docs/seams.md。
分层、准入规则与债务登记见 docs/architecture.md。

目录导航

| 路径 | 内容 |
| src/ + build-whale.js | 插件源码(33 模块)与构建脚本 |
| whale-map.md | 构建时自动生成的模块/函数导航(Agent 与人类共用) |
| docs/architecture.md | 架构与分层:作用域三层、三档准入规则、债务登记与触发线 |
| whale-assistant/ | 插件包(宿主半区 lib/index.js + 页面半区 client.js + 注册样本) |
| ensure-whale-assistant.ps1 | 插件注册脚本(写 profile 依赖 + 注册行,幂等) |
| parts/style.css | 鲸鱼全部样式 |
| test-whale.js / test-chip-gate.js | 单元测试(vm 沙箱 670+ 断言 / 闸门纯函数 19 断言) |
| FEATURES.md / CHANGELOG.md / docs/seams.md | 用户功能手册 / 版本变更记录 / 调试与测试导出缝清单 |
| shell/ + scripts/fix-shell.ps1 | 桌面瘦壳源码与安装脚本(可选增强) |
| docs/shell-setup.md | 桌面壳手动安装指南 |

常见问题

- 出现两只鲸鱼 / 通知双份 —— 插件被注册了两次:确认 profile cordis.patch.yml 只有一行 ui-whale-assistant 注册,且没有同时启用包内 bundle patch。
- 点历史条目 / 双击通知没有跳转 —— 0.4.0 起跳转已内置(经 DSH 官方 sessions 服务),升级到 0.4.0 即可(0.3.x 依赖一个未随仓库分发的补丁,对 GitHub 用户不可用);仍无效就 Ctrl+F5 刷新后重试。
- 后台任务的完成通知不来 / 迟到 —— 0.4.0 起网页版走 SSE 实时推送,正常不再迟到;若通知彻底消失,多半是标签页被浏览器「内存节省」功能丢弃了(重开标签页即可)。
- 鲸鱼旁出现 ⚠️ —— 健康自检发现依赖失效,点开看逐项明细,多数一次 Ctrl+F5 恢复(见下"健康自检")。
- 没有声音 —— 检查免打扰时段、音量与音色设置(右键菜单 → 声音);逐项排查见 FEATURES.md 音效系统一节。
- 清空历史后对话名会丢吗 —— 不会:真名存在独立的"通讯录"(localStorage dsh-whale:titles,与历史分离),清空历史不影响鲸鱼认名。

健康自检

鲸鱼每 60 秒自检一次依赖(服务端事件轮询与 SSE 推送 / 用量 DOM 读取 / 会话跳转桥)。
一切正常时零痕迹;检测到失效会在鲸鱼旁出现 ⚠️ 小图标,点开看逐项明细;
控制台同步输出 [🐋] Health check: {...}。多数失效一次 Ctrl+F5 即可恢复。

作者与许可

- 作者:LengMu-Cloud(github.com/LengMu-Cloud)
- 许可:MIT

免责声明

本项目是 DeepSeek Harness(DSH)的第三方非官方插件,与 DeepSeek 官方无关。
插件仅通过 DSH 公开插件接口与公开 HTTP 路由工作,不含、不分发 DSH 的任何代码。
MIT 许可证只覆盖本仓库的原创代码。DSH 是 DeepSeek 的产品,其权利归其权利人所有。
预览分享卡片长什么样 ↓LengMu-Cloud/dsh-whale-assistant
分享 · DeepSeek Harness Hub
LengMu-Cloud/dsh-whale-assistant

在界面角落播报任务进度、用量与提醒

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