DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

Hope2023Dcr /

Hope2023Dcr/dsh-gallery

Verified

产出台:图片 / 文件 / 音视频实时可见、当场校验;原生产出标签(素材 / 过程稿 / 定稿 / 未归类)可手动改且持久生效,改标签动作与图上圈选批注攒进反馈篮,由人审核合并后发送,全程零自动发送;视频「截取当前帧」自动存入当前对话资产;图上左键画矩形框、右键多点闭合成实心多边形,可导出 ComfyUI 直接可用的 RGBA 遮罩(选区内 alpha=0、RGB 保留原图),另出红 / 绿 / 蓝纯色半透明填充预览图供目视核对;把图拖进对话框会自动带上文件名与绝对路径(含对应主遮罩名),Agent 不必

★ 1 Stars0 Forks1 IssuesN/A Community rating0 Confirmed installs
View on GitHubProject homepage
READMESource: main@5b361e83

产出画廊 · DeepSeek Harness (DSH) 插件

核心问题:Agent 干活的过程是黑箱。 DSH 默认只在任务结束时才列出产出的文件名和路径 —— 中间生成的东西你看不见, 出了偏差只能等它跑完再返工。

这个插件把产出目录变成右侧栏里的实时画廊:图片生成就可见、文件点开就预览、 视频音频能在面板里直接播放并拖进度条, 让你在任务进行中就能看到产出、当场校验,而不是结束后才发现做错了。

📌 当前是 0.x 开发预览版:核心能力(实时看见、当场校验、就地处置)已可用。 v0.13.6 起,判定还能攒成一条结构化决策草稿写进输入框,由你确认后发送(L1 人工闸门); 自动 steer / 喊停正在跑的任务(L2 / L3)尚未实现,列在路线图里。

一句话边界:能看见 → 能表态 → 能把判断写成草稿送回对话(人确认); 不能自动改变一个正在跑的任务。

Version License Zero dependencies Platform DSH plugin

关键词:DeepSeek Harness 插件 · DSH plugin · 产出画廊 · output gallery · 图片画廊 · image gallery · 文件预览 · file preview · 音视频画廊 · media gallery · 视频预览 · video preview · 反馈篮 · feedback basket · 决策草稿 · decision draft · 人工确认 · human-in-the-loop · 侧边栏面板 · sidebar panel · Agent 产出管理 · output artifacts


它解决什么问题

痛点:任务跑完你才知道结果

让 Agent 出 30 张图、改一份报告、跑一段脚本 —— 它埋头干几分钟甚至几十分钟, 你看不到中间产物。等到最后它念一串路径,你才发现:

  • 第 3 张图的风格就跑偏了,30 张全废
  • 报告第 2 段引用了错的资料,整篇要重写
  • 脚本输出了 50 个中间文件,你不知道哪个是最终版

返工成本是「一次性验证」的好几倍。

解法:把产出目录变成实时画廊

插件直接盯磁盘上的产出目录(Agent 真正写文件的地方),做成右侧栏画廊:

效果 说明
图生成就可见 每 5 秒自动刷新,缩略图实时滚动,不顺眼当场喊停
文件点一下就开 调 DSH 原生侧栏预览(Markdown 渲染、代码高亮都是 DSH 自己的)
只看本对话的 多个对话混在一起时,按「当前对话」筛,一眼分清谁做的
过程产物也算 脚本跑出来的中间图、Agent 打开看过的图,都算本对话产出 —— 过程不黑箱

和市面上的「对话图片查看器」不一样在哪

常见的对话图片灯箱 这个插件
看哪里 对话里的图片附件 磁盘上的产出目录(Agent 真正写文件的地方)
能看什么 只有图片 图片 + 49 种文档/代码/数据文件
怎么打开文件 无 调 DSH 原生侧栏预览
多个对话混在一起 不区分 可按「本对话产出」筛
过程产物 看不到 脚本生成的中间图也能看到

一句话安装:解压后在该目录执行 node install.mjs,然后重启 DSH。 详细步骤见安装,常见问题见已知限制。


功能

反馈与干预速览(v0.13.6)

