DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Session Files — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
S

@deepseek-ai/dsh-session-files

Session Files

Session file upload for the DeepSeek Harness Web UI: an attach button lets the user upload arbitrary files (not just model-native images); files land in the session workspace under uploads/<sessionId>/, and an injected in-session note tells the model which directory belongs to this session; a share_

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:MST19711/dsh-session-files#46316fb99fbcd9e8fb04105cf910b89b958e8761
READMECompatibilityVersions

Description

Session file upload for the DeepSeek Harness Web UI: an attach button lets the user upload arbitrary files (not just model-native images); files land in the session workspace under uploads/<sessionId>/, and an injected in-session note tells the model which directory belongs to this session; a share_session_file tool lets the model hand files to the user as clickable download cards inline in the conversation. Since 0.3.0 the upload entry yields to the built-in uploader when the harness ships one (dsh >= 0.1.5). Since 0.4.0 the plugin also adds its own download link to the new 0.1.5 surfaces that only open files: a Download item in the delivered-file card's action menu (taking over that caret when a desktop-less Host disables the built-in menu) and a per-row download button in the right Sidebar's file browser. 0.4.1 is a bug-fix release: the 0.4.0 failure toast function was named `notify`, which shadowed the store's own `notify()` in the same bundle scope and made every store update append an empty red toast at the bottom of the page while silencing store subscribers. 0.5.0 makes the whole host half world-agnostic: every workspace read/write/delete now goes through the official filesystem seam (ctx.fs) and the subprocess seam instead of node:fs, so the plugin works identically in a local workspace and in a remote SSH workspace (where the session cwd only exists on the far side); a node:fs fallback is kept for hosts that ship no ctx.fs.

Compatibility and provenance

Session Files is published as @deepseek-ai/dsh-session-files and currently resolves to version 0.5.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
9/13/2026

Versions

0.5.0stable
9/13/2026
0.4.1stable
9/13/2026
0.4.0stable
9/12/2026

Related plugins

Loading related plugins…

Latest
0.5.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
9/13/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in productivity-workflow.

Codex Ui@michengai/dsh-codex-uiDSH Codex UI — 为 DeepSeek Harness Web 提供 Codex 风格侧栏、工作区会话树、全局搜索和轮次导航 · A Codex-style sidebar, workspace session tree, global search, and turn navigation for DSH WebAcp App@deepseek-ai/dsh-acp-appThe dsh ACP profile bundle: automation-only JSON-RPC stdio and process lifecycle over dsh-baseAutomation@michengai/dsh-automationExecute coding tasks on a schedule in an independent DSH Session, with dual-entry management via a Web settings page and Agent.Easyrewritedsh-easyrewriteDSH Web内目前最无感的消息撤回、重编辑插件,原版体验,兼容性强,功能简单可开关,设置丰富,现代化轻量ui框架。The most seamless message recall & re-edit plugin for DSH Web — native experience, strong compatibility, simple toggles, rich settings, modern lightweight UI. DSH Web で最もシームレスなメッセージ撤回・再編集プラグイン——ネイテ

README

Session Files — DSH 会话文件的任意文件上传

npm 包名 / 仓库名 @deepseek-ai/dsh-session-files。

让用户可以在 DSH Web 界面里给当前会话上传任意文件(不限图片),并把文件落到本会话工作区的专用目录:

<session.workspace>/uploads/<sessionId>/<文件名>
  • <session.workspace>:当前会话的工作目录(session cwd);
  • uploads/:专门存放此类内容的目录(约定名,可通过代码顶部常量调整);
  • <sessionId>/:对应该 session 的子目录。

上传成功后插件自动向该会话注入一条消息,引导 LLM 知道「哪一个目录对应本 session」并提供文件清单;会话恢复时若该目录已存在,也会再次提示模型。

