DeepSeek Harness plugin

dsh-upload-file

让 dsh Web GUI 支持把任意文件上传进对话:composer 附件按钮(SVG 图标 + 多选)+ 待发送文件条(类图片上传)+ OS 文件拖拽上传 + 会话内文件卡片(方案 B)+ 宿主端持久化存储 + read_uploaded_file 模型工具(无需构建,纯 JS)。

Jump to install

Source facts

Repository
OctKwong30/dsh-upload-file
Latest update
Aug 20, 2026
Category
Tools & Capabilities
GitHub stars
0
Format
plugin
Catalog evidence
Upstream dsh.bundle evidence
Evidence path
package.json#dsh.bundle
Checked against
0.1.0-rc.8
Upstream check date
2026-08-20

This evidence comes from the upstream catalog. This site has not installed, run, or security-reviewed the plugin.

Install

Start with a prompt that asks an agent to review the GitHub repository and source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to review the GitHub repository and source first.

Do not install or run any commands yet. Read this plugin's GitHub repository, README, and relevant source code. Then answer the questions below clearly and directly so I can decide whether it fits my needs:

1. What is this plugin, and what problem does it solve?
2. Who is it for, and what are its typical use cases?
3. How is it used after installation? Include one minimal example.
4. What known limitations or privacy, security, compatibility, or maintenance risks does it have?
5. Give a clear recommendation: recommend, conditionally recommend, or do not recommend, with reasons.

Distinguish statements documented by the repository, inferences from source code, and unknowns. If evidence is insufficient, say so explicitly. Do not guess or simply repeat the README.

GitHub: https://github.com/OctKwong30/dsh-upload-file
Plugin: dsh-upload-file
Author: OctKwong30

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer3 files
README.mdSource · read only

dsh-upload-file

让 DeepSeek Harness Web GUI 支持把任意文件上传进对话,两种入口:composer 输入框的附件按钮(SVG 回形针图标,多选),以及直接把 OS 文件拖进 composer 区域。选中的文件先由浏览器上传到宿主进程持久化存储,并以胶囊 chip 显示在 composer 上方的「待发送文件」条(与 shell 图片上传的「待发送图片」条同一体验):文件名 + 大小 + 移除按钮,发送时自动把干净的 markdown 链接(📎 名称(大小),绝对 URL 内含 sha256 id)并入消息文本;发送后会话里的用户消息渲染成文件卡片(图标 + 文件名 + 大小 + 打开,含文件链接的消息为卡片行 + 剩余文本气泡,纯文本消息保持官方气泡原样);模型通过 read_uploaded_file 工具读取文件内容(文本直接返回,二进制返回元数据与下载地址)。

文件字节不会进入对话日志——进入对话的只有引用文本,与官方 describe-image 插件的图片上传采用同一套思路。

功能

  • composer 工具行新增附件按钮(conversation.input.left 槽位,SVG 回形针图标,与 shell 工具按钮同款胶囊样式),支持一次多选文件上传;上传中图标切换为旋转进度弧。
  • 待发送文件条:已上传待发送的文件以胶囊 chip 显示在 composer 上方(conversation.input.dock 槽位的 FileDockrole="group" aria-label="待发送文件"),每个 chip 含回形针图标 + 文件名 + 大小 + 移除按钮;草稿保持干净(仅一个不可见占位符用于让“仅发文件”时发送按钮可用,发送钩子会在提交时剥离)。
  • 发送钩子:结构性包装 conversation.sendSession(与 describe-image 同款、幂等、可卸载、发送失败自动恢复待发条),发送时把待发送文件的链接并入消息文本;无待发文件时原样穿透,不拦截任何其他发送。
  • 会话内文件卡片:以 conversation.chat.node(key=user / steering,priority -1)接管用户消息渲染——消息含本插件文件链接时渲染成卡片行(role="group" aria-label="待发送文件",图标 + 文件名 + 大小 + 打开链接,纯链接消息不渲染气泡,类图片附件);否则完整复刻官方用户气泡(图片画廊 + MessageText + 时钟 + 复制按钮,官方 CSS 令牌逐条对齐)。渲染崩溃时 slots 会退役本 entry 并自动回退到官方渲染器。
  • 拖拽上传:把 OS 文件拖到 composer 区域时显示“松开以上传”提示条(document 级监听),松开即上传并进入待发送文件条。图片拖放不拦截,仍走 shell 自带的图片管线。
  • 宿主 POST /dsh-upload/attach 接收 base64 JSON,校验大小后按内容寻址(sha256:<hex>)落盘到 ~/.dsh/uploads/,返回 [file attachment …] 注释与 markdown 链接。
  • GET /dsh-upload/raw/<id> 以附件形式下载/预览已上传文件(跨重启可用,侧车元数据 + 摘要校验)。
  • 模型工具 read_uploaded_file:接受裸 id / 注释 JSON / markdown 链接三种引用形式,文本文件返回解码内容(上限内),二进制文件返回元数据 + 下载 URL。
  • 设置分区 dsh-upload-file(Settings → 插件配置):maxFileBytes(默认 20 MiB)、maxTextReadBytes(默认 256 KiB)、uploadsDir(默认空 = ~/.dsh/uploads)。
  • 纯 JavaScript(ESM + __ModuleLoader__ 静态包),无需构建,安装即可加载。

