DeepSeek Harness Hub
← 返回列表

lucagiftzek/dsh-artifacts

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
未验证

为 DSHDeepSeek HarnessWeb GUI 侧边栏提供的一个 Artifacts产物标签页。

尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/10 · 已提供中文文档

为 DSH(DeepSeek Harness)Web GUI 侧边栏添加一个“产物”标签页:列出智能体生成的文件,并就地预览,支持实时重载。

综合分
29.7
GitHub 分
29.7
用户评分
★ Stars
1
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add lucagiftzek/dsh-artifacts
该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/20(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-artifacts

为 DSH(DeepSeek Harness)Web GUI 侧边栏提供的一个 Artifacts(产物)标签页。

智能体会生成文件——一份 HTML 报告、一个仪表盘、一张图表、一个 CSV。此标签页会在侧边栏中按最新优先的顺序列出它们,并就地预览其中一个,这样正在观察会话的人就能看到它产出了什么,而无需手动把路径复制到浏览器中。

它是侧边栏自身标签页(资源管理器、编辑器、终端、浏览器)的同级,而非覆盖层:它通过它们所使用的同一个公共扩展点进行注册。

它的功能

- 通过 ctx.betterSidebar.registerTab 注册一个标签页,dsh-artifacts:library。
- 按最新优先的顺序列出产物目录,并带有类型徽章、大小和存在时长。
- 点击某一行,在标签页内的 iframe 中预览它,使用索引提供的相对 URL,因此它与 GUI 同源,并会随浏览器现有的会话 cookie 一起加载。
- Open ↗ 会在真实的浏览器标签页中打开它,Copy link 会复制可分享的绝对 URL,Reload 会重新获取预览,Refresh 会重新读取索引。
- 每 5 秒轮询一次,仅在标签页处于活动状态且面板打开时,使用侧边栏专门为此提供的 visible prop。
- 工具栏和行的几何尺寸刻意采用固定盒模型:任何标签或指标都不会随状态改变宽度,因此轮询重新渲染不会让工具栏抖动。

如果你的服务器会向所提供的 HTML 中注入实时重载片段(参考实现见 docs/artifact-index-endpoint.md),那么当文件被重新生成时,预览会自行刷新。本插件不实现该功能,也不需要了解它。

要求

- 已挂载 dsh-better-sidebar 的 DSH Web GUI(入口 id 为 better-sidebar)。
如果注册表缺失,客户端部分会记录一个错误并且不注册任何内容——它从不抛出异常,因此缺失依赖会降级为“没有标签页”,而不是损坏的侧边栏。
- 某个同源 HTTP 端点,响应 docs/artifact-index-endpoint.md 中的小型 JSON 索引契约。DSH 本身不定义产物目录或索引路由,所以这是你需要接上的唯一一块。一个独立的参考服务器和一个发布脚本位于 contrib/。

安装

从 GitHub 安装
dsh plugin --profile web add github:lucagiftzek/dsh-artifacts

或从本地检出安装
git clone https://github.com/lucagiftzek/dsh-artifacts
dsh plugin --profile web add link:./dsh-artifacts

dsh plugin 是 pnpm 的透传,因此 add 也会把该包追加到 dsh.profile.bundles。移除命令是 dsh plugin --profile web remove dsh-artifacts。

激活需要重启 dsh-web,这会生成新的启动令牌并终止任何进行中的会话。此后对 lib/client.js 的重新构建会被实时拾取——所提供的 rev 会改变,刷新浏览器即可。

将它指向你的产物

默认索引 URL 是 /report/?list=1。无需重新构建即可按浏览器覆盖它:

localStorage['dsh-artifacts:indexUrl'] = '/artifacts/index.json'
端点必须返回:

{ "count": 2, "items": [
{ "name": "report.html", "url": "/report/report.html", "ext": "html",
"size": 11160, "mtime": 1788934528 }
] }

url 可以是相对路径或绝对路径。插件在没有其他任何东西的情况下也能渲染
(badge、缺失的 size)会静默降级。完整契约,以及如何使其仅保留元数据并限制在单个目录内,请参见
docs/artifact-index-endpoint.md。

将列表范围限定到当前聊天

一个目录通常存放每个会话的输出,因此该标签页可以缩小列表范围。当侧边栏提供会话 id 时,请求会带上
&session=;能够归属产物的端点会为每个条目返回一个布尔值
mine,并且该标签页会显示 This chat / All 切换,当有内容时默认使用
This chat。

归属明确是端点自身的职责,而不是插件的职责——只有宿主知道会话是什么。完全支持忽略该参数: 省略
mine,切换就不会渲染,这正是 contrib/ 中的参考服务器所做的。唯一要避免的错误是为你不了解的产物输出 mine: false;该标签页会将布尔值解读为“归属已运行”,并会提供一个永久为空的 This chat 视图。除非它是真的,否则什么都不要说。docs/artifact-index-endpoint.md 描述了一条可行的转录扫描规则,包括为什么要缓存它并验证 id。

架构:为什么 node 半边是空的

lib/index.js 不导入任何内容,也不注册任何内容。这是有意为之的,两个原因都是值得在设计时防范的失败:

1. 它仍然必须存在。 客户端模块宿主扫描会从挂载在宿主 Loader 中的包读取 dsh.client
声明。没有挂载,就没有可提供的 bundle。
2. 错误的宿主导入是致命的,而不是局部的。 本插件作者运行的一个 DSH profile 正是因此被搞垮:两个插件从
@deepseek-ai/dsh-settings 导入了已安装版本并未导出的符号。该 ESM 导入在加载时变成了硬性的 SyntaxError,loader 条目抛出异常,并且
dsh 在启动完成前以 1 退出——数百次重启,站点完全宕机。零导入的宿主半边不会以这种方式失败。
3. 未满足的 inject 会挂起启动。 宿主半边上的 inject: [] 避免了由没有任何东西提供的 inject
所导致的“1 entry did not activate”失败。

所有数据都通过 HTTP 到达浏览器,因此该插件不需要宿主服务、不需要文件系统访问,也不需要设置命名空间。

构建

pnpm install                 # esbuild is a devDependency
node scripts/build.mjs       # writes lib/client.js (+ map)

设置 ESBUILD_MAIN=/path/to/esbuild/lib/main.js 以针对位于其他位置的打包器进行构建,这可以保持构建离线。

客户端 bundle 是包装在 web 启动工厂中的 CJS
(window.__ModuleLoader__.load({ id, factory }))。react 和
react/jsx-runtime 保持外部化,并解析到 shell 自身的实例——所服务的 URL 是 combo 形式 /plugins/??dsh-artifacts/client.js&rev=…,而不是普通的按插件路径。构建后运行两道关卡:

- 纯净性 —— 任何 @deepseek-ai/ 都不得进入 bundle;值导入会内联一个 shell 包的重复运行时实例。
- 种子词 —— 每个裸 require 都必须是已声明的外部依赖,否则模块系统会在物化时大声抛出错误。

测试

node test/run.mjs            # 离线:无浏览器、无 DSH_HOME、无网络

test/render.mjs 以浏览器模块系统的方式物化 bundle,驱动 registerTab,并以结构化方式渲染六种状态——空库、带选中项的已填充库、隐藏标签页、获取错误、消失的选中项,以及 busy 下的工具栏几何布局。它播种真正的 react/jsx-runtime,使元素是真实的,并为 react 提供一个可编程的桩,使 hooks 无需 dispatcher。

test/fetch.mjs 从轮询间隔中捕获 load(),并驱动每一种获取结果,包括代理返回 HTML 而非 JSON 的认证重定向情况。

这两套测试已经证明了自身的价值。渲染套件捕获到一个消失的选中项在 effect 中被同步,导致有一帧绘制出的 iframe 指向一个刚刚 404 的路径——现在它是在渲染期间派生的。它后来还捕获到一个工具栏在每次轮询时宽度都会变化,因为某个按钮标签随 busy 而切换。

面向 agents

skills/publish-artifact/SKILL.md 是一个即插即用的 skill,教 agent 这个标签页所读取的约定:在哪里写入 artifacts、如何命名它们,以及永远不要在其中放入什么。将它复制到 $DSH_HOME/skills/、~/.agents/skills/ 或项目的 .dsh/skills/。

许可证

MIT —— 见 LICENSE。版权所有 (c) 2026 Loukas "Luca" Tzekos。

随你怎么用它。唯一的要求是署名:保留版权行,如果你公开 fork 它,在 README 中注明 "based on dsh-artifacts by Luca Tzekos" 会不胜感激。见 NOTICE。

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群