过程可见只是第一步;看到不对的产出能当场表态、并把判断送回主线,才是这个插件的落点。

能力 状态 说明
过程可见 / 中间产出即时展现 ✅ 5 秒刷新;含脚本生成图、read_image 看过的图、子智能体会话产出
三类资产当场校验 ✅ 图片放大 8×、文件原生侧栏预览、音视频面板内播放 / 拖进度条 / 截帧
反馈篮 6 动作(表态 / 定稿) ✅ 通过 · 不要这张 · 定为最终版 · 单维重做 · 选择性重生成 · 设为参照
结构化决策草稿(L1 人工闸门) ✅ 攒成一条带 Annotation N 编号的反馈写进 composer 草稿,零自动发送、人确认再发
对外接口 seam v1 ✅ window.dshGallerySeam 暴露选择 / 标记 / 草稿只读能力,不含发送能力
按标记筛选 / 批量处置 ❌ 未实现
自动 steer / cancel 正在跑的任务(L2 / L3) ❌ 未实现;规划放独立包、默认关

完整约束见下文「反馈篮」「对外接口(seam v1)」「路线图」三节。

图片画廊

能力 说明
自动刷新 每 5 秒轮询,查看大图时自动暂停,不打断
缩略图 客户端 canvas 压缩到 200px(不是原图直塞),并发闸门 4,进入视口才加载
放大查看 滚轮缩放(最大 8×,以光标位置为中心)、左键或中键拖动平移
看原图 缩略图右键「查看原图」直接按原图像素打开;查看器内切换原图/预览(底部按钮、右键、O 键),切换时保留缩放与位置;按需加载并显示进度,不预加载
音视频画廊 视频/音频独立第三栏;视频首帧缩略图(进入视口才抽帧);点击面板内播放(原生 <video>/<audio>,支持拖动进度条);体积上限 200 MB 可调
右侧控制列 放大后出现 ▲ / ▼ 按钮 + 轨道 + 滑块,没有鼠标也能操作
键盘操作 ↑↓ 平移、←→ 切图、+/- 缩放、0 复位、O 切原图、Esc 退出
退出回位 单击退出,回到原来那张缩略图的精确位置,不是列表顶部

文件画廊

列文档 / 代码 / 数据 / 压缩包 / 链接 / 设计文件,共 49 种扩展名(不含图片,图片归图片画廊)。

操作 行为
点整张卡片 / 点「👁 预览」 用 DSH 原生侧栏打开预览(Markdown 渲染、代码高亮都是 DSH 自己的)
点「⧉ 复制路径」 复制绝对路径,按钮变 ✓ 已复制 反馈 1.6 秒
点「📂」 在资源管理器里定位该文件

音视频画廊

列视频 / 音频,共 16 种扩展名(视频 7 种、音频 9 种),独立第三栏,不混进文件列表。

操作 行为
点整张卡片 在面板内弹出播放器
视频卡片 显示首帧缩略图(进入视口才抽帧,避免一次解码几十个视频)
拖进度条 ✅ 实测 127 MB 可拖;GB 级未做大小分档 —— 面板内播放走 blob(整包载入后交给浏览器,可任意 seek)
点开到可播 ✅ 1.1 MB 视频与 96.5 秒音频约 250 ms;127 MB 实测 502 ms,可正常拖动;GB 级未做大小分档
播放器里「📷 截取当前帧」 把当前画面存成 PNG,文件名带时间码(如 片子_00-12-34.png)
浏览器解不了格式 显示提示 +「▶ 用系统播放器打开」/「📂 打开所在文件夹」两个按钮

技术说明:媒体走双通道

  1. 独立 Range 路由(ctx.webServer.register,Node 原生 req/res): 支持 Range: bytes=... 的常规区间、开放区间、后缀区间,以及 416 不可满足。 用于视频首帧缩略图抽取、直链读取与其他需要分段读取的场景。
  2. 面板内播放走 /api 网关的 raw + blob:POST {op:'raw'} 取完整字节, URL.createObjectURL(blob) 交给 <video> / <audio>。

