【免费下载链接】dsh-ads
把 DSH 变成 2005 年门户网站|Parody ads, fake games, and popups for the DSH Web UI
dsh-ads是把 DSH(DeepSeek Harness)变成 2005 年门户网站的 DSH 广告插件。它的架构精髓在于Node 端与浏览器端彻底分离:一半跑在宿主服务器进程里、只负责"发现与缓存",另一半跑在浏览器里、只负责"渲染广告",两者之间只用两根 HTTP 路由传数据。看懂这套"双入口 + cordis 补丁"的设计,你就能明白一个 DSH 插件是如何被完整装进一个 profile 的。
先看懂整体:一个插件,两个"半身"
dsh-ads不是一坨代码,而是两个能独立加载的入口,各自只干自己擅长的事:
- Node 端(服务器半身):运行在 DSH 的 Web 宿主进程里。它不画任何像素,只向宿主的 HTTP 服务器注册两条路由,并在后台搜索 GitHub 的
dsh-plugintopic、做缓存与降级。 - 浏览器端(浏览器半身):运行在用户的页面里。它注册三个 UI 插槽,把浮动广告、推理中途门、对话内广告"挂"进会话,并按语言热切换整套素材。
两半之间的"线"只有一根——src/protocol.ts 里定义的两条路由和它们的数据结构。
Node 端:只干两件事,注册两条路由 🪝
Node 端的入口是 src/index.ts,构建产物是 lib/index.js。它对宿主只声明了一个能力注入:
export const inject = ['webServer']然后在apply()里,通过ctx.webServer.register(...)把两条"精确路由"挂到宿主 Web 服务器上:
| 路由 | 路径 | 提供什么 |
|---|---|---|
| 赞助清单 | /dsh-ads/registry.json | 带dsh-plugintopic 的社区插件列表(已过滤、已截断) |
| 星检测 | /dsh-ads/star-check.json | 宿主自己那个 GitHub 账号有没有 star 本插件 |
它的几个设计点很值得学:
- 动态层才有 Node 端存在的意义。内置横幅是烤进浏览器包的,根本不需要宿主;只有"给真实社区插件打广告"这一层,才需要宿主去搜 GitHub。
- 多级降级链。清单发现走
loadRegistry():先用认证过的ghCLI,再用环境变量 token,再退回 GitHub 匿名公共 API,最后落到一份内置快照——保证"离线、被限流、没凭据"都不断广告。 - 缓存 + 并发合并。清单默认缓存 30 分钟(
cacheMinutes),同时用inflight把并发请求合并,避免多个会话同时打开时各自 shell out 一次gh;星检测则"一旦看到 star 就进程内记住,没看到不记",方便"先 star 再点重新检测"。
浏览器端:三个插槽,把广告"挂"进会话 🧩
浏览器端入口是 src/client/index.tsx,产物 lib/client.js。它注入['slots', 'locale'],在apply()里注册三种性质完全不同的挂载点:
| 插槽 | 作用 | 对应组件 |
|---|---|---|
conversation.input.dock | 挂载浮动广告层 + 推理中途门(零行内占位,全部走 Portal) | AdDockEntry |
settings.section | 设置面板里多一页"广告(非官方)"开关 | AdsSectionEntry |
conversation.chat.turnTail | 把广告插进对话正文,而非浮在上面 | InlineAdEntry |
推理中途门("流式回答时假装暂停 inference"的彩蛋)就挂在 dock 上:
广告开关则单独成页,而不是藏在会消失的海报里:
一个关键细节:这三个入口都从ctx.locale这个observable读语言,所以切换 DSH「设置 → 语言」时,当前页面立即换掉整套素材、文案和交互,不用刷新。
两者之间只走一根线:protocol 路由与数据流 📡
两半不共享任何运行内存,唯一的契约是 src/protocol.ts:
REGISTRY_ROUTE = '/dsh-ads/registry.json'、STAR_ROUTE = '/dsh-ads/star-check.json'RegistryPayload(source标记来自gh-cli / github-token / github-public / snapshot)、StarCheckPayload(starred / absent / unavailable)
浏览器端在 src/client/registry.ts 里每次页面加载只 fetch 一次(模块级共享 Promise),拿到清单后"一份清单、两处投放":侧栏 gutter 取轮播子集(中文 8 个 / 英文 3 个),对话内 feed 拿完整列表做公平轮转(见 src/client/feed.ts,"最少被看到的先上")。星检测同理:浏览器先问 Node 路由,unavailable就退回匿名翻页 stargazers(src/client/star-check.ts)。
| 数据 | 谁产生 | 谁消费 | 走哪条路由 |
|---|---|---|---|
| 社区插件清单 | Node 端catalog.ts | 浏览器端registry.ts | /dsh-ads/registry.json |
| 星状态 | Node 端star-host.ts | 浏览器端star-check.ts回退 | /dsh-ads/star-check.json |
降级是优雅且正确的:浏览器端拿不到路由(比如 TUI、ACP、headless 这种没有 Web 宿主的场景),fetchPlugins()直接吞掉错误返回空列表——内置横幅照常,只是少了动态那一层。
cordis 补丁与双入口注入:插件如何被装进 DSH 🔌
这部分是"插件怎么被加载"的关键,答案在 package.json 与 cordis.patch.yml。
1)cordis 补丁(bundle 级注入)
cordis.patch.yml 只有一小段,作用是把本插件插入某个 profile 的layer 栈:
- insert: - id: dsh-ads name: '@nagi-ovo/dsh-ads'它由package.json的dsh.bundle.patch指向。这就是"cordis 补丁"——在打包/装配阶段声明"把dsh-ads这一层加进去"。
2)双入口(exports 级注入)
package.json的exports同时暴露了两个入口,分别给两种运行环境:
| 入口 | 指向 | 跑在哪 | apply签名 |
|---|---|---|---|
. | lib/index.js | Node 宿主 | apply(ctx: HostContext, config?) |
./client | lib/client.js | 浏览器 | apply(ctx: ClientContext) |
3)客户端额外注入(dsh.client)
dsh.client.platform: "web"标记这是 Web 客户端插件;dsh.client.inject: ['@deepseek-ai/dsh-client-locale']再把语言包一起注入进浏览器端——这正是上面"locale 热切换"能用的前提。
4)构建怎么产出这两个入口
tsdown.config.ts 定义了两个构建任务:
- Node 半:
src/index.ts→lib/index.js,ESM、platform: node、带.d.ts,框架包(cordis、schemastery)保持neverBundle外部。 - 浏览器半:
src/client/index.tsx→lib/client.js,CJS、platform: browser,把平台模块表保持外部、其余(含 base64 内联的素材)全部打进单文件,并用window.__ModuleLoader__.load({ id, factory })包一层,供 DSH Web 壳的模块加载器在/plugins/<id>/client.js处执行。
小结:一张表看懂"双半身 + 补丁 + 双入口"
| 维度 | Node 端 | 浏览器端 |
|---|---|---|
| 入口文件 | src/index.ts → lib/index.js | src/client/index.tsx → lib/client.js |
| 导出格式 | ESM | CJS(__ModuleLoader__包装) |
| 注入能力 | webServer | slots、locale |
| 核心职责 | 注册两条路由、发现与缓存 | 三个插槽渲染广告、拉取路由 |
| 缺失时降级 | 无动态层,内置广告照常 | 无广告层(TUI/ACP/headless 正确降级) |
| 装配方式 | dsh.bundle.patch+ exports. | dsh.client.*+ exports./client |
一句话记忆:Node 端管"从哪来"(发现 + 缓存),浏览器端管"长什么样"(渲染 + 热切换),protocol.ts是它们之间唯一的线,cordis.patch.yml负责把插件插进 profile,exports的两个入口则分别交给服务器和浏览器去加载。想动手看代码,建议从 src/protocol.ts 这条"线"入手,再分头读两半的apply(),最后对照 tsdown.config.ts 理解产物是怎么被分别生成的。
【免费下载链接】dsh-ads
把 DSH 变成 2005 年门户网站|Parody ads, fake games, and popups for the DSH Web UI
相关推荐
深入解析 Firefox Send 前端应用层 app/:双端入口、choo 路由与浏览器端加密架构
深入解析 Firefox Send 前端应用层 app/:双端入口、choo 路由与浏览器端加密架构 导读 本文以仓库 app/readme.md https:
后端前端协程与Flow在MVVMLin中的应用:响应式编程最佳实践
协程与Flow在MVVMLin中的应用:响应式编程最佳实践 MVVMLin是一个基于MVVM架构用Kotlin+Retrofit+协程+Viewbinding+
OCLP-Mod 补丁机制全解析:OpenCore 设置、注入 Kext 与磁盘补丁的完整实现指南
OCLP Mod 补丁机制全解析:OpenCore 设置、注入 Kext 与磁盘补丁的完整实现指南 导读 本文以 OCLP Mod 仓库的官方补丁说明文档( d
操作系统驱动开发固件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考