特性

  • 🖇 聊天输入区左侧新增「上传文件」按钮(DSH 官方回形针图标),支持多选、任意类型(文本/PDF/压缩包/音视频/二进制…)
  • 📁 文件落在 <workspace>/uploads/<sessionId>/,只有用户真正上传时才创建目录(无上传则目录不存在)
  • 🧠 上传成功后经 agent.inject 注入模型可见消息:会话上传目录绝对路径 + 相对路径约定 + 文件清单
  • 🔁 会话启动/恢复时,若上传目录已存在,自动注入同等的目录提示(休眠会话也能知道该看哪里)
  • 🗂 输入区上方 dock 显示已上传文件芯片:点击打开/预览,× 删除
  • 📥 文件可通过浏览器直接下载(文本/图片/PDF 内联预览,其余附件下载)
  • 🎁 模型提供文件下载(v0.2.0):模型调用 share_session_file 工具即可把工作区内 任意文件(处理结果等)递到对话流——渲染为可点击的下载卡片(文件名/类型/大小/说明), 会话恢复后卡片依然可见
  • ⚙️ 设置页可配:启用开关、检测到 dsh 自带上传时自动让位、是否显示文件 dock;展示单文件大小上限与当前让位状态
  • 🚀 上传入口让位(v0.3.0):dsh 0.1.5 自带任意文件上传,输入区已有「添加附件」。本插件 默认在检测到它时隐藏自己的回形针,避免出现两个功能重叠的按钮;取消该设置即可切回本插件的 入口(两者落点不同:本插件 → 会话工作区,内置 → DSH 附件库)
  • 💬 交付语义消歧(v0.3.0):把「用 share_session_file 把文件发到用户浏览器(可下载)」 与「内置 present 在 DSH 主机桌面上打开文件」明确区分给模型,并注册为 system prompt 规则(每会话恒在)——远程访问 Web 时后者根本用不上,模型却容易误以为已经交付
  • ⬇️ 新 UI 下载入口(v0.4.0):dsh 0.1.5 自带的「交付文件卡片」与右侧 Sidebar 的 「文件」浏览都只能打开/预览文件,没有把文件交给用户的手段(卡片的下拉菜单在无桌面 主机上还是禁用的)。本插件在这两处补上自己的下载链接:交付卡片「打开」右侧的 ⌄ 菜单 多一项「下载」,主机无桌面时接管那个失效的 ⌄ 位置;文件浏览的每一行右侧多一个 下载按钮(见「新 UI 下载入口」)
  • 🔐 安全:sessionId 白名单 + 文件名净化;path 下载/分享严格锁定在会话工作区内 (拒绝 ..、越出 cwd 的绝对路径);单文件大小上限默认 512 MiB
  • 🩹 空红框修复(v0.4.1):v0.4.0 的失败提示函数与 store 的 notify() 同作用域同名, 函数声明提升后覆盖了后者——每次 store 更新都会在页面底部插一个空文本的红色小椭圆, 同时 store 订阅通知失效。v0.4.1 把提示函数改名 showToast 并加空值防线(见下)
  • 🛰 远程工作区可用(v0.5.0):宿主半的所有工作区读写都改走官方文件接缝 (ctx.fs + ctx.subprocess),不再假设「会话 cwd 就是宿主上的真实目录」。 在 SSH 远程工作区会话里,上传落盘、列表、下载/预览、删除、share_session_file 全都落到远端主机上;宿主没有 ctx.fs 的旧版本自动退回本地 node:fs 实现 (行为与 v0.4.1 相同)

界面

  • 输入区左侧(会话存在时):回形针图标按钮,上传中显示剩余计数角标。 dsh ≥ 0.1.5 上默认让位给内置的「添加附件」,此按钮不出现(见「上传入口让位」)
  • 输入区上方 dock:「已上传 N」+ 文件芯片(名称/大小/删除),以及「本会话上传目录」的绝对路径
  • 对话流:模型调用 share_session_file 后,该条工具调用渲染为文件卡片 (图标 + 文件名 + 类型/大小 + 说明 + 「下载」按钮),点击即保存
  • 对话流·交付文件卡片(dsh ≥ 0.1.5):「打开」右侧的下拉菜单里多一项「下载」; 主机没有桌面导致该菜单整体失效时,那个 ⌄ 由本插件接管,点开是「下载 / 复制下载链接」
  • 右侧 Sidebar·「文件」浏览(dsh ≥ 0.1.5):每个文件行右侧一个安静的下载按钮
  • 设置:「设置 → 会话文件上传」——四个开关 + 单文件上限 + 当前让位状态与下载入口状态 (「[生效] …」/「[已让位] …」/「[已关闭] …」,状态是显式可见的,不会"按钮悄悄消失")