为什么播放要单独走 blob:DSH 桌面宿主在转发 Host 响应时会剥掉 Content-Length(见 app.asar 的 lib/main.js,WITHHELD_RESPONSE_HEADERS), Chromium 因此拿不到文件总长度,<video>.seekable 恒为 [0,0] —— 能播但进度条拖不动。blob 是完整数据在内存,Chromium 知道确切大小,seekable 覆盖全长。

代价:播放时整包载入内存(等于文件大小)。实测 127 MB 用时 502 ms; GB 级文件暂未做大小分档,仍会走 blob。

体积上限默认 200 MB,可用 maxMediaBytes 调整。

右键菜单(图片 / 文件 / 音视频通用)

在任意卡片上右键:

项目 行为
🚫 隐藏 从列表移除,文件仍在磁盘上(记录在 dsh-gallery.json 的 hidden 数组)
📂 打开所在文件夹 资源管理器定位到该文件
⧉ 复制路径 复制绝对路径到剪贴板
🗑 删除文件 二次确认后删除,不可恢复

⚠️ 删除做了三层保护:前端确认弹窗 → API 强制 confirm: true → 路径越界校验。

分页

三个画廊都是每页 60 条,网格下方常驻页码条:

第 1–60 条 · 共 114 条   还有 54 张
                  ‹  1  2  ›
  • 页码点击切页,页数多时折叠为 1 … 5 6 7 … 20
  • 切换「图片/文件」或「全局/当前对话」时自动回到第 1 页
  • 列表右侧另有 ▲ / ▼ 滚动辅助列(无滚轮时用)

分类开关

[全局资产]  [当前对话]
  • 全局资产:所有扫描目录下的全部内容,按时间倒序
  • 当前对话:只显示本对话真正产出过的文件 —— 通过解析 DSH 会话日志得出,不是按时间瞎猜

「当前对话」的产出判定覆盖三类来源:

来源 为什么算
write / edit / present Agent 直接写文件 / 声明交付,路径必是产出
read_image 打开过的图片 Python 等脚本生成的图不在 write 调用里,但 Agent 一定会打开看效果
子智能体会话里的产出 子智能体是独立会话,按 parentSession 合并它的产出路径

这条设计是为了「任务进行中即时可见、便于及时校正」—— 中间产物、调试图、脚本输出都能在过程里看到,而不是等任务收尾。

多扫描目录

DSH 每个会话有独立的 cwd,产出可能落在任意工作区(如 G:\DSH任务文件\xxx), 不一定都在 G:\DSH产出。所以插件支持配置多个扫描目录:

{
  "roots": [
    "G:/DSH产出",
    "G:/DSH任务文件"
  ]
}

设置面板(⚙)里可直接增删,每项显示 ✓(存在)/ ✗(缺失标红)。改完立即生效。

产出根目录可配置

装上不会空白。 插件按这个顺序确定扫描目录:

  1. 面板内设置的多目录列表(最高优先,改完立即生效,无需重启)
  2. 设置或 cordis.patch.yml 里的单个 root(旧写法,兼容)
  3. 自动探测:先找 ~/DSH产出、~/Documents/DSH产出、~/Desktop/DSH产出、~/Downloads/DSH产出,再遍历各盘符找 <盘符>:\DSH产出(循环 A–Z,代码里不写死任何字母,所以装在哪个盘都能自动找到)

一个目录都没有时,面板会直接给出「修改产出根目录」的入口。

隐藏管理

设置面板(⚙)里有「已隐藏 N 个 · 全部恢复」:

  • 列出被隐藏的文件(前 10 个,悬停看完整路径)
  • 点「全部恢复」一键清空隐藏列表,被隐藏的重新出现
  • 恢复不删除文件,只是清掉记录

安装

前置

已安装 DSH 桌面版或 Web 版。

方式零:DSH 插件页一行装(最省事)

打开 DSH → 插件页 → 添加插件 → 安装第三方插件,在输入框粘贴:

github:Hope2023Dcr/dsh-gallery

点安装。DSH 会自动从 GitHub 拉取并装好,装完重启 DSH。

想锁定版本(推荐,避免仓库更新导致行为变化)—— 钉 tag,不要钉 commit:

