为 DSHDeepSeek HarnessWeb GUI 侧边栏提供的 Artifacts产物标签页。
30.6/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/29 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查有告警:npm 同名包「dsh-artifacts」归属 zoahdev/dsh-artifacts,装到的可能不是本插件。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add lucagiftzek/dsh-artifacts该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · browser
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 37 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意npm 同名包「dsh-artifacts」归属 zoahdev/dsh-artifacts,装到的可能不是本插件
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-artifacts @ 0.1.1
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/14 07:37:47
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 64 处,展示前 51 条)
- 发起网络请求lib/client.js:75
const res = await fetch(API + route, opts); - 发起网络请求lib/client.js:287
const res = await fetch( - 写入剪贴板lib/client.js:661
await navigator.clipboard.writeText(abs(r.url)); - 写入剪贴板lib/client.js:695
await navigator.clipboard.writeText(abs(item.url)); - 读取本地文件lib/engine/cli.js:34
return JSON.parse(readFileSync(0, "utf8")); - 读取本地文件lib/engine/save.js:239
} else if (existsSync(finalDir)) updating = true; - 写入本地文件lib/engine/save.js:243
mkdirSync(target.path, { recursive: true }); - 读取本地文件lib/engine/save.js:247
if (updating && existsSync(finalDir)) cpSync(finalDir, stage, { recursive: true }); - 删除本地文件lib/engine/save.js:252
unlinkSync(dst); - 写入本地文件lib/engine/save.js:258
mkdirSync(dirname(dst), { recursive: true }); - 写入本地文件lib/engine/save.js:259
writeFileSync(dst, bytesOf(c)); - 写入本地文件lib/engine/save.js:269
writeFileSync(join(stage, "template.json"), JSON.stringify(tj, null, 2) + "\n"); - 写入本地文件lib/engine/save.js:270
writeFileSync(join(stage, "README.md"), readme.endsWith("\n") ? readme : readme + "\n"); - 读取本地文件lib/engine/save.js:273
const sizeTotal = all.reduce((a, f) => a + statSync(join(stage, f)).size, 0); - 读取本地文件lib/engine/save.js:297
if (existsSync(finalDir)) { - 写入本地文件lib/engine/save.js:299
renameSync(finalDir, old); - 删除本地文件递归lib/engine/save.js:307
if (old) rmSync(old, { recursive: true, force: true }); - 删除本地文件递归lib/engine/save.js:320
if (existsSync(stage)) rmSync(stage, { recursive: true, force: true }); - 读取本地文件lib/engine/save.js:320
if (existsSync(stage)) rmSync(stage, { recursive: true, force: true }); - 删除本地文件递归lib/engine/save.js:321
if (trial) rmSync(trial, { recursive: true, force: true }); - 读取本地文件lib/engine/templates.js:52
return statSync(p).isDirectory(); - 读取本地文件lib/engine/templates.js:59
return statSync(p).isFile(); - 读取本地文件lib/engine/templates.js:66
statSync(p); - 读取本地文件lib/engine/templates.js:87
accessSync(d, FS.W_OK); - 读取本地文件lib/engine/templates.js:119
return JSON.parse(readFileSync(path, "utf8")); - 读取本地文件lib/engine/templates.js:125
raw = readFileSync(p, "utf8"); - 读取本地文件lib/listing-cli.js:17
const text = readFileSync(0, "utf8"); - 读取本地文件lib/listing.js:174
text = readFileSync(listingFile(env), "utf8"); - 写入本地文件lib/listing.js:190
mkdirSync(storeDir(env), { recursive: true }); - 写入本地文件lib/listing.js:191
appendFileSync(listingFile(env), JSON.stringify(e) + "\n"); - 读取本地文件lib/listing.js:242
return statSync(path, { bigint: true }).mtimeNs.toString(16); - 读取本地文件lib/listing.js:256
public: rel.includes("/") ? false : existsSync(join(dir, rel) + ".public") - 读取本地文件lib/listing.js:274
reg = JSON.parse(readFileSync(join(store, "registry.json"), "utf8")); - 读取本地文件lib/listing.js:282
text = readFileSync(join(store, "claims.jsonl"), "utf8"); - 读取本地文件lib/listing.js:317
entries = readdirSync(dir); - 写入本地文件lib/listing.js:536
mkdirSync(storeDir(env), { recursive: true }); - 写入本地文件lib/listing.js:538
appendFileSync(join(storeDir(env), "claims.jsonl"), rels.map((name) => JSON.stringify({ name, session, time: now, how: "tool" }) + "\n").join("")); - 写入本地文件lib/listing.js:606
mkdirSync(dir, { recursive: true }); - 写入本地文件lib/listing.js:611
renameSync(tmp, target); - 删除本地文件lib/listing.js:614
unlinkSync(tmp); - 读取本地文件lib/plugin-skills.js:51
if (!existsSync(root)) return [] - 读取本地文件lib/plugin-skills.js:53
for (const entry of readdirSync(root).sort()) { - 读取本地文件lib/plugin-skills.js:57
if (!statSync(d).isDirectory() || !existsSync(p)) continue - 读取本地文件lib/plugin-skills.js:57
if (!statSync(d).isDirectory() || !existsSync(p)) continue - 读取本地文件lib/plugin-skills.js:58
const { meta } = parseSkillFile(readFileSync(p, 'utf8'), p) - 读取本地文件lib/plugin-skills.js:85
const raw = await readFile(locator, { encoding: 'utf8', signal: options.signal }) - 写入本地文件lib/tools.js:85
mkdirSync(store, { recursive: true }); - 写入本地文件lib/tools.js:87
appendFileSync(join(store, "claims.jsonl"), rels.map((name) => JSON.stringify({ name, session, time: now, how: "tool" }) + "\n").join("")); - 发起网络请求server/bridge.js:38
return fetch(API + route, opts).then(function (r) { - 写入剪贴板server/bridge.js:157
try { navigator.clipboard.writeText(String(text)); toast('Copied - paste it into the chat'); } catch (e) {} - 发起网络请求server/bridge.js:330
fetch(probe, { cache: 'no-store', credentials: 'same-origin' }).then(function (r) { return r.text(); }).then(function (t) {
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 列出智能体生成文件
- 就地预览文件
- 支持实时重载
README
由 DeepSeek 最新模型翻译生成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。
展开完整文档(README 剩余 1 节)
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/。
安装
from GitHub
dsh plugin --profile web add github:lucagiftzek/dsh-artifacts
or from a checkout
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=…,而不是普通的按插件路径。构建后运行两道关卡:
- purity —— 任何 @deepseek-ai/ 都不得进入 bundle;值导入会内联一个 shell 包的重复运行时实例。
- seed words —— 每个裸 require 都必须是已声明的外部依赖,否则模块系统会在物化时大声抛出异常。
Test
node test/run.mjs # offline: no browser, no DSH_HOME, no network
test/render.mjs 以浏览器模块系统的方式物化 bundle,驱动 registerTab,并结构化地渲染六种状态 —— 空库、带选中项的有内容库、隐藏标签页、获取错误、消失的选中项,以及 busy 下的工具栏几何。它注入真实的 react/jsx-runtime,使元素是真正的元素,并为 react 提供一个可编程的 stub,这样 hooks 无需 dispatcher。
test/fetch.mjs 从轮询间隔中捕获 load(),并驱动每一种 fetch 结果,包括代理返回 HTML 而非 JSON 的 auth-redirect 情况。
这两个测试套件已经证明了它们的价值。render 套件捕获了一个消失的选中项在 effect 中被同步的问题,这会导致绘制一帧时 iframe 指向一个刚刚 404 的路径 —— 现在它是在渲染期间派生的。它后来还捕获了一个工具栏在每次轮询时改变宽度的问题,因为按钮标签随 busy 切换。
For agents
skills/publish-artifact/SKILL.md 是一个即插即用的技能,教 agent 这个标签页所读取的约定:在哪里写入 artifacts、如何命名它们,以及永远不要在其中放入什么。将它复制到 $DSH_HOME/skills/、~/.agents/skills/,或项目的 .dsh/skills/。
License
MIT —— 见 LICENSE。Copyright (c) 2026 Loukas "Luca" Tzekos.
随你怎么用。唯一的要求是署名:保留版权行,如果你公开 fork 它,在 README 中注明 "based on dsh-artifacts by Luca Tzekos" 会不胜感激。见 NOTICE。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
lucagiftzek/dsh-artifacts
为 DSHDeepSeek HarnessWeb GUI 侧边栏提供的 Artifacts产物标签页。
相关插件 · 浏览器
智能体插件框架deepseek-ai/deepseek-harness
DeepSeek Harnessdsh是由 DeepSeek AI 开发的开源 agent harness智能体框架。
★ 270,422已汉化DSH
71.9
多设备 Agent 看板YaoApp/yao
✨ 所有 Agent 和工作区集中管理,覆盖你的每一台设备。任务看板追踪进度,桌面端、移动端、浏览器、API…
★ 8,147已汉化DSH
71.2
可扩展侧边栏工作台omdsh-dev/DSH-better-sidebar
DSH 的双工作台:原生右侧栏 + 自绘底部面板,并把 ctx.betterSidebar 服务开放给所有插件
★ 4,761已汉化DSH
71.1
浏览器自动化桥Tencent/BrowserSkill
你的 Agent。你的浏览器。连接,就能协作。
★ 9,967已汉化DSH
71
AI 小说创作工作台EthanYoQ/AI-Novel-Writer
AI 小说作家 / AI Novel Writer
★ 1,591已汉化DSH
70.7
智能体浏览器引擎platonai/Browser4
DeepSeek Harness 集成
★ 1,175已汉化DSH
70.4
这是你的仓库?认领条目