dsh-deepseek-web
Verified@dpharness/dsh-deepseek-web · v0.3.0 · MIT · Web UI
网页版 AI 一键入口:点击侧边栏按钮弹出站点选择弹窗(六站图标网格),选中即在右侧边栏浏览器 tab 里打开 DeepSeek / Kimi / 豆包 / 腾讯元宝 / 通义千问 / 智谱清言的免费网页版(走 Electron webview,不受 CSP frame-ancestors 限制)。站点列表在 lib/client.js 的 SITES 常量里,可自由增删。
Install
dsh plugin add @dpharness/dsh-deepseek-web Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Readme
dsh-deepseek-web — 网页版 AI 一键入口
在 DeepSeek Harness 桌面版的侧边栏底部加一个 「网页版 AI」 按钮:点一下弹出居中的站点选择弹窗 (六站品牌图标网格),选中哪家就在右侧边栏的浏览器 tab 里打开它的免费网页版,和当前会话并排。
默认六站:DeepSeek 网页版 · Kimi · 豆包 · 腾讯元宝 · 通义千问 · 智谱清言(可自由增删,见下)。
动机:简单问题不想走 API 计费,但又不想每次手动开浏览器、找网址、切窗口。
英文速览见 English quickstart。
为什么不是 iframe
| 方案 | 结论 |
|---|---|
把网页版 <iframe> 嵌进 GUI |
❌ 不可行。chat.deepseek.com 等站点响应头带 content-security-policy: frame-ancestors 'none',浏览器会拒绝渲染 |
| 反向代理剥掉 CSP | ⚠️ 能绕过,但要自己处理登录、WAF(HWWAFSESID)、SSE 流、证书与资源改写,脆且慢 |
| 用 DSH 桌面版自带的右侧栏浏览器面板 | ✅ 采用。它用 Electron <webview>(独立 Chromium guest)承载页面,frame-ancestors 对 guest 不生效;本插件只负责省掉「每次手输网址」 |
面板本体是 DSH 内置插件 @deepseek-ai/dsh-client-ui-sidebar-browser(desktop profile 默认启用)。
本包只做一件事——调用它的公开入口:
ctx.sidebarRight.openTab("browser", { params: { url: "https://chat.deepseek.com" } })
打开失败时(非桌面端、右侧栏服务不可用)自动退回 window.open,桌面端由主进程
setWindowOpenHandler → shell.openExternal 转给系统浏览器,不会「点了没反应」——
而且回退时带的是你选中的那一站,不是写死的默认站。
站点列表
站点就是 lib/client.js 顶部的 SITES 常量,整个配置面就这一个数组,
顺序 = 菜单顺序,第一项是默认站点。加一站就追加一行:
const SITES = [
{ id: "deepseek", label: "DeepSeek 网页版", url: "https://chat.deepseek.com" },
// { id: "chatgpt", label: "ChatGPT", url: "https://chatgpt.com" },
];
已收录站点的本机探活结果(Chrome UA,curl 层):
| 站点 | 结果 | 站点 | 结果 | |
|---|---|---|---|---|
| chat.deepseek.com | 200 | doubao.com | 200 | |
| kimi.com | 200 | yuanbao.tencent.com | 200 | |
| www.qianwen.com | 200 | chatglm.cn | 200 | |
| chatgpt.com | 403 | claude.ai | 403 | |
| perplexity.ai | 403 |
千问有两个互不相通的站:
www.qianwen.com是国内版(中文,阿里「千问」),chat.qwen.ai是国际版 Qwen(英文界面、独立账号体系)。本插件用国内版;tongyi.com/tongyi.aliyun.com现在都 301 到qianwen.com。
403 别急着下结论:那是 curl 撞上 Cloudflare 机器人拦截,不代表浏览器里打不开。 ChatGPT / Claude / Gemini 默认在代码里注释掉了,用之前请在面板里实测后自行放开。
图标
菜单里每一站显示的是各家的品牌图标,以 data URI 内联在 lib/client.js 的
ICONS 常量里——不热链、不发额外请求、离线可用:
- DeepSeek 用官方
favicon.svg(单色#4D6BFE),其余五站用各家 favicon 归一化成 48×48 PNG8(每张 0.8–1.6 KB); - 图标版权归各家所有,此处仅用于标识对应服务;
ICONS里没有条目的站点自动退回通用地球图标,所以新加站点不配图标也不会缺图—— 想换成品牌图标,往ICONS里补一条"站点 id": "data:image/png;base64,…"即可。
站点侧的硬限制
guest 的权限请求、下载、原生弹窗全被拒绝(http/https 弹窗会被转开成新的 sidebar tab)。
- 用 Google / Apple 账号第三方登录的站点(ChatGPT、Gemini 常见)可能卡在 OAuth 流程;
- 少数站点会识别 Electron UA 而给出不同的页面;
- 这些都不影响「已经登录过的站点」——它们靠的是 guest 自己的会话 Cookie。
要求
- DeepSeek Harness 桌面版(Electron),使用
desktopprofile; - 内置的右侧栏浏览器面板可用(桌面版默认启用,无需单独安装)。
已验证环境:macOS + DSH 桌面版 + desktop profile。Web profile 下右侧栏浏览器用的是
<iframe sandbox=...>,frame-ancestors 'none' 依然生效,因此这个入口在纯 Web profile 里
只会走系统浏览器回退路径。
安装
方式一:npm 包(推荐,装完即可升级)
dsh plugin --profile desktop add @dpharness/dsh-deepseek-web
包名是 scoped 的
@dpharness/dsh-deepseek-web。不要装 npm 上的dsh-deepseek-web—— 那个同名包属于另一位作者(y-wi),与本项目无关,功能也不同。
方式二:从仓库挂本地目录(改代码时用)
git clone https://github.com/zhanghao3693/dsh-deepseek-web.git ~/Documents/dsh-deepseek-web
bash ~/Documents/dsh-deepseek-web/install.sh # 默认 desktop profile
# bash ~/Documents/dsh-deepseek-web/install.sh web # 或指定 profile 名
脚本幂等,做三件事:建 symlink → 补 profile 的 dependencies + dsh.profile.bundles → 打印重启提示。
然后需要重启一次 DSH 宿主(点左侧栏底部的「重启」按钮,或重开应用),生效后左侧栏底部出现「网页版 AI」。
⚠️ 2026-10-17 起包名由
dsh-deepseek-web改为@dpharness/dsh-deepseek-web(原名在 npm 上被占用)。 从旧版升级时,请把 profilepackage.json的dependencies与dsh.profile.bundles里的 旧键删掉,再按上面任一方式安装;否则会重复挂载。
⚠️ 改名时还必须同步三处运行时标识,否则按钮会静默消失(host 行还在、控制台无报错):
cordis.patch.yml里insert行的name—— 这不是随便起的标签,而是 Loader 行名,@deepseek-ai/dsh-client-modules的nearestPackage()用「行名 === package.json 的name」 判定包归属,对不上就返回undefined→resolveMeta()返回null→ client 半边被静默丢弃。lib/client.js顶部的window.__ModuleLoader__.load({ id })。- 同一文件里
<style>的data-plugin(HMR 按它回收样式,留着旧 id 会积下僵尸<style>)。
host 侧的挂载行由本包自带的 cordis.patch.yml 通过 dsh.bundle.patch 提供,
不要再往 profile 自己的 cordis.patch.yml 里写 insert(会重复挂载出两个按钮)。
卸载
PKG="$HOME/.dsh/profiles/desktop/package.json"
# 1. 从 $PKG 的 dependencies 与 dsh.profile.bundles 里删掉 "@dpharness/dsh-deepseek-web"
# (若从旧版升级,旧键 "dsh-deepseek-web" 也要删)
# 2. rm "$HOME/.dsh/profiles/desktop/node_modules/@dpharness/dsh-deepseek-web"
# 3. 重启 DSH
已知代价
- 登录不跨应用重启保留。 桌面版给这个面板分配的存储分区是
dsh-sidebar-browser-${randomUUID()}(进程内创建、没有persist:前缀),Cookie 只活在本次进程里。 每次重启 DeepSeek Harness 后需要重新登录一次。好消息是 tab 的标题/URL 会被保存, 重启后点「恢复」即可,不用重输网址。 - 面板里是真正的网页版,没有 API:DSH 的模型路由无法自动把「简单问题」转发过去。
这条入口是给手动问免费问题时用的;要做 API 侧的分流请走
@deepseek-ai/dsh-llm-pi-ai的路由配置。
文件
| 文件 | 作用 |
|---|---|
lib/index.js |
host 半边(stub:name + 空 apply),cordis loader 需要一个服务端入口 |
lib/client.js |
浏览器半边:SITES 站点表 + ICONS 品牌图标表 + 注册 sidebar.footer.action 槽位的入口按钮(id: deepseek-web,order: 15),点击弹出宿主管家 Modal 站点选择弹窗 |
cordis.patch.yml |
bundle patch:insert: [{ id: deepseek-web, name: "@dpharness/dsh-deepseek-web" }](name 必须与 package.json 的 name 逐字相等) |
locale/zh.json / locale/en.json |
插件说明书元信息(供插件清单类界面读取) |
install.sh |
装/校验 profile 挂载 |
关键常量(排障用)
- 浏览器页类型 kind:
"browser"(BROWSER_KIND,见@deepseek-ai/dsh-client-ui-sidebar-browser/lib/client.js) - 传参形状:
tab.navigation.params.url - 槽位:
sidebar.footer.action(list;注册字段id/order/label,渲染 props{ t, wide }) - 入口 id:
deepseek-web;order15(夹在dpharness= 12 与restart= 20 之间) sidebarRight服务故意不写进inject,改为惰性解析:服务缺失时只回退,不会让插件永久 pending(dsh-locale-fallback曾因声明了缺失的 inject 把整个 boot 拖挂)- 站点图标:
siteIcon(site, size)先查ICONS[site.id](data URI → 内联<img className="dswb_icon">), 没有才走「通用图标」解析链IconNewChatOutlineRegular→...Medium→...20→IconGlobeOutline*→...Medium→...14;整条链全都没有时返回null而不是undefined——渲染期抛错会被 slot 的 错误边界吃掉,表现为「按钮静默消失」 - 展开态用
useState;点按钮时优先渲染宿主管家Modal(@deepseek-ai/dsh-client-ui-primitives, portal 到 body、mask 点击与 Escape 自动关闭、aria-modal),弹窗内是 3 列图标卡片网格。 宿主没导出Modal时自动退回内联下拉菜单,那条回退路径才需要自己挂documentcapture 阶段的 click 监听与 Escape 处理
变更记录
- 0.3.0 — 站点选择从内联下拉菜单改为居中 Modal 弹窗(宿主管家组件,3 列图标网格);
千问改用国内版
www.qianwen.com;修正改名后 client 半边静默丢失(按钮消失)。 - 0.2.1 — 包名改为 scoped
@dpharness/dsh-deepseek-web。 - 0.2.0 — 单站入口泛化为六站清单;站点菜单改用各家品牌图标(内联 data URI)。
- 0.1.0 — 首个版本:DeepSeek 网页版一键入口。
English quickstart
A one-click multi-site entry for DeepSeek Harness Desktop: it opens a free web AI chat (DeepSeek / Kimi / Doubao / Yuanbao / Qwen / ChatGLM) inside DSH's built-in right-sidebar browser panel, side by side with your current session.
- The built-in panel (
@deepseek-ai/dsh-client-ui-sidebar-browser, enabled by default in thedesktopprofile) renders pages in an Electron<webview>— an isolated Chromium guest — socontent-security-policy: frame-ancestors 'none'does not apply (it only blocks<iframe>embedding). - This package just calls the panel's public API:
ctx.sidebarRight.openTab("browser", { params: { url } }), falling back towindow.openwhen the sidebar service is unavailable. - The site list is the
SITESarray at the top oflib/client.js. - Each site shows its own brand icon, inlined as a data URI in the
ICONSmap of the same file — no hotlinking, no extra requests, works offline; a site with noICONSentry falls back to a generic globe glyph.
# npm(推荐)
dsh plugin --profile desktop add @dpharness/dsh-deepseek-web
# 或从仓库挂本地目录
git clone https://github.com/zhanghao3693/dsh-deepseek-web.git ~/Documents/dsh-deepseek-web
bash ~/Documents/dsh-deepseek-web/install.sh
# then restart the DSH host (restart button at the sidebar foot, or relaunch the app)
Caveats: cookies for that panel live in an in-memory partition
(dsh-sidebar-browser-${randomUUID()}), so you must log in again after each app restart; guest
permission requests, downloads and native popups are denied (http/https popups become new sidebar
tabs), so OAuth-via-popup logins may not complete. It is the real web app, with no API — DSH's
model router cannot dispatch to it automatically.
License
MIT — 见 LICENSE。