git+https://github.com/Hope2023Dcr/dsh-gallery.git#v0.13.6

tag v0.13.6 对应本次发布(含 S3-a 反馈契约、blob 播放可拖、reveal 修复)。 钉 commit 会随文档回填提交而漂移,且不利于复现安装来源。 更推荐直接用 npm(npm i dsh-gallery)—— 版本号跟着 latest 走,不用每次手工核对哈希。

⚠️ 这种方式需要能访问 GitHub。DSH 的「国内镜像」只代理 npm 包,不代替 GitHub 下载。

方式一:一键脚本(推荐,可离线)

下载本仓库(Code → Download ZIP,或 git clone),解压后在解压出来的目录里执行:

node install.mjs

脚本会自动:

  1. 定位 DSH 主目录(优先 DSH_HOME 环境变量,回退 ~/.dsh)
  2. 列出可用 profile 让你选(只有一个时直接用它,多个时默认 desktop)
  3. 校验源文件齐全
  4. 复制到 <profile>/node_modules/dsh-gallery/
  5. 在 profile 的 package.json 的 bundles 里注册
  6. 自动备份原 package.json 为 package.json.bak-dsh-gallery

可选参数:

node install.mjs --profile desktop   # 指定 profile
node install.mjs --dry-run           # 只看会做什么,不写入

脚本幂等:重复运行不会重复注册 bundle。

装完必须重启 DSH(不是刷新页面)。

方式二:手动安装

1. 找到你的 profile 目录

平台 路径
Windows %USERPROFILE%\.dsh\profiles\desktop
macOS / Linux ~/.dsh/profiles/desktop

如果 desktop 不存在,看你实际用的 profile 名(profiles/ 下有什么就用什么)。

2. 复制文件到插件目录

目标:<profile>/node_modules/dsh-gallery/

需要放进去的文件:index.js、client.js、package.json、cordis.patch.yml、icon.svg、locale/。

Windows PowerShell:

$target = "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-gallery"
New-Item -ItemType Directory -Force -Path $target | Out-Null
Copy-Item index.js,client.js,package.json,cordis.patch.yml,icon.svg -Destination $target
Copy-Item locale -Destination $target -Recurse

macOS / Linux:

target=~/.dsh/profiles/desktop/node_modules/dsh-gallery
mkdir -p "$target"
cp index.js client.js package.json cordis.patch.yml icon.svg "$target/"
cp -r locale "$target/"

3. 在 profile 的 package.json 里注册

编辑 <profile>/package.json,在 bundles 数组里加一项:

{
  "bundles": [
    "dsh-gallery"
  ]
}

4. 重启 DSH

必须完全退出再打开(不是刷新页面)。Host 半部只在进程启动时加载。

5. 打开面板

三个入口任选:

  • 左侧边栏脚部的 ▦ 按钮
  • 对话输入框右侧的 ▦ 按钮
  • 右侧栏点 +,「开始」页里的「产出画廊」卡片

6. 设置产出目录

第一次打开如果显示「目录不存在」,点面板里的 ⚙ 设置,填入你的产出目录绝对路径,保存即可生效。


配置项

编辑 <插件目录>/cordis.patch.yml:

config:
  # root: 'D:/产出'      # 不填就走自动探测
  maxItems: 60            # 每页显示多少条
  maxDepth: 3             # 向下扫描几层目录
  skipDirs:               # 跳过这些目录(体积大、无产出)
    - node_modules
    - .git
    - ...

⚠️ 不建议在这里写 windowHours。 它是「扫描多久以内的文件」,代码默认是一整年 (为了让「全局按对话分组」能覆盖历史对话)。在这里写死 24 会让分组只剩当天产出。 确实想改的话,写进 <DSH_HOME>/dsh-gallery.json 更合适。

改完重启 DSH 生效。只想改目录的话,建议用面板里的 ⚙ 设置,那个不用重启。


兼容性

