DeepSeek Harness Hub
← 返回列表

futrime/webdsh

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
需源码安装

webdsh — 浏览器标签页中的 DeepSeek Harness,无需服务器,无需安装

暂不能直接安装(需源码编译或环境不满足):缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装。 · 最近上游提交 2026/8/29 · 已提供中文文档

仅浏览器版本的 DeepSeek Harness 构建

综合分
44.2
GitHub 分
44.2
用户评分
★ Stars
30
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add futrime/webdsh
缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装,改用 GitHub 源安装
数据截至 2026/9/17(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查需源码安装

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

npm 包deepseek-web-harness(未发布到 npm,仅可源码安装)
Node 引擎要求 >=22 · 基线 Node 22.19 满足
dsh CLI 依赖要求 0.1.1-rc.2 · 最新 ? 兼容
入口文件缺少入口声明

缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装

验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/17 23:37:52

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/cordis-plugin-group@deepseek-ai/cordis-plugin-hmr@deepseek-ai/cordis-plugin-include@deepseek-ai/cordis-plugin-loader@deepseek-ai/cordis-plugin-timer@deepseek-ai/cosmokit@deepseek-ai/dsh@deepseek-ai/dsh-agent@deepseek-ai/dsh-agent-default-model@deepseek-ai/dsh-agent-instructions@deepseek-ai/dsh-agent-loop
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

webdsh

webdsh — 浏览器标签页中的 DeepSeek Harness,无需服务器,无需安装

浏览器标签页中的 DeepSeek Harness —— 真正的 agent,真正的 Node,无需运行服务器。

Live
Deploy
License

DeepSeek Harness(dsh)是一个
agent harness,其中一切皆为插件。dsh web 运行一个 Node 主机,并为其提供
浏览器客户端。webdsh 就是它,以静态文件的形式 —— 主机运行在
页面内部,而 agent 的命令运行在 WebContainers 中:
Node 本身,就在标签页里。

- ⚡ 无需运行任何东西。 没有服务器,无需安装,没有本地 Node —— harness 在页面中启动。
- 🌍 容器也在线。 页面的 CORS 策略被预加载到它启动的每一个 Node 进程中,因此容器内的 fetch 会自动通过代理重试被拒绝的主机 —— http://example.com 现在在那里可以响应了,而以前不行。
- 🖥️ 真正的 Node,真正的 Python。 npm install 和 pip install 都能用,终端和 agent 共享同一个容器。
- 💾 或者一整台 PC。 设置 → Machine 将容器替换为 v86,并提供 128 台机器 —— v86 的整个目录,从 512 字节的引导扇区游戏到 Windows 2000,其中 127 台无需任何设置即可启动 —— 模拟的 x86,在自己的屏幕上,带有那台机器实际拥有的工具集。
- 🧭 或者一个浏览器。 第三台机器是真实网络的真实标签页,助手以三种方式驱动它们:页面结构(一棵带标签的树,对一切可点击之物都有句柄)、像素,或页面自身的 JavaScript。多标签页,拥有自己的 cookie 和按站点持久化的存储 —— 并且每个标签页都被沙箱隔离到不透明源中,因此页面无法触及此 harness、其存储或你的密钥。这是浏览器自身的规则,而非此构建所做的承诺:每条逃逸路径都会返回 SecurityError,而 npm run test:browser 会对此进行检查。
- 🤖 而且它可以被编程。 对于一张有二十行的表格来说,每回合一个动作是错误的形态,因此浏览器机器也接受程序:browser_task 运行 getByRole('button', {name: 'Save'}).click(),在一个具名任务空间中重试 expect、iframe、弹窗、对话框、下载和上传,并在多次调用之间保留其页面、变量和登录状态——还带有回执,因此一个在表单中途被中断的运行可以被询问发生了什么,而不是被重复执行。模型自己的代码运行在它自己的不透明源中,不持有此页面的任何东西:将浏览的网站挡在外面的同一道边界,也把模型编写的脚本挡在外面。
- 🌐 PC 在线。 默认使用 WISP 中继,因此客户机获得真正的 TCP——https://、包管理器、ssh——而没有中继时,页面本身就是路由器:它应答客户机的 DHCP、DNS 和 ping,并以浏览器 fetch 承载 HTTP,经过应用其余部分使用的同一套 CORS 策略。wget http://example.com 在模拟的 Buildroot 上两种方式都能工作;来自容器的同一 URL 则回答 fetch failed。
- 👁️ 它能看见。 附加一张图片,模型就能读取它:由浏览器自己的解码器进行方向校正、限制大小并按路由的预算重新编码,同时沿途剥离来源的 EXIF 和色彩配置文件。你自己添加的模型会被询问它接受什么,因此你自己网关上的视觉模型到达时是睁着眼睛的,而不是被注册为纯文本。
- 🧩 真正的插件。 从 npm、tarball、GitHub 或路径安装——从浏览器中。
- 📦 真正的 dsh。 已发布的 @deepseek-ai/ 包,未经修改:135 行中有 120 行与 dsh web 组合它们的方式完全一致。
- 🔒 属于你的。 文件、会话和密钥都存放在你浏览器的存储中。没有任何内容被上传。

目录

- 背景
- 安装
- 用法
- 维护者
- 贡献
- 许可证

背景

这里没有任何东西是 dsh 的分支。代理循环、工具注册表、模型适配器以及
整个 Web 客户端都在安装时来自 npm;唯一的修改是一个
cordis.patch.yml 层——这正是 dsh 为此记录的机制。

这个仓库添加的是底层的平台:一个同步的 POSIX
文件系统,镜像到 IndexedDB(src/vfs),在其上实现的 node:
(src/node),会话可以运行于其上的运行时——WebContainers 和一个
模拟的 x86 PC(src/runtime),以及一个由沙箱化 frame 构建的浏览器
(src/browser)——一个用于 /api 的页内虚拟服务器、每个出站请求都要经过的 CORS 策略以及赋予模拟机器的网络
(src/net),还有此构建附带的插件(packages/)。

六个组合行被替换,每一个都是因为随附的那一行命名了页面不可能拥有的东西——
或者,就 shell 的情况而言,无法诚实描述的东西。另外四个是重新配置而非替换,包括那个决定是否
这次部署根本不可能打开一条路径。npx tsx scripts/alignment.ts 会打印出
全部差异。

安装

无需安装——打开页面即可。如果你想自己运行:

npm ci
npm run build        # → dist/
node scripts/serve.mjs 4173

需要 Node 22 或更新版本。dist/ 是使用相对 URL 的纯静态文件,因此它既能在
域名根目录下工作,也能在项目路径或本地目录下工作。

用法

打开页面,选择一个工作区,开始对话。六条路由上的 42 个模型已预先注册,
因此它会在向你询问任何东西之前先给出回答。

侧边栏中有三样东西:

- 文件——工作区,正如智能体和终端所看到的那样。把文件拖进来;把文件、
目录或勾选框选中的内容取出去。点击助手提到的路径即可在此处打开它。
- 机器—— Ctrl+ 。本次会话运行在什么之上:Node 容器的终端、模拟 PC
的实时屏幕、浏览器的标签栏和地址栏。点击屏幕,机器就会接管你的键盘和鼠标;
按 Escape 归还。浏览器的标签页就是助手正在操作的那些标签页,而不是它们的
第二份副本——它点什么,你就看到什么。
- 设置——用哪台机器、哪些模型、哪个 CORS 代理、哪些插件。

在宽窗口中,两个面板停靠在对话旁边;在窄窗口中,它们沿底部停靠,并且从对话
中占据宽度,而不是覆盖它。

机器。 设置 → 机器提供三种类型:Node 容器、一个浏览器,以及 128
台模拟 PC——即 v86 的完整目录,其中 127 台无需任何
设置即可启动。该选择会在下次加载时生效,因为它决定了助手获得哪些工具:
容器中的 jsh、Node 和 Python;浏览器上的 browser_navigate、
browser_snapshot、browser_click、browser_screenshot、browser_eval
等等;客户机上的 sh 或 dos 以及 vm_screenshot、vm_key、vm_type、
vm_mouse 等,其磁盘与你的工作区不共享任何内容。客户机只会获得当前对其
可用的工具,而不会获得那些会返回空结果的工具——没有文本的桌面上没有
vm_screen,从未启用鼠标的提示符下没有 vm_mouse。唯一剩下的 Arch 需要
一个用于其 9p 树的主机——从你的计算机打开一个,它就会留在你的浏览器中,
或者将该设置指向一个提供这些内容的主机。npm run v86:catalog 会打印出与
上游的差异;npm run v86:boot -- --bundled --as-shipped 会重新启动全部
127 台。磁盘来自 v86 自己的 copy/images 以及 src/runtime/v86-mirror.json
中指定的主机,主要是
AndyZijianZhang/webdsh-images,
其 NOTICE.json 记录了每个镜像的来源以及依据何种许可证。

该目录无法容纳的是 v86 无法执行的操作系统。OpenHarmony 是人们最常问到的
一个:它的所有目标都是 ARM、RISC-V、
Xtensa、C-SKY 或 x86-64,而 v86 仅支持 32 位,因此没有可提供的镜像,也没有对应的行。docs/openharmony-on-v86.md 中有证据,而 npm run openharmony:check 会从上游重新读取它,因此答案不会在无人察觉的情况下过时。

浏览器机器。 标签页,位于此页面无法从中访问的框架中。每一个都被沙箱化,没有 allow-same-origin,这赋予了它不透明源——因此浏览器本身会拒绝它访问此页面的 DOM、其 localStorage、其 IndexedDB 以及其中的密钥。这一选择牺牲了其他一切:不透明源文档不受 Service Worker 控制,无法跨源获取任何内容,并且会从 localStorage、sessionStorage、document.cookie 和 indexedDB 中同样收到 SecurityError。所有这些都是在写下任何一行之前测量过的。

因此,页面就是浏览器的网络和存储进程,而框架只是它的渲染器。页面通过此处其他所有内容所使用的同一 CORS 策略进行获取,重写文档使其自包含,并通过消息通道将 cookie 和按站点存储传递到 shim 中。三项测量塑造了它:Service Worker 永远不会控制不透明源,因此通常的同源代理技巧行不通;data: URL 不会污染 canvas,而 blob: URL 会,因此每个子资源都以内联 data: 形式存在,否则 browser_screenshot 在任何带有图片的页面上都会出错;而 window.location 是 defineProperty 唯一拒绝的全局对象,这就是为什么脚本文本用 acorn 解析,并且命名 location、top 和 parent 的表达式被重写为读取虚拟对象——一个根据自身 URL 进行路由的站点可以正常工作,而每个大型站点都附带的框架破坏脚本则悄无声息地不起作用。

两个限制,在此处以及模型读取的工具描述中都明确说明。请求中不携带 cookie——Cookie 是浏览器禁止页面设置的标头,而 set-cookie 不跨源暴露——因此 cookie 在页面内部工作并在访问之间持久化,登录后的任何内容都无法访问。大多数主机需要 CORS 代理,因为大多数网络不允许跨源读取;没有代理,只有发送 access-control-allow-origin 的主机才能被浏览。npm run test:browser 针对本地夹具站点驱动所有这些,包括隔离。

截图。 驱动一台它能看到的机器的模型会拍摄它来查看它,而两个屏幕工具——模拟 PC 上的 vm_screenshot、标签页上的 browser_screenshot——都会像 read_image 返回文件一样直接返回图片:一次调用,无需打开任何东西。图片也不会同时写入工作区。观看启动是每隔几秒截一次图,检查页面是每次编辑再截一次图,而文件面板被它们填满并不是任何人想要的。仍然会写入文件的是助手为一个值得保留的视图命名路径,或者一个完全无法展示图片的模型(在那里文件就是
整个答案),以及“设置 → 机器 → 截图”,它会为任何想要记录的人保留每一张截图。

你添加的模型。 “设置 → 模型”接受任何 OpenAI 兼容的路由:一个基础 URL、一个密钥,以及获取模型。该列表所说明的模态信息会与其他内容一并读取,因此端点描述为接受图像的模型会被注册为接受图像——网关上的 GLM-5.3-Flash 就是用来衡量这一点的案例。没有任何猜测:一个未描述任何模态的列表会让其模型停留在该路由的默认位置,也就是文本,而你自己声明的条目永远不会被重写。如果你的路由什么都没说,而它的模型确实能处理图片,那么在该模型于设置文档中的条目上写 input: [text, image],就是这里为你补全的全部内容。该页面附带的名单也以同样的方式描述,来自每个服务自己的目录——除了 OVHcloud,它根本不发布任何模态信息,所以它的视觉模型改为被问了一个关于图片的问题,并回答了它。(该路由随后会拒绝每个代理回合都携带的工具定义,这是它自己的一堵墙,该由提供商来挪开;这里改变的是,该页面不再拒绝发送它本可以发送的图片。)

机器的网络。 一台模拟 PC 会获得一块以太网卡,而该页面就在它的另一端:它自己应答客户机的 ARP、DHCP、DNS 和 ping,并把客户机 TCP 内的 HTTP 请求转换为 fetch 调用——这些调用会经过上面的 CORS 策略,先直连,只有当某个主机拒绝浏览器时才走代理。所以一台模拟的 Buildroot 可以 wget http://example.com;从容器访问同一个 URL 会返回 fetch failed,因为它的请求从 StackBlitz 的 worker 发出,该页面永远看不到它们,也无法自动重试。80 以外的端口也可以工作,而原版 v86 会重置这些端口。

标签页无法承载的是 TLS:从客户机内部发起的 https:// 必须在这里终止,所以这些连接会被拒绝,而不是一直挂起;而通过 HTTPS 提供此页面时,只要主机需要,此页面就会在线上把普通 http:// 当作 HTTPS 发送。它只是出站 HTTP,仅此而已——没有到客户机内运行的服务器的入站路由,没有超出该页面伪造的 DHCP 和 DNS 之外的 UDP,也没有 cookie 或 CORS 隐藏的响应头,所以任何需要登录的东西都无法工作。ping 和 DNS 由该页面应答,而不是由被指定的主机应答。客户机被拒绝访问此页面自己的源,因为 fetch 是由标签页发起的,而同源请求根本不需要 CORS——那会成为通往 harness 自身 /api 的一条线路。你计算机的网络不会被阻止:localhost、局域网和 v86 的 .external 名称都可以工作。

这就是底线。默认配置了一个 WISP 中继,有了它,客户机就拥有真正的 TCP,而不是 HTTP 形态的 TCP:https:// 可以端到端工作,包管理器和 ssh 成为可能,DNS 也是真实的。代价是,一个
第三方承载机器发送的每一个字节,包括 TLS 会话内部的字节
它只是在转发——Settings → Network 说得很明白,一键即可清除,
清除后页面内的桥接仍然可用。当机器启动时不应答的中继会为该桥接被丢弃,
而不是留下一个悄无声息、什么都不做的网络。某个特定 guest 是否有该网卡的驱动,
是关于其磁盘的事实:它是按机器测量的——目前有三台——而一台尚未被测量的机器
会被如实描述为如此,而不是被许诺一个网络。

容器的网络。 WebContainer 的请求从 StackBlitz 自己的 worker 发出,
在那里页面的被修补过的 fetch 和 public/sw.js 都看不到它们——因此
应用其余部分所应用的 CORS 重试永远无法触及它,而 shell 工具的建议是
手动为代理加前缀。它是被内置进来的:src/container/net-shim.ts 在启动时
写在 shell 旁边,并通过 NODE_OPTIONS 预加载到每个 Node 进程中,因此
被拒绝的请求会通过配置的代理自动重试一次,无论它来自哪里。实测:
fetch('http://example.com') 在没有它时返回 fetch failed,有它时返回页面。

配置了中继后,globalThis.dshConnect(host, port) 还会给容器一个真正的
TCP socket——即模拟机器的中继,用一个设置同时服务两个运行时。它是被提供
而不是覆盖安装在 net.connect 上,因为 Node 自己的 fetch 建立在该函数
之上,接管它会让进程中的每个请求都挂起。在该 socket 之上使用 TLS 在这里
行不通:此运行时的 tls 会去访问普通流所没有的内部结构,因此 https
仍然是 fetch 的职责。

插件。 在编辑器中输入 /plugin add ,或 Settings → Plugins。
接受 npm 名称、tarball URL、owner/repo#ref 或路径。组合在启动时固定,
因此更改会在下次重新加载时生效。

持久化。 工作区、会话和记录在重新加载后仍然保留。
window.dsh.exportFs() 下载一个 zip;window.dsh.reset() 清除全部内容。

值得了解:容器的 shell 是 jsh,不是 bash,并且不附带 git;
python3 是编译为 WebAssembly 的 CPython 3.14,首次使用时获取,因此
它有 pip 但没有编译器、没有子进程、没有 socket——并且要写 python3,
因为 jsh 将 python 设为别名并在途中丢失了引号。

维护者

@futrime

贡献

欢迎在 futrime/webdsh 提交
issue 和 PR。提交遵循 Conventional Commits;
npx tsc --noEmit 和 npm test 应先通过;npm run test:vision、
npm run test:v86 和 npm run test:workload 覆盖镜像流水线、模拟机器
以及 agent 在每台机器上完成真实任务,而 npm run test:machine-network
在不启动任何东西的情况下测试 guest HTTP 桥接的解析器及其拒绝行为。

许可证
Apache-2.0 © Zijian Zhang。它所组合的
@deepseek-ai/* 包由 DeepSeek AI 根据其自身条款发布,而它获取的磁盘镜像仍归其各自作者所有。

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群