鱼皮AI导航
鱼皮AI导航
  • 主页
  • 社区
  • AI工具
  • AI知识库
  • AI提示词
  • MCP
  • Skills
  • AI学习资源
  • AI资讯
  • GitHub开源
登录/注册

dsh-drop-any-file

让 DSH 网页聊天支持拖拽任意类型文件:非图片文件保存到当前会话工作区,供 Agent 读取使用。

界面增强
访问 GitHub
文档README

dsh-drop-any-file · 让 DeepSeek Harness (DSH) Web 聊天支持拖拽任意类型文件

扩展 DeepSeek Harness (DSH) Web UI 聊天的拖拽能力,让任意文件类型都能被接受——内置输入框只允许图片(PNG/JPG/WebP/GIF)内联附加,其余一律拒绝。拖入非图片文件将保存到当前会话工作区,供 Agent 读取使用。

English: README.md · LLM 索引: llms.txt · Agent 指南: AGENTS.md

关键词 / Keywords: dsh-plugin · deepseek-harness-plugin · drag-drop · file-upload · workspace · attachment · any-file · 拖拽 · 任意文件 · 工作区

仓库 / Repo

GitHub: Zenjibad/dsh-drop-any-file · 需要 DSH ≥ 0.1 及 web profile。


📑 目录

  • ✨ 特性
  • 🏗️ 工作原理
  • 🚀 快速开始
  • ⚙️ 配置
  • ❓ 常见问题
  • ⚠️ 安全须知
  • 📦 项目结构
  • 🙏 致谢

✨ 特性

特性说明
📥 任意文件类型拖入 .pdf、.zip、.txt、.csv、.bin…… 不再出现「仅支持 PNG/JPG」的拒绝提示
💾 保存到工作区每个拖入的非图片文件都会写入当前会话的工作区目录,Agent 可用常规文件工具读取/搜索/使用
🖼️ 图片行为不变只包含图片的拖拽仍走内置内联附加流程——已有的好用功能不受影响
🚫 绕过输入框拒绝在 window 上以捕获阶段监听拖拽事件,先于输入框的仅图片处理器执行,拒绝 toast 不会触发
🫳 拖拽遮罩 + 提示拖拽时显示全窗口主题遮罩(「松手保存到工作区」);保存后用 toast 提示结果(成功或失败原因)
🛡️ 文件名清洗 + 大小上限文件名取 basename 并剔除非法路径字符;请求体 80 MB / 文件 60 MB 上限
🌗 主题自适应遮罩与 toast 全部使用 --dsw-alias-* 设计令牌,亮/暗色自动跟随
♨️ 重启常驻真实 profile 打包插件:dsh plugin add 安装一次,每次 DSH 启动自动加载 —— 无需 cordis_define、无需每次重装

🏗️ 工作原理

▼
text
复制代码
用户把非图片文件拖入聊天窗口 │ Client 半区(浏览器) ▼ └─ window 上捕获阶段监听:dragenter / dragover / dragleave / drop (从 conversation.input.dock 席位注册,该席位携带 sessionId) └─ drop 含非图片文件?→ preventDefault + stopPropagation (输入框的仅图片处理器根本收不到该事件) └─ FileReader → base64 → fetch POST /drop-any-file/api body: { sessionId, fileName, base64 } │ Host 半区(DSH 进程内) ▼ └─ webServer 路由 POST /drop-any-file/api └─ 解析目标目录:sessions.get(sessionId).header.cwd(即工作区) └─ 清洗 basename → 解码 base64 → node:fs writeFile └─ 返回 { ok, saved: { name, path, bytes } } │ Client 半区(浏览器) ▼ └─ toast:「已保存到工作区:<文件名>」(或错误信息)
  • 浏览器主动拉取/提交:无推送、无事件;只有用户真正放下文件时才 POST,Host 一律返回 JSON(失败时 {ok:false,error},绝无非 JSON 500)。
  • 纯图片拖拽放行:处理器提前 return、不 stopPropagation,内置的内联附加流程照常运行。
  • 持久化:随包声明 dsh.bundle(cordis.patch.yml)+ dsh.client(exports["./client"] 打包产物),作为真实 profile 插件安装,DSH client-modules 每次启动都会扫描加载。

