본문으로 건너뛰기
B

dsh-plugin-webrelay

baisbt/dsh-plugin-webrelay

사이트별 DOM 어댑터가 있는 same-origin reverse proxy를 통해 외부 AI 채팅 사이트를 DSH 사이드 패널에 삽입합니다. composer 버튼으로 호스트 모델이 초안을 고치게 하거나, 대화를 압축·최적화해 임베디드 사이트로 보내고 답변을 가져와 composer에 최종 반영하는 2라운드 흐름을 실행할 수 있습니다.

설치

dsh plugin --profile web add github:baisbt/dsh-plugin-webrelay

README

dsh-plugin-webrelay

DSH(DeepSeek Harness)Web 中继插件:把外部 AI 网页搬进 DSH 右侧,并用一个按钮完成「提示词优化 / 与外部 AI 协作优化」。


目录


项目简介

dsh-plugin-webrelay 是 DeepSeek Harness (DSH) 的一个双面插件(host 半 ESM/Node + client 半 CJS/Browser),发布名为 @dsh-external/dsh-webrelay。

它解决一个日常痛点:你同时在 DSH 和多个外部 AI 网页(DeepSeek / ChatGPT / 豆包 / 通义千问 / Gemini)之间来回复制粘贴、切换窗口。本插件把外部 AI 网页嵌进 DSH 右侧面板,并在输入框旁给出一个闪电按钮,把「写提示词 → 找外部 AI 审阅 → 把结果整理成终稿」这条链路收进一个按钮里。

  • 同源嵌入:面板里的外部页面不是普通 iframe,而是经插件自带的 relay 反向代理加载的同源页面——因此可以直接读写页面 DOM,实现自动投放提示词与抓取回复。
  • 只读为默认,写入需点击:整条链路中只有「发送到浏览器」这一步会向外部站点写入,且必须由你在弹窗里明确点击;等待、抓取、复查全部只读。
  • 零 @deepseek-ai/* 运行时强依赖:host 侧只用 inject: ['webServer'],llm / tools / sessionQuery 全部运行时懒取,缺服务时对应功能降级而非插件拒载。

核心功能

① 右侧内置浏览器

通过插件自带的 relay 反向代理同源嵌入外部 AI 对话网页,带站点识别徽章、捕获存档与「系统浏览器打开」降级通道。面板可开合、可拖拽调宽,站点页签来自配置文件。

② 闪电按钮(⚡,位于模型选择器左侧)

提供两个动作:

  1. 优化提示词(不发送):调用 DSH 宿主 LLM,把草稿改写得更清晰可执行。弹窗展示(可编辑),支持 撤回 / 重新生成 / 插入输入框,绝不自动发送。
  2. 与外部 AI 协作优化:一条双轮闭环—— 压缩对话上下文 → 第一次优化(初稿)→ 发送到浏览器 → 等待并捕捉外部回复 → 第二次优化(终稿)→ 写入 DSH 输入框(不自动发送)。 全程分步弹窗、可编辑、可撤回。 未连接外部浏览器时该项显示为 🔗 连接外部浏览器(不是禁用态):点击即自动尝试接入——联动站点会启动联动浏览器并打开标签页,其余站点会打开右侧面板加载页面;连接完成后即变为 ⚡ 与外部 AI 协作优化。

另有独立的 🖥 面板开关按钮,用于打开 / 关闭右侧浏览器面板。

③ 捕获存档 + 智能体工具

外部回复可保存为 Markdown 文件($DSH_HOME/webrelay/captures/*.md),面板「捕获历史」可查看,并注册 webrelay_captures 智能体工具——DSH 会话中的智能体可直接检索引用,减少重复思考。

④ 站点管理界面

面板头部「管理」按钮打开站点管理弹窗,支持添加 / 排序 / 隐藏 / 删除 / 恢复默认,以及多浏览器实例与账户绑定(详见 配置说明)。

环境依赖

依赖版本 / 说明
Node.js插件为 ESM 包("type": "module"),需 Node 20+;本机开发用 node / pnpm
pnpm包管理器(仓库含 pnpm-lock.yaml)。dsh plugin add/remove 内部就是调它,因此使用者也需 PATH 上有 pnpm
DSH需可用的 dsh CLI。DSH 处于 developer preview,客户端快照/契约字段可能变化
浏览器内置模式用你当前浏览器即可;**联动模式(CDP)**需本机安装 Chrome 或 Edge(未指定路径时自动探测,Windows/macOS/Linux 均已覆盖)

依赖清单(来自 package.json):

  • 运行时依赖:yaml ^2.6.1
  • 开发依赖:typescript ^5.9.3、tsdown ^0.22.14、@types/node ^24.13.3、@types/react ~18.3.1、@types/react-dom ~18.3.0
  • peerDependency:cordis: *(宿主契约标记;react / react-dom 由浏览器 loader 的模块表提供,不作为包依赖声明)

关键路径(下文频繁出现,先集中说明):

路径含义
$DSH_HOMEDSH 主目录。默认 ~/.dsh,可由环境变量 DSH_HOME 覆盖(Windows 默认 %USERPROFILE%\.dsh)
$DSH_HOME/webrelay/sites.yml用户配置文件(首次运行自动从出厂默认复制)
$DSH_HOME/webrelay/captures/捕获存档目录(capture.dir 为 null 时)
$DSH_HOME/webrelay/browser-profile/<id>各联动浏览器实例的独立配置子目录
sites.default.yml出厂默认配置(仓库存放于包根,随插件分发,勿手改)

快速开始

按你的身份选一条路:

你的情况走哪条
只想用插件(不改代码)方式 A / B / C 任选一条
要改源码、参与开发本地开发(link 模式)

三种方式都只需一条命令。dsh plugin --profile web add <参数> 会把参数原样转发给 profile 目录下的 pnpm add,因此 pnpm 支持的来源(本地路径、tarball、registry 包名、github: / git+https://)都能用。

方式 A:tarball 安装(推荐)

不依赖 npm 发布,也不触发构建脚本审批——tarball 内已含构建产物 lib/。

# ① 在插件仓库里打出 tarball,产出 dsh-external-dsh-webrelay-<version>.tgz
pnpm install --ignore-workspace
pnpm pack

# ② 把 .tgz 交给使用者,在其机器上执行(路径换成实际位置)
dsh plugin --profile web add /绝对路径/dsh-external-dsh-webrelay-0.1.0.tgz

# ③ 验证插件已进入配置层
dsh web --dump-config | grep webrelay

成功判断依据:第 ② 步以 Done in … 结束;第 ③ 步输出含 dsh-webrelay 条目。

该 tarball 的实际内容(pnpm 11.7.0 实测,共 9 项):lib/index.js + lib/client.js 及各自 sourcemap、sites.default.yml、cordis.patch.yml、package.json、README.md、LICENSE——不含 src/。安装后 lib/index.js 可直接 import(导出 apply、inject: ["webServer"]、name),因为产物已预构建,整个安装过程不会请求构建脚本审批。

方式 B:从 npm registry 安装

前提:包已发布到 npm。当前尚未发布,且需要先拥有 @dsh-external 这个 scope。

dsh plugin --profile web add @dsh-external/dsh-webrelay

与方式 A 同理:registry tarball 同样自带 lib/,且 registry 安装不会触发 prepare 构建。

方式 C:从 GitHub 直接安装

dsh plugin --profile web add github:Baisbt/dsh-plugin-webrelay

⚠️ 这条路需要额外放行一次构建脚本。 仓库的 lib/ 被 .gitignore 排除,lib/ 是由 package.json 的 prepare: tsdown 在安装时现构建的;而 pnpm 11 默认拦截依赖的构建脚本(strictDepBuilds 默认 true)。因此首次执行会以 ERR_PNPM_IGNORED_BUILDS 失败,同时 pnpm 会把一个占位项写进 profile 的 pnpm-workspace.yaml:

$DSH_HOME/profiles/web/pnpm-workspace.yaml

把 pnpm 打印出来的那个 key 置为 true,再重跑同一条 add 命令即可:

allowBuilds:
  # 键名以 pnpm 实际打印的为准
  <pnpm 打印的 key>: true

注意键的粒度:pnpm 11 不接受单独写包名来放行 git 来源的依赖,必须精确到解析出的 commit 路径;用仓库 URL 作键是 11.11.0 起才支持的能力。不想处理这一步就用方式 A。

# 1. 安装依赖(插件目录独立于 DSH 仓库 workspace,必须加 --ignore-workspace)
pnpm install --ignore-workspace

# 2. 构建:产出 lib/index.js(host)+ lib/client.js(浏览器)
pnpm build

# 3. 类型检查
pnpm typecheck

# 4. 以 link 模式注册进 DSH(构建会在 pnpm install 的 prepare 钩子自动执行)
dsh plugin --profile web add link:D:/path/to/dsh-plugin-webrelay

# 5. 验证插件已进入配置层
dsh web --dump-config | grep webrelay

# 6. 启动
dsh web

启动后打开 DSH Web UI,输入框右侧(模型选择器左侧)应出现 ⚡ 与 🖥 两个按钮。

卸载:dsh plugin --profile web remove @dsh-external/dsh-webrelay。 卸载后 $DSH_HOME/webrelay/(用户配置与捕获存档)会保留;彻底清除请手动删除该目录。


具体操作流程

以下按从零开始的顺序展开。每一步都给出:操作目的 → 具体命令 / 操作 → 成功判断依据。

第 0 步:准备(前置条件)

目的:确认开发与运行环境就绪,避免后续步骤半途失败。

操作:

  1. 确认 Node 与 pnpm 可用:

    node -v
    pnpm -v
    
  2. 确认 dsh CLI 可用:

    dsh --version
    

成功判断依据:三条命令均正常输出版本号,无 command not found。


第 1 步:安装依赖

目的:拉取构建与类型检查所需的依赖。

操作:

cd D:/path/to/dsh-plugin-webrelay
pnpm install --ignore-workspace

成功判断依据:

  • 命令以 Done(或类似成功提示)结束,退出码 0;
  • 目录下出现 node_modules/;
  • lib/ 目录已生成——因为 package.json 里配置了 "prepare": "tsdown",pnpm install 后会自动执行一次构建。

--ignore-workspace 不可省略:插件目录独立于 DSH 仓库的 workspace,否则 pnpm 可能把它当作 workspace 成员处理。


第 2 步:类型检查与构建

目的:确认代码类型正确,并产出 host / client 两个 bundle。

操作:

pnpm typecheck    # 等价于 tsc -p tsconfig.json --noEmit
pnpm build        # 等价于 tsdown

成功判断依据:

  • pnpm typecheck 无任何输出(无错误即成功),退出码 0;

  • pnpm build 输出两个产物且均标记构建完成:

    产物格式说明
    lib/index.jsESMhost 半(含 yaml,node: 内置模块保持 external)
    lib/client.jsCJSclient 半,外包一层 window.__ModuleLoader__.load({...}),由浏览器 loader 加载

    同时会生成对应的 .js.map 文件(sourcemap: true)。

构建配置见 tsdown.config.ts。client 半的 react / react-dom / cordis / @deepseek-ai/dsh-client-* 必须保持 external——打进 bundle 会产生第二份实例,破坏 cordis DI。

本机辅助脚本(可选):如果所在终端对子进程 stdout 捕获不可靠(长输出被截断),可用仓库自带的脚本把结果落盘再查看:

node scripts/check.cjs --file ./tsc-out.txt   # 类型检查结果写入文件
node scripts/build.cjs --file ./build-out.txt # 构建输出写入文件

第 3 步:把插件装进 DSH

目的:让 DSH 在启动时加载本插件。

这里是源码开发场景(link 模式)的装法。普通使用者请改用 快速开始 里的方式 A / B / C(tarball / npm / GitHub),不必 clone 源码。

操作:

dsh plugin --profile web add link:<插件绝对路径>

例如:

dsh plugin --profile web add link:D:/dsharness/deepseek-harness/router/dsh-plugin-webrelay

成功判断依据:

dsh web --dump-config | grep webrelay

输出中应能看到 dsh-webrelay 插件条目(由包内 cordis.patch.yml 的 insert 段注入)。

原理:package.json 的 dsh.bundle.patch 指向 ./cordis.patch.yml,其中定义了:

- insert:
    - id: dsh-webrelay
      name: '@dsh-external/dsh-webrelay'
      config: {}

dsh plugin add 时它会被追加进 dsh.profile.bundles。


第 4 步:初始化配置

目的:生成本地站点配置文件,供你按需调整。

操作:无需手动操作——首次运行时插件会自动把出厂默认 sites.default.yml 复制为 $DSH_HOME/webrelay/sites.yml。之后编辑用户文件即可:

# 路径参考
#   Windows: %USERPROFILE%\.dsh\webrelay\sites.yml
#   macOS / Linux: ~/.dsh/webrelay/sites.yml

成功判断依据:

  • $DSH_HOME/webrelay/sites.yml 文件已存在,且内容与仓库根目录的 sites.default.yml 一致。

要点:

  • 该文件每次读取都重新解析(文件极小),因此改完无需重启 DSH;
  • 解析失败时会回退出厂默认,并把损坏文件重命名为 sites.yml.bak;
  • 除「站点管理 → 恢复全部默认」外,管理界面的操作会以结构化方式写回 YAML,手写注释会被覆盖。

本步可跳过:默认配置开箱可用(DeepSeek 已端到端实测)。需要调选择器或多账户时再看第 6 步与配置说明。


第 5 步:启动 DSH 并验证插件已生效

目的:确认插件在真实运行环境中正常加载。

操作:

dsh web

然后打开 DSH Web UI。

成功判断依据(按顺序核对):

#检查项预期结果
1输入框工具行模型选择器左侧出现 ⚡ 与 🖥 两个按钮
2点击 🖥右侧滑出浏览器面板,顶部有站点页签(DeepSeek / ChatGPT / 豆包 / 通义千问 / Gemini)与「管理」按钮
3面板加载页面选一个页签,iframe 经 /dsh-webrelay/proxy/<rid>/<target> 加载出站点页面
4识别徽章页面加载完成后,面板右上角徽章从「未识别」变为「已识别」
5代理回环命令行执行下方 curl,应返回站点列表 JSON
curl -s http://127.0.0.1:3080/dsh-webrelay/api/sites

返回含 sites 数组的 JSON 即代表 host 侧路由已注册、信任校验通过。

排障提示:

  • 面板提示「站点配置加载失败或为空」→ 检查 $DSH_HOME/webrelay/sites.yml 是否存在且为合法 YAML;
  • 面板提示「所有站点均已隐藏」→ 在「管理」里恢复显示;
  • 页面嵌入失败(盾 / 登录墙 / 站点改版)→ 用面板底部「系统浏览器打开」降级通道。
  • 调试探针:浏览器控制台执行 window.__DSH_WEBRELAY_DEBUG__.getState() / setState(...) 可读写插件状态机。

第 6 步:站点登录与联动浏览器(可选但推荐)

目的:让插件能真正往外部站点自动投放提示词、并抓回回复。内置(relay)模式下你先在面板里登录一次即可;若希望登录态长期保存、且不受你日常浏览器窗口干扰,建议用联动模式。

操作:

  1. 打开面板 →「管理」→ 找到目标站点 → 把「打开方式」切到 联动。
  2. 单击该站点页签。插件会自动启动 / 复用绑定的联动浏览器实例,并以站点地址为初始页打开标签页(不会遗留 about:blank)。
  3. 在弹出的联动浏览器窗口中登录一次——登录态长期保存在 $DSH_HOME/webrelay/browser-profile/<id>,不影响你正在使用的浏览器。

成功判断依据:

  • 联动浏览器窗口弹出并停留在站点登录页 / 对话页;
  • 面板中的联动视图显示「已就绪」状态,并能列出该站点的标签页;
  • 该站点页签对应面板区域显示匹配到的 target,🖥 与 ⚡ 的识别状态为「已识别」。

多浏览器 / 多账户(可选):在「管理」弹窗中「+添加联动浏览器」,每个实例 = 独立进程 + 独立调试端口 + 独立配置子目录;同类型浏览器的多个账户可经 profile(Chrome 账户配置目录名,如 Default / Profile 1,chrome://version 可查)承载。站点经 browser: <实例id> 绑定——例如 DeepSeek 绑 Edge 工作号、ChatGPT 绑 Chrome 主号。

相关配置项:cdp.port(默认实例端口 9222,仅回环)、cdp.browserPath、cdp.headless(无窗口模式,自测用);browsers: 段定义实例表。


第 7 步:跑通两条主流程

流程 A:优化提示词(不发送)
步骤操作成功判断依据
A1在 DSH 输入框写下草稿—
A2点 ⚡ →「✨ 优化提示词(不发送)」弹窗打开,标题「第 1 次优化」,正文流式输出
A3流式结束弹窗进入可编辑态,出现三个按钮:撤回 / 重新生成 / 插入输入框
A4点「插入输入框」优化后的文本写入 DSH 输入框,弹窗关闭,消息未被发送

全过程不发送任何内容给外部站点。

流程 B:与外部 AI 协作优化(双轮闭环)

前置:右侧面板已打开目标站点并处于「已识别」状态(流程 A 的 A2 之后,若未连接,菜单项会显示「🔗 连接外部浏览器」,点击即可自动接入)。

阶段操作成功判断依据
B1输入框写草稿 → 点 ⚡ →「⚡ 与外部 AI 协作优化」弹窗显示「正在压缩对话上下文…」(S1,静默内部步骤)
B2等待第一次优化完成弹窗标题「⚡ 第 1 次优化(待外发)」,右上角显示 目标:<站点名>,正文流式输出,可编辑
B3核对无误后点 「发送到浏览器 →」弹窗切换为「⚡ 正在处理」,显示倒计时(默认上限 120s)。这是整条链路唯一一次对外写入
B4等待外部 AI 回复完成自动进入「✨ 第 2 次优化(终稿)」,标题栏提示已吸收外部回复的字符数
B5需要时点「查看外部回复」打开原始回复弹窗,可查看 / 复制 / 保存存档
B6点「插入输入框」终稿(去掉引导语前缀后的正文)写入 DSH 输入框,不自动发送

超时分支(B3/B4 等待超过 optimize.relayTimeoutMs):

  • 弹窗转为「⏱ 等待超时」,提供三个动作:撤回 / 继续等待(只读重读页面,不重发)/ 采用已抓内容 →(用已捕获的部分内容直接走终稿优化)。
  • 超时不判失败,不会在外部站点留下重复消息。

任一步都可撤回:点「撤回」即丢弃,不写不存。


第 8 步:卸载与升级

卸载:

dsh plugin --profile web remove @dsh-external/dsh-webrelay

成功判断依据:dsh web --dump-config | grep webrelay 不再输出插件条目。

$DSH_HOME/webrelay/(用户配置 + 捕获存档 + 浏览器配置目录)会保留,便于重装后延续。彻底清除请手动删除该目录。

升级(link 模式):拉取新代码后在插件目录重新构建,重启 dsh web 即可:

pnpm install --ignore-workspace
pnpm build

第 9 步:发布与部署(可选)

本插件是本地插件:走 link:(开发)或 方式 A 的 tarball 即可使用,不发布到 npm 也能分发。

给外部使用者时,按目标环境选一条:

目标做法
免发布、免审批pnpm pack 出 .tgz 交给对方(方式 A)
有 npm 发布条件发布到 registry,对方 add @dsh-external/dsh-webrelay(方式 B)
直接指向仓库对方 add github:Baisbt/dsh-plugin-webrelay,需放行构建脚本(方式 C)

package.json#files 已声明打包白名单:

lib / sites.default.yml / cordis.patch.yml / README.md / LICENSE

即 pnpm pack 产出的 tarball 只含构建产物与配置模板,不含源码(src/ 不在其中)。

白名单中的 LICENSE 已随仓库提供(MIT,见仓库根目录 LICENSE)。


配置说明

用户配置文件为 $DSH_HOME/webrelay/sites.yml(首次运行自动从 sites.default.yml 复制)。主要配置项:

sites.*:站点定义

键说明
name展示名
home内置浏览器打开的入口地址
match站点识别与代理白名单域名(同时是安全边界,代理只转发白名单内站点)
experimentaltrue = 实验性适配(未端到端实测)
hidden从页签隐藏,但识别与代理仍生效
openIn打开方式:relay(内置 iframe)/ cdp(专用联动浏览器)/ system(当前浏览器新标签页)
browser联动模式绑定的浏览器实例 id(browsers 表的键;null = 默认实例)
adapter.*DOM 适配选择器,全部为候选选择器链,按序取第一个命中的元素

adapter 子项:input(对话输入框)、inputContentEditable(是否 contenteditable)、send(发送按钮候选,可空数组 → 用 Enter 发送)、sendMode(enter / click / enter-then-click)、replies(助手回复节点候选)、generating(生成中标记候选)。

站点改版时改这里即可,无需改代码。

relay.*:反向代理

  • stripHeaders:从上游响应剥离的响应头(解除 iframe 嵌入与脚本限制);
  • injectShim:是否注入运行时 shim(改写 fetch/XHR/EventSource/WebSocket,使 SPA 的同源请求继续走代理);
  • upstreamTimeoutMs:单请求上游超时(默认 60000)。

optimize.*:提示词优化与协作

键默认说明
provider / modelnull优化用模型;null = 自动(client 传入 → 配置 → 第一个可用 provider)
temperature / maxTokens0.4 / 4096采样参数
reasoningEffortoff思考链档位(off / low / high / max);off 可避免推理 token 耗尽 maxTokens
stylepreservepreserve 贴着原文语气做小切口改写(结果自然);structured 允许分节结构化重排
structureHintnull追加给优化器的结构偏好(如「输出必须是 JSON schema」),优先级高于 style
extractProvider / extractModelnull外部回复二次提取(整理)专用模型;null = 沿用上面的设置
extractTemperature0.2整理温度(低于优化温度,倾向忠实还原)
extractMaxTokens8192整理输出的 token 上限
relayTimeoutMs120000等待外部 AI 回复的上限(毫秒);超时不判失败,弹窗可「继续等待」或「采用已抓内容」
contextLimit40上下文压缩读取的对话条数(越大背景越完整、token 消耗越高)

capture.*:捕获存档

  • dir:存档目录;null = $DSH_HOME/webrelay/captures;
  • recentLimit:面板历史默认展示条数(默认 30)。

cdp.* / browsers.*:专用联动浏览器

  • cdp.port(默认 9222,仅回环)/ cdp.browserPath(null = 自动探测 Chrome、Edge)/ cdp.startupTimeoutMs / cdp.headless(默认 false,日常使用建议关闭无头以便正常过站点风控);

  • browsers:联动浏览器实例表,每个实例 = 独立进程 + 独立调试端口 + 独立配置子目录。示例:

    browsers:
      chrome-main: { label: Chrome 主号, type: chrome, profile: Default, port: 9222 }
      edge-work:   { label: Edge 工作号, type: edge, profile: "Profile 1", port: 9223 }
    

站点管理界面

面板头部「管理」按钮打开站点管理弹窗,配置文件路径显性展示,支持:

  • 添加站点:填名称 + 网址即可(域名白名单与 id 自动提取,DOM 适配先用通用候选链,可后续改 YAML 收窄);
  • 排序:↑/↓ 调整页签顺序(写回 YAML,用户层条目优先展示);
  • 隐藏:从页签隐藏但识别与代理仍生效(可随时恢复显示);
  • 打开方式:三档循环切换 内置 / 联动 / 浏览器;
  • 删除:自定义站点直接删除;出厂站点写入 deleted: 列表(可「重置」恢复);
  • 恢复全部默认:整份配置还原为出厂模板(含注释)。

注意:除「恢复全部默认」外,管理操作以结构化方式写回 YAML,文件中的手写注释会被覆盖。

附件提示(只提示,不代传)

有些需求本身依赖某个文件的内容(「按这份配置改一下」「照这个 JSON 写代码」)。优化提示词时,优化器会顺带判断这次是否属于这种情况,若是则在弹窗里显示一条轻量提示:

📎 本次提示词可能需要附件——需要一份 docker-compose.yml 与相关 env 示例 请在外部浏览器里用页面自带的附件按钮上传;本插件不会读取或代传任何文件。

要点:

  • 这只是提示。插件不检测你的磁盘、不扫描目录、不读取任何文件,也不代你上传——零文件操作;
  • 上传请自行使用外部浏览器/宿主页面自带的附件按钮(回形针 📎),传完后照常点「发送到浏览器」;
  • 提示内容由优化器按需判断:不需要附件时整块不渲染,不会每个弹窗都挂一条无用的提示;
  • 插件因此不承担「文件采集与处理」职责——复杂度与维护面都最小化。

附件上传不由本插件承担:站点是否支持附件、附件按钮长什么样,都取决于站点自身。因此 sites.yml 中没有附件控件相关配置。

站点支持矩阵

站点状态说明
DeepSeek端到端实测(UI / 代理 / 识别 / 优化全链路)未登录或站点风控时页面资源可能被其自身拦截,属站点侧行为
ChatGPT适配器已配置,未做账号级实测Cloudflare / 登录墙可能阻止嵌入,用「系统浏览器打开」降级
豆包 / 通义千问 / Gemini实验性选择器为社区公开结构,需按实际页面微调 sites.yml

各站点的对话 / 回复选择器改版后请复核 sites.*.adapter.*。嵌入失败的通用降级:面板底部「系统浏览器打开」按钮。

安全与合规

  • relay 代理仅接受回环请求且要求 Origin 同源;目标域名必须在 match 白名单内——不构成开放代理。
  • Cookie 仅保存在进程内存中的 per-rid jar(8 小时无活动自动回收),重启即清空,不落盘。
  • 向外部 AI 网站的内容操作以用户点击触发为前提。双轮闭环中,「发送到浏览器」是唯一一次对外写入(须你在弹窗里明确点击);此后对页面的全部操作(等待、捕捉回复、续等复查)均为只读。闪电按钮选项一与「优化提示词」全程不发送。
  • 插件不读取你的任何文件:本插件没有读盘逻辑,不存在扫描、枚举或后台读取目录的行为。提示词可能依赖某个文件时,它只会提示你一句(需要哪类材料),实际上传由你在外部浏览器里手动完成。
  • 调试端口仅回环;插件只对 URL 命中站点 match 白名单的标签页执行注入。
  • 用户需自行遵守目标网站的服务条款,风险自担。

架构速览

host 半(relay 反向代理 / 上下文压缩 / 外发与捕捉 / 提示词优化 / 智能体工具)与 client 半(闪电按钮 / 面板 / 弹窗 / 编排与页面读写器)通过 /dsh-webrelay/* 同源路由通信。前端仅使用 additive 槽位(conversation.input.right、shell.overlay),不与宿主或其他插件冲突;卸载后宿主无残留。

侧入口关键模块
hostsrc/index.tsrelay.ts(代理)/ optimize.ts(优化)/ context-compress.ts(压缩)/ extract.ts(整理)/ page-adapter.ts(CDP 表达式)/ cdp.ts(联动浏览器)/ captures.ts(存档)/ tools.ts(智能体工具)
clientsrc/client/index.tslightning.ts(闪电按钮)/ flow.ts(六阶段编排)/ panel.ts(面板)/ modals.ts(弹窗)/ relay-run.ts(iframe 读写器)/ state.ts(store)

host 自有路由(全部 /dsh-webrelay/ 前缀,经信任校验):

路由方法说明
/dsh-webrelay/proxy/<rid>/<target>any反向代理(白名单 + 信任校验)
/dsh-webrelay/api/sitesGET站点列表(含 adapter 选择器)
/dsh-webrelay/api/sites/managePOST站点管理(添加 / 删除 / 隐藏 / 排序 / 重置 / 绑定实例)
/dsh-webrelay/api/optimizePOST提示词优化(流式)
/dsh-webrelay/api/compressPOST对话上下文压缩(流式)
/dsh-webrelay/api/extractPOST抓取内容二次提取整理(流式)
/dsh-webrelay/api/cdp/statusGET联动浏览器与标签页状态
/dsh-webrelay/api/cdp/launchPOST启动 / 复用联动浏览器实例
/dsh-webrelay/api/cdp/openPOST打开 / 激活站点标签页
/dsh-webrelay/api/cdp/capturePOST只读读取联动标签页正文
/dsh-webrelay/api/cdp/closePOST关闭联动标签页
/dsh-webrelay/api/cdp/sendPOST外发并等待回复(唯一写入路由,用户点击触发)
/dsh-webrelay/api/capturesGET / POST列出 / 新增捕获
/dsh-webrelay/api/captures/readGET?file= 读取单条(含路径穿越校验)
/dsh-webrelay/api/contextPOST读取会话全量事件并压成转写

插件没有任何读盘路由:附件只做提示,不做采集与投递。

详细设计见 TECHNICAL.md(技术方案)与 DESIGN.md(产品设计与需求清单)。

已知限制

  • Service Worker 无法经代理注入;部分站点 JS 内硬编码的跨源请求会被 CORS 拦截。
  • DSH 处于 developer preview,客户端快照 / 契约字段均做了防御式访问,但 API 变化仍可能影响功能。
  • system 打开方式(当前浏览器新标签页)下,自动注入与抓取不可用——该模式只适合手动使用。
  • 调试探针:控制台 window.__DSH_WEBRELAY_DEBUG__.getState() / setState() 可读写插件状态机。

许可证

MIT(见 package.json 的 "license" 字段)。

관련 플러그인