安装

方式一:从 GitHub 安装(推荐)

dsh plugin --profile web add github:OctKwong30/dsh-upload-file
# 重启 web GUI:dsh web(或按你的启动方式重启)

dsh plugin add 把参数转发到 profile 目录的 pnpm 执行:github: 前缀由 pnpm 直接从 GitHub 拉取仓库(同样支持 git+https://github.com/OctKwong30/dsh-upload-file.gitOctKwong30/dsh-upload-file 简写);安装后因包声明了 dsh.bundle.patch,会自动加入 dsh.profile.bundles 层。

升级到新版本:

dsh plugin --profile web update dsh-upload-file
# 再重启 web GUI

方式二:本地源码安装(开发调试)

cd D:/Projects/自由讨论
dsh plugin --profile web add ./dsh-upload-file
# 重启 web GUI:dsh web

./dsh-upload-file 这类相对路径会以你调用 dsh 的目录为锚点解析(等价 pnpm link),改完 lib/*.js 后重启 dsh web 即生效,适合边改边验;确认后推送到 GitHub,其他人即可用方式一安装。

方式三:--patch overlay 临时开发加载

# 用绝对路径指向 lib/index.js 的覆盖层(仅开发用)
cat > upload-overlay.yml <<EOF
- insert:
    - id: dsh-upload-file
      name: D:/Projects/自由讨论/dsh-upload-file/lib/index.js
EOF
dsh web --patch ./upload-overlay.yml

方式四:手动编辑 profile 补丁

把以下内容追加到 ~/.dsh/profiles/web/cordis.patch.yml,并确保 dsh-upload-file 已作为依赖安装到该 profile:

- insert:
    - id: dsh-upload-file
      name: dsh-upload-file

使用

按钮上传

1. 打开任意会话,在输入框工具行点击回形针按钮(鼠标悬停提示“上传文件到对话”)。 2. 选择本地文件(默认上限 20 MiB,可多选)。 3. 每个文件以胶囊 chip 出现在 composer 上方的待发送文件条(文件名 + 大小 + × 移除),草稿保持干净;即使不输入文字,发送按钮也可用(“仅发文件”消息)。 4. 发送。发送钩子自动把每条链接并入消息文本(链接格式如下),会话里的用户消息渲染成文件卡片(图标 + 文件名 + 大小 + 打开;纯链接消息不显示气泡,类似图片附件;文字 + 文件则文字气泡 + 卡片行):

📎 [report.pdf(12.1 KiB)](http://127.0.0.1:3080/dsh-upload/raw/sha256:abc…)

5. 点击卡片打开/下载文件;模型从链接 URL 提取 sha256:abc… 后调用 read_uploaded_file 读取(参数可传裸 id、链接或 URL)。

拖拽上传

1. 从系统文件管理器把一个或多个文件拖到 Web GUI 的 composer 区域。 2. 出现“松开以上传文件到对话”提示条后松开鼠标。 3. 非图片文件自动上传并进入待发送文件条(同按钮流程);图片文件交给 shell 的图片管线(不冲突,可混用)。

架构

浏览器半部 lib/client.js               宿主半部 lib/index.js
+---------------------------+          +----------------------------------+
| 📎 附件按钮 + 拖放 inlay |  base64  | POST /dsh-upload/attach          |
| (input.left / input.dock)| ───────▶ |   → 校验/落盘 ~/.dsh/uploads/    |
| 上传 → 待发送文件条(rail) |          |   → 返回 note + markdown          |
| 发送钩子: sendSession 包装 |          | GET /dsh-upload/raw/<id> 下载    |
|   → 链接并入消息文本       |          | read_uploaded_file 模型工具      |
| 会话内卡片: chat.node 接管 |          |                                  |
|   (key=user/steering, -1) |          |                                  |
|   含链接→卡片;否则复刻官方 |          |                                  |
+---------------------------+          +----------------------------------+

双语文案

浏览器半部内置 zh / en 迷你词典,随 GUI 语言设置切换:附件按钮提示、拖放提示、待发送文件条、错误提示(超限/读取失败/网络错误),以及文件卡片复刻官方气泡所需的全部文案(复制、时钟、图片画廊等)。

与官方插件体系的关系(参考文档):

  • 第一个 Harness 插件apply(ctx) + inject 插件形态。
  • 开发一个 TooldefineTool 工具定义。
  • 打包与安装插件dsh.bundle.patch 组合包机制与 dsh plugin --profile <name> add
  • 客户端模式参考已装插件 @linxin666/dsh-tool-describe-image(attach 路由 + sendSession 发送钩子)与 @linxin666/dsh-client-ui-aionui-panelconversation.input.dock 槽位 + conversation.input.for(actx) 写草稿 + 拖放 inlay 的 document 监听模式)。

配置

Settings → 插件配置 → dsh-upload-file:

字段默认说明
maxFileBytes20971520单文件字节上限
maxTextReadBytes262144read_uploaded_file 文本预览上限
uploadsDir(空)上传根目录;空 = ~/.dsh/uploads

安全说明

  • id 必须匹配 sha256:[0-9a-f]{64},杜绝任意路径读取。
  • 文件名清洗为 basename,去掉路径分隔、换行与控制字符,防头注入。
  • 上传/下载都在本机 loopback 的 webServer 上;内容寻址 id 不可猜测。
  • 客户端声明 mediaType 仅作展示与文本判定,不信任为安全边界。

已知限制与扩展方向

  • 待发送文件条渲染在 composer 上方conversation.input.dock 槽位),shell 的图片条渲染在输入卡内部;位置略有差异但交互一致。
  • 为让“仅发文件”消息可用,草稿中会写入一个不可见占位符(U+200B),发送钩子提交前剥离;若发送钩子因 shell 升级而失效,占位符会以空文本随消息发出(shell 会忽略空消息)。刷新页面后 rail 清空,但已上传的字节仍在 ~/.dsh/uploads/(内容寻址,无害)。
  • 会话内文件卡片依赖手写复刻官方用户气泡:随 shell 升级可能漂移(官方 CSS 类名是构建期哈希)。若官方气泡样式更新导致观感不一致,只需同步本插件 CHAT_CSS 中的 .dsh-uf-* 规则;渲染逻辑崩溃时 slots 会自动回退到官方渲染器,不会白屏。卡片仅识别本插件生成的绝对 URL 链接(/dsh-upload/raw/sha256:…),旧格式(相对路径 / JSON 注释)消息按普通文本渲染。
  • 混合拖入“图片 + 非图片”时,非图片由本插件上传,图片由 shell 图片管线处理;若你的 shell 的 drop 监听器在插件之后注册或调用了 stopImmediatePropagation,混合/纯图片拖放可能被其独占,此时用附件按钮即可。
  • 上传文件不做定期清理;如需会话级生命周期可在宿主侧挂定时清理任务。
  • 拖放提示条使用内联样式,未跟随皮肤主题;如需定制可自行加 CSS。
  • 本包 lib/*.js 是可直接运行的产物;若想改用 TS/JSX 工程化,可参考 dsh-web-ui 家族仓库(tsdown + dsh.bundle.patch)的构建方式。

License

MIT