dsh-drag-file
v0.1.2
Published
Drag files (e.g. Excel) onto the DSH web composer: shows a file chip above the input and sends the resolved absolute path as plain text — the agent reads the file itself.
Maintainers
Readme
dsh-drag-file
Drag & drop any file into the DeepSeek Harness (DSH) web composer — send its absolute path, not the file.
把文件(Excel、PDF、CSV……)直接拖进 DSH Web 输入框:上方显示文件占位 chip,发送的消息实际携带该文件的绝对路径(纯文本,一行一个路径)。Agent 用自己的文件工具读取内容——插件本身不读取、不上传任何文件内容。
Author: gezhigang · License: MIT
为什么需要它
DSH 原生只支持拖拽图片附件——拖 Excel/PDF/Zip 进去会被弹「仅支持图片」的错误。而这个插件走另一条路:
┌──────────┐ 文件名 ┌─────────────┐ 磁盘搜索 ┌──────────────┐
│ 浏览器 │ ─────────→ │ Host 插件 │ ──────────→ │ 工作区 + 常用 │
│ 拖拽事件 │ │ dragFile/ │ │ 目录(可配置) │
└──────────┘ │ resolve │ ←────────── └──────────────┘
↑ └─────────────┘ 绝对路径候选
│ │
│ 唯一匹配:自动写入草稿 ▼ 多匹配:chip 上点选
┌──────────────────────────────────────┐
│ 输入框草稿: /Users/you/Downloads/a.xlsx │ ← 实际发送的就是这行文字
└──────────────────────────────────────┘- ✅ 不传文件内容——只有文件名和路径跨过浏览器/host 边界,隐私安全
- ✅ Agent 用全量能力处理文件——xlsx/pdf/pptx 等 skill、大文件、二进制格式都不受「图片附件」限制
- ✅ 路径可见可编辑——发送前能看到会发什么,也能手动改
- ✅ 与原生图片拖拽共存——纯图片仍走内置附件流程,互不干扰
使用效果
- 从 Finder / 资源管理器拖文件到页面 → 输入框上方出现虚线投放横幅
- 松手 → host 按文件名在磁盘上搜索:
- 唯一匹配 → 自动生成文件 chip,绝对路径写入草稿
- 多处同名 → chip 列出候选路径,点选一个
- 找不到 → chip 提示「未找到」(可手动补路径或关闭)
- 输入框里就是那行路径,可继续追加指令,例如:
/Users/gezg/Downloads/0818/BI各类价格看板-20260820.xlsx
帮我按车型统计各类价格差异,输出一份汇总表- 发送 → Agent 收到路径文本,自己去读文件并执行任务
安装
从 npm 安装(推荐)
dsh plugin --profile web add dsh-drag-filenpm 包已内置构建产物(lib/),安装即用,无需本地构建。
从 GitHub 安装
dsh plugin --profile web add github:gezg/dsh-drag-fileGit 安装获取的是源码。仓库已提交
lib/构建产物,无需本地构建;若 pnpm ≥10 拦截构建脚本,在 profile 的pnpm-workspace.yaml里allowBuilds后重跑add。
本地开发安装
git clone https://github.com/gezg/dsh-drag-file
dsh plugin --profile web add /path/to/dsh-drag-file或手动编辑 ~/.dsh/profiles/web/package.json:
{
"dependencies": {
"dsh-drag-file": "file:/path/to/dsh-drag-file" // 或 "github:owner/repo"
},
"dsh": {
"profile": {
"bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-drag-file"]
}
}
}然后 pnpm install 并重启 web profile(浏览器页面也要刷新,client bundle 随页面加载)。
配置
在 profile 的 cordis.patch.yml 覆盖(所有字段可选):
- id: dsh-drag-file
name: dsh-drag-file
config:
searchDirs: ["~/Downloads", "~/Desktop", "~/Documents"] # 工作区之外的搜索目录(~ 自动展开)
workspaceDepth: 10 # 工作区内搜索深度(目录层数)
searchDirsDepth: 3 # 各额外目录的搜索深度
maxResults: 20 # 单次拖拽返回的候选路径上限搜索自动跳过 node_modules、.git、dist、Library 等目录;文件名匹配大小写不敏感。
工作原理(面向 DSH 插件开发者)
典型的 host + client 双面插件(参考 dsh-at-file 的架构模式):
src/
├── index.ts # Host:DragFileRuntime(TypertRemoteService)+ schemastery 配置
├── files.ts # Host:有界磁盘搜索(BFS、忽略清单、深度/数量上限、AbortSignal)
├── contract.ts # 共享 wire codec(zod):dragFile/resolve 描述符
├── typert.ts # Host:Typert manifest(严格注册,不依赖装饰器标记)
└── client/
├── index.ts # document 级捕获阶段拖拽监听 + Remote 挂载 + dock 注册
├── dock.tsx # 'conversation.input.dock' seat:横幅/chips/候选点选
├── model.ts # snapshot store + 草稿路径行解析(POSIX & Windows)
├── remote.ts # client 侧 Remote 贡献声明
├── locales.ts # 中英文案(ctx.locale.register)
└── styles.ts # 样式注入(--dsw-alias-* design tokens)关键设计:
- 发送机制 = 草稿文本:
inputActions.setDraft()把路径逐行写入草稿,发送即纯文本——没有隐藏的提交时注入,用户看到什么就发什么 - 与原生图片流程的边界:drop/
dragenter/dragover均为捕获阶段监听;纯图片拖拽放行给内置 InputBar,含非图片的拖拽stopImmediatePropagation()整体接管(同时避免内置「仅支持图片」报错与全屏遮罩残留) - 路径 chip = 草稿解析视图:dock 解析草稿中的绝对路径行渲染 chip,× 删除即删对应行——草稿是唯一真相源
- Remote 解析路径:namespace 服务经
ctx.reflect.get('remote.dragFile')获取(dotted read 会在 Loader 内部分叉处中断)
开发
pnpm install --config.auto-install-peers=false
pnpm run typecheck # tsc --noEmit(需本机已装 DSH,见 tsconfig paths 注释)
pnpm run build # esbuild:lib/index.js (host) + lib/client.js (client bundle)
tsconfig.json的 paths 指向本机~/.dsh/profiles/node_modules/@deepseek-ai/*类型;构建本身不依赖它。修改代码后pnpm run build+ 重启 profile 即可生效(file:依赖为硬链接,无需重新 install)。
平台兼容性
- macOS / Linux:完整支持
- Windows:支持。host 侧用
node:path(自动\分隔),~/Downloads按用户目录展开;草稿 chip 同时识别 POSIX(/Users/...)与 Windows(C:\Users\...、D:/data/...)路径;文件名匹配大小写不敏感,与 Windows 文件系统一致
设计边界:含空格的路径行不会渲染为 chip(插件产出的路径按精确文件名解析、不含空格;宽松匹配会误吞普通文本行)。拖拽主路径不受影响。
License
MIT © gezhigang
