dsh-host-adapter-client
Manifest validBrowser-side adapter layer: single source of truth for ctx service/event names in browser bundles, generated from server-side source code.
dsh-host-adapter-client · DSH 客户端适配层(服务名 / 事件名唯一来源)
这是什么
浏览器端适配层:把
ctx的服务名与事件名做成唯一来源,由服务端源码生成。它解决什么
前端插件里手写
'task-board'这种字符串,是"改一处、忘一处、线上静默失效"的经典来源。这里从服务端源码生成常量表,再用一条命令装进 profile,同时给出--verify只读校验 —— 让"名字对不对"变成机器判断,而不是靠人记。一条命令跑起来
npm i -g @kira905/dsh-host-adapter-client dsh-host-adapter-deploy --dry-run # 先看它要改哪三个文件先看它长什么样(真实输出)
用法 dsh-host-adapter-deploy [--dry-run] [--verify] 把本包的客户端适配层装进 web profile:备份三件套 → 复制包文件 → 改 package-map 与 cordis.patch.yml(幂等)。
它不附带什么(先看清楚,省得装完失望)
这套开源出来的是能用的工具 + 装完自检 + 设计文档。有两块不在开源范围里:
- 「自己盯着活干」的那套引擎:定时调度、队列盯守、管家日报、自主决定要不要动手 —— 这几件还没整理出来放(整理完会陆续放)。它的设计本身是公开的,写在
ops-handoff-design仓里,想自己实现的人照着做得到。- 「出事喊到人」的通道:企业微信、语音播报这类 —— 不随开源发布。
所以:装完你拿到的是一套能用的工具,不是一个会自己上班的管家。
本仓是插件(只有客户端半)+ 2 个 bin(
dsh-host-adapter-deploy/dsh-host-adapter-sync);它不走dsh.bundle(插件package.json里那行「让 DSH 启动时自动挂上我」的声明,本仓刻意不写),靠自带的deploy.mjs代劳 —— 由它替你把挂载清单cordis.patch.yml写好 —— 装它 =node deploy.mjs --dry-run先看计划、node deploy.mjs真装(参数表见 §4.1)。 手工insert时注意:现网 profile patch 里写的是裸名 entry name(dsh-host-adapter-client),不是带 scope 的包名 —— 照带 scope 的包名去找会找不到。
装完自检(三条只读验法)
<profile> 换成你实际用的 profile(放插件的那个格子,默认 web),<数据根> 换成你的 DSH 数据根(默认 ~/.dsh)。
# ① 组合树里有没有它(只读、约 0.6 秒、不启服务)
dsh --profile <profile> --dump-config | Select-String "dsh-host-adapter-client"
# 期望:出现一行 "# == <?>",问的是它有没有被挂上(本仓包名 @kira905/dsh-host-adapter-client;带 scope 装的写带 scope 名、
# 老工装 / 手写的可能是裸名 —— 两种都搜一遍),同一个 id 的计数必须 == 1
# ② 组合列表里有没有它(只读)
Get-Content <数据根>/profiles/<profile>/package.json | Select-String "@kira905/dsh-host-adapter-client"
# 期望:**两处都没有是正常的** —— 本包刻意不进 `dependencies` / `dsh.profile.bundles`;
# 它的登记在 <数据根>/profiles/<profile>/node_modules/.package-map.json(deploy.mjs 写)
# ③ 命令在不在 —— 【只查存在,不执行】
Test-Path <数据根>/profiles/<profile>/node_modules/.bin/dsh-host-adapter-deploy.CMD # 装进 profile 的
Test-Path "$env:APPDATA\npm\dsh-host-adapter-deploy.CMD" # npm i -g 装的
# 期望:True。两条路径按你实际用的装法挑一条
探针只做存在性检查(只看命令文件在不在,不执行任何命令)。 要不要用
--help验,见本仓当前说明与该命令的参数表。
浏览器 bundle(
window.__ModuleLoader__.load({id, factory}))物理上引用不到服务端包的lib/host-adapter.mjs。于是各客户端 bundle 里的ctx服务名(webServer/settings/sessions…)与事件名(connection/reset…)只能写成裸字面量 —— 主包一升级, 改点就散在全生态。本包给浏览器侧一个可
require()的常量模块:SVC(服务名)+EV(事件名)+ 版本号, 由服务端唯一源lib/host-adapter.mjs生成(不是手抄),带sourceSha256头, 可幂等重生成、可校验同源。
⚠️ 先读这段(比任何用法都重要)
- 这是一个 DSH 插件包,不是命令行工具。 装进 web profile 后由宿主 cordis loader 加载;
必须做 patch insert(
cordis.patch.yml加一条insert),否则客户端面不进 boot graph。 本仓的deploy.mjs会自动做这件事(也支持--verify只读核对)。 - 插件登记 id = 包名 =
@kira905/dsh-host-adapter-client。 历史教训:__ModuleLoader__.load({id})的 id 与包名不一致时,HTTP 200 但插件不挂载 (宿主按包名索引客户端模块表)。 lib/host-adapter.js与lib/host-adapter.d.ts是生成产物,别手改。 改了会在下次sync-client-host-adapter.mjs时被覆盖,--verify也会判红。- 三个脚本的未知参数处理不一致(详见 §4):
deploy.mjs:有参数白名单(未知参数 ⇒ 退出码 2,不写盘)—— 安全。sync-client-host-adapter.mjs:KNOWN白名单,未知参数会被忽略但只做"生成/校验", 最坏是写产物文件(本仓内的两个文件),不会碰 profile。- 两者都实现了
-h/--help;本文件不在代码块里给帮助示例(参数表在 §4)。
1. 它解决什么问题
DSH 主包的事件名 / 服务名会随版本变(删事件、改语义、换粒度)。把字面量散落在 N 个自研包里, 升级时改点随功能数增长。本包把这件事收口成:
- 唯一源:
lib/host-adapter.mjs(纯函数、零依赖、零 IO,SVC+EV+HOST_ADAPTER_VERSION) - 派生产物:
lib/host-adapter.js(浏览器 bundle)+lib/host-adapter.d.ts(类型声明) - 生成器:
sync-client-host-adapter.mjs(幂等;头里带sourceSha256) - 部署器:
deploy.mjs(把包装进 web profile + 加cordis.patch.ymlinsert + 三重门禁)
消费方(其它客户端 bundle):
const A = require('@kira905/dsh-host-adapter-client')
const inject = [A.SVC.slots, A.SVC.locale]
ctx.on(A.EV.CONNECTION_RESET, handler)
消费方的
package.json必须在dsh.client.external里声明本包 —— 宿主按它排序 boot graph (依赖先 register),否则同步require()会 MISS 模块表。
同源说明
本仓部分文件与一套内部生产实现同源(同一份工程长期演进下来的两处落点)。
- 同源程度:按行级同源度口径统计(同名可比件里,仓内文件的非空行有多少能在参照件中找到,多重集扣减),本仓「≥50% 行同占比」= 100%。
- 这意味着:本仓是那套实现的提炼导出 —— 既不是逐字副本,也不是完全重写的独立实现。拿单个文件当"独立参考实现"读之前,请先跑下面的判据。
- 怎么复跑:同源度扫描器见
dsh-quality-toolkit的dsh-sim-scan.mjs(--repo <本仓> --prod-root <参照根>);分档阈值与口径写在它的config/sim-scan.json里,不藏在代码里。 - 许可:本仓许可见仓根
LICENSE(有子树例外时以子树LICENSE为准)。
2. 仓库结构(全量文件)
dsh-host-adapter-client/
├── deploy.mjs # 装进 web profile(幂等;门禁①逃逸 import ②产物同源 ③语法)
├── sync-client-host-adapter.mjs # 生成器:唯一源 → host-adapter.js + .d.ts(幂等 + --verify)
├── lib/
│ ├── index.js # host 半:空插件(inject=[] / apply(){}),只把本包塞进 boot graph
│ ├── host-adapter.js # 生成产物:浏览器 bundle(loader id = 包名)
│ ├── host-adapter.d.ts # 生成产物:类型声明
│ ├── host-adapter.mjs # **唯一源**:SVC / EV / 版本(纯函数、零依赖、零 IO)
│ ├── dsh-home.mjs # DSH home / web profile 目录解析(环境变量优先)
│ └── deploy-guard.mjs # 部署门禁共享件(参数白名单 / 逃逸 import 扫描 / 冒烟 import)
├── README.md
├── README.en.md
├── CHANGELOG.md
├── LICENSE
├── package.json
├── .gitignore
└── .gitattributes
3. 装法(两条路,都需要 patch insert)
3.1 推荐:用 deploy.mjs
# 只读核对:实体 vs 源码(不写盘)
node deploy.mjs --verify
# 预演:打印将写入的文件与 patch 片段(不写盘)
node deploy.mjs --dry-run
# 真装(会先备份 profile 的三份声明文件 + 既有实体目录)
node deploy.mjs
# 装进隔离环境(不碰生产 profile)
$env:DSH_HOME = '<你的测试 home>'; node deploy.mjs
它做三件事:
- 备份 profile 的
package.json/.package-map.json/cordis.patch.yml(+ 既有实体目录); - 复制
package.json+lib/{index.js,host-adapter.js,host-adapter.d.ts}到<DSH_HOME>/profiles/web/node_modules/@kira905/dsh-host-adapter-client/; .package-map.json加packages条目;cordis.patch.yml追加insert(- id: "@kira905/dsh-host-adapter-client";已存在则跳过)。
不进 profile.bundles、不改 profile.dependencies —— client 插件进 bundles 会崩
"declares no dsh.bundle"。
3.2 手工装(不想跑部署脚本时)
- 把整个包目录拷到
<DSH_HOME>/profiles/web/node_modules/@kira905/dsh-host-adapter-client/; - 在
<DSH_HOME>/profiles/web/node_modules/.package-map.json的packages里加:"@kira905/dsh-host-adapter-client": { "url": "./@kira905/dsh-host-adapter-client", "dependencies": {} }; - 在
<DSH_HOME>/profiles/web/cordis.patch.yml追加:
- insert:
- id: "@kira905/dsh-host-adapter-client"
name: '@kira905/dsh-host-adapter-client'
- 重启 DSH(插件入口在 boot 期加载)。
4. 命令(唯一权威参数表)
4.1 deploy.mjs —— 装进 web profile
| 参数 | 说明 |
|---|---|
| (无参数) | 装进当前 DSH_HOME(默认 ~/.dsh = 生产) |
--dry-run | 只打印计划,不写任何文件 |
--verify | 只读:逐文件比对「实体 vs 源码」 |
--help / -h | 用法 |
- 参数白名单:未知参数 ⇒ 退出码
2,不写盘(这是 2026-09-16 事故后立的规矩)。 - 退出码:
0通过 ·1门禁未过或部署失败 ·2用法/参数错误。 - 门禁(全部在写操作之前):①
lib/里解析后逃出插件目录的相对 import; ② 生成产物与唯一源同源;③ 源文件node --check。
4.2 sync-client-host-adapter.mjs —— 生成产物
| 参数 | 说明 |
|---|---|
| (无参数) | 生成(幂等:内容相同即跳过),写 lib/host-adapter.js + lib/host-adapter.d.ts |
--dry-run | 预览要写的文件与 sha |
--verify | 只校验不写;不一致 ⇒ 退出码 1 |
--self-test | 自检(临时目录里的假唯一源 + 内存字符串,零生产写入) |
--help / -h | 用法 |
未知参数会被忽略(
KNOWN数组只用于帮助文本)—— 但它只会写本仓两个产物文件,不碰 profile。
5. 环境变量
| 变量 | 含义 | 缺省 |
|---|---|---|
DSH_HOME | DSH home(profiles/web/ 在其下) | ~/.dsh |
BUTLER_DSH_HOME | 同上的更高优先级覆盖(测试环境用) | 未设 |
6. 已知限制
- 只做常量收口,不做行为适配:本包不提供"事件语义差异"的兼容层(那属服务端适配层)。
dsh.profile.bundles为空(刻意):本包是 client 插件,必须走cordis.patch.yml的insert,进 bundles 会崩。- 产物必须随唯一源重生成:改了
lib/host-adapter.mjs之后要跑生成器,否则--verify红。 - 包名带 scope ⇒ 文件路径是
node_modules/@kira905/dsh-host-adapter-client/(多一层目录); 老布局(裸名)的 profile 需要重新部署。 - 未在真实宿主上验证挂载(本仓发布的是源码与生成器,不含运行时实测记录)。
7. 许可
AGPL-3.0 + 商业授权(双许可),全文见 LICENSE。
个人 / 学习 / 开源项目:按 AGPL-3.0 自由使用与修改(衍生作品须同样开源)。 闭源 / 商业场景:需另行获取商业授权 —— 请通过本仓 Issue 联系。
AGPL-3.0 本身不禁止商用,它要求的是衍生作品同样开源; 「+ 商业授权」= 双许可(要么按 AGPL 开源、要么买商业授权)。
8. 相关仓
dsh-butler-archive · dsh-diagnostics-extra · dsh-quality-toolkit · dsh-ops-toolkit ·
dsh-board-toolkit · dsh-memory-toolkit · dsh-imgtmpl · dsh-gongwen ·
dsh-api-balance-folded · dsh-notekit(GitHub / Gitee 同名)。
Comments
Loading…
Similar plugins
by lyp88997
自建 DSH 浏览器服务:单例 CDP 守护 + DSH ctx.browser provider + 兼容 dsh-univer-office 的可执行包装(非 root 服务器环境)
★ 0
MIT
JavaScript
Oct 3, 2026
dsh plugin --profile web add dsh-browser-serviceby flymysql
DSH host-side bridge for the DSH Browser Client extension: a token-authenticated /ext-api RPC proxy + /ext-events.mux WebSocket event stream + bidirectional /ext-api-control channel, so a browser extension page (which cannot pass the same-origin /api trust fence) can drive the harness from a floating panel and operate the current page via page_* tools.
★ 0
MIT
JavaScript
Sep 21, 2026
dsh plugin --profile web add dsh-browser-hostby zou-hong-run
一个 DeepSeek Harness 插件:在 ctx.web seam 上注册网页搜索和网页抓取两个 provider,后端使用 DeepSeek 原生的 Search / Fetch JSON API。 它接入 harness,而不是自带模型工具:模型侧 web_search / web_fetch 的 schema、provider 选择与结果渲染仍由 dsh-tool-web 负责;本
★ 4
↓ 235/wk
MIT
JavaScript
Oct 31, 2026
dsh plugin --profile web add dsh-deepseek-searchby whitefirer
dsh(DeepSeek Harness)插件:让 agent 读写浏览器所在机器的本地文件——File System Access 授权 + WS 中继,含非安全上下文兼容模式
★ 4
↓ 150/wk
MIT
JavaScript
Aug 23, 2026
dsh plugin --profile web add dsh-browser-fsby zengxiaolou
Annotation browser in the DSH sidebar: a real Chrome page streamed over CDP with input forwarded, where picking an element or selecting text attaches its source location, component stack, styles and a
★ 1
MIT
JavaScript
Oct 26, 2026
dsh plugin --profile web add dsh-annotate-browserby drscrewdriver
DSH 浏览器插件(原 dsh-ego-browser):让 Agent 通过 CDP 接入真实 Chrome —— 远程目标序列与激活、实时视频/截图回传、登录导入。Remote-CDP agent browser for DeepSeek Harness.
★ 31
↓ 11.4k/wk
NOASSERTION
TypeScript
Nov 10, 2026
dsh plugin --profile web add dsh-browser-cdp