🚀 快速开始

标准安装:dsh plugin add(重启常驻)

从本仓库安装:

▼
bash
复制代码
# 本地目录(在本仓库父目录执行): dsh plugin --profile web add ./dsh-drop-any-file # 或直接从 GitHub(任意 DSH 机器): dsh plugin --profile web add github:Zenjibad/dsh-drop-any-file # 或: dsh plugin --profile web add git+https://github.com/Zenjibad/dsh-drop-any-file.git

dsh plugin add = 向 profile 做 pnpm add + dsh.profile.bundles 协调:识别到本包的 dsh.bundle 声明后,把 dsh-drop-any-file 追加进 bundle 栈。重启 DSH,然后硬刷新浏览器标签页(Ctrl+F5)。启动时 client-modules 扫描器解析 exports["./client"],拖拽处理器随即生效。无需 cordis_define,重启后依旧。

⚠️ 注意:安装(或更新)客户端插件后必须硬刷新页面(Ctrl+F5)——DSH 客户端 HMR 只会热替换已加载的 bundle,不会把新增的 bundle 注入已打开的标签页。

手动挂载(备选)

  1. git clone https://github.com/Zenjibad/dsh-drop-any-file.git(任意位置)。
  2. 在 ~/.dsh/profiles/web/package.json 的 dependencies 加 "dsh-drop-any-file": "link:<仓库路径>",然后在 profile 目录 pnpm install。
  3. 重启 DSH。

使用前提

  • 任意处于活动状态的 DSH web 会话(保存目标是当前会话的 cwd)。
  • 没有打开会话 → 没有可保存的位置 → 插件不生效(输入框保持默认行为)。

⚙️ 配置

无配置文件、无持久化设置。行为由源码中的常量固定:

可调项位置默认值
POST 请求体上限(base64)src/index.ts 中的 MAX_BODY_BYTES80 MB(约 60 MB 文件)
单个文件上限src/index.ts 中的 MAX_FILE_BYTES60 MB
保存目标每次 drop 时解析sessions.get(sessionId).header.cwd(会话工作区)
拖拽拦截src/client/index.tsx在 window 上捕获阶段监听 dragenter/dragover/dragleave/drop
Toast 时长src/client/index.tsx6 秒

❓ 常见问题

Q: 我拖了文件还是提示「仅支持 PNG、JPG、WebP、GIF 格式的图片」? A: 插件没有加载到当前页面。先重启 DSH(如果 Host 半区尚未挂载),再硬刷新浏览器标签页(Ctrl+F5)。新增的客户端 bundle 只有整页刷新才会加载——HMR 不会把新 bundle 加进已打开的标签页。

Q: 我拖了文件但没反应 / 没有 toast? A: 拖拽必须发生在聊天窗口上方、且已打开会话,并且 drop 中至少要有一个非图片文件。如果全是图片,则走内置附加流程(设计如此)。可查看浏览器控制台的 drop-any-file save error 日志。

Q: 文件保存到哪里? A: 当前会话的工作区目录(sessions.get(sessionId).header.cwd)——也就是 Agent 的工作目录,Agent 可以用 read/glob/grep 等工具直接读取。

Q: 支持一次拖多个文件吗? A: 支持——drop 中每个非图片文件都会按顺序保存,toast 会逐一列出保存的文件名并统计失败数。

Q: 能拖超过上限的大文件吗? A: 不能——Host 对超过 60 MB 的文件返回 413,客户端显示失败 toast。如需更大文件,改 src/index.ts 里的 MAX_FILE_BYTES(以及 MAX_BODY_BYTES)后重新构建。

Q: 装了本插件后旧的动态插件还在? A: 本插件是打包式而非动态——没有动态孪生。若你之前安装过动态拖拽处理器,请用 cordis_stop / cordis_undefine 停掉,避免双重拦截。

