Skip to content

Releases: KNLCXY/dsh-websift

dsh-websift 1.0.8 — 白框、死代理路由、并发抓页串内容

Choose a tag to compare

@KNLCXY KNLCXY released this 24 Oct 14:59

三个实测取证的 bug,全部修掉

(1.0.7 只在本机装过、未对外发布,两版的修复合起来正式发一次。三个问题都是 1.0.0 起就有的,不是新引入的。)

① 桌面上那块白色矩形 = 隐藏的内核窗口

launchChrome 的 spawn 选项里带着 windowsHide: true。它本意只是「别弹控制台窗口」,但在 Windows 上会通过 STARTUPINFO 传 SW_HIDE,把程序自己第一次 ShowWindow 覆盖掉 —— 浏览器窗口从头到尾都是隐藏的:

  • 隐藏的 Chromium 窗口仍会在桌面上留下一整块纯白矩形,尺寸正好等于 --window-size
  • 「可视模式」形同虚设:看不到窗口,扫码登录那类操作根本没法做

取证:同一个内核、同样参数,只差 windowsHide 各起一个 —— false 的 IsWindowVisible=True,true 的 False;再对纯净桌面采样,启动一个隐藏窗口后四个采样点全从桌面蓝 RGB(0,165,247) 变成 RGB(255,255,255),对它发一次 SW_MINIMIZE 立刻恢复桌面色。

修复:去掉 windowsHide。msedge / chrome 都是 GUI 子系统程序,本来就不会创建控制台,去掉对谁都无害。

② 「端口在监听」被当成「代理能用」

proxyAlive() 只做一次 TCP 连接测试。实测 Clash Verge 进程活着、7897 也在监听,但所有节点都挂了 —— 对任何网址都返回空。旧逻辑判「代理在线」,把浏览器指到 --proxy-server=死端口,于是每个页面都是「无法访问此网站」的空白错误页。

