dsh-file-drop
 
> English: Drag a PDF / .py / Excel (.xlsx) / CSV file straight into the DeepSeek Harness composer. Files appear as format cards (colored PDF/XLSX/CSV/PY badge + name) above the input; on send, compact [file attachment ...] references are attached and the model reads the content through the read_file_attachment tool — with dependency-free built-in PDF and XLSX extractors. Zero runtime dependencies, no build step.
把 PDF / .py 文件直接拖进 DSH(DeepSeek Harness)对话框,模型自动读取并分析内容的小插件。
- 🚫 零运行时依赖:PDF 与 XLSX 解析都是内置的纯 JS 实现(Node 内置
zlib+ 手写解析器),不装 pdf.js/xlsx 库,不依赖任何其他 DSH 插件 - 🏷 格式卡片:拖入后输入框上方显示带格式徽章的小卡片(PDF / XLSX / CSV / PY),可单独移除,不再往草稿里塞长引用
- 📦 纯 ESM、无需构建:装完即用,没有
npm run build - 🔌 双平面封装:host 半(上传路由 +
read_file_attachment工具 + PDF 提取器)+ browser 半(拖拽拦截 + 输入框插入),各模块互相独立 - 🗂 文件落盘镜像:拖入的文件同时存到当前工作区
.dsh-drops/,你(和模型自己的文件工具)都能直接看到原文件
效果
1. 把 .pdf / .py / .xlsx / .csv 文件从资源管理器拖进 DSH 窗口,松手; 2. 输入框内部顶部出现与图片缩略图同款的格式卡片:独立预览框(带格式字样 PDF / XLSX / CSV / PY 的彩色页面图)+ 悬停 × 移除 + 文件名 tooltip;轨道作为卡片内的流式行占位——草稿文字自动下移、互不遮挡,图片与文件同时拖入时文件排在图片下方; 3. 点发送时自动把紧凑引用 [file attachment {"attachmentId":"sha256:…","kind":"pdf","name":"论文.pdf"}] 附到消息末尾(文件字节本身不进对话); 4. 模型调用 read_file_attachment 工具读取内容——PDF 提取文本层、XLSX 转 TSV 表格、CSV/.py 原样返回——然后进行分析。
sequenceDiagram
participant U as 用户拖入 .pdf/.py
participant C as browser 半 (lib/client.js)
participant R as /dsh-file/attach (lib/routes.js)
participant S as 内存存储 (lib/store.js)
participant T as read_file_attachment (lib/tool.js)
participant P as PDF 提取器 (lib/pdf-text.js)
U->>C: 拖放文件(capture 阶段拦截,图片照旧走官方逻辑)
C->>R: POST base64 字节 + kind + cwd
R->>S: sha256 内容寻址存储(FIFO 上限 64 条)
R->>U: 镜像写入 <cwd>/.dsh-drops/<文件名>
R-->>C: 返回紧凑引用 + attachmentId
C->>C: 输入框上方显示格式卡片(可移除)
Note over C: 发送时自动把引用附到消息末尾
Note over T: 用户发送消息,模型看到引用
T->>S: 按 attachmentId 取字节
T->>P: PDF? 提取文本层(Flate/LZW/ToUnicode/...)
T-->>T: 返回文本(支持 start/maxChars 分页续读)安装
> 环境:Node 22.19+(DSH 自带)、dsh CLI。
方式 A:本地仓库链接安装(推荐,改代码最方便)
# 1. 克隆本仓库
git clone <your-repo-url> dsh-file-drop
# 2. 把包链接进 web profile
dsh plugin --profile web add link:D:/path/to/dsh-file-drop> ⚠️ 链接安装的依赖解析:DSH 的模块回退机制对 link 包按真实目录解析依赖(Node 默认跟随符号链接),所以本仓库目录下需要一个指向 DSH 安装目录的扁平链接。安装后运行一次: > > ``sh > node scripts/link-host-deps.mjs D:/path/to/DSH # 例如 D:/xl/DSH,或设置 DSH_APP_ROOT 后省略参数 > `` > > 该链接位于被 .gitignore 忽略的 node_modules/ 下,不影响 Git 提交。
方式 B:从 npm 安装(发布后)
dsh plugin --profile web add dsh-file-drop两种方式都还需要最后一步 —— 把 host 插件挂进 profile 的补丁层。编辑 ~/.dsh/profiles/web/cordis.patch.yml,追加:
# dsh-file-drop:拖入 PDF/.py 自动引用 + read_file_attachment 工具
- insert:
- id: dsh-file-drop
name: 'dsh-file-drop'重启 DSH(完全退出再启动,或重启服务器进程),刷新 GUI 页面即可。
> 或者作为 profile bundle 安装:把 "dsh-file-drop" 加进 profile > package.json 的 dsh.profile.bundles 列表 —— 此时本仓库自带的 > cordis.patch.yml(dsh.bundle.patch)会自动生效,无需手改补丁层。
使用
| 格式 | 扩展名 | 大小上限 | 模型拿到什么 |
|---|---|---|---|
| 24 MiB | 文本层(分页标记) | ||
| Excel | .xlsx | 16 MiB | 每个工作表一段 TSV([工作表 名称] 标题) |
| CSV | .csv | 8 MiB | UTF-8 原文 |
| Python | .py | 2 MiB | UTF-8 源码(latin1 兜底) |
- 拖入后文件以格式卡片形式显示在输入框内部顶部(图片缩略图同一位置):徽章写格式、卡片写文件名,点 × 单独移除;卡片不影响草稿,发送时才把紧凑引用附到消息末尾
- 图片拖入不受影响,仍走 DSH 官方图片逻辑;混合拖入时,四种格式由本插件接管,其余文件会提示「已忽略」
- 多文件可一次拖入;每个文件一张卡片
- 文件同时落盘到
当前会话工作区/.dsh-drops/,重名自动加-2、-3… - 大文件:工具默认一次返回 12 万字符,
truncated: true时模型会按start续读,无需你干预
目录结构(封装说明)
| 文件 | 平面 | 职责 |
|---|---|---|
lib/index.js | host | 入口:注册工具 + 上传路由,导出公共 API |
lib/tool.js | host | read_file_attachment 工具定义(参数校验/输出 schema/分页) |
lib/routes.js | host | /dsh-file/attach HTTP 路由 + 上传载荷校验 + 落盘镜像 |
lib/store.js | host | 内存附件注册表(sha256 内容寻址,FIFO 上限 64 条) |
lib/pdf-text.js | host | 零依赖 PDF 文本层提取器(详见下节) |
lib/table-text.js | host | 零依赖 XLSX 提取器(ZIP 中央目录 + OOXML 工作表) |
lib/client.js | browser | 拖拽拦截、上传、输入卡片内格式卡片(overlay 插槽,图片位)、发送钩子、toast |
cordis.patch.yml | 补丁 | 插件挂载行(bundle 安装时自动应用) |
scripts/link-host-deps.mjs | 工具 | 为链接安装创建 host 依赖扁平链接(见安装说明) |
test/ | 测试 | node --test,覆盖提取器/过滤器/存储/上传校验 |
内容解析能力与边界
XLSX / CSV:XLSX 由内置的 ZIP 中央目录读取器(STORE + DEFLATE)+ OOXML 解析器提取——工作表名、共享字符串表、inline/数值/布尔单元格都支持,输出为 TSV;CSV 直接按 UTF-8 返回。不支持旧版 .xls(BIFF 二进制)、加密工作簿和外部链接引用。
支持:FlateDecode / LZWDecode / ASCIIHex / ASCII85 过滤器;ObjStm 对象流(PDF 1.5+);Tj/TJ/'/"/T*/Td/TD/Tm 文本算子;/ToUnicode CMap (bfchar+bfrange,中文 CID 字体通常可正确提取);/Encoding /Differences 西文字形名;WinAnsi/Standard 编码与 UTF-16BE 字符串;TJ 负向 kerning 的空格启发式。
不支持的边界:纯扫描/图片型 PDF(没有文本层,工具会明确提示「未能提取到文本」,此时可让模型用 .dsh-drops/ 里的原文件自行 OCR);无 ToUnicode 的 CID 子集字体;Form XObject 文本仅在整页提取为空时通过兜底扫描兜住。
在作者真实语料上的表现:34/66 篇 PDF 完整提取(含 200 万字符的扫描书目、BIG-bench 等),平均约 115 ms/篇;其余为无文本层的扫描件。
安全与限制
- 附件注册表是进程内内存存储:DSH 服务器重启后旧引用失效,工具会提示重新拖入(磁盘镜像文件仍在
.dsh-drops/) - 上传路由仅在本机 loopback GUI 内使用;
cwd由客户端随请求携带,落盘限定在<cwd>/.dsh-drops/,文件名经 basename 清洗、拒绝路径穿越 - 字节上限:PDF 24 MiB / .xlsx 16 MiB / .csv 8 MiB / .py 2 MiB,可在
lib/routes.js的常量处调整
上传到 GitHub
本仓库已经按发布标准包装好:MIT License、node --test 测试(16 例)、GitHub Actions CI(.github/workflows/test.yml,Node 22/24 双版本)、npm pack 白名单(files 字段)、npm 生命周期钩子 prepack(发布前自动跑测试)。发布前只需:
cd D:/xl/plugin/dsh-file-drop
git init -b main
# 1) 首次提交需要身份(换成你自己的名字/邮箱)
git config user.name "Your Name"
git config user.email "you@example.com"
git add .
git commit -m "dsh-file-drop: drag PDF/.py into the composer for analysis"在 GitHub 上新建空仓库 dsh-file-drop(不要勾选 README/.gitignore/license,避免冲突),然后:
git remote add origin https://github.com/Nafiygond/dsh-file-drop.git
git push -u origin main推送后第一件事:Settings → Actions → General → Workflow permissions 勾选 Read and write permissions(CI 徽章需要),随便推一个 commit 触发一次 workflow,看到 ✅ 即可。
发布到 npm(可选)
npm login
npm publish # prepack 会自动先跑测试;dry-run 预览: npm pack --dry-run- 包名
dsh-file-drop未带 scope,若已被占用或想用@you/dsh-file-drop,需同步改 4 处:package.json的name、cordis.patch.yml的name、lib/index.js的export const name、lib/client.js里__ModuleLoader__.load的id(四处保持一致即可); - 发布后 README 里方式 B(
dsh plugin --profile web add <包名>)对其他人即可用。
加分项:录一段 10 秒拖拽演示 GIF 放在 README 顶部;LICENSE 里的 Copyright 换成你的名字。
开发与测试
npm test # node --test,无需构建
node scripts/link-host-deps.mjs <DSH 安装目录> # 链接安装后运行一次修改 host 半(lib/*.js 除 client.js)→ 重启 DSH 生效;修改 browser 半 (lib/client.js)→ 重启 DSH 并刷新页面(客户端 bundle 在启动时按 rev 哈希注入)。
License
MIT