安装(官方方式)

前置:dsh 已安装且目标 profile(默认 web)在运行。本插件通过官方的 dsh plugin add 安装(dsh plugin 是 pnpm 的薄转发层);包内声明了 dsh.bundle.patch(自带 cordis.patch.yml),因此 plugin add 一步即可完成安装,无需手动编辑任何 profile 配置。

# 方式一:仓库脚本(自动 npm pack + dsh plugin add)
bash install.sh

# 方式二:手动执行官方命令
npm pack -y                        # 产物 deepseek-ai-dsh-session-files-<ver>.tgz
dsh --profile web plugin add ./deepseek-ai-dsh-session-files-<ver>.tgz

安装成功后重启 dsh(让 profile 重新组合 bundle 层),刷新浏览器即可在输入区左侧看到 📎 按钮。

验证

重启并刷新页面后:

  • 单元/集成测试(两套,都零第三方依赖):
    npm test          # test-host.mjs(本地世界)89 项 + test-host-remote.mjs(远程世界)38 项
    
    后者把会话 cwd 设成宿主上不存在的远端占位拼写,只经"远端接缝"映射到真实目录, 因此任何一处漏改的 node:fs 都会立刻失败;
  • 打开一个会话,输入区左侧出现 📎;点它选任意文件上传,输入区上方出现「已上传 N」芯片;
  • 命令行核对(把 <dsh-address> 换成你实际访问 dsh 的地址):
    # 客户端插件已加载(应以 window.__ModuleLoader__.load( 开头)
    curl -s http://<dsh-address>/plugins/@deepseek-ai/dsh-session-files/client.js | head -c 80
    # 配置端点
    curl -s http://<dsh-address>/dsh-session-files/config
    # 列表端点(目录不存在时返回空列表,不创建目录)
    curl -s 'http://<dsh-address>/dsh-session-files/list?sessionId=<某会话id>'
    
  • 工作区核对:`ls <workspace>/uploads/<sessionId>/` 应能看到刚上传的文件;未上传过的会话不应存在 uploads/<sessionId>/ 目录

上传入口让位(v0.3.0)

dsh 0.1.5 起自带任意文件上传(@deepseek-ai/dsh-client-file-upload,宿主服务 fileUploads, 客户端服务 fileUpload),输入区自带「添加附件」回形针。本插件若照旧渲染自己的回形针, 用户会看到两个功能重叠的按钮。

设置项 检测到 DSH 自带上传时自动让位(默认开) 控制这件事。刻意做成设置项而不是 硬编码自动判断,因为两者落点语义不同,静默切换会埋雷:

本插件内置(dsh ≥ 0.1.5)
落点会话工作区 uploads/<会话ID>/$DSH_HOME/attachments/v1/(内容寻址)
属性可写;随工作区备份;文件侧栏可见只读副本;不在工作区;侧栏看不到
模型拿到一条说明本会话上传目录的注入消息逐条 prompt 的文本 handle + 只读路径

探测走两条渠道取「或」,因此不会出现按钮先闪出来再消失:客户端服务(ctx.get("fileUpload"), apply 时同步可得)与宿主 /config 的 builtinUpload(权威但异步,作为兜底)。 dsh 0.1.0-rc.x 上两条都是 false,行为与 v0.2.2 完全一致。

交付语义:「发给用户」≠「在用户电脑上打开」(v0.3.0)

内置的 present 工具(dsh 0.1.5 新增,挂在 agent preset 里)只把工作区文件声明为交付物, 它提供的动作是在 DSH 主机(服务器)的桌面上打开文件 / 在文件管理器中显示。用户远程访问 Web 时那个动作不可用(宿主在打开前就用 workspaceDesktop().available 拦掉),而模型很容易 把「我调用了 present」当成「用户已经拿到文件了」,于是不再调用 share_session_file。