项 说明
宿主 DSH 桌面版 / Web 版,bundle 走 web 平台;本机已在 DSH 0.2.1-rc.5 上完整验证
最低宿主版本 未声明硬下限(不编造);0.2.2-rc.1 上未做完整回归,从新版回退过的用户请先看「已知限制」第 1 条
Node >= 20(仅安装 / 校验脚本需要;插件运行时零第三方依赖)
系统 Windows / macOS / Linux 都能装;「打开所在文件夹」定位到文件仅 Windows,其他平台打开所在目录
安装后 必须完全退出并重启 DSH —— Host 半部只在进程启动时加载,刷新页面不够
宿主内部格式依赖 「当前对话」判定与自动标记读 session.v4.jsonl.zstd 的 tool/call 事件,DSH 大版本升级后需回归验证;其余功能不受影响
权限边界 只读扫描目录,状态只写两个本地 JSON;删除文件需二次确认且不可逆。详见安全与隐私

更完整的兼容性说明(含媒体双通道与宿主 Content-Length 剥除行为)见仓库内 RELEASE.md 的「兼容性」一节。


已知限制

  1. 「当前对话」分类依赖 DSH 会话日志格式。 它读 ~/.dsh/sessions/<分组>/<sessionId>/session.v4.jsonl.zstd,解析 tool/call 事件。DSH 大版本升级后这个功能可能失效,需要回归验证;其余功能不受影响。
  2. 只扫一层层的目录,深度默认 3 层。 特别深的目录结构会漏。
  3. 扫描时间窗口默认一年。 文件多时会拖慢扫描(已做缓存,稳态约 150 ms)。
  4. 文件画廊故意不显示图片。 图片归图片画廊,避免两边重复。
  5. reveal(资源管理器定位)仅 Windows 有效。 其他平台会走 xdg-open 打开所在目录。
  6. 「未归类」是诚实的不知道。 会话日志里查不到归属的文件标为「未归类」, 而不是猜成某个类别。这类文件多来自早期对话或手动拷入。

安全

风险等级:低。 插件只读你本机的产出目录,不上传、不执行任何文件。

能力 做法
文件预览 全部委托 DSH 原生侧栏预览器,插件自己不渲染文件内容 —— 不引入第二套渲染栈
不执行任何文件 不运行脚本、不打开可执行文件、不解压压缩包。唯一的 spawn 是调起资源管理器定位(explorer.exe /select)
删除操作 三层保护:前端二次确认 → API 强制 confirm: true → 路径越界校验(isInside(root))
路径穿越防护 所有文件操作都经 isInside(root, absolute) 校验,只允许在扫描目录内
HTTP 路由 POST /api/dsh-gallery(走 DSH /api 网关,需认证)负责列表与操作;另有一条独立 GET/HEAD 媒体路由用于缩略图抽取与分段读取(详见下方「媒体路由的安全边界」)。面板内播放的整包读取也走 /api 网关的 raw 分支,不经 dsh-app:// 媒体管线

删文件是唯一不可逆操作,所以做了三层保护;隐藏只是从列表移除,文件不动。

媒体路由的安全边界

音视频播放需要浏览器能直接 GET 一个 URL(<video src> 无法发 POST), 所以 v0.11.0 新增了一条独立的媒体路由。它不属于 /api 网关、不经过 DSH 的网关认证, 因此该路由自己做了三道防护:

防护 做法 不做的后果
① 只读 只接受 GET / HEAD,其余 405 可被当作写入跳板
② 跨站拒绝 Sec-Fetch-Site: cross-site 或 Origin 与 Host 不匹配 → 403 任意网页都能盗读本机产出
③ 路径白名单 解析后必须落在扫描的 roots 内(isInside),.. 无法越界 能读磁盘任意文件
附带 X-Content-Type-Options: nosniff 浏览器可能把内容当 HTML 执行

这三道是必需的,因为路由绕过了网关认证。若在代码里看到这条路由却没有校验, 那是缺陷不是设计。


隐私

全部本地,不出机器。

