← 返回AI教程
🌐 其他

DeepSeek Harness 插件:Excel 拖进输入框,AI 自己去读文件

来源:掘金 · 发布于 2026-08-21 09:09:31
DeepSeek Harnes
给 DeepSeek Harness 写了个插件:Excel 拖进输入框,AI 自己去读文件 痛点:DSH 的输入框只认图片

DeepSeek Harness 插件:Excel 拖进输入框,AI 自己去读文件

gezg 2026-08-21 12 阅读4分钟

给 DeepSeek Harness 写了个插件:Excel 拖进输入框,AI 自己去读文件

一次「顺手解决小痛点」的插件开发实录:从调研 DSH 插件体系,到逆向官方包类型契约,再到和原生图片拖拽「斗智斗勇」的全过程。

痛点:DSH 的输入框只认图片

用 DeepSeek Harness(下称 DSH) Web GUI 的同学应该都遇到过:想把一个 Excel 拖进输入框让 AI 分析,结果弹出一个错误提示——只支持上传 png 等图片。

但这事儿仔细想想,其实根本不需要「上传文件」:

  • DSH 的 Agent 本来就有文件系统工具(read、glob、grep……),给它一个绝对路径它就能自己去读;
  • Excel/PDF 这类文件,走「图片附件」通道本来就不通,走「路径引用」通道反而能享受 Agent 的全量技能(xlsx 解析、pandas、大文件处理);
  • 文件内容不跨浏览器边界,隐私上也更安全。

于是我写了一个 DSH 插件:dsh-drag-file——把任意文件拖进输入框,上方显示文件占位 chip,发送的消息实际是这行文件的绝对路径。AI 收到路径,自己去读文件。

image.png

效果演示

你(从 Finder 拖一个 Excel 进输入框区域)
    ↓ 松手
输入框上方出现文件 chip:📄 20260820.xlsx
    ↓ host 在磁盘上按文件名搜索(工作区 + ~/Downloads 等)
输入框草稿自动填入:
    /Users/xxx/Downloads/0818/20260820.xlsx
    ↓ 你继续打字
    /Users/xxx/Downloads/0818/20260820.xlsx
    帮我按车型统计各类价格差异,输出一份汇总表
    ↓ 发送
Agent 收到路径文本 → 自己用文件工具读取 → 开始干活

关键点:发送的就是纯文本。没有隐藏的附件注入,用户在输入框里能看到、能编辑即将发出的路径——所见即所发。

调研:DSH 插件长什么样

DSH 是「一切皆插件」的微内核架构(底层是 Cordis 框架),官方文档里有插件开发教程和 extension cookbook。一个插件就是一个导出 apply(ctx) 函数的 TypeScript 模块:

import type { Context } from '@deepseek-ai/cordis'

export const name = 'my-plugin'
export const inject = ['tools']   // 声明依赖的服务

export function apply(ctx: Context) {
  // 通过 ctx 注册能力:工具、事件监听、UI slot……
}

我这个插件是典型的 host + client 双面插件:

  • Host 面(Node.js 进程):能访问磁盘。负责「文件名 → 绝对路径」的搜索,以 Typert Remote 服务的形式暴露给浏览器
  • Client 面(浏览器):负责拖拽事件捕获、文件 chip 渲染、把路径写进输入框草稿

两端通过 DSH 的 Typert Remote 机制通信(带严格 zod schema 校验的 RPC),共享一个 contract 文件定义 wire 格式。

一个绕不开的浏览器安全限制

有人会问:浏览器拖拽事件里不是有 File 对象吗,为什么不直接拿路径?

因为浏览器出于安全考虑不暴露绝对路径——File.name 只有文件名。所以「文件名 → 绝对路径」必须在 host 侧做磁盘搜索,这也是为什么需要 host/client 双面结构:

浏览器                        Host (Node.js)
──────                        ─────────────
拖拽事件:file.name ──────→  dragFile/resolve(sessionId, name)
                              │
                              ├─ 搜索会话工作区(深度 10)
                              ├─ 搜索 ~/Downloads、~/Desktop、~/Documents(深度 3)
                              │  (跳过 node_modules/.git 等)
                              ↓
chip 显示候选路径    ←──────  { candidates: [{ path, inWorkspace }], truncated }
唯一匹配自动填入草稿

安装使用

已发布到 npm,一行命令:

dsh plugin --profile web add dsh-drag-file

(也可以从 GitHub 安装:dsh plugin --profile web add github:gezg/dsh-drag-file)

重启 web profile、刷新页面即可。默认搜索会话工作区 + ~/Downloads、~/Desktop、~/Documents,都可以配置:

- id: dsh-drag-file
  name: dsh-drag-file
  config:
    searchDirs: ["~/Downloads", "~/Desktop", "~/Documents"]
    workspaceDepth: 10
    searchDirsDepth: 3
    maxResults: 20

macOS / Linux / Windows 全支持(Windows 的 C:\Users\... 路径 chip 也认)。

写在最后

整个过程最大的感受是:DSH 的「一切皆插件」不是口号——输入框上方的座位(slot)、草稿写入的动作(inputActions)、host 侧的 RPC(Typert Remote)全是公开可扩展的接缝,一个「拖文件」的小功能完全不需要碰框架一行代码。

而插件开发的乐趣恰恰在这种「和原生行为划清边界」的博弈里:捕获阶段拦截、合成事件复位、草稿即真相源——每一个坑背后都是对框架事件流的更深一层理解。

仓库在这里,欢迎 star / PR:

github.com/gezg/dsh-dr…

如果这篇对你有帮助,或者你在 DSH 上也踩过类似的坑,评论区聊聊 👋