share_session_file 走的是浏览器下载卡片,是远程用户真正拿到文件的唯一方式 (dsh 0.1.5 全库只有 dsh-session-log-export 用了 Content-Disposition,没有任何 download 属性或下载包;文件侧栏只是有界预览)。三处让模型知道:

  1. share_session_file 的工具描述(首句即「把文件直接发给用户」);
  2. 注入的会话消息尾部(短句,只在真有上传文件时出现);
  3. system prompt section dsh-session-files:delivery-vs-open(每会话恒在)——与官方 ui-deliverables 宿主半用的同一个缝;其 order 在版本间变过(0.1.0-rc.x 是字面量 190,0.1.5 起是 getSectionOrder("DELIVERABLE_FILE_REFERENCES") = 9000), 因此本插件走 getSectionOrder(...) + 1,旧版回退 190 + 1,两代都紧跟在官方指引之后。

文案写成「若你的工具列表里有 present」的条件句式,不做存在性探测:0.1.0-rc.x 上该工具 还不存在;0.1.5 上它在 agent preset(agent plane)里,而 profile 作用域的 tools.get() 看到的是全局层视图,探测并不可靠。

新 UI 下载入口(v0.4.0)

dsh 0.1.5 的 Web UI 多了两处"看文件"的地方,两处都只有打开,没有交付:

新界面它自带的能力缺的那一半
交付文件卡片 ui-deliverables(对话流每轮末尾)「打开」把文件在主机桌面上用默认应用打开;⌄ 菜单有「用默认应用打开」「打开所在文件夹」主机没有桌面时整个菜单 disabled,⌄ 点不动;有桌面时对远程用户也没意义——两处都没有下载
右侧 Sidebar 的「文件」浏览 ui-sidebar-files点行 → 在 Sidebar 里预览没有下载;想拿到文件只能先预览再想办法

本插件正是"把工作区文件交给用户浏览器"的那一半,于是在这两处补上自己的下载链接 (GET /dsh-session-files/file?sessionId=…&path=…&download=1,与 share_session_file 卡片同一个端点、同一套工作区越界校验):

  1. 交付卡片:能借 DSH 的 ⌄ 菜单就借——菜单打开时注入一项「下载」(克隆它自己的菜单项 节点,因此样式天然一致)。菜单因主机无桌面而 disabled(根本打不开)时,在同一位置 接管:隐藏那个失效的 ⌄,放一个外观一致的 ⌄,点开是本插件自己的小菜单 ——「下载」+「复制下载链接」。主机能力恢复(菜单可用)时自动把位置还回去。
  2. 文件浏览:每个文件行的右侧加一个安静的下载按钮,点击直接下载,不改变"点行打开预览" 的原行为;嵌套目录、中文/空格文件名都照常(路径经 URL 编码走同一端点)。

为什么是 DOM 注入:dsh 0.1.5 的客户端扩展点里没有"交付卡片菜单项"和"文件树行操作" 这两席(sidebar.right.tab.menu.item 只覆盖 tab 胶囊的右键菜单),而这两处恰恰是用户找 下载的地方。注入只做三件事——追加自己的节点、临时隐藏一个已经失效的按钮(可逆, 能力恢复即还原)、监听点击;不移动、不删除、不修改 DSH 自己的节点内容。观察者被节流到 4 次/秒,且只在 MutationObserver 报告变化时运行。

设置项 在新版 UI 的交付卡片 / 文件浏览里提供下载入口(默认开) 可以随时关掉: 关掉会立刻回收所有注入物(包括还原被隐藏的 ⌄),重新打开立刻恢复,不需要刷新页面。 dsh 0.1.0-rc.x 上这两个界面不存在,注入自然什么也不做,行为与 v0.3.0 一致。