项 说明
网络请求 零。插件不发起任何外部请求(已核查源码:无 http/https/axios/WebSocket 引用)
上传 无。没有任何上报、遥测、统计
状态落盘 两个 JSON,都在 <DSH_HOME>/:dsh-gallery.json(扫描目录 / 隐藏列表等设置)、dsh-gallery-marks.json(v0.13.0 起新增,卡片判定标记)。没有第三个写入位置
写入方式 主路径走 tmp → rename 原子写:host/settings.js 的 writeSettingsFile、host/marks.js 的 writeMarks(后者 tmp 名带 pid + 随机后缀,并发写不会互踩)。host/http.js 另有若干处直接 writeFile
会话日志 只读。解析 ~/.dsh/sessions/** 来判定「本对话产出」,不修改、不复制、不上传
文件内容 预览时实时读磁盘,不写进任何索引或缓存文件
内存缓存 会话日志解析结果只在内存里(按 路径+mtime+size 做键),不落盘

会话日志里包含你的对话内容,插件只抽取 tool/call 事件里的文件路径, 不读取、不存储对话文本。

两条边界容易混淆,单独说明:

  • 「📷 截取当前帧」不在上面这张表里 —— 它走浏览器原生 a.download (src/client/07-media.js),不经过插件服务端写盘,图片落到你浏览器默认的下载目录。
  • 「🗑 删除文件」是显式不可逆操作 —— 需二次确认,属于用户主动发起的删除, 见安全章节;它不是"插件在后台落盘",不要和上面的状态文件混为一谈。

对外接口(seam v1)

插件在 window.dshGallerySeam 暴露一个窄接口,供独立包 / 扩展使用:

window.dshGallerySeam = {
  version: 1,
  getSelection(),        // → { relPath, source: 'viewer'|'context-menu'|'focus' } | null
  subscribe(fn),         // → 退订函数;选中项变化时回调
  getMarks(),            // → Promise<{ [relPath]: mark }>
  setMark(relPath, mark),// → Promise<boolean>
  getFeedbackDraft(),    // → 最近一次生成的草稿文本
}

卡片 DOM 兜底:所有卡片(图片 / 文件 / 音视频)都挂 data-gallery-relpath="<relPath>",独立包可直接按属性定位,不依赖 React 内部状态。

这个 seam 不含发送能力 —— 发送永远由用户在 composer 里手动确认。

反馈篮(v0.13.0 起)

标记产出 → 攒成一条结构化反馈 → 写进输入框草稿 → 由你确认后手动发送。

动作 用途
通过 / 不要这张 / 定为最终版 判定
单维重做 只改某一维(色调 / 材质…),其余锁死
选择性重生成 只重做选中的这几张
设为参照 作为同批的参照

设计约束(有意为之):

  • 零自动发送:只写 composer 草稿,发送永远由人点。
  • 零 inject:不声明 conversation.input / sessions / agents —— 实测声明它们会让插件在 web boot 阶段 pending、宿主判定启动失败。 草稿写入走纯 DOM 多路径,全部失败才落剪贴板(并明确提示「未写入输入框」)。
  • 历史会话禁用提交:条目归属会话与当前会话不同时,提交按钮禁用。
  • 契约不是自由文本:导出 JSON 与渲染文本同一 shape,带 Annotation N 编号。

路线图

已实现(v0.13.6)

能力 说明
反馈篮 6 种动作 通过 / 不要这张 / 定为最终版 / 单维重做 / 选择性重生成 / 设为参照
结构化决策草稿(L1) 攒批后按 Annotation 1..N 生成一条草稿,只写进 composer、零自动发送,由人确认
对外 seam v1 window.dshGallerySeam —— 只读,不含任何发送能力
过程可见与即时校验 三类资产(图片 / 文件 / 音视频)实时刷新、面板内预览与播放
反馈篮独立入口 右下角常驻「反馈篮 · N 条」按钮,关掉也能重开(v0.13.5)

未实现(诚实标注,不画大饼)

计划 状态
版本历史(同一文件跨 turn 的修改点,只存 size/mtime) ❌ 未实现
交付物手动 pin(除 present 之外的标记方式) ❌ 未实现 —— 注意区别:反馈篮的「定为最终版」产出的是一条判定草稿(文本,人要确认),并不等于把 pin 写进主线状态;真正的"标记进状态"还没做
按标记筛选 / 批量处置 ❌ 未实现(能表态了,但还不能按判定筛出卡片、批量处理)
图片框选批注 / A/B 对比 / 参数回灌(S3-b) ❌ 未实现
自动 steer / cancel 独立包(S3-c) ❌ 未实现
跨扫描目录合并视图(目前按目录分组) ❌ 未实现
文件内容变更 diff 预览 ❌ 未实现

已在考虑但不确定做不做:

  • HTML/SVG 预览 —— 这类文件由模型生成,直接渲染有执行脚本的风险。当前策略是 「交给 DSH 原生预览器」,跟着宿主的安全策略走。如果将来自己做,会强制 <iframe sandbox="">。

和其他产出类插件的区别

DSH 生态里有几类「产出管理」插件,容易混淆。本插件的定位是「过程可见」,不是「事后归档」:

本插件 事后归档类插件(如 dsh-output-gallery)
何时出现 实时,5 秒刷新 任务/turn 结束时批量扫描
要解决的问题 跑到一半发现方向错了要返工 任务产出了几十个文件,分不清哪个是最终版
交付物判定 自动(present 声明过) 需要手动标记
典型场景 批量出图时边看边纠正提示词 项目结束整理归档

两者互补而非重复:想看过程用这个,想归档历史用那个。


开发:改源码后必须构建

client.js 是构建产物,改源码后不构建,改动不会生效:

npm run build      # 生成 client.js(并同步生成 host/protocol.js)
npm run build -- --check   # 只读比对,产物与源码有漂移会报错

源码在 src/:

路径 内容
src/client/0X-*.js 13 个分片(主容器、组件、工具)
src/client/styles.css 面板样式(构建时内联进 client)
src/shared/protocol.js 协议单一真源:ROUTE / MEDIA_ROUTE / 扩展名表
src/build-manifest.json 分片顺序与产物配置

为什么必须构建:DSH 加载器要求 client.js 是单文件、单个 __ModuleLoader__.load、无 ESM import/export —— 源码可以分模块,但产物必须合并。 Host 侧不同:Node 原生支持多文件,所以 host/ 是源码即产物,零构建。

技术说明(给想改代码的人)

架构

结构

dsh-gallery/
├── package.json        # bundle 清单 + dsh.client(web 平台)
├── cordis.patch.yml    # 插入 Host 行与默认配置
├── index.js            # Host 半部:扫描、图片尺寸解析、会话日志解析、HTTP 路由
├── client.js           # 浏览器半部:侧栏 tab UI、缩略图、放大、设置面板
├── locale/zh.json      # 中文文案
├── locale/en.json
└── icon.svg

两端分工

半部 能做什么 不能做什么
index.js(Host) 读文件、扫目录、注册 HTTP 路由、调 child_process 不能碰 DOM
client.js(浏览器) 渲染 UI、拿 slot props、调 ctx.sidebarRight.* 不能直接读磁盘

数据流:client fetch(ROUTE) POST 给 host → host 处理 → 返回 JSON / 字节。

⚠️ 改代码后怎么生效

改了哪个文件 生效方式
client.js 刷新页面(秒级)
index.js 必须重启 DSH 进程(分钟级)

判断「跑的是不是新代码」:哈希一致 + 进程启动时间 < 文件修改时间 → 运行的是旧模块,需要重启。

关键实现点

  • 图片尺寸解析:Host 侧直接读 PNG IHDR / JPEG SOF / WebP VP8·VP8L·VP8X 头部,零依赖
  • 缩略图压缩:客户端 createImageBitmap + OffscreenCanvas,不把原图塞进 <img>
  • tab 保活:注册 tab 类型时声明 keepMounted: true,切到别的 tab 再回来状态不丢
  • 原生预览地址:dsh-resource://file/session/<sessionId>/<编码路径>,文档预览只认 session 作用域
  • 会话日志多帧 zstd:DSH 日志每次追加写一帧,必须按魔数 0x28 0xB5 0x2F 0xFD 切开逐帧解压,单次解压只能拿到第一帧

许可

MIT。随便用、改、分发。

—/ 5

No ratings yet

Verified DSH bundle

Commit 5b361e835d5d

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout