dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
一组面向 DeepSeek Harness(DSH) 的开源插件:让模型自己操作浏览器、在会话内查找、统计 Token 用量,以及在任务完成或等待确认时弹出桌面通知。
Plugins for DeepSeek Harness (DSH) — English below.
English · 本仓库以中文为主,英文版见文末。
每个插件都是一个独立的 DSH profile bundle,可以单独安装,彼此之间不共享代码或运行时状态。
| 包 | 形态 | 说明 |
|---|---|---|
browser | Host,browser_* 工具 | 通过 Playwright 驱动真实 Chromium:打开页面、读取 ARIA 树、点击/输入、截图、处理对话框与下载、录制 WebM。纯 Host 插件,没有客户端 UI。 |
chat-search | Host + Web 客户端 | 会话内查找:在会话头部打开查找栏,边输入边高亮已渲染对话中的匹配并逐个跳转,不修改对话 DOM。 |
notification | Host + Web 客户端 | Windows 桌面消息通知:任务完成、等待确认或等待回答时弹出系统通知,两种场景提示音不同;点击通知经本机协议回传并打开对应会话(窗口隐藏时同时唤回)。 |
usage-stats | Host + Web 客户端 | 跨全部会话的 Token 用量统计:当日/累计 Token、缓存命中率、一年活动热力图、每日趋势、按模型明细。只读本地会话日志,数据不出本机。 |
dsh web)。每个包都是一个 DSH profile bundle。安装一个插件要做四件事:
dsh.profile.bundles;cordis.patch.yml 插入对应的 Cordis 组件;git clone https://github.com/fakeNihilist/dsh-plugins.git
编辑 <DSH_HOME>/profiles/<profile>/package.json —— 默认 profile 是 desktop,DSH_HOME 通常是 ~/.dsh:
{
"dependencies": {
"@local/dsh-plugin-browser": "link:D:/code/dsh-plugins/packages/browser",
"dsh-plugin-chat-search": "link:D:/code/dsh-plugins/packages/chat-search",
"dsh-plugin-usage-stats": "link:D:/code/dsh-plugins/packages/usage-stats",
"dsh-plugin-notification": "link:D:/code/dsh-plugins/packages/notification"
},
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"@local/dsh-plugin-browser",
"dsh-plugin-chat-search",
"dsh-plugin-usage-stats",
"dsh-plugin-notification"
],
"patchReload": "live"
}
}
}
路径按你的实际情况调整;不需要的插件删掉即可。browser 插件保留历史包名 @local/dsh-plugin-browser,其余使用普通的 dsh-plugin-* 名字。所有包都设置了 "private": true —— 它们从 checkout 安装,不发布到 npm。
link: 只记录路径,包仍然要出现在 profile 的 node_modules 里。通过 DSH 插件管理器安装时它会自动处理;如果是手动 checkout,就自己创建链接:
$profileRoot = Join-Path $env:USERPROFILE '.dsh\profiles\desktop'
$nodeModules = Join-Path $profileRoot 'node_modules'
New-Item -ItemType Directory -Force $nodeModules | Out-Null
New-Item -ItemType Junction -Path (Join-Path $nodeModules 'dsh-plugin-chat-search') `
-Target 'D:\code\dsh-plugins\packages\chat-search'
New-Item -ItemType Junction -Path (Join-Path $nodeModules 'dsh-plugin-usage-stats') `
-Target 'D:\code\dsh-plugins\packages\usage-stats'
New-Item -ItemType Junction -Path (Join-Path $nodeModules 'dsh-plugin-notification') `
-Target 'D:\code\dsh-plugins\packages\notification'
# macOS / Linux
ln -s /path/to/dsh-plugins/packages/chat-search "$HOME/.dsh/profiles/desktop/node_modules/dsh-plugin-chat-search"
ln -s /path/to/dsh-plugins/packages/usage-stats "$HOME/.dsh/profiles/desktop/node_modules/dsh-plugin-usage-stats"
ln -s /path/to/dsh-plugins/packages/notification "$HOME/.dsh/profiles/desktop/node_modules/dsh-plugin-notification"
browser 插件自带安装脚本,会完成它自己那一步(包括创建 node_modules/@local junction 和跑契约测试):
pwsh -File packages/browser/install.ps1 -Profile desktop
重启 Host(或新开一个会话),browser_* 工具才会出现。chat-search、usage-stats 与 notification 还带有 Web 客户端 bundle:重启后再刷新一次浏览器窗口。
各包的配置项、用法和排错见它们自己的 README:
packages/browser/README.mdpackages/chat-search/README.mdpackages/notification/README.mdpackages/usage-stats/README.md仓库根目录没有依赖:每个包都是自成一体的。在包目录里开发,只有要跑测试时才需要安装该包的开发依赖。
# 依次跑每个包的测试(Node.js 测试运行器)
node scripts/test-all.mjs
# 只跑单个包
cd packages/chat-search
npm test
有些沙箱禁止 node:test fork 子进程所需的管道。这种情况下改用 in-process 方式跑:
$env:NODE_TEST_FLAGS = '--experimental-test-isolation=none'
node scripts/test-all.mjs
browser 插件的契约测试与 smoke 测试还需要真实的 DSH 环境(提供 @deepseek-ai/dsh-tools、@deepseek-ai/cordis)以及启动 Chromium 的权限;受限沙箱里会报 browser_unavailable 或 ERR_MODULE_NOT_FOUND。具体命令见该包的 README。
dsh-plugins/
├─ packages/
│ ├─ browser/ # browser_* 工具(纯 Host)
│ ├─ chat-search/ # 会话内查找(Host + Web 客户端)
│ ├─ notification/ # 桌面消息通知(Host + Web 客户端)
│ └─ usage-stats/ # Token 用量仪表盘(Host + Web 客户端)
├─ scripts/
│ └─ test-all.mjs # 依次跑每个包的测试
├─ LICENSE
└─ package.json # workspace 根,无依赖
usage-stats 在本机读取 DSH 会话日志并渲染,不发起网络请求,数据不出本机。browser 驱动本机浏览器;它会发出什么网络请求,取决于被打开的页面。页面内容对模型而言是不可信数据。chat-search 只读取当前 Web 客户端里已经渲染的对话。notification 只读取本机 Session 列表并生成本机系统通知,不向任何服务发送通知内容。MIT © 2026 fakeNihilist
Each plugin is an independent DSH profile bundle. They can be installed separately, and they share no code or runtime state with each other.
| Package | Surface | What it does |
|---|---|---|
browser | Host, browser_* tools | Drives a real Chromium through Playwright: open pages, read the ARIA tree, click/type, capture screenshots, handle dialogs and downloads, record WebM. Host-only, no client UI. |
chat-search | Host + Web client | Find-in-conversation: a find bar in the Session header highlights matches in the rendered transcript and steps through them in place, without mutating the conversation DOM. |
notification | Host + Web client | Windows desktop notifications: native toasts when a task finishes or a Session waits for approval or an answer, with distinct sounds; clicking a toast sends that Session back through a local protocol and opens it (restoring a hidden window as well). |
usage-stats | Host + Web client | Whole-corpus token usage: today/cumulative tokens, cache hit rate, a year-long activity heatmap, daily trend, and a per-model breakdown. Read-only from local session logs — nothing leaves the machine. |
dsh web).Every package is a DSH profile bundle. Installing one means four things:
dsh.profile.bundles,cordis.patch.yml insert its Cordis component,git clone https://github.com/fakeNihilist/dsh-plugins.git
Edit <DSH_HOME>/profiles/<profile>/package.json — the default profile is desktop, and DSH_HOME is usually ~/.dsh:
{
"dependencies": {
"@local/dsh-plugin-browser": "link:D:/code/dsh-plugins/packages/browser",
"dsh-plugin-chat-search": "link:D:/code/dsh-plugins/packages/chat-search",
"dsh-plugin-usage-stats": "link:D:/code/dsh-plugins/packages/usage-stats",
"dsh-plugin-notification": "link:D:/code/dsh-plugins/packages/notification"
},
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"@local/dsh-plugin-browser",
"dsh-plugin-chat-search",
"dsh-plugin-usage-stats",
"dsh-plugin-notification"
],
"patchReload": "live"
}
}
}
Adjust the paths and remove the plugins you do not want. The browser plugin keeps its historical package name @local/dsh-plugin-browser; the others use plain dsh-plugin-* names. All of them set "private": true — they are installed from a checkout, not published to npm.
A link: spec only records the path; the package still has to appear in the profile's node_modules. When you install through the DSH plugin manager it takes care of this. For a manual checkout, create the link yourself:
$profileRoot = Join-Path $env:USERPROFILE '.dsh\profiles\desktop'
$nodeModules = Join-Path $profileRoot 'node_modules'
New-Item -ItemType Directory -Force $nodeModules | Out-Null
New-Item -ItemType Junction -Path (Join-Path $nodeModules 'dsh-plugin-chat-search') `
-Target 'D:\code\dsh-plugins\packages\chat-search'
New-Item -ItemType Junction -Path (Join-Path $nodeModules 'dsh-plugin-usage-stats') `
-Target 'D:\code\dsh-plugins\packages\usage-stats'
New-Item -ItemType Junction -Path (Join-Path $nodeModules 'dsh-plugin-notification') `
-Target 'D:\code\dsh-plugins\packages\notification'
# macOS / Linux
ln -s /path/to/dsh-plugins/packages/chat-search "$HOME/.dsh/profiles/desktop/node_modules/dsh-plugin-chat-search"
ln -s /path/to/dsh-plugins/packages/usage-stats "$HOME/.dsh/profiles/desktop/node_modules/dsh-plugin-usage-stats"
ln -s /path/to/dsh-plugins/packages/notification "$HOME/.dsh/profiles/desktop/node_modules/dsh-plugin-notification"
The browser plugin has an installer that does its step — including the node_modules/@local junction and its contract tests — for you:
pwsh -File packages/browser/install.ps1 -Profile desktop
Restart the Host (or open a new session) so browser_* tools appear. chat-search, usage-stats, and notification also add a Web client bundle: reload the browser window once after the restart.
Each package README documents its own configuration keys, usage, and troubleshooting:
packages/browser/README.mdpackages/chat-search/README.mdpackages/notification/README.mdpackages/usage-stats/README.mdThere are no root dependencies: every package is self-contained. Work inside a package directory, and install its dev dependencies only if you run its tests.
# Every package, one after another (Node.js test runner)
node scripts/test-all.mjs
# A single package
cd packages/chat-search
npm test
Some sandboxes deny the child-process pipes that node:test uses to fork one process per test file. In that case run the runner in-process:
$env:NODE_TEST_FLAGS = '--experimental-test-isolation=none'
node scripts/test-all.mjs
The browser plugin's contract tests and smoke test additionally need a real DSH environment (for @deepseek-ai/dsh-tools, @deepseek-ai/cordis) and permission to start Chromium; a restricted sandbox reports browser_unavailable or ERR_MODULE_NOT_FOUND instead. See its README for the exact commands.
dsh-plugins/
├─ packages/
│ ├─ browser/ # browser_* tools (Host-only)
│ ├─ chat-search/ # in-conversation search (Host + Web client)
│ ├─ notification/ # desktop notifications (Host + Web client)
│ └─ usage-stats/ # token usage dashboard (Host + Web client)
├─ scripts/
│ └─ test-all.mjs # run every package's tests
├─ LICENSE
└─ package.json # workspace root, no dependencies
usage-stats reads DSH session logs on the local machine and renders them; it makes no network requests and nothing leaves the machine.browser drives a local browser; what it sends over the network is whatever the pages it is pointed at request. Page content is treated as untrusted data by the agent.chat-search only reads the rendered conversation in the current Web client.notification reads the local Session list and raises local operating-system notifications; notification content is never sent anywhere.MIT © 2026 fakeNihilist