✨ 特性
| 能力 | 说明 |
|---|---|
| 🔀 视觉自动路由 | 纯文本会话里贴图,无需手动切换——含图请求自动改派官方视觉模型 deepseek-v4-flash-vision-exp,文字请求零开销走文本模型 |
| 📎 通用文件附件 | 原版只收图片;本插件支持拖入/粘贴任意文件(docx/xlsx/pdf/txt/zip…)→ 附件卡片 → 落盘 → agent 按路径读取 |
| 🗂️ 文件类型图标 | 附件卡片按扩展名显示彩色类型方块(Word 蓝 W / Excel 绿 X / PDF 红 P…) |
| 💾 持久化落盘 | 文件保存到 ~/.dsh/attachments/v1/files/,会话历史保留附件块与完整绝对路径 |
| 🛡️ 崩溃修复 | 修复文件草稿发送/删除时 Cannot read properties of undefined (reading 'startsWith') |
| 🧩 随包核心补丁 | 6 个核心文件的替换清单 + 一键原位重打包器,改的是 DSH 桌面端核心 |
⚠️ 开关说明:两种功能、两套机制(重要)
很多用户会困惑「DSH 插件列表里的滑块开关为什么管不住文件附件」。因为这两个功能挂在完全不同的两层:
| 功能 | 挂在哪一层 | 怎么生效 | 滑块开关(启用中)管得到吗 |
|---|---|---|---|
| 🔀 视觉路由 | dsh-periscope 插件 bundle |
DSH 启动时按插件列表加载 | ✅ 管得到——开关切换的就是它 |
| 📎 文件附件 | DSH 核心 6 个包(app.asar 内) |
用 install.ps1 给 app.asar 原位打补丁,一经打包即固定 |
❌ 管不到 |
为什么?
- 视觉路由是插件:它通过 DSH 的插件系统在运行时加载。插件列表的滑块开关,控制的就是「
dsh-periscope插件是否被加载」,所以只影响视觉路由。 - 文件附件是核心补丁:DSH 核心的
session.promptwire 校验 schema 是dsh-host-apiproxy模块内部常量,第三方插件在运行时无法扩展。要给 DSH 增加「任意文件」能力,只能直接修改核心,而app.asar是一次性打包的——它不属于插件的运行时开关范畴。
实际表现:
- 文件附件是否生效,只取决于
app.asar是否被打过补丁(有没有跑过install.ps1)。跟滑块开关无关:打过补丁 → 关掉滑块文件附件照样生效;没打过 → 滑块开再大也没用。 - 滑块开关在「插件列表里」看到的效果仅限视觉路由那一半。
✅ 所以滑块开关不是「没用」,而是它只管视觉路由;文件附件需用
install.ps1打app.asar补丁。这两件事要分开看待。
🚀 一键安装(推荐)
只适配 DSH Desktop 桌面客户端(以单个
app.asar打包核心的形态)。请在 Windows 上操作,且每次 DSH 升级后都要重做一次。
本插件已发布到 npm:dsh-periscope@0.3.4。仓库根目录自带一个一键安装脚本 install.ps1,它会一次性完成「安装 bundle + 修正确版本号 + 重打包 app.asar」,用户不必手工拆两步。
方式 A:从 GitHub 仓库(zip / clone)
# 1) 完全退出 DSH Desktop
# 2) 进入仓库目录(解压 zip 或 clone 后的目录),运行:
Set-ExecutionPolicy -Scope Process Bypass -Force
.\install.ps1
方式 B:从 npm 安装
npm install dsh-periscope
npx dsh-periscope-install
也可以直接用 DSH 的插件入口:
dsh plugin add dsh-periscope@0.3.4 # 精确版本 → 插件列表正确显示版本
脚本会自动做这几件事:退出检测 → 备份 app.asar → 以精确版本 dsh plugin add dsh-periscope@<ver> 安装/更新 bundle(把依赖从 ^0.2.0 修正为 ^0.3.3,从而让 DSH 插件列表正确显示版本)→ 用已安装包内的 scripts/repack-inplace.mjs 对 app.asar 做原位重打包(注入 6 个补丁核心文件,保留原生模块)→ 校验 + 提示重启。
- 手动指定版本 / profile:
.\install.ps1 -Version 0.3.3 -Profile desktop - 离线(不走 npm registry):
.\install.ps1 -FromLocal
⚠️ 关键点:插件列表显示的是本地安装版本。此前停在
0.2.0是因为依赖写成了^0.2.0(^0.2.0=>=0.2.0 <0.3.0,永远够不到 0.3.x)。用精确版本安装即可绕过该限制,让版本号正确显示。
3. 重新打开 DSH
拖入 / 粘贴一个非图片文件,即可看到带类型图标的附件卡片;发送后 agent 会按路径读取它。DSH 插件列表应显示 dsh-periscope v0.3.3。
📖 工作原理
文件附件功能位于 DSH 核心包(wire 协议、附件存储、composer、模型适配器),而核心校验 schema 是 dsh-host-apiproxy 模块内部的常量,第三方插件运行时无法扩展——因此本插件随包携带对桌面端核心的补丁。
拖入/粘贴任意文件 📎
→ composer 附件卡片(类型图标 + 文件名 + 大小,可删除)
→ 发送:文件字节(base64) 作为 {type:"file"} 部件随 prompt 上送
→ host 校验并落盘:~/.dsh/attachments/v1/files/<sha256>-<文件名>
→ 会话持久化:{type:"file", file:{name, size, path, …}} 内容块(历史渲染附件卡片)
→ 模型请求:file 块投影为文本
[附件:名称(大小)\n完整路径:<绝对路径>\n请读取该文件内容后继续。]
→ agent 用文件工具按路径读取并处理 🔧
为什么不是把文件直接发给模型? DeepSeek 官方 Files API 仅支持 JPEG/PNG/GIF/WebP 图片,非图片文档无法直接送入模型。路径式消费是 agent 架构下的等价体验(Codex 同款做法):文件真实落盘,agent 用 read/bash/pwsh 等工具读取。
默认限制(可通过 dsh-attachment-local 配置调整):单文件 20 MiB、单条消息 20 个文件、单条合计 200 MiB;客户端与 host 双重校验。
🛠️ 配置
官方 DeepSeek 无需任何设置即开箱即用:
| 字段 | 默认值 | 说明 |
|---|---|---|
provider |
deepseek-official |
承载模型的路由 provider |
textModels |
["deepseek-v4-flash", "deepseek-v4-pro"] |
含图请求会被路由到视觉模型的文本模型 |
visionModel |
deepseek-v4-flash-vision-exp |
含图请求使用的视觉模型 |
在 profile 的 cordis.patch.yml(用户层会整体替换该行配置)覆盖:
- id: periscope
config:
provider: deepseek-official
textModels: [deepseek-v4-flash, deepseek-v4-pro]
visionModel: deepseek-v4-flash-vision-exp
该 provider 的模型目录需同时包含这些文本模型与一个声明了 image 输入的视觉模型(DeepSeek 目录已满足)✅
📁 仓库结构
| 路径 | 说明 |
|---|---|
patches/manifest.mjs |
6 个核心文件的 old→new 替换清单(约 30 处,供审查/演进) |
patches/asar-patched/ |
已打补丁的 6 个核心文件(重打包时直接打进 app.asar) |
scripts/repack-inplace.mjs |
原位重打包:只替换 6 个文件,保留其余文件字节与原生模块结构 |
scripts/apply-file-attachments.ps1 |
一键入口:退出检测 → 备份 → 重打包 → 校验 |
scripts/patch-core.mjs |
apply / revert / verify / diff(面向松散核心的历史方式) |
lib/ · cordis.patch.yml |
插件本体与 DSH 补丁声明 |
涉及的 6 个核心包:@deepseek-ai/dsh-attachment、dsh-attachment-local、dsh-host-apiproxy、dsh-llm-deepseek、dsh-client-ui-conversation、dsh-client-ui-attachment。
❓ FAQ
Q:DSH 升级后文件附件不能用了?
A:正常。DSH 每次升级都会重新打包 app.asar,功能随之失效。重新运行一次 apply-file-attachments.ps1 即可(升级前先备份 app.asar)。
Q:用官方 asar extract→pack 行不行?
A:不行。naive 的 extract→pack 会孤立 unpacked 原生模块(conpty / sharp / koffi),导致 DSH 无法启动。请使用仓库自带的原位重打包器。
Q:支持 Web / CLI / 源码形态吗?
A:不支持。本插件只适配 DSH Desktop 桌面端以单个 app.asar 打包核心的形态。
Q:为什么非图片文件要 agent 按路径读,而不是直接发给模型? A:DeepSeek 官方 Files API 只接受图片。路径式消费是 agent 架构下的等价体验。
Q:node 路径找不到?
A:脚本内置了 DSH runtime 与 Codex runtime 两个候选;仍不行时改 scripts/apply-file-attachments.ps1 里的 $node。
⚠️ 风险与免责声明
本插件通过直接修改 DSH 桌面端的核心文件来工作,属于非官方行为。 请在使用前充分了解:
| 风险 | 说明 |
|---|---|
| 🔄 DSH 升级即失效 | 升级重新打包 app.asar,功能随之失效,需重跑脚本。 |
| 💥 损坏与不可启动 | 重打包有误或补丁与新版核心不匹配时 DSH 可能无法启动。脚本每次自动备份 app.asar → app.asar.bak。 |
| 🧩 内核不匹配 | 补丁针对编写时的核心版本;升级后替换项可能对不上,需按新版核心重新生成。 |
| 🔬 非官方行为 | 修改的是核心文件而非插件 API;DSH 官方不承诺稳定。 |
| 💾 本地落盘 | 附件明文保存到 ~/.dsh/attachments/v1/files/,路径与块会持久化,注意隐私与磁盘占用。 |
| 📎 非图片需 agent 读 | 非图片文档由 agent 按路径读取;read_image 工具自身的准入不受影响。 |
| 🧪 仅 Windows 桌面端 | 当前脚本面向 Windows + app.asar 形态。 |
还原方法(DSH 完全退出后运行):
Copy-Item "D:\DSH\DSH Desktop\resources\app.asar.bak" "D:\DSH\DSH Desktop\resources\app.asar" -Force
若 DSH 已无法启动,先还原备份;如首次运行无
.bak,直接到 DSH 官网重新下载覆盖安装。
🗺️ 路线图
- 面向新版 DSH 核心的自动补丁重生成
- 会话导出时打包附件字节
- 支持更多平台的桌面端形态
- 上游原生支持文件附件(长期方向)
🤖 关于 vibecoding
本项目全程由 AI 结对编程(vibecoding)完成:需求描述、实现、调试、核心 app.asar 重打包器、文档均由 AI 编码代理协作产出,作者负责验证与发布。欢迎 PR / Issue。
📣 加入交流群 / 支持项目
🐧 QQ 交流群:332689798(小鲸子TV)——欢迎扫码加入,提交 Bug、交流使用心得:
⭐ 如果觉得好用,请给项目点个 Star 支持一下!你的反馈能帮助它变得更好。
No comments yet. Be the first to write one.