已知边界

  • 注入依赖 DSH 自己界面上的稳定锚点:[data-presented-file](卡片)、卡片预览按钮的 title(绝对路径)、⌄ 的 aria-haspopup="menu"、文件行的 li[data-files-entry=file] 与 data-files-path。DSH 改这些锚点时要跟着改(dsh 0.1.5-rc.1/rc.2 实测均可用)。
  • 菜单项注入只在点击 ⌄ 之后发生,因此不会影响没打开菜单时的 DOM。
  • 「本轮文件改动」(produced files)那些内联文件芯片仍未提供下载入口:它们是行内文字链接, 没有下拉位置可依附,加图标会破坏阅读节奏。需要时可先用 Sidebar 预览或 share_session_file。

远程工作区(SSH)支持(v0.5.0)

工作区在远端主机上时(会话 cwd 由提供者插件路由到 SSH,例如 dsh-workspace-enhancement),宿主上的 cwd 只是一个占位拼写 (<DSH_HOME>/dsw-routes/<机器id>/<远端绝对路径>),真正的文件在远端。v0.4.1 及以前, 宿主半直接 node:fs 操作 cwd —— 落到虚空,于是下载/预览报 文件不存在或不是普通文件、 上传报 文件落盘失败、列表为空。v0.5.0 把这一层整体换成官方接缝:

能力走的接缝
解析 / 元信息 / 列目录ctx.fs.resolve / stat / listDir
下载、预览ctx.fs.readByteRange(1 MiB 一窗,不整文件进内存)
小文本上传ctx.fs.writeText
二进制 / 大文件上传ctx.subprocess(sh -c 'cat > "$1"',流式)
建上传目录、删除文件ctx.subprocess(mkdir -p / rm -f;接缝没有这两个能力)
给模型/界面的路径ctx.fs.processPath = 执行世界里的绝对路径(远端会话给远端路径)

世界完全由接缝决定(本地 / SSH / 容器 / WSL),插件不再猜;node:fs 只用于宿主侧 临时文件,以及宿主没有 ctx.fs 时的 LOCAL_FS 兜底(等价 v0.4.1 行为,也因此 inject 里刻意不写 "fs")。细节、两个实测踩坑(远端 writeText 不建父目录、 为什么不能把 fs 放进 inject)与验证矩阵见 RELEASE_NOTES-v0.5.0.md。

v0.4.1:修掉页面底部那个空的红色椭圆

v0.4.0 新增的失败提示函数写成了 function notify(text),而本文件上面 store 段里 早有一个 function notify()(通知 React 订阅者)。DSH 的客户端插件是一个 flat bundle, factory: (require) => { … } 的函数体就是唯一作用域 —— 两个同名声明里后者覆盖前者:

function notify() { for (const fn of listeners) fn(); }   // store,被覆盖
function notify(text) { …appendChild(空红框)… }            // v0.4.0 toast,实际生效

