# dsh-vision-toggle · 模型视觉能力开关插件 [English](./README.md) | **中文** > 为 DeepSeek Harness (dsh) 桌面端提供模型视觉开关:让用户自主控制每个配置的模型是否支持图片输入——拨动开关即可按模型开启/关闭视觉能力,无需手改配置文件、无需重启。 ## 功能概览 | 功能 | 说明 | |---|---| | 模型列表 | 读取 `llm-pi-ai` provider 路由中声明的所有模型,按 provider 分组展示 | | 视觉开关 | 逐模型切换图片输入:开启为 `['text','image']`,关闭为 `['text']` | | 即时生效 | 写入官方配置,`llm-pi-ai` 检测到变化后重新注册,无需重启即可生效 | | 乐观更新 | 开关立即切换;若 host 写入失败则自动回滚 | | 国际化 | 中英双语,跟随 dsh 桌面端语言设置 | ## 背景 dsh 官方已支持多模态(图片理解),内置 `deepseek-v4-vision-exp` 模型。但**设置页无法配置自定义 provider / 第三方模型的输入模态**(`input`)。如果你添加自己的 provider(如通过 LM Studio / vLLM / Ollama 提供的 OpenAI 兼容服务),即便其模型实际支持视觉,发送图片仍会报: ``` 当前模型不支持图片 ``` 目前唯一的绕法是手动编辑 `settings.yaml`,给对应模型加上 `input: [text, image]`——既脆弱又易出错。 本插件消除了这个摩擦点:它操作官方 `llm-pi-ai` 设置命名空间,在设置页为每个模型提供一个「**支持图片**」开关,拨动开关即可替你把模型的 `input` 模态写好。 ## 安装 ### 前置条件 - DeepSeek Harness (dsh) 桌面端 - Node.js >= 18 ### 在 dsh-desktop 项目中集成 1. 安装插件: ```bash dsh plugin add @lijian-ui/dsh-vision-toggle ``` 2. 重启桌面端。 ### 本地开发 ```bash # 进入插件目录 cd extensions/dsh-vision-toggle # 安装依赖 npm install # 构建 npm run build # 监听模式 npm run watch # 类型检查 npm run typecheck ``` 构建产物在 `lib/` 目录下,通过 junction 自动同步到 `node_modules/@lijian-ui/dsh-vision-toggle`。每次构建后需重启桌面端加载新 bundle。 ## 使用方式 1. 打开 dsh 桌面端 2. 进入 **设置** → **模型视觉能力**(位于其他设置分节之后) 3. 该分节列出所有已配置模型,按 provider 分组,每个模型右侧有一个「支持图片」开关: - **开启**:模型可接收图片输入,聊天时即可发送图片 - **关闭**:模型为纯文本 > 拨动开关只是把该模型的 `input` 设为 `['text','image']` 或 `['text']`,正好命中 dsh 判断「模型是否支持图片」的逻辑。 ## 技术架构 ### 目录结构 ``` extensions/dsh-vision-toggle/ ├── src/ │ ├── index.ts # Host 端入口(注册 remote 服务 + typert 契约) │ ├── remote.ts # Host 端 RPC:listModels / setVision(读写 llm-pi-ai 配置) │ └── client/ │ ├── index.ts # Client 端入口(SECTION_ID、RPC 注册、inject) │ ├── VisionToggleSection.ts # 设置页组件(按 provider 分组的模型列表 + 开关) │ └── client-i18n.ts # 客户端国际化(中/英) ├── lib/ # 构建产物(index.mjs + client.js) ├── package.json ├── tsdown.config.ts └── cordis.patch.yml ``` ### Host 端(`src/remote.ts`) 提供以下 RPC 方法: | 方法 | 功能 | |---|---| | `listModels()` | 列出所有 `providers[*].models` 中声明的模型,含当前 `input` 模态与是否支持视觉 | | `setVision(provider, modelId, enabled)` | 将指定模型的 `input` 改写为 `['text','image']`(开)或 `['text']`(关)并持久化 | ### 配置读写 插件操作的是 **官方 `llm-pi-ai` 设置命名空间**(`settingsNamespace('llm-pi-ai')`,由 `@deepseek-ai/dsh-llm-pi-ai` 拥有)——正是支撑模型选择与「当前模型不支持图片」错误的那份配置: - **读**:`settings.get('llm-pi-ai')` 返回 provider 路由;每个模型的实际 `input` 缺省时回退到 provider 的 `defaultInput`。 - **写**:使用 `settings.update('llm-pi-ai', { providers: ... })` 并传入**重建的完整 `models` 数组**。因为基于路径操作的 `settings.mutate` API 无法定位数组索引(会把整个数组替换掉),所以这里改为重建数组。 由于 `llm-pi-ai` 每次请求都会解析 `input` 并在配置变化时重新注册,因此拨动开关即时生效,无需重启。 ### 开关机制 ``` 用户点击开关 → client 乐观更新该行(立即切换状态) → RPC 调用 host 端 setVision(provider, modelId, enabled) → host: 读取配置,重建 models[],settings.update('llm-pi-ai', …) → llm-pi-ai 检测到变化并重新注册模型路由 → 配置写入 settings.yaml;下一条消息即按新模态处理 ``` 若 host 写入失败,client 会恢复开关原状并提示错误。 ## 国际化 支持中文和英文两种语言,翻译文件在 `src/client/client-i18n.ts` 中。语言切换跟随 dsh 桌面端的语言设置。 ## 技术栈 - **语言**:TypeScript - **构建**:tsdown (rolldown) - **前端**:React 18 - **RPC**:`@deepseek-ai/dsh-typert-protocol` / `@deepseek-ai/dsh-typert-registry`(host remote) - **配置**:`@deepseek-ai/dsh-settings`(命名空间 `llm-pi-ai`) ## 许可证 MIT ## 相关链接 - [DeepSeek Harness (dsh)](https://github.com/deepseek-ai/dsh)