README
dsh-browser-bridge
在 Chrome 侧边栏里直接嵌入完整的 DSH Web,让浏览器里的真实页面成为当前开发对话中的一等公民:DSH 既能像往常一样读写文件、执行命令,也能通过你显式授权的标签页,直接观察、操作和验证页面,而不必换到另一个“浏览器专用对话”里。
效果展示

在完整 DSH Web 对话中通过 @当前标签页 附加左侧开发页面,DSH 可以沿用已有的代码上下文继续观察、操作和验证页面。
核心特色
- 侧边栏里就是 DSH Web 本身,不是另一个聊天客户端。 你在侧边栏看到的正是平时使用的完整 DSH Web,可以打开原有开发对话并延续其上下文;bridge 无需再实现和维护一套独立的对话界面。
- 延续原来的开发对话,而不是另起炉灶。 不用开新对话,也不必把问题重新描述一遍——在正在进行的开发对话中,通过
@当前标签页按钮(或@引用源browser-tabs)把当前页面显式授权给这一条 prompt,DSH 就能在同一个上下文里继续检查、交互、定位问题、修改代码并验证。 - 页面按 prompt 显式授权。 授权只对当前这一条 prompt 生效:turn 结束、取消或从队列移除、标签页关闭、桥接断开时自动失效,下一条 prompt 必须重新附加。弹窗、新开的标签页、发送后切换的活动标签页都不会被隐式授权。
- 结构化、有据可查的浏览器证据。 不是把整个浏览器交给模型,而是通过一组稳定的结构化工具返回证据:DOM 状态、计算样式、几何信息、精确 URL、console 错误、失败的网络请求,以及截图。
- 权限按需且临时的。 CDP 会话在第一次工具调用时才懒附加,turn 结束时自动断开;没有任何访问会隐式延续到未来的 prompt。
一个典型的开发闭环
这是本项目的首要使用场景——开发反馈回路:
- DSH 修改源码。 在开发对话中让 DSH 用现有的文件与 Shell 工具改代码,例如调整样式或修复逻辑。
- HMR 更新页面。 开发服务器热更新已经开在 Chrome 里的页面,浏览器立即呈现新版本。
@当前标签页授权。 在同一个对话的输入框上方点击@当前标签页,把正在显示的页面授权给当前 prompt,然后发送。- 同一对话中观察、操作、诊断。 DSH 读取真实页面的 DOM、计算样式与几何信息,必要时点击、输入、滚动,并查看 console 错误和失败请求来定位问题。
- 继续改代码并复验。 根据浏览器证据再次修改源码,HMR 又一次刷新页面,DSH 继续观察验证,直到结果符合要求。
整个过程中只有一个对话:上下文不丢失,页面只是被显式授权的“证据与操作对象”。例如可以直接接着刚才的开发过程说:
刚才改的按钮 hover 还是不对。
@当前标签页请在当前页面悬停检查;如果有问题,继续修改源码并复验。
同样的原语也适用于问题复现、信息提取、表单操作等轻量浏览器自动化场景——它不只是一个验收工具,也不是全局的 Computer Use。
工作方式(架构)
Chrome side panel
└─ embedded DSH Web (iframe)
└─ DSH client plugin
├─ @ tab references and shortcut
└─ origin-checked postMessage
↕
Chrome extension service worker
├─ prompt grant vault
├─ CDP session manager (chrome.debugger)
└─ authenticated WebSocket
↕
DSH host plugin (pairing, grants, tools)
↕
DSH agent runtime
三个组成部分共享同一个与传输无关的协议包(packages/protocol):
extension/—— Manifest V3 侧边栏扩展(React + shadcn 壳),负责标签页发现、prompt 授权(grant)与chrome.debugger会话;它不实现聊天界面。packages/dsh-plugin/—— 一个可安装的外部 DSH 插件,包含客户端一半(composer 集成)与宿主一半(配对、授权、工具)。packages/protocol/—— 双方共享的带版本号线上协议 schema(配对、授权、桥接请求、工具结果、错误、版本协商)。
把标签页授权给 prompt
- 输入框上方的
@当前标签页按钮一键附加当前 Chrome 标签页到 prompt。按钮通过 DSH 官方conversation.input.dockslot(注册序 30)显示在输入框正上方:排在 Todo(0)、Goal(10)、Queue(20) 等输入 dock 条目之后、最靠近输入框,左边缘与输入卡片对齐、垂直间距 6px;空白首页(hero)下宿主间距为 12px,由插件 CSS 补偿为同样的 6px,因此空白首页与已有对话中位置一致。 @引用源(browser-tabs)列出可附加的标签页,可以一次附加多个;每个附加页面获得稳定别名(如page_1、page_2),并在 prompt 中附带净化后的标题/URL 元数据。- 授权是按 prompt 生效的:turn 的 durable
turn/end(包括完成、错误、取消与 dispose)、引用标签页关闭或终态桥接断开都会立即撤销。Chrome 扩展授权另有 10 分钟滑动空闲超时:新的、已通过校验的浏览器工具调用在执行期间不计 idle,最后一个调用结束后重新开始 10 分钟倒计时,但整条 prompt 最长不超过 6 小时。相同 request 的并发、失败或延迟重传只重放原结果,不执行、不续租;短暂断线期间产生的撤销会在同一 logical session 重连时优先送达。下一条 prompt 仍需重新附加。 - 弹窗或新打开的标签页永远不会被隐式授权;发送消息后切换活动标签页也不会把授权重定向到新页面。
浏览器工具
当一个 prompt 拥有至少一个有效授权时,以下工具仅在该 turn 内存在:browser_observe、browser_inspect、browser_screenshot、browser_act、browser_navigate、browser_wait、browser_console、browser_network。
| 工具 | 作用 |
|---|---|
browser_observe |
返回页面身份、生命周期状态、语义化 DOM/无障碍内容,以及短生命周期的元素引用;默认不含整段文本(text: true 显式请求),过滤 InlineTextBox 与重复 StaticText |
browser_inspect |
查询指定元素(引用/选择器/批量 targets)的表单状态(value/checked/selected 等)、属性、文本、几何与可见性;计算样式仅在显式请求 properties 时返回;密码/secret 字段不泄漏明文 |
browser_screenshot |
截取当前视口或指定元素,并返回图片附件证据;仅当前模型明确支持图片输入时执行 |
browser_act |
点击、输入(type 追加/replace: true 覆盖)、fill(原生 setter 可靠覆盖 input/textarea/select/datetime-local)、选择、悬停、聚焦、按键、滚动;可用 actions 批量顺序执行并附带 expect 后置条件 |
browser_navigate |
打开 HTTP(S) 地址、后退/前进、刷新 |
browser_wait |
等待元素、文本、URL、生命周期状态,或一段有界的页面稳定窗口 |
browser_console |
返回标签页被附加以来观察到的 console 错误与相关日志 |
browser_network |
返回标签页被附加以来失败的请求与加载错误(不含请求头与请求体) |
browser_screenshot 会在访问浏览器前检查当前 DSH provider/model 的图片输入能力。DeepSeek chat-completions 等纯文本模型会收到可恢复的文本工具错误,并可继续改用 browser_observe / browser_inspect;截图不会写入会话历史,也不会导致后续轮次持续失败。
元素引用是短生命周期的:页面导航会使全部引用失效,DOM 替换可能使个别引用失效,工具此时返回 stale_element 而不是猜测其他目标。
console 与 network 证据有界:从 debugger 附加时开始记录,随授权一起删除;任何情况下都不会返回请求头、请求体、cookie 或密码值。
权限与安全边界
debugger—— CDP 会话:首次工具调用时懒附加,授权结束时断开。打开 DevTools 会分离会话,并返回可恢复的debugger_detached错误。tabs—— 仅用于读取标签页标题/URL 供@引用使用,不记录任何常驻浏览历史。storage—— 本地设置,以及chrome.storage.session中用于 service worker 启动对账的非机密归属台账。- 只有 HTTP(S) 标签页可附加。
- 首个版本支持本地 DSH Web 来源(
localhost、127.0.0.1)与 Chrome 118+。 - 原始 CDP 透传默认关闭;不支持无痕窗口标签页;默认无遥测;任何访问都不会隐式延续到后续 prompt。
- 如果 DSH Web 无法被嵌入侧边栏,面板会显示可操作的嵌入诊断。
- 意外的跨域跳转会暂停进一步的写入(
navigation_requires_confirmation),读取仍然可用,直到新的 prompt 显式附加新页面。 - 附加的页面内容只作为外部证据注入模型,并被明确标注为证据而非指令。
通过 npm 安装
插件已发布到 npm:@ycp424c/dsh-browser-bridge。适用于 DSH 0.0.1-rc.2+ 的 web profile:
# 1. 安装依赖(等价于在 profile 目录执行 pnpm add)
dsh plugin add --profile web @ycp424c/dsh-browser-bridge
# 2. 挂载插件:把包名追加到 ~/.dsh/profiles/web/package.json 的 bundles
# "dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "@ycp424c/dsh-browser-bridge"] } }
# 3. 重启
dsh web
插件的 peerDependencies(@deepseek-ai/cordis、@deepseek-ai/schemastery 及 @deepseek-ai/dsh-*)由 DSH 本体提供,无需单独安装。
浏览器扩展(extension/)不发布 npm;需要扩展能力的场景仍按下方源码方式构建并“加载已解压的扩展程序”。只用 Vite Provider 的场景不需要扩展。
安装与运行(源码开发)
环境要求:Node.js ^22.19.0 || >=24.0.0(启用 Corepack)、pnpm 11.7.0、Chrome 118+,以及一份本地 DSH 源码检出。
# 1. 将 DSH 插件链接到本地 DSH 源码检出
pnpm link:dsh -- /absolute/path/to/dsh
# 2. 安装依赖并验证(类型检查 + 单元测试 + 构建)
pnpm install --frozen-lockfile
pnpm check
# 3. 构建插件并安装到 DSH 的 web profile
pnpm --filter @ycp424c/dsh-browser-bridge build
dsh plugin --profile web add /absolute/path/to/dsh-browser-bridge/packages/dsh-plugin
dsh web
# 4. 构建扩展,然后在 chrome://extensions 中启用开发者模式并"加载已解压的扩展程序"
pnpm --filter @ycp424c/dsh-browser-bridge-extension build
pnpm --filter @ycp424c/dsh-browser-bridge-extension zip
扩展输出目录为 extension/output/chrome-mv3。加载后点击工具栏图标打开侧边栏,第一个界面会让你配置本地 DSH Web 来源(默认 http://127.0.0.1:3080),面板随后在 iframe 中嵌入 DSH Web 并显示连接横幅。
完整的分步清单(本地链接、冻结安装、pnpm check、插件 profile 安装、解压扩展加载、更新、卸载及逐错误排查)见 INSTALL.md。
Vite Provider:无需扩展的页面接入
Chrome Extension 与 Vite provider 是互补的接入方式,而非替代关系:
| 维度 | Chrome Extension | Vite Provider |
|---|---|---|
| 安装 | 加载解压扩展 | 零安装,Vite 插件注入 |
| 页面 | 任意标签页(CDP) | 由当前 Vite 构建承载的页面 |
| 能力 | 全部 browser_*(含截图、network) |
可靠子集:observe、inspect、act、navigate、wait、console |
| 证据 | DOM、CDP、原生截图、浏览器级 console/network | DOM 语义投影、合成输入、HMR generation、console 缓冲 |
| 前提 | Chrome 118+ | 页面由你的 Vite 构建注入 Runtime |
安装与配置
pnpm add -D @ycp424c/dsh-browser-bridge-vite
import { dshBrowserBridge } from '@ycp424c/dsh-browser-bridge-vite'
export default defineConfig({
plugins: [
dshBrowserBridge({
dshOrigin: 'http://127.0.0.1:3080',
bridge: {
enabled: true,
injectInBuild: false, // 生产构建默认不注入
autoConnectInBuild: false, // 显式注入后默认休眠
},
panel: {
enabled: true, // false 只关闭嵌入 UI,bridge 仍可用
visible: false, // true 仅做健康探测,成功后显示入口
shortcut: 'Alt+Shift+D',
queryParameter: 'dsh',
},
}),
],
})
- 开发环境默认自动连接本地 DSH 并注册页面 target,但不自动打开面板:
panel.visible: false(默认)保持 UI 完全隐藏;panel.visible: true也只允许在本地健康探测成功后显示 launcher 入口,抽屉始终只在显式激活(快捷键、?dsh=1、launcher 点击)时打开。 - 生产构建默认不注入;显式
injectInBuild: true后仍默认休眠(零本地网络请求),只有快捷键、?dsh=1或本地激活开关才会激活;autoConnectInBuild: true才允许每个访问者主动探测并连接;panel.visible: true只做健康探测并在成功后显示入口,不注册 target。 panel.enabled: false只关闭嵌入 UI,bridge 激活管线照常运行,仍可从独立 DSH Web 的@开发页面附加。dshOrigin只接受回环地址:localhost、*.localhost、127.0.0.0/8、::1。配置拒绝凭据、非 HTTP(S) 与远程地址,且不扫描端口。- 所有配置都会进入前端产物:schema 拒绝任何秘密形态的字段,不要把 token/密钥放进配置。
引用与授权(与扩展一致的显式边界)
@开发页面:从本地 Host 回读所有已连接的 Vite target,可一次附加多个。@当前开发页:仅当 DSH Web 嵌在目标页面(Shadow DOM 面板)中出现,指向承载当前面板的 target,且 targetId 与 origin 必须通过 Host 回读校验。- 附加只创建 composer 引用;发送 prompt 时才申请一次性 grant,绑定 session/turn/target;没有引用就没有模型工具。turn 完成、取消、移除、超时、页面关闭、跨 origin 离开都会撤销授权。
可靠能力表
| 工具 | Vite 支持 | 说明 |
|---|---|---|
browser_observe |
✅ | 有界语义 DOM 投影、ARIA、短生命周期引用;去重后的节点列表,text 按需返回 |
browser_inspect |
✅ | 表单状态/属性/文本/按需计算样式/几何/可见性,敏感值遮罩 |
browser_act |
✅ | click/type/fill/select/focus/press/scroll;受控输入走原生 setter + input/change;hover 为合成事件(synthetic: true, cssPseudoState: false) |
browser_navigate |
✅ | 仅同源 URL/前进/后退/刷新;跨 origin 在导航前拒绝 |
browser_wait |
✅ | selector/text/url/ready/稳定窗口/下一 generation |
browser_console |
✅ | 注入后的 console、window error、unhandledrejection,有界 200 条并带 generation |
browser_screenshot |
❌ | 返回稳定 unsupported_operation |
browser_network |
❌ | 返回稳定 unsupported_operation |
HMR 会使旧元素引用失效(stale_element),并递增 generation;断线后的写操作绝不自动重放。生产页面没有 HMR capability,generation 等待返回 unsupported_operation。
本地 DSH-only 边界与 CSP
- Runtime 只连接本机回环 DSH;不保存 token、grant 或页面证据到 localStorage/扩展存储;唯一的持久化写入是用户显式激活开关。
- Host 侧 Vite broker 默认只接受回环 origin 的页面注册(
localhost、*.localhost、127/8、::1),远程站点页面无法注册为 target;确需放行非回环 origin 时,可在插件配置中显式设置viteAllowedOrigins: ['https://example.com']。 - Vite WebSocket 升级与
/targets、/grants一样要求回环 Host 头(防 DNS rebinding),且握手Origin必须与页面声明 origin 精确一致(浏览器必带 Origin,缺失即拒绝)。 - 生产站点若设置 CSP,需在响应头中允许所选回环来源,例如:
frame-src http://127.0.0.1:* http://localhost:*;
connect-src http://127.0.0.1:* http://localhost:*
ws://127.0.0.1:* ws://localhost:*;
插件不会放宽服务器响应头中的 CSP,只会给出文档与运行时诊断:面板嵌入失败显示 embedding_blocked 诊断与“在新标签页打开本地 DSH”的降级入口;本地网络/连接被阻止时显示失败横幅与重试。
验收状态
Chromium 自动化(Playwright)已覆盖注入、观察/操作、React/Vue 受控输入、HMR、多页面路由、unsupported 能力、HTTPS 生产 fixture 与 CSP 诊断(e2e/vite-provider.spec.ts、e2e/vite-security.spec.ts)。真实 Chrome 与 Arc 人工门禁按计划单独记录在
docs/testing/vite-provider-manual.md,截至 2026-08-11 状态为未完成(需要运行中的真实 DSH 实例),不得以 Chromium 结果推断通过。
设计文档
更多「網頁與瀏覽器」外掛
last30days-skill-cn
作者 jesseovo
last30days-cn 是一個 AI Agent 技能(Skill),能夠自動搜尋中國網際網路 8 大主流平臺最近 30 天的內容,綜合分析後生成有據可查的研究報告。
dsh-browser
作者 lum1104
dsh plugin: Chrome sidebar extension that lets DeepSeek Harness operate your browser directly, no vision capabilities required. 一款 Chrome 側邊欄擴充套件程式,可讓 DeepSeek Harness 直接操控您的瀏覽器,無需視覺能力。
modsearch
作者 liustack
The web search plugin for DeepSeek Harness, and the search bridge for every model without native web access. Ask the web or X, get structured JSON evidence. | 🥇 全網最強的 DeepSeek Harness 聯網搜尋外掛🥇。為不能聯網的模型補上搜索。問網頁或 X,拿回結構化 JSON 證據(搜尋、抓取、引用)。
anysearch-dsh
作者 anysearch-team
為 DeepSeek Harness 提供的 AnySearch 網頁搜尋提供方與高階搜尋工具。
