
Security News
Rust 1.100 Will Add Dependency Cooldowns to Cargo
Rust 1.100 will add opt-in dependency cooldowns to Cargo, giving security scanners and maintainers time to catch malicious crate releases.
dsh-browser-tool
Advanced tools
DSH browser tool: drive Chromium tabs (headless / CDP-attached / spawned apps / user's real Chrome via the OMP-style Browser Relay) with an open-close-run + tab scripting API, ported from oh-my-pi.
DSH(DeepSeek Harness)浏览器工具包:在 Agent 会话中驱动 Chromium 打开标签页、执行脚本、观察页面,并把截图/文本结果直接回传给模型。核心逻辑从 oh-my-pi 的 browser 工具迁移而来,保持「open / run / close」三段式语义与 OMP 风格的 browser-relay。
puppeteer-core + @puppeteer/browsers 自动下载,支持 stealth 注入);DSH_BROWSER_CDP_URL);不拥有浏览器,释放时只 disconnect;dsh-browser-relay serve)接管用户自己正在用的 Chrome,带标签页分组排队、debugger ban 恢复等 OMP 语义。page、browser、tab(完整 Tab API:goto/observe/ariaSnapshot/screenshot/extract/click/type/fill/press/scroll/drag/waitFor*/evaluate/select/uploadFile/ref…)、display、print、console、assert、wait、sleep;read/write/env/tree/tool/agent/parallel/pipeline/phase/log/budget 等 omp 专属 helper 明确报错;OP_DEADLINE_SLACK_MS=1000),超时走 tab worker recycle 或强制回收;page,但 cell 里注册的 page.on/once/addListener/… 只活到本次 run 结束——结束时被精确摘除,回调同步抛错或返回 rejected promise 都只记 warn 并写进 run 输出,不会逃逸成进程级 uncaughtException;需要跨 run 自动处理 JS 对话框(如 beforeunload)时用 open 的 dialogs:"accept"|"dismiss",不要依赖上一条 cell 残留的监听器。kill 一并结束自己拥有的浏览器。
kill 对它们也无效,绝不杀用户自己的浏览器)。kill: true:工具描述与 kill 参数说明都会要求 agent 在结束浏览器工作时这么做,且 close 的返回消息会明确告诉 agent 浏览器是否仍存活(其他标签页还持有)或已随本标签终止,形成即时提示,避免遗留 headless Chromium 进程。session/disposed)时释放该会话创建的标签页,插件卸载时释放全部标签页。agent.inject() 给模型注入一条一次性 user-role 提示("仍有 N 个标签未关,收尾请用 kill:true"),不唤醒 driver,只在下一回合被模型看到;同一批未关标签只提示一次,全部关闭后复位。可用 DSH_BROWSER_REMIND_AGENT=0 关闭,同时会打 warn 日志记录泄漏的标签。dsh-browser-relay):serve(HTTP+WS,伪装 Chrome CDP discovery /json/version、/json/list、/cdp)、install(把扩展装入 ~/.dsh/browser-relay/extension)、status。扩展资产提交在 src/assets/relay/extension-assets。src/
index.ts 工具注册(单工具 `browser`:open/run/close)
config.ts DSH_BROWSER_* 环境变量合并
browsers/ 浏览器核心
registry.ts 四种 kind 的获取/持有/释放(引用计数)
launch.ts headless 启动、stealth、UA 覆盖、Chromium 下载
tab-supervisor.ts 标签生命周期与 tab worker 编排
tab-worker.ts Tab API 实现(页面侧)
runtime.ts 单元运行时(尾表达式返回、display/print)
run-listeners.ts run 作用域监听器隔离 + dialog 幂等收尾(handled 即跳过)
aria/aria-snapshot.ts aria 快照与 ref 选择器
final-expr.ts Babel 末表达式注入(移植 omp returnFinalExpression)
relay/ Browser Relay
server.ts HTTP+WS 服务(/ext /cdp /json/*)
bridge.ts CDP 伪装:Target 域、minted tab/page 会话、OMP.claimTarget
daemon.ts 空闲探测 + detached 拉起
cli.ts serve|install|status
作为 DSH profile 的 bundle 挂载。先停掉正在运行的 dsh,再装 —— 在服务运行期间改它的 node_modules 会让运行中的进程读到残缺的依赖树。
cd ~/.dsh/profiles/<你的 profile> # 例如 web
dsh plugin --profile <你的 profile> add dsh-browser-tool
从 npm 安装,lib/ 已随包发布,装完即可用,无需本地构建。
然后在该 profile 的 package.json 里把它加进 dsh.profile.bundles(顺序放最后即可):
{
"dsh": {
"profile": {
"bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-browser-tool"]
}
}
}
截图依赖 sharp 的原生模块,pnpm 默认会跳过它的构建脚本,需在 profile 的 pnpm-workspace.yaml 里放行:
allowBuilds:
sharp: true
重启 dsh 后 browser 工具即出现在工具列表中。验证:
dsh --profile <你的 profile> --dump-config | grep dsh-browser-tool
@deepseek-ai/dsh-tools、@deepseek-ai/schemastery 声明为 peerDependencies 而非 dependencies,这一点很关键:DSH 通过 ~/.dsh/profiles/node_modules/@deepseek-ai/ 的符号链接农场把宿主运行时暴露给插件,插件不声明就会向上查找命中宿主那一份。
若把它们写进 dependencies,pnpm 会在 profile 里装第二份实体拷贝;nodeLinker: hoisted 下插件解析到近的那份、宿主用自己那份,两边模块实例不同。dsh-tools 的调度器挂在模块内的 Symbol() 上,跨实例读取得到 undefined,结果是所有工具调用都死在 scheduler.prepare()。
browser action:"open" name:"wiki" url:"https://en.wikipedia.org" headless:false
browser action:"run" name:"wiki" code:"await tab.observe(); await tab.click('text/Log in');"
browser action:"close" name:"wiki"
| 变量 | 作用 |
|---|---|
DSH_BROWSER_ENABLED | 0 禁用工具 |
DSH_BROWSER_HEADLESS | 1 默认 headless |
DSH_BROWSER_RELAY / DSH_BROWSER_RELAY_URL | 1 时走 relay(默认 http://127.0.0.1:9224) |
DSH_BROWSER_CDP_URL | 默认 connected 目标 |
DSH_BROWSER_SCREENSHOT_DIR | 截图落盘目录 |
DSH_BROWSER_NO_WEBP | 1 时模型副本用 PNG |
DSH_BROWSER_NODE | 跑 sharp 的普通 Node 可执行文件;缺省按 DSH_PRIMARY_RUNTIME + dependencies/node/bin/node 推导 |
DSH_BROWSER_INSTALL_CHROME | 0 不自动下载 Chromium |
DSH_BROWSER_REMIND_AGENT | 0 关闭回合结束的"仍有标签未关"回灌提示 |
DSH_BROWSER_DONOR_CACHE | 额外的 Chromium 复用来源(@puppeteer/browsers 缓存目录) |
PUPPETEER_EXECUTABLE_PATH / DSH_BROWSER_EXECUTABLE | 指定 Chromium 可执行文件 |
PUPPETEER_PROXY_* | 下载/Chrome 代理(透传 puppeteer) |
需要 headless Chromium 时按以下顺序解析,只有全部落空才会下载:
PUPPETEER_EXECUTABLE_PATH / DSH_BROWSER_EXECUTABLE;DSH_BROWSER_DONOR_CACHE、~/.omp/puppeteer(oh-my-pi)、PUPPETEER_CACHE_DIR、~/.cache/puppeteer;第 4 步只认 @puppeteer/browsers 的缓存布局(chrome/<platform>-<buildId>/)。构建号完全一致时直接采用,否则取该缓存里最新的一版(仍然省掉一次下载)。复制的是整个构建目录并保留可执行位,落到本包缓存后即与来源解耦——oh-my-pi 清理自己的缓存不会影响这里。复制失败时退化为直接启动来源里的二进制。
Playwright 的缓存(chromium-<revision>)不在支持范围:它的 revision 编号无法映射到 Chrome for Testing 的 buildId。
Sharp 的 Linux 预编译 libvips 静态链接了一份 GLib,而 Electron 的 Linux 二进制链接系统 GLib 并把符号泄漏进进程空间,两者撞名后进程内第一次碰图片就 SIGABRT(electron#46323)。本包因此在 process.versions.electron 存在且平台为 linux 时不在自身进程加载 sharp,改为用普通 Node 起一个 worker 子进程跑整条编码阶梯(帧协议见 src/browsers/image-worker-protocol.ts);其它运行时——包括 macOS / Windows 的 Electron——仍在进程内编码,不多起进程。
顺带说明:升级 sharp 替代不了这个子进程。本机实测(Electron 44.7.0 / 43.3.0 Linux):0.33.5 的图片操作 28/28 次直接 SIGABRT;0.34.5 的编码路径在 ELECTRON_RUN_AS_NODE=1 下能跑通,但同一版本同一份 glib,metadata() 在该形态下 8/8 次 SIGSEGV(GUI 形态反而通过,即结果依赖宿主 loader 状态),0.35.5 也仍然崩,并且 sharp 自己会打印 [SharpElectronLinux] Warning: Binaries provided by Electron for use on Linux may be incompatible with sharp。上游 electron#46323 至今 open,sharp 官方安装文档明写 Electron Linux 不兼容。所以这里不碰 sharp 版本,只把进程切开;本包的编码路径也从不调用 metadata()(尺寸靠纯 JS 头部探测),子进程里只做编码。
worker 用的 Node 按顺序取第一个真实存在的可执行文件;一个都找不到时只警告一次并原图透传,截图本身不会失败:
DSH_BROWSER_NODE;$DSH_PRIMARY_RUNTIME/dependencies/node/bin/node(桌面壳会设置它);$DSH_BUNDLED_PRIMARY_RUNTIME/dependencies/node/bin/node。回归检查:普通 Node 下验证进程内路径不回归,Electron 下验证已切到子进程(修复前这一步必崩,退出码 134):
npm run check:image-worker
ELECTRON_RUN_AS_NODE=1 DSH_PRIMARY_RUNTIME=/path/to/primary-runtime /path/to/electron scripts/image-worker-check.mjs
注意 smoke 的截图(1280x960、约 10KB)会命中 image.ts 的快速路径,并不经过编码,所以它不能当作编码链路的证据;编码链路的证据由上面的 check:image-worker 提供,它直接在 Electron 进程里跑一次真实编码并断言宿主进程没有映射 libvips。
npm run check # tsc --noEmit
npm run build # tsc + 资产拷贝(src/assets → lib/assets)
bun test # 单元测试(util/kind/aria/run-output/runtime/bridge/relay-server)
npm run smoke # 构建后用真实 headless Chromium 全链路冒烟
npm run check:image-worker # 构建后验证截图编码路径(Electron 下验证已切子进程)
npm run relay -- serve --port 9224
evaluateOnNewDocument 脚本 + UA 覆盖),不套 omp 反检测 patch;sharp 实现(Bun.Image 移除),Electron Linux 下改由普通 Node 子进程执行(见上文);@babel/parser(无 AST 不引入 babel 全家桶)。MIT © 画野 (mtaech)
浏览器核心与 Browser Relay 的逻辑移植自 oh-my-pi 的 browser 工具。
FAQs
DSH browser tool: drive Chromium tabs (headless / CDP-attached / spawned apps / user's real Chrome via the OMP-style Browser Relay) with an open-close-run + tab scripting API, ported from oh-my-pi.
The npm package dsh-browser-tool receives a total of 608 weekly downloads. As such, dsh-browser-tool popularity was classified as not popular.
We found that dsh-browser-tool demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Rust 1.100 will add opt-in dependency cooldowns to Cargo, giving security scanners and maintainers time to catch malicious crate releases.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.

Security News
Anthropic’s free OSS Scanner uses Mythos and other Claude models to find open source vulnerabilities and send maintainers reports with proposed fixes.