后果有两条:

  1. 看得见:store 每次 update()(切换会话、刷新文件列表、visibilitychange、 上传进度、页面加载…)都会往 document.body 插一个空文本的红框 (fixed / left:50% / bottom:28px / #ec1313 / radius:10px → 28×16 px 的红色小椭圆), 4.2 秒后自动移除;
  2. 看不见:store 的订阅通知整个失效,subscribe(force) 的组件与注入器的 scheduleSweep 收不到通知,会话切换后下载入口可能持着过期的 sessionId。

修法即改名 + 空值防线(宿主半一行未动):

-    function notify(text) {
+    function showToast(text) {
+      if (text === undefined || text === null || text === "") return;

排查记录、复现脚本与截图:DSH/tasks/2026-09-13-dsh-red-ellipse/; 可复用教训:DSH/knowledge/dsh-client-plugin-notify-shadowing.md。

目录与模型引导

  • 上传目录固定为会话 cwd 下的 uploads/<sessionId>/,模型可通过 fs 工具直接访问(相对 cwd 或绝对路径);
  • 上传成功后注入的模型可见消息包含:目录绝对路径、相对路径约定、本次文件清单,以及「用户提到上传的文件时,先列目录再按需读取」的指引;
  • 会话启动/恢复时(agent/session-start)若目录已存在,注入同类提示;目录不存在则不做任何事(也不会创建);
  • 引导消息同时告知 share_session_file 工具:用户索要文件时,应调用它(而不是只报路径)。

安全说明

  • sessionId 必须匹配 [A-Za-z0-9._-]{1,80} 且是当前已加载的会话;
  • 文件名只取叶子名,拒绝路径分隔符、控制字符、./..、隐藏文件与超长名;
  • 单文件大小上限默认 512 MiB(uploads 目录在首次上传时创建,临时文件写在同一目录并以 .part- 前缀隔离,成功后原子 rename);
  • 下载端点做了类型映射与目录锁定,GET 只能读取该会话目录内的文件。

卸载(官方方式)

dsh --profile web plugin remove @deepseek-ai/dsh-session-files

随后重启 dsh 并刷新页面;plugin remove 会自动把本插件从 dsh.profile.bundles 层移除(不再加载),无需手动清理配置。已上传的文件保留在 uploads/<sessionId>/,不会被删除。

打包与发布

npm run check     # ① 同作用域重名检测(含检测器自测)——prepack 会自动先跑
npm pack          # ② 产物 deepseek-ai-dsh-session-files-<ver>.tgz

prepack 钩子已接上 npm run check:检测不过就打不出包。 CI 见 .github/workflows/checks.yml(push/PR 跑 node --check + npm run check, 零依赖、不需要 npm install)。

发布到 npm 前把 package.json 的 "private": true 去掉。发布到 GitHub: 仓库即本目录(不含 node_modules/);tgz 可保留在仓库中作为安装资产, 或改用 GitHub Releases 附件 + 仓库内保留 install.sh 与文档。更新发行物时 请同时新增 RELEASE_NOTES-v<ver>.md 并更新本 README 与 GITHUB_INTRO.md。

防同名覆盖:scripts/check-client-shadowing.mjs

客户端半是一个 flat bundle——window.__ModuleLoader__.load({ factory: (require) => { … } }) 的函数体就是唯一作用域。在这个作用域里写两个同名 function 声明(或 function + var), 后者会静默覆盖前者:语法合法、不抛错、不打日志,node --check 与打包都不报, 只在运行时以"某个功能莫名失效 / 多出一个奇怪的 DOM 节点"的形式暴露。

v0.4.0 就栽在这上面:失败提示 notify(text) 覆盖了 store 的 notify(), 于是每次 store 更新都往页面底部插一个空的红色 toast(详见 RELEASE_NOTES-v0.4.1.md 与 DSH/knowledge/dsh-client-plugin-notify-shadowing.md)。

检测器做的是作用域级比对,而不是简单的文本 grep:

  • 自己写的词法器,正确跳过注释 / 字符串 / 模板 / 正则(CSS 模板里的 {} 不会打乱作用域);
  • 按 {}、for (…)、catch (…) 建作用域树,只报同一作用域内的重名;
  • 区分 function 声明与具名函数表达式(React.memo(function X(){}) 不误报)、 区分语句位置的 class 与 class extends 匿名表达式;
  • var 归到最近的函数作用域;空圆括号/大括号不配平会在报告里警示;
  • 内置 12 条自测(含"扁平 bundle 里两个同名 function"这一真实形态、正则/模板/块作用域 /for…of 各一条防误报用例);检测器自身不可信时直接以退出码 2 终止。
node scripts/check-client-shadowing.mjs                 # 缺省扫描 ./lib/*.js
node scripts/check-client-shadowing.mjs lib/client.js   # 指定文件
node scripts/check-client-shadowing.mjs --self-test     # 只跑自测
node scripts/check-client-shadowing.mjs --json          # 机器可读

退出码:0 干净;1 发现会覆盖的重复声明;2 用法/读取/自测失败。

精度实测:对 dsh 0.1.5-rc.2 自带的 50+ 个官方 client bundle(含大量压缩代码、 具名函数表达式、class extends)零误报;对 v0.2.2 / v0.3.0 判为干净, 对 v0.4.0 精确报出 notify(第 271 行 vs 第 370 行)。

可复用副本(供其它插件仓库取用):DSH/templates/plugin-checks/。

License

MIT