dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
模型速选器:在模型下拉框左侧添加按钮,弹出全量模型选择窗口(提供商分组、实时搜索、提供商筛选、读取用户配置的真实能力标签、推理徽章、最近使用与推理档位选择器),选中后立即回写原生下拉框并生效。
在 DeepSeek Harness 会话窗口右下角 模型下拉框的左侧 添加一个小按钮。
点击按钮弹出全量模型选择窗口:按提供商分组、实时搜索、提供商筛选、
真实能力标签、推理徽章、当前选中高亮,加载 / 失败 / 会话占用等状态都有清晰呈现。
选择模型后立即回写模型下拉框并生效 —— 因为它与原生下拉框共用同一条
per-session 模型目录与 selectModel 提交路径("任一端切换,另一端立刻显示")。


提供商 · 模型(如 火山方舟 · deepseek-v4-flash-ga),
点一下即切回常用模型;<select>,避免深色主题下系统面板惨白);行内的 📝 文本 / 🖼️ 图像 标签不是从模型描述文字里猜的,而是读
用户自己配置里声明的 input 列表(pi-ai 提供商配置,如
providers.<id>.models[].input: [text, image])。实现走 DSH 已有的
settings Remote 读取 settings 文档,扫描各命名空间的 providers → models[].input
建索引;配置里没写 input 的提供商就不显示标签(如实反映配置,不做臆测)。
增删配置里的 input,标签随之变化。
契约说明(已验证):能力标签用
group.id查询索引,而group.id与 settings 中providers的配置 key 同命名空间(DSH 的 modelCatalog 以provider.id作为分组 id、provider.name作为显示名)。因此providers.volcengine-agent-plan这类配置 key 能被可靠匹配;若未来 DSH 改变这一命名约定,标签会安静地不显示(不会报错),插件其余功能不受影响。
为什么只能从配置读(已验证):浏览器侧拿到的
modelCatalogRPC 返回的 模型对象只有id/name/description/reasoning,不含input—— DSH 的 Host 侧在构建浏览器目录时把input字段投影丢弃了(见buildModelCatalog)。因此插件无法从模型目录兜底读取能力,配置是浏览器侧 唯一的input来源。想给某个模型显示能力标签,就在 pi-ai 提供商配置里为它 写input:# profile 的 cordis.patch.yml,llm-pi-ai 提供商配置内 models: - id: deepseek-v4-flash-ga-260731 input: [text, image] # 声明后插件即显示「文本 / 图像」标签这也解释了为什么同一个模型 id 在不同用户那里标签可能不同——它如实反映 各自配置,而非模型本身的客观能力。
conversation.input.right slot —— 这是一个
kind: list、scope: session 的官方扩展点,composer 栏在渲染模型
seat(conversation.input.model)之前渲染它,因此按钮天然出现在
模型下拉的左边。ctx.inject(['slots', 'modelDirectories'], …) 拿到
ctx.modelDirectories(由 @deepseek-ai/dsh-client-ui-model-selection
注册的共享服务),对当前会话解析出与原生下拉同一个
ModelDirectory 实例。directory.select({ provider, model, reasoningEffort })
→ 走与原生下拉完全相同的 selectModel RPC。成功后共享 store 更新,
原生模型下拉的标签自动回写,会话模型切换立即生效。ctx.inject(['…', 'remote', 'remote.settings']) 注入的
settings Remote 读取:settings.describe() 返回各命名空间的合并配置,
从中提取 provider → model → input[]。注意 remote.<namespace> 必须显式
写进 inject 列表(cordis 规则),只注入根 remote 会在访问时报
cannot get property "remote.settings" without inject。支持 web 与 desktop 两个 profile(platform: web 的插件在两者中均生效)。
git clone https://github.com/faxble/dsh-model-picker.git
dsh plugin --profile web add /path/to/dsh-model-picker
把 /path/to/dsh-model-picker 换成实际 clone 路径;桌面版把 web 换成
desktop:
dsh plugin --profile desktop add /path/to/dsh-model-picker
安装后重启 DeepSeek Harness,在「设置 → 插件」中启用 dsh-model-picker,
或确认它已自动启用。
dsh plugin --profile web add github:faxble/dsh-model-picker
%USERPROFILE%\.dsh\profiles\desktop)的 package.json 中:
dependencies 增加 "dsh-model-picker": "file:D:\\Dev\\VibeCoding\\dsh-model-picker";dsh.profile.bundles 增加 "dsh-model-picker"。pnpm install。dsh-model-picker/
├── package.json # 包元数据 + dsh.client 声明(platform: web)
├── index.js # Host 半身(no-op,仅承载 bundle 行)
├── cordis.patch.yml # bundle patch:一行 insert(name 为裸包名)
├── client.js # 浏览器半身:ModuleLoader bundle(由 src/ 构建)
├── install.ps1 # 安装脚本(web / desktop)
├── src/ # 源码(ES modules,开发用)
│ ├── dict.js # zh/en 文案字典
│ ├── pure.js # 纯逻辑:排序/搜索打分/MRU/能力标签(单测覆盖)
│ ├── style.js # CSS(主题变量)
│ ├── icons.js # SVG 图标
│ └── entry.js # ModuleLoader bundle 入口(组件 + apply)
├── scripts/build.mjs # esbuild 打包脚本
├── test/ # node:test 单元测试
└── README.md
react),
全部颜色来自 DSH 主题 CSS 变量,切换深浅色主题无需重载。
client.js 是构建产物,开发期用 pnpm build 从 src/ 生成。conversation.input.right 目前没有任何占用者,
注册不会遮蔽既有 UI。提供商 · 模型(如 火山方舟 · deepseek-v4-flash-ga),
提供商名在模型左侧、本地化并浅灰次要显示,跨提供商时避免同名模型混淆。--dsw-alias-brand-text 做选中行文字色 ——
它的语义是"品牌色块上的文字"(浅色主题设计值),深色主题下解析为深色,
配软高亮底会变成黑字看不清;文字统一用 --dsw-alias-label-primary。改 src/ 后执行 pnpm build 重新生成 client.js,再复制到 profile 触发
HMR 热更新(页面无需刷新,DSH 会检测到文件变更并重新加载 bundle):
pnpm build
Copy-Item .\client.js $env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-model-picker\client.js -Force
单元测试:pnpm test(node --test,覆盖 src/pure.js 的纯逻辑)。
构建校验:pnpm check(node --check 产物)。CI 会校验 client.js 是否为
最新构建,改了 src/ 忘了 build 会让 CI 失败。
若要源码改动即时生效(免复制),改用 link: 符号链接方式安装。
移除插件:DSH「设置 → 插件」里卸载 dsh-model-picker 即可。