Q: 如何彻底移除? A: dsh plugin --profile web rm dsh-drop-any-file(或删除 profile 依赖与 bundle 条目)后重启 DSH。

⚠️ 安全须知

  • 防路径穿越:文件名先取 path.basename(),再剔除所有非法路径字符(<>:"/\\|?* 与控制字符),恶意文件名也无法逃出工作区。
  • 写入范围受限:文件只写入解析出的会话 cwd,绝不写入任意路径。
  • 大小上限:请求体上限 80 MB、解码后文件上限 60 MB,Host 不会缓冲无界载荷。
  • 无额外 I/O:插件不发起网络请求、不执行 shell、不扫描磁盘——只做请求的那一次文件写入。
  • 同源 base64 传输:文件字节以 base64 JSON 提交到同源路由(DSH webServer),不经过任何第三方端点。

📦 项目结构

▼
text
复制代码
dsh-drop-any-file/ ├── src/ │ ├── index.ts # host 半区:body 读取、会话 cwd 解析、文件名清洗、writeFile、/drop-any-file/api 路由 │ └── client/index.tsx # client 包:捕获阶段拖拽监听、遮罩、toast、POST 到 host 路由 ├── cordis.patch.yml # dsh.bundle patch(启动时插入插件行) ├── tsdown.config.ts # 打包 host(node ESM)+ client(CJS ModuleLoader) ├── package.json # name、exports["./client"]、dsh.client + dsh.bundle ├── lib/ # 构建产物(index.js、client.js) ├── AGENTS.md # AI agent 仓库指南 ├── llms.txt / llms-full.txt ├── README.md / README.zh.md └── LICENSE

🙏 致谢

  • DeepSeek Harness — DSH 插件/动态运行时、Slots、主题、webServer、client-modules。
  • headroom-stats-plugin — 打包式 client 插件构建模式参考(tsdown host/client 拆分、cordis.patch.yml、dsh.client)。
  • DSH-better-sidebar — 打包式 client 插件构建模式的另一参考。

📄 License

MIT

界面增强

快捷安装

复制到终端去安装插件

dshplugin--profilewebaddgithub:Zenjibad/dsh-drop-any-file

温馨提示

装插件等于在本机跑第三方代码,权限与你相同,能读文件、用凭据、访问网络,工具审批管不到。请只装可信来源,并尽量锁定 commit。

站长:程序员鱼皮 老鱼简历 商务合作 增值电信业务经营许可证
2026 鱼皮AI导航 | 沪ICP备19026706号-6
站长:程序员鱼皮 老鱼简历 商务合作 增值电信业务经营许可证
2026 鱼皮AI导航 | 沪ICP备19026706号-6
🔥热门工具
朱雀AI检测朱雀AI检测
朱雀AI检测助手朱雀AI检测助手
LovartLovart
老鱼简历老鱼简历
WritePass官网WritePass官网
面多多面多多
CursorCursor
星月写作星月写作
零感AI零感AI
墨得问题墨得问题
dsh 插件推荐
DSH-agent-bridge
在 Web 输入框中切换原生 DSH Agent 与 Grok Build,并通过 ACP 代理 Grok Build 会话及斜杠命令。
dsh-gui-hanhua
DeepSeek Harness 界面信息汉化插件:工具调用卡片、插件列表、命令菜单与权限选择器显示中文,保留英文原名。
ai-plugin#dsh-plugin
aipx 工具包:技能之外还有 Hub Console 控制台——用约 4 个元工具代理全部 MCP 服务器,含服务器池健康、工具级启停、工具目录,以及直观展示 mcp_search 返回结果的搜索试验场。
dsh-gpu-pulse
DSH Web 界面内置的悬浮 GPU 监控:紧凑可拖动的条带,每张独立 GPU 一行(精确名称、利用率、显存、温度、功耗),数据来自 nvidia-smi;侧边面板或侧边卡片打开时保持在最上层;驱动支持时还列出显存占用最高的进程;无 NVIDIA 驱动的机器会退化为 n/a 胶囊。
dsh-sticky-notes
泡泡猫的即时便签 — 支持彩色标签、置顶、定时提醒与密码保护。