雪上加霜:插件完全不认识 Chromium 的错误页(chrome-error://chromewebdata/),导航到错误页时 CDP 调用是「成功」的,错误页被当成正常正文返回,路由缓存 10 分钟内也不作废。

修复:

  1. 新增 proxyUsable():端口在监听且真的转发过一次才算能用(两个探针都不通才算死;端口探活与转发测试分开缓存,互不拖累)
  2. 路由决策全部改用它;browser_proxy 的 status/test 把「端口」和「转发」分开报
  3. 认识错误页:Page.navigate 的 errorText / chrome-error: 一律如实报错,并作废该域名路由与代理健康缓存
  4. 代理打不开时自动退回直连重试一次(proxy: always 是用户显式要求,不擅自改)

对照实验(起一个「只接受连接、永不响应」的假代理):1.0.0 和 1.0.6 都把三个测试站点判成「走代理」,行为一模一样 —— 所以「1.0 是正常的」是因为那时代理节点还活着,不是代码变坏了。

③ 并发抓多页时串内容

web_digest 用 Promise.all 并发抓链接,而整个插件只复用一个工作标签(刻意的)。并发导航同一个标签 = 互相覆盖:

  • 轻则一个链接直接 net::ERR_ABORTED(被另一次导航打断),两个链接只回来一个
  • 重则 A 站读到的是 B 站的 DOM,而且错误内容会被写进 15 分钟页面缓存(缓存键取的是请求 URL),之后一直以 cached: true, ms: 0 张冠李戴地供应

实盘踩到的样子:两页调用里多出「重定向重复 1 条已合并」(两个不同 URL 抓回来的 final URL 相同);紧接着单页查 example.com,标题却是 iana 的「Example Domains」、正文是 iana 那段话、耗时 0.0s,并且数字与上一次完全相同。

修复:加一把浏览器串行闸门(withBrowserLock),只锁「驱动工作标签」这一件事 —— stack=official 的 HTTP 直连那一档照旧并发;loginFlow 自己开新标签(/json/new),不进锁(否则一次登录会把队列堵几分钟)。

测试

新增三条回归测试,全部断言可复跑:

  • test-deadproxy —— 假代理「只监听不转发」必须判不可用、路由退回直连
  • test-window —— 白框回归锁(DSH_WEBSIFT_LIVE=1 时额外做真机窗口可见性校验)
  • test-serial —— 本地两个内容截然不同的页面,断言每个 URL 都拿到自己的正文(可传 lib 目录做修复前后对照;修复前跑会失败:ERR_ABORTED + 只回来 1 页)

另修 test-offline:还在用改名前的旧路由 /_browser-kernel/settings(一跑就崩),且末尾 reset 会把用户真实设置洗成默认值 —— 现在跑完自动还原。

npm test = rank / failed / route / deadproxy / window / serial,6/6 通过。

安装

dsh plugin --profile <profile> add dsh-websift@1.0.8     # 从 npm
dsh plugin --profile <profile> add file:/路径/dsh-websift-1.0.8.tgz   # 离线 tgz(本 Release 附件)

改完宿主代码必须重启 DSH 才生效。

dsh-websift 1.0.6 — 代理路由不再走死代理

Choose a tag to compare

@KNLCXY KNLCXY released this 24 Oct 13:48

dsh-websift 1.0.6 — 代理路由不再把请求交给死代理

1.0.5(Edge 新标签页兼容)未单独发布,已并入本版。

踩到的坑

代理端口没人监听(Clash 没开 / 挂了)时,插件会无条件判「走代理」——因为直连探测抛异常那条分支写的是 route = 'proxy',根本没查代理是否活着。

结果:内核被带上 --proxy-server=http://127.0.0.1:7897,所有抓取都报

ERR_CONNECTION_CLOSED — 无法访问此页面

看起来像「网络坏了」,其实是自己被路由到了死端口上。实测抓 example.com 就中招了。

三处修复

  1. 探测兜底:探测失败时先查代理是否在线 —— 不在线就仍走直连,而不是交给死代理
  2. 缓存校验:读路由缓存时,若缓存说走代理、而代理已经不在线 → 当场作废并重新探测
  3. 失败失效:走代理的抓取失败时,丢掉该域名的路由缓存 + 重置代理健康状态(下次重新探测)

测试

新增 test/test-route.mjs,确定性验证:

  • 临时把 proxyUrl 指向必定没人监听的 127.0.0.1:1(跑完自动还原设置文件)
  • 让直连探测抛异常(就是旧代码走错的那条分支)
  • 断言判定为 「直连可用」(旧代码会说「走代理」)

全套 6 个测试通过:test-rank / test-json / test-digest / test-find / test-failed / test-route。

本版还包含

  • 1.0.5:空白页判定兼容 edge://newtab/(Edge 下不再每次浏览器重启就多开一个标签)
  • 1.0.4:工作标签只按自己记下的 id 认领(不按 URL 猜,绝不误关你自己的标签)
  • 1.0.3:工作标签 id 落盘 ~/.dsh/storages/websift/state.json,跨 DSH 重启复用

⚠️ 改完必须重启 DSH 才生效(宿主半在进程启动时加载,不热更新)。

安装

dsh plugin --profile <profile> add dsh-websift      # latest = 1.0.6

校验:sha256sum -c SHA256SUMS.txt

dsh-websift 1.0.4 — 按 id 认领工作标签(不再按 URL 猜)

Choose a tag to compare

@KNLCXY KNLCXY released this 24 Oct 13:29

dsh-websift 1.0.4

修掉 1.0.3 里一个会误伤用户的设计

1.0.3 为了清理「越堆越多的工作标签」,是按 URL 像不像搜索页(bing / google / baidu / …)来认领和关闭标签的。

这是错的:用户也会在同一个浏览器窗口里自己搜东西 —— 那样会把用户的标签当成插件自己的,
复用甚至关掉。

1.0.4 改成只认我们自己记下的标签 id:

  • ~/.dsh/storages/websift/state.json 里存 ourTabIds(上限 20)+ workTargetId
  • 认领、复用、关闭,都只在这些 id 里选 —— 绝不按 URL 猜
  • 抓取/摘要核心一行未动(5 个测试全过)

行为说明(第一次可能还是会多一个标签)

改动后第一次运行(还没有任何记录)如果找不到空白页/新标签页,仍会新开一个工作标签;
从第二次起就固定复用同一个,跨 DSH 重启也不再堆积。

⚠️ 必须重启 DSH(宿主半在进程启动时加载)。重启后可自查:state.json 出现,
并且你自己开的标签不会被关。

安装

dsh plugin --profile <profile> add dsh-websift      # latest = 1.0.4

校验:sha256sum -c SHA256SUMS.txt

dsh-websift 1.0.3 — 工作标签页落盘(修搜索页堆积)

Choose a tag to compare

@KNLCXY KNLCXY released this 24 Oct 13:16

dsh-websift 1.0.3 — 修「浏览器窗口里搜索页越堆越多」

现象

每次用完,浏览器窗口总是停在 Bing 搜索结果页,而且标签越攒越多。

根因

  1. 插件复用同一个工作标签页,并且故意停在刚访问的页面(不闪回空白页 —— 这是早先你反馈过的)
  2. 但「复用哪个标签」只记在内存里:browserState.workTargetId
  3. DSH 一重启就忘了。忘了之后再找可复用的标签时,只认 about:blank / 新标签页 ——
    而那个工作标签正停在搜索结果页,认不出来 → 再开一个
  4. 于是每开一次会话就多留一个搜索页

修复

  • 工作标签页的 id 落盘:~/.dsh/storages/websift/state.json,跨 DSH 重启复用同一个标签
  • 重启后若发现我们自己留下的搜索页(bing / google / baidu / sogou / so.com / duckduckgo / yandex),
    复用其中一个并关掉其余同类标签 —— 只动我们自己留下的,不碰你手动开的标签

⚠️ 改完必须重启 DSH(宿主半在进程启动时加载)。重启后可自查:~/.dsh/storages/websift/state.json 会出现,
且窗口里的搜索页不再堆积。

安装

dsh plugin --profile <profile> add dsh-websift      # latest = 1.0.3

校验:sha256sum -c SHA256SUMS.txt

dsh-websift 1.0.2 — 修失败报告 + README 配图

Choose a tag to compare

@KNLCXY KNLCXY released this 24 Oct 13:09

dsh-websift 1.0.2

修了一个「把失败说成正常」的 bug

一个页面都没取到正文时,web_digest 会回:

正文本来就短(0 字符),直接给要点

——把抓取失败说成了「内容本来就少」。现在它会如实报告,并逐条列出失败的链接和原因:

一页正文都没取到(2 个链接全失败)—— 多半是打不开、被拦截或需要登录;先用 browser({ url }) 单独打开其中一个确认
未取到:a.invalid(模拟失败:https://a.invalid/) / b.invalid(模拟失败:https://b.invalid/)

新增 test/test-failed.mjs 锁住这个行为(已并入 npm run test:failed)。

README 配图

  • docs/images/hero.png —— 能力总览(一次调用读多页 / 真实搜索链接 / JS·登录态·截图)
  • docs/images/ledger.png —— 一次调用的账本:抓回的正文 vs 返回的摘要

图随 npm 包一起分发(docs/ 在白名单里)。

Edge 内核实测记录

场景 结果
整页截图(JS 重的站点) ✅ 1401×1845,1.2 MB,full_page 生效
多页抓取 ✅ 单页 917 字符 → 摘要 444(压缩 52%);被墙的页面按失败计入并在抬头列出
login 动作超时路径 ✅ 25.5s 干净返回「未检测到登录完成,窗口还开着」,不挂死

登录的成功路径需要真人在窗口里扫码/输密码,尚未实测。

安装

dsh plugin --profile <profile> add dsh-websift          # npm,latest = 1.0.2
dsh plugin --profile <profile> add github:KNLCXY/dsh-websift

校验:sha256sum -c SHA256SUMS.txt

dsh-websift 1.0.1 — 发布到 npm

Choose a tag to compare

@KNLCXY KNLCXY released this 24 Oct 12:35

dsh-websift 1.0.1 — 发布到 npm

内容与 1.0.0 完全一致,只是版本号 +1:npm 的暂存发布机制占住了 1.0.0(见下)。

现在可以从 npm 安装

dsh plugin --profile <你的 profile> add dsh-websift

为什么是 1.0.1

npm 现行的发布政策(2026)对新账号几乎不友好,这次的完整排障路径:

卡点 突破
发布必须 2FA 或带 bypass-2FA 的 token 账号没有硬件安全密钥,且 TOTP 已被 npm 服务端下线(Adding a new TOTP 2FA is no longer supported)
建 bypass token 要求「至少选一个包」 但账号里没有任何包 → 表单里没有可选项,死锁
npm stage publish 官方描述是「把 2FA 证明推迟到批准时」。暂存会为新包名创建占位包 0.0.0-stage —— 账号这才算「有包」
token 表单现在可选「所有包 + bypass 2FA + 读写」 ✅ 建出可用 token
直接发 1.0.0 → 409 Cannot publish over previously staged version 暂存的 1.0.0 无法批准(批准同样要求已注册的安全密钥)→ 改发 1.0.1

所以:npm 上的 1.0.1 == GitHub 上的 1.0.0 内容。占位的 0.0.0-stage 与暂存的 1.0.0 会自行过期。

安装(三种都可以)

dsh plugin --profile <profile> add dsh-websift                     # npm
dsh plugin --profile <profile> add github:KNLCXY/dsh-websift       # GitHub
dsh plugin --profile <profile> add "file:<下载路径>/dsh-websift-1.0.1.tgz"

校验:sha256sum -c SHA256SUMS.txt(本页附件)

装完重启 DSH 生效。

dsh-websift 1.0.0 — 首个正式版

Choose a tag to compare

@KNLCXY KNLCXY released this 24 Oct 08:31

dsh-websift 1.0.0 — 首个正式版

给 DeepSeek Harness 的省 token 网页阅读插件。底层是真 Chrome/Edge(CDP 驱动),一次调用读完多个页面、按相关性筛掉不相关的,只回一段带账本的摘要。

四个工具

工具 作用
web_find 真浏览器搜索,返回真实链接(不是 so.com/link 那种跳转壳)
web_digest 搜索/给定链接 → 抓正文 → 相关性闸门 → 抽关键句 → 压缩摘要(实测省 82–98% 上下文)
browser text / html / eval / screenshot / login
browser_proxy 三档代理 auto / always / never,实时切换不用重启

1.0 之前的稳定能力

  • 内核自动探测:Chrome / Edge / Brave / Chromium / 应用内置(豆包、夸克…),换机器不用手改配置
  • 代理三档 + Clash Verge 可选联动(端口不通时自动启动;启动后自动最小化窗口)
  • 两套闭环可选:plugin(全走浏览器,默认)/ official(官方 API 搜索 + 抓取)
  • 所有 CDP 调用带超时:内核卡住最多等 30 秒就报错,不会拖死整轮对话
  • 统一命名:路由 /_websift/*、存储 ~/.dsh/storages/websift(旧目录自动复制迁移,配置不丢)

安装

dsh plugin --profile <你的 profile> add "file:<下载路径>/dsh-websift-1.0.0.tgz"

或直接从仓库装:

dsh plugin --profile <你的 profile> add github:KNLCXY/dsh-websift

校验(同页附件 SHA256SUMS.txt):

sha256sum -c SHA256SUMS.txt

装完必须重启 DSH

宿主半与 client 半都在进程启动时装配一次;面板里的按钮/开关也要重启后才出现。

版本口径

1.x 起是正式版;0.9.x 及更早全部是预发布,仅作历史留档。


1.0.0 起行为冻结:只修 bug、不再改接口;要动接口就走 2.0。

v0.9.26 — 统一改名(路由 / 存储 / id)

Choose a tag to compare

@KNLCXY KNLCXY released this 24 Oct 08:15

预发布(Pre-release),0.x 一律不算正式版。

0.9.26 — 发布前最后一次统一改名

改什么 从 → 到
宿主路由 /_browser-kernel/* → /_websift/*
存储目录 ~/.dsh/storages/browser-kernel → ~/.dsh/storages/websift
输入框 dock id browser-kernel-toggle → websift-toggle
清单 id dsh-websift.local → dsh-websift

全仓 33 处旧名已清零(包内仅剩 2 处故意保留:迁移常量与本次变更说明)。

配置不会丢

存储目录改名带复制式迁移:新目录不存在、旧目录存在时,把 settings.json 复制过去;旧目录原样保留作备份。

实测:新目录 37 个键、关键值(stack / visible 等)与旧文件一致;四条新路由(settings / clash / window / chrome-candidates)全部注册。

⚠️ 必须重启 DSH

路由和 dock id 变了,不重启的话旧 client 半会去请求已经不存在的旧路由,面板会报错。

安装

dsh plugin --profile <你的 profile> add "file:<下载路径>/dsh-websift-0.9.26.tgz"

校验:sha256sum -c SHA256SUMS.txt

v0.9.25 — 修卡死根因 + 最小化窗口按钮

Choose a tag to compare

@KNLCXY KNLCXY released this 24 Oct 08:08

预发布(Pre-release),0.x 一律不算正式版。

0.9.25

修掉两次「整轮卡死」的根因

33 处 CDP 调用都没有超时,内核一旦卡住(实测 Edge 截图那次),await cdp.send(…) 永不返回 → 整个工具调用挂死 → 只能重启 DSH。

现在 connect().send() 统一 30s 超时(新设置 cdpTimeoutMs,3000–120000 可调),CDP 的 HTTP 端点也加了 AbortSignal。

面板新增

  • 「最小化窗口」按钮(POST /_browser-kernel/window);headless 时会说明「没有窗口可最小化」
  • 「启动代理后最小化」开关(autoMinimizeOnClash,默认开):点「启动 Clash Verge」成功后自动把浏览器窗口收起来
  • 高级设置补上 cdpTimeoutMs 输入框(此前只能改配置文件)

本次验证

项 结果
Edge 内核截图 正常,1416×808,3.7s(图像已核对是真页面)
四条路由 settings / clash / window / chrome-candidates 全部注册
window 路由 非法 action → 400;GET → 405;headless → 明确报「没有窗口可最小化」
设置读写 autoMinimizeOnClash 与 cdpTimeoutMs 的 snapshot / POST / reset 均正常
4 个单测 全过

安装

dsh plugin --profile <你的 profile> add "file:<下载路径>/dsh-websift-0.9.25.tgz"

校验:sha256sum -c SHA256SUMS.txt

装完必须重启 DSH(宿主半与 client 半都在启动时装配)。

v0.9.23 — 设置即时生效 + http 政务站可读

Choose a tag to compare

@KNLCXY KNLCXY released this 23 Oct 07:18

预发布(Pre-release),0.x 一律不算正式版。

攒了两个实修一起发。

0.9.23

  • browser 工具每次重读设置:之前用的是启动时的快照,改 visible / 代理参数后只能重启 DSH 才生效,与面板写的「改完即生效」不符
  • 关掉 Chrome 的 HTTPS 强制升级(--disable-features=HttpsUpgrades):中文政务站大量还是 http://,被强升 https 后变成「网站不安全」错误页(实测 qingxiu.gov.cn),官方 HTTP fetch 却正常

0.9.22

  • 官方 fetch / search 加超时:之前没有超时,站点不响应就会把整个工具调用拖死(实测抓 GameBanana 时整轮卡死)。现在 20s 超时后按原逻辑回退浏览器

安装

dsh plugin --profile <你的 profile> add "file:<下载路径>/dsh-websift-0.9.23.tgz"

校验:sha256sum -c SHA256SUMS.txt

装完重启 DSH:宿主侧代码要重新加载。