集中安装更新与卸载社区插件,一键批量升级
36.5/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查未通过:缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add veildawn/dsh-plugins该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · market
装得上吗
npm 包存在但缺 main/exports/bin 入口声明,源码安装也可能起不来
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 0 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-plugins @ 0.1.2
✓Node 引擎要求 >=20.3 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明
源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/3 03:18:37
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件写入剪贴板(不计风险)读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 179 处,展示前 122 条)
- 发起网络请求plugins/dsh-ai-proxy/lib/index.js:1098
const res = await fetch(modelsUrl, { - 发起网络请求plugins/dsh-ai-proxy/lib/index.js:1122
let res = await fetch(modelsUrl, { - 发起网络请求plugins/dsh-ai-proxy/lib/index.js:1129
res = await fetch(modelsUrl, { - 发起网络请求plugins/dsh-ai-proxy/lib/oauth.js:95
const res = await fetch(base + '/.well-known/oauth-authorization-server', { signal }) - 发起网络请求plugins/dsh-ai-proxy/lib/oauth.js:154
response = await fetch(endpoint, { - 发起网络请求plugins/dsh-ai-proxy/lib/oauth.js:411
await fetch(revocationEndpoint, { - 写入剪贴板plugins/dsh-file-viewer/lib/client.js:335
try { const ok = await writeClipboard(text); if (ok) return true; } catch (_) {} - 写入剪贴板plugins/dsh-file-viewer/lib/client.js:338
try { await navigator.clipboard.writeText(text); return true; } catch (_) {} - 发起网络请求plugins/dsh-file-viewer/lib/client.js:1812
fetch(`/api/changes.summary?${new URLSearchParams({ sessionId: sid, seq: String(seq) })}`) - 发起网络请求plugins/dsh-file-viewer/lib/client.js:1843
fetch(`/api/changes.summary?${new URLSearchParams({ sessionId: sid, seq: String(seq) })}`) - 写入剪贴板plugins/dsh-file-viewer/lib/client.js:3207
writeClipboard(rawText).then(() => { - 发起网络请求plugins/dsh-file-viewer/lib/client.js:3621
const head = await currentWin.fetch(downloadUrl, { method: "HEAD", credentials: "same-origin" }); - 发起网络请求plugins/dsh-file-viewer/lib/client.js:3642
const resp = await currentWin.fetch(downloadUrl, { method: "GET", credentials: "same-origin" }); - 执行外部命令固定命令plugins/dsh-file-viewer/lib/index.js:2446
execFile( - 写入本地文件plugins/dsh-im-bot/lib/index.js:108
await mkdir(dirname(filePath), { recursive: true }); - 写入本地文件plugins/dsh-im-bot/lib/index.js:111
await writeFile(tmp, `${JSON.stringify(value, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 }); - 写入本地文件plugins/dsh-im-bot/lib/index.js:113
await rename(tmp, filePath); - 删除本地文件plugins/dsh-im-bot/lib/index.js:117
await rm(filePath, { force: true }); - 写入本地文件plugins/dsh-im-bot/lib/index.js:118
await rename(tmp, filePath); - 删除本地文件plugins/dsh-im-bot/lib/index.js:124
await rm(tmp, { force: true }).catch(() => {}); - 读取本地文件plugins/dsh-im-bot/lib/index.js:136
const raw = await readFile(filePath, 'utf8'); - 发起网络请求plugins/dsh-image-gen/lib/image.js:236
resp = await fetch(first.url, { signal: controller.signal }); - 写入本地文件plugins/dsh-image-gen/lib/image.js:272
mkdirSync(path.dirname(savePath), { recursive: true }); - 写入本地文件plugins/dsh-image-gen/lib/image.js:273
writeFileSync(savePath, image.buffer); - 发起网络请求plugins/dsh-image-gen/lib/image.js:330
? await fetch(endpoint, init) - 读取本地文件plugins/dsh-image-gen/lib/provider.js:131
return readdirSync(root, { withFileTypes: true }) - 读取本地文件plugins/dsh-image-gen/lib/provider.js:134
.filter((name) => existsSync(join(root, name, 'cordis.yml'))) - 读取本地文件plugins/dsh-image-gen/lib/provider.js:475
for (const file of readdirSync(profileDir).sort()) { - 读取本地文件plugins/dsh-image-gen/lib/provider.js:499
for (const file of readdirSync(profileDir).sort()) { - 读取本地文件plugins/dsh-image-gen/lib/provider.js:509
if (!existsSync(file)) continue; - 读取本地文件plugins/dsh-image-gen/lib/provider.js:510
collectProviderBlocks(loadDshYaml(readFileSync(file, 'utf8')), raw); - 发起网络请求plugins/dsh-image-gen/lib/proxy.js:637
const request = transport.request( - 读取本地文件plugins/dsh-image-gen/lib/settings.js:43
if (!existsSync(filePath)) return null; - 读取本地文件plugins/dsh-image-gen/lib/settings.js:44
const parsed = JSON.parse(readFileSync(filePath, 'utf8')); - 写入本地文件plugins/dsh-image-gen/lib/settings.js:87
mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 }); - 写入本地文件plugins/dsh-image-gen/lib/settings.js:88
writeFileSync(filePath, `${JSON.stringify(next, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 }); - 读取本地文件plugins/dsh-image-gen/lib/settings.js:133
if (!existsSync(filePath)) return 'inferred (no settings file yet)'; - 读取本地文件plugins/dsh-jev/lib/index.js:336
const key = readFileSync(path, 'utf8').trim(); - 读取本地文件plugins/dsh-jev/lib/index.js:351
const content = readFileSync(fallbackEnv, 'utf8'); - 发起网络请求plugins/dsh-jev/lib/index.js:1171
return fetch(targetUrl, init); - 读取本地文件plugins/dsh-jev/lib/provider.js:121
return readdirSync(root, { withFileTypes: true }) - 读取本地文件plugins/dsh-jev/lib/provider.js:124
.filter((name) => existsSync(join(root, name, 'cordis.yml'))) - 读取本地文件plugins/dsh-jev/lib/provider.js:465
for (const file of readdirSync(profileDir).sort()) { - 读取本地文件plugins/dsh-jev/lib/provider.js:489
for (const file of readdirSync(profileDir).sort()) { - 读取本地文件plugins/dsh-jev/lib/provider.js:499
if (!existsSync(file)) continue; - 读取本地文件plugins/dsh-jev/lib/provider.js:500
collectProviderBlocks(loadDshYaml(readFileSync(file, 'utf8')), raw); - 发起网络请求plugins/dsh-jev/lib/proxy.js:618
const request = transport.request( - 读取本地文件plugins/dsh-jev/lib/settings.js:50
if (!existsSync(filePath)) return null; - 读取本地文件plugins/dsh-jev/lib/settings.js:51
const parsed = JSON.parse(readFileSync(filePath, 'utf8')); - 写入本地文件plugins/dsh-jev/lib/settings.js:117
mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 }); - 写入本地文件plugins/dsh-jev/lib/settings.js:118
writeFileSync(filePath, `${JSON.stringify(next, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 }); - 写入本地文件plugins/dsh-jev/lib/settings.js:121
chmodSync(filePath, 0o600); - 读取本地文件plugins/dsh-plugin-manager/lib/core.js:237
if (existsSync(npmrcPath)) { - 读取本地文件plugins/dsh-plugin-manager/lib/core.js:238
const text = readFileSync(npmrcPath, 'utf8') - 读取本地文件plugins/dsh-plugin-manager/lib/core.js:735
if (existsSync(unpackedCli)) { - 读取本地文件plugins/dsh-plugin-manager/lib/core.js:785
if (!existsSync(manifestPath)) return {} - 读取本地文件plugins/dsh-plugin-manager/lib/core.js:786
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) - 读取本地文件plugins/dsh-plugin-manager/lib/core.js:800
if (!existsSync(dir)) return map - 写入本地文件plugins/dsh-plugin-manager/lib/core.js:1099
writeFileSync(patchPath, newLines.join('\n'), 'utf8') - 写入本地文件plugins/dsh-plugin-manager/lib/core.js:1158
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf8') - 删除本地文件递归plugins/dsh-plugin-manager/lib/core.js:1180
rmSync(orphanPath, { recursive: true, force: true }) - 写入本地文件plugins/dsh-plugin-manager/lib/core.js:1487
writeFileSync(lockfilePath, kept.join('\n') + '\n', 'utf8') - 写入本地文件plugins/dsh-plugin-manager/lib/core.js:1579
writeFileSync(lockfilePath, patched.text, 'utf8') - 写入本地文件plugins/dsh-plugin-manager/lib/core.js:1698
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf8') - 写入本地文件plugins/dsh-plugin-manager/lib/core.js:1823
writeFileSync(lockfilePath, kept.join('\n') + '\n', 'utf8') - 读取密钥环境变量plugins/dsh-plugin-manager/lib/index.js:150
const envToken = process.env.GITHUB_TOKEN || process.env.GH_TOKEN || '' - 发起网络请求plugins/dsh-plugin-manager/lib/index.js:187
const proxyAgent = new EnvHttpProxyAgent() - 发起网络请求plugins/dsh-plugin-manager/lib/index.js:188
const defaultHttpFetch = (url, init = {}) => undiciFetch(url, { ...init, dispatcher: proxyAgent }) - 写入本地文件plugins/dsh-plugin-manager/lib/index.js:482
writeFileSync(COMMUNITY_DISK_CACHE_PATH, JSON.stringify(data), "utf8") - 读取本地文件plugins/dsh-plugin-manager/lib/index.js:495
if (existsSync(COMMUNITY_DISK_CACHE_PATH)) { - 读取本地文件plugins/dsh-plugin-manager/lib/index.js:496
const diskData = JSON.parse(readFileSync(COMMUNITY_DISK_CACHE_PATH, "utf8")) - 读取本地文件plugins/dsh-plugin-manager/lib/index.js:896
if (existsSync(cliPath)) { - 读取本地文件plugins/dsh-plugin-manager/lib/index.js:1044
if (existsSync(manifestPath)) originalManifestText = readFileSync(manifestPath, 'utf8') - 读取本地文件plugins/dsh-plugin-manager/lib/index.js:1044
if (existsSync(manifestPath)) originalManifestText = readFileSync(manifestPath, 'utf8') - 写入本地文件plugins/dsh-plugin-manager/lib/index.js:1134
mkdirSync(downloadDir, { recursive: true }) - 读取本地文件plugins/dsh-plugin-manager/lib/index.js:1138
if (existsSync(cachedPath)) { - 写入本地文件plugins/dsh-plugin-manager/lib/index.js:1149
writeFileSync(cachedPath, buf) - 写入本地文件plugins/dsh-plugin-manager/lib/index.js:1193
try { writeFileSync(manifestPath, originalManifestText, 'utf8') } catch {} - 写入本地文件plugins/dsh-plugin-manager/lib/index.js:1294
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf8') - 写入本地文件plugins/dsh-plugin-manager/lib/index.js:1442
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf8') - 发起网络请求plugins/dsh-remote-control/lib/client.js:233
const response = await globalThis.fetch(SESSION_PATH, { - 发起网络请求plugins/dsh-remote-control/lib/client.js:278
await globalThis.fetch(SESSION_PATH, { - 写入剪贴板plugins/dsh-remote-control/lib/client.js:471
try { await navigator.clipboard.writeText(text); ok = true; } catch {} - 读取本地文件plugins/dsh-remote-control/lib/index.js:148
if (profile?.patchPath && existsSync(profile.patchPath)) return profile.patchPath - 读取本地文件plugins/dsh-remote-control/lib/index.js:151
if (existsSync(candidate)) return candidate - 读取本地文件plugins/dsh-remote-control/lib/index.js:156
if (existsSync(candidate)) return candidate - 读取本地文件plugins/dsh-remote-control/lib/index.js:158
if (existsSync(webCandidate)) return webCandidate - 读取本地文件plugins/dsh-remote-control/lib/index.js:332
const content = readFileSync(patchPath, 'utf8') - 写入本地文件plugins/dsh-remote-control/lib/index.js:335
writeFileSync(patchPath, updated, 'utf8') - 写入剪贴板plugins/dsh-system-prompt-editor/lib/client.js:564
await navigator.clipboard.writeText(text) - 读取本地文件plugins/dsh-task-models/lib/index.js:161
const text = await readFile(path, 'utf8') - 写入本地文件plugins/dsh-task-models/lib/index.js:177
await mkdir(dirname(keyPath), { recursive: true, mode: 0o700 }) - 写入本地文件plugins/dsh-task-models/lib/index.js:178
await writeFile(keyPath, key, { encoding: 'utf8', mode: 0o600 }) - 发起网络请求plugins/dsh-task-models/lib/index.js:216
response = await fetch(url, { - 读取本地文件plugins/dsh-task-models/lib/index.js:578
const scopes = await readdir(root, { withFileTypes: true }) - 读取本地文件plugins/dsh-task-models/lib/index.js:585
raw = await readFile(join(base, name)) - 写入本地文件plugins/dsh-terminal/build.mjs:55
writeFileSync('lib/client.js', finalOutput) - 启用终端会话(PTY)plugins/dsh-terminal/lib/index.js:79
ptyProcess = nodePty.spawn(selected.path, selected.args, { - 读取本地文件plugins/dsh-terminal/lib/shell.js:52
if (existsSync(pwsh7)) { - 读取本地文件plugins/dsh-terminal/lib/shell.js:54
} else if (existsSync(pwsh7Preview)) { - 读取本地文件plugins/dsh-terminal/lib/shell.js:58
if (existsSync(winPs)) { - 读取本地文件plugins/dsh-terminal/lib/shell.js:62
if (existsSync(cmd)) { - 读取本地文件plugins/dsh-terminal/lib/shell.js:66
if (existsSync(gitBash)) { - 读取本地文件plugins/dsh-terminal/lib/shell.js:68
} else if (existsSync(gitBash64)) { - 读取本地文件plugins/dsh-theme-studio/lib/css.js:108
return readFileSync(join(stylesDir(), name), 'utf8') - 读取本地文件plugins/dsh-theme-studio/lib/host-modules.js:343
const { size } = statSync(path) - 读取本地文件plugins/dsh-theme-studio/lib/host-modules.js:382
if (!existsSync(scopeDir)) continue - 读取本地文件plugins/dsh-theme-studio/lib/host-modules.js:385
names = readdirSync(scopeDir) - 读取本地文件plugins/dsh-theme-studio/lib/host-modules.js:393
if (!statSync(file).isFile()) continue - 读取本地文件plugins/dsh-theme-studio/lib/host-modules.js:420
else if (existsSync(join(root, 'app.asar'))) asarPath = join(root, 'app.asar') - 读取本地文件plugins/dsh-theme-studio/lib/host-modules.js:423
if (!existsSync(asarPath)) return [] - 读取本地文件plugins/dsh-theme-studio/lib/settings.js:448
if (!existsSync(filePath)) return null - 读取本地文件plugins/dsh-theme-studio/lib/settings.js:449
const parsed = JSON.parse(readFileSync(filePath, 'utf8')) - 写入本地文件plugins/dsh-theme-studio/lib/settings.js:471
mkdirSync(path.dirname(filePath), { recursive: true }) - 写入本地文件plugins/dsh-theme-studio/lib/settings.js:472
writeFileSync(tmp, `${JSON.stringify(settings, null, 2)}\n`, 'utf8') - 写入本地文件plugins/dsh-theme-studio/lib/settings.js:473
renameSync(tmp, filePath) - 读取本地文件plugins/dsh-theme-studio/lib/settings.js:477
if (existsSync(tmp)) renameSync(tmp, `${tmp}.stale`) - 写入本地文件plugins/dsh-theme-studio/lib/settings.js:477
if (existsSync(tmp)) renameSync(tmp, `${tmp}.stale`) - 写入本地文件plugins/dsh-theme-studio/lib/settings.js:534
mkdirSync(dir, { recursive: true }) - 写入本地文件plugins/dsh-theme-studio/lib/settings.js:535
writeFileSync(path.join(dir, name), data) - 读取本地文件plugins/dsh-theme-studio/lib/settings.js:560
if (!existsSync(full)) return { ok: false, error: '背景图不存在' } - 读取本地文件plugins/dsh-theme-studio/lib/settings.js:561
const data = readFileSync(full)
扫描于 2026/11/3(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
DeepSeek Harness 社区插件:插件管理器、AI Proxy 连接器、模型角色、spec 模式等
README
由 DeepSeek 最新模型翻译生成dsh-plugins(DeepSeek Harness 社区插件)
官方 DeepSeek Harness(DSH)社区插件 Monorepo 工作区。每个插件独立版本管理、独立测试、按需独立发布 Release。
📦 插件列表(Plugins Roster)
| 插件名称 | 目录 | 说明 | 最新独立版本 |
| dsh-plugin-manager | plugins/dsh-plugin-manager | 插件管理中心,也是自有插件的更新/卸载管理器(专属拼图图标、移动端全量响应式触控适配、自有插件一键批量更新(N)、支持配置 GitHub Token 把 API 配额提升到 5000 次/小时,并提供 Atom feed 无感兜底、社区 21 分类、静默直接复制指令、剪贴板写入全路径兜底、异步平滑重启与自动恢复、桌面端宿主版本识别穿透 asar 归档、修复卸载插件时误用无 scope 短名导致 pnpm remove 报错、tarball 安装统一采用 pnpm alias 确保 scoped 命名、自动识别并一键清理新旧短名双份冲突、修复插件更新后因 name mismatch 导致 cordis.patch.yml 配置被跳过丢失问题、新版本检查全面基于 npm registry 真实版本数据、自有插件目录新增中文标题与描述登记、已废弃插件仅允许卸载并在
展开完整文档(README 剩余 1 节)
dsh-plugins(DeepSeek Harness 社区插件)
官方 DeepSeek Harness(DSH)社区插件 Monorepo 工作区。每个插件独立版本管理、独立测试、按需独立发布 Release。
📦 插件列表(Plugins Roster)
| 插件名称 | 目录 | 说明 | 最新独立版本 |
| dsh-plugin-manager | plugins/dsh-plugin-manager | 插件管理中心,也是自有插件的更新/卸载管理器(专属拼图图标、移动端全量响应式触控适配、自有插件一键批量更新(N)、支持配置 GitHub Token 把 API 配额提升到 5000 次/小时,并提供 Atom feed 无感兜底、社区 21 分类、静默直接复制指令、剪贴板写入全路径兜底、异步平滑重启与自动恢复、桌面端宿主版本识别穿透 asar 归档、修复卸载插件时误用无 scope 短名导致 pnpm remove 报错、tarball 安装统一采用 pnpm alias 确保 scoped 命名、自动识别并一键清理新旧短名双份冲突、修复插件更新后因 name mismatch 导致 cordis.patch.yml 配置被跳过丢失问题、新版本检查全面基于 npm registry 真实版本数据、自有插件目录新增中文标题与描述登记、已废弃插件仅允许卸载并在列表中标注、自有插件目录补登 dsh-repo-wiki 仓库知识库中文标题/描述与专属书本图标) | v0.3.61 |
| dsh-model-roles | plugins/dsh-model-roles | 模型角色路由、自动分工、识图子代理、计划模式与顾问复核(/advisor、局域网访问放行、专属分支路由图标) | v0.4.32 |
| dsh-remote-control | plugins/dsh-remote-control | 通用 DSH 远程/局域网访问安全控制与特权通道插件(Token 密钥认证、密码锁屏门禁 Unlock Screen、特权 RPC 白名单桥接、HTTP 非安全上下文全局兼容、专属地球网络图标、桌面端/Web 版局域网地址自识别与端口展示、卡片化设置面板与访问地址一键复制、修复启用远程访问开关点击后不生效、局域网绑定改用具体网卡 IP 以适配 DSH 0.2.x 拒绝通配地址、修复端口行标签与按钮文字被挤成两行) | v0.1.38 |
| dsh-ai-proxy | plugins/dsh-ai-proxy | AI Proxy Service 网关对接插件(协议层外包给宿主官方 llm-pi-ai 适配器并自动材料化路由、Chat/completions/Anthropic messages/Responses 三格式、最高推理强度开关、OAuth 2.0 PKCE 认证、令牌过期前主动轮换与阶梯推理映射、把网关 /v1/models 的 modality(text/image/decision)写入材料化路由供静态判断) | v0.3.20 |
| dsh-mobile-adapter | plugins/dsh-mobile-adapter | DSH 移动端全量体验优化(原生图片/相册上传、工作区工具箱整合文件查看器/本地终端/提示词历史、移动端右侧栏避让与一键返回对话、对话框底部全操作按钮圆形统一规范、输入框下方统计行固定单行三列(槽位 row/nowrap、末位文字省略号、≤360px 再降级)并按实测高度动态收进卡片且不再依赖 :has()、视口高度自适应、Segmented Control Tabs、全量弹窗防溢出、输入区聚焦防整页放大、应用级浮层按宿主稳定属性压过移动端顶栏、宿主类名存活与去哈希兜底、设置页头部选择条左右贴边与顶栏无缝一体化融合、一键全屏(Fullscreen API 收起浏览器导航栏与底部工具栏,应用自身顶栏/标题栏/tabs 全部保留 + 100dvh 重铺 + 退出状态同步)、模型选择菜单滚动修复(容器保持 overflow:hidden 让内部滚动区接手)、顶栏收口为「☰ + 标题 + 操作下拉 + 全屏」(轨迹切换/新建工作区/右侧侧边栏收进下拉面板并按可用性动态显示,修复面板条目被误判为不可用而全部隐藏)) | v0.1.62 |
| dsh-file-viewer | plugins/dsh-file-viewer | 工作区文件查看器(PC 端全屏切换;桌面端避开 Windows 原生标题栏按钮,接管原生「在应用中打开」与更改卡片打开;桌面版标题栏避让改为 important 偏移,以赢过抽屉自身的 inset 声明(修复 v0.3.6 起因 inset 展开而复发的问题);移动端触屏长按右键菜单防抖与底部抽屉;路径复制与 @ 引用;语法高亮;Markdown/JSON、图片、PDF、Excel、Word;安全访问路径双重持久化保存;下载上限独立提至 100MB,预览上限保持 20MB;浏览器交原生下载管理器接管,桌面端流式显示百分比进度;非 ASCII 文件名与错误回显安全加固;标题字阶与品牌色前景改用宿主真实 token,以兼容单色品牌主题;输入栏入口几何对齐宿主原生「+」按钮;右侧内容区多标签页,标签右键刷新/关闭/关闭其它/关闭所有;左侧目录树与右侧标签页实时联动(高亮跟随当前标签而非最后点击、自动展开祖先目录并滚动定位、加载中即高亮、历史版本与 diff 标签不误标、修复高亮选择器与实际属性所在元素不匹配导致从未生效的问题、修复阅读字号步进器在 Markdown/JSON 预览中无效的问题(宿主根节点用 font 简写写死字号,改为逐根节点重声明并连带行高);补齐 macOS 桌面版交通灯按钮避让(优先消费宿主 --dsh-frame-overlay-top,含 DPI 缩放与全屏撤销);桌面版抽屉左上角对齐宿主内容卡圆角(消费 --dsh-windows-content-radius,修复抽屉与会话标题栏拼成一条连续横带、看起来像盖在窗口之上的一层);工具栏移除语言识别来源常驻文字(改入语言下拉框 tooltip,消除同一排控件随来源变宽的跳动);目录树右键新增「删除文件/目录」(红色危险项 + 确认弹窗写明目标与相对路径、目录需显式递归、根目录与越界路径一律拒绝、删完关闭失效标签并重读树);工作区改动 diff 上方新增「打开文件」跳转到文件本体(删除态置灰说明,diff 标签副标题加「· 改动」以便与文件标签区分);修复打开文件后其所在目录无法折叠(展开逻辑误依赖自身写入的 expanded 状态,改为只依赖当前文件并经 ref 读树状态);文件标签右键新增「定位文件」,手动让目录树重新展开并滚动到该文件(明确放行一次性展开守卫,非文件标签置灰);修复 Markdown 目录面板行被压扁导致文字下半部分被裁(flex 行缺 flex:none,改为行保持高度、列表自行滚动);新增侧栏收起/展开开关(整栏收放让内容区占满,宽度独立持久化不被重置,隐藏而非卸载以保留滚动与展开状态,手机端隐藏,且收起/展开状态持久化,重开浏览器仍是上次状态);修复会话中点击卡片「全部 N 个文件」展开按钮被误判为文件而弹出查看器(按 aria-expanded 识别 disclosure 控件并排除,卡片本体仍可点击);会话末尾的计划卡片(exit_plan_mode 方案)改由插件打开(宿主按 call id 从会话日志取出 Markdown 落盘到 ~/.dsh/file-viewer/plans,左栏改为该会话的计划列表导航,原先前缀与路径规则全不匹配导致落到宿主原生工件面板);安全访问路径弹窗中的「内置工作区」清单改为可折叠且默认折叠(只读参考信息,本机实测展开占 363px、折叠 36px,省出 327px;状态单独持久化,与侧栏收起互不影响);计划卡片改为落盘到工程内 <工作区>/.dsh-plans/<标题>-<callId>.md 并作为纯净普通文件打开(写入本地 Git 私有忽略配置 .git/info/exclude 零污染工作区,目录树默认放行 .dsh-plans 显示,文件名带 callId 防同名覆盖,左栏永远保留完整目录树,标签页带 × 可直接关闭);修复重启后历史计划卡片点击无反应(归档检索由"全量扫描 501 个文件 438MB 耗时 21.2 秒"改为"按 sessionId 直接寻址 389ms",快约 54 倍;兜底扫描加 80 文件/5 秒预算,结果缓存与并发单飞,重复点击 2ms;实测否掉 Node 内置 zstd 解码器——多帧归档只解出首帧 211 字节且静默失败,改为依赖 zstd 二进制并在缺失时报 plan-archive-unavailable;超过 8 秒提供「改用原生面板打开」逃生入口;禁止猜"第一个工作区"以免计划写错项目)) | v0.3.39 |
| dsh-terminal | plugins/dsh-terminal | (已废弃,插件管理器中只能卸载、不能安装或更新) 跨平台本地交互式终端(移动端专属对话框底部工具箱二合一入口、PC 端隐藏、多标签并发、触控辅助键盘) | v0.1.17 |
| dsh-archive-manager | plugins/dsh-archive-manager | 会话归档管理器(侧边栏实时归档计数徽章、一键恢复会话与彻底删除清理磁盘空间) | v0.2.15 |
| dsh-prompt-history | plugins/dsh-prompt-history | 提示词历史导航、修改重发与跨端同步器(已发气泡悬浮✏️修改与🔄重发、移动端提示词按钮归入工作区工具箱、自适应底部抽屉、严格会话绑定防串门、宿主持久化跨端漫游、输入栏入口几何对齐宿主原生「+」按钮) | v0.4.13 |
| dsh-theme-studio | plugins/dsh-theme-studio | 主题工作室:默认保持 DSH 原生风格,提供系统默认 + 5 款内置主题(ZCode 官方 / ZCode 单色极简 / 苹果玻璃 / 玻璃彩色 / 极光流光)切换、统一 Token 契约(一份 HOST_TOKEN_MAP 服务全部主题,宿主 145 个 --dsw- 全覆盖)、插件兼容层(显式定义插件引用但宿主未定义的别名,并逐插件扫描守护)、背景(纯色/图片/不透明度)、字体、字号、11 项字段颜色可视化自定义并持久化到 ~/.dsh/theme-studio/settings.json、白名单式输入校验防 CSS 注入、首屏直出零闪烁、变量按 body/:root 分层解决宿主特异性覆盖、prefers-reduced-transparency 无障碍退化、输入卡内权限与模型选择器去掉背景框与描边(与相邻「+」按钮视觉一致)、修复玻璃主题下模型选择菜单无法滚动(菜单容器规则排除内层滚动区)、新增极光流光主题(三层漂移光斑 + 聚焦流光边框 + 运行态呼吸波纹,光斑层不用 filter:blur 以保住核显帧率)、状态条动效抽离为 11 档独立开关(默认原生零侵入)、新增设置页与全仓库插件的组件层主题适配(宿主 144 个交互控件按属性模式兜底跨构建命中)、修复极光停止生成按钮动效误选普通发送按钮导致闲置时持续重绘(改为按 aria-label / svg rect 限定运行态)、消除极光动态光斑与全屏毛玻璃死锁(全屏大容器免除每帧高斯卷积,GPU 占用降至 0%~1% 并恢复 120/144 FPS)、移动端顶栏与主容器在极光主题下改回原生贯通式(左、右、上顶边贴合,不留缝隙,无圆角与浮动卡片化留白)、任务面板 TodoPanel 圆角优化(去除 999px 胶囊大圆角畸变,改用 16px 极光微弧卡片圆角并呼应输入卡)、修复桌面版侧栏丢失主题色(Windows 让位规则改用 :where() 降权,特异性 (0,3,1)→(0,2,1)/(0,2,2),不再压死极光与玻璃的 transparent 让位与 ::before 材质)、修复选择面板选中态完全不可见(透明底规则的 :not() 链把特异性抬到 (0,6,1),压掉只有 (0,2,1) 的选中态;现对齐特异性并补左侧 2px 主色竖条,五款主题统一生效) | v0.3.6 |
| dsh-zcode-theme | plugins/dsh-zcode-theme | (已废弃,插件管理器中只能卸载、不能安装或更新;兼容薄壳) ZCode 主题已并入 dsh-theme-studio 的 zcode / zcode-mono 内置主题;本包仅保留旧属性与样式标签 id 以保证平滑升级,薄壳产出的变量与工作室逐值相同、检测到 data-theme-studio 时让位、不再调用 overrideTokens 以免覆盖其它主题 | v0.3.0 |
| dsh-jev | plugins/dsh-jev | 决策模型原生工具插件(可直接下拉选择 dsh 已配置的服务商与模型,此时接口地址与 API Key 完全由服务商配置解析;也可手写 baseURL/Key/模型 ID。决策模型按 /v1/models 的 modality、静态 modality(含 dsh-ai-proxy 材料化写入)、classifier 协议、模型类型与名称识别;默认仍为 TypeSafe Jev 官方地址、Choice/Score/Noul 三大决策原语、/v1/systemone 与 /v1/decisions 端点切换、代理访问支持 http/https/socks5、常驻决策策略切面引导智能体何时调用) | v0.2.6 |
| dsh-image-gen | plugins/dsh-image-gen | DSH 原生生图插件(把文生图作为原生工具暴露,可直接下拉选择 dsh 已配置的服务商与模型、或手动填写 baseURL/Key,内置尺寸与画质选择,支持 http/https/socks5 代理;设置面板可实时切换并测试连通性) | v0.1.5 |
| dsh-task-models | plugins/dsh-task-models | 独立子任务模型路由插件(按任务类型为子代理选择模型、显式标签优先与词边界匹配、规则试运行预览、workflow 模型标注附路由解释、可选 TypeSafe Jev 决策、可选轻量分类回退、有界决策超时与取消传播、不依赖任何 Agent Preset 或角色路由插件) | v0.3.0 |
| dsh-im-bot | plugins/dsh-im-bot | 集成机器人:企业微信智能机器人(长连接 API 模式,无需公网地址)与个人微信(腾讯 iLink Bot 官方接口)双通道、微信发消息驱动 DSH 会话的双向通信(/new /use /sessions /status /stop /notify /help 内置命令)、回合完成与失败告警主动回推发起聊天、白名单安全默认拒绝、每 peer 限流与分片、断线指数退避重连、扫码登录、绑定关系可视化管理、im_bot_send 原生工具与 /dsh-im-bot/send 通用推送接口 | v0.1.14 |
| dsh-system-prompt-editor | plugins/dsh-system-prompt-editor | 系统提示词可视化编辑器(默认展示当前真实系统提示词;按名称定位改为下拉框,列出真实段落并附中文含义与悬停预览;同行字段顶部对齐,修正下拉框错位;五种定位方式与五种改写动作;可按预设或会话限定生效范围;追加段落走正式 section 注册;保存前实时预览与逐条命中反馈;优先写入官方 settings 服务并原子落盘;任一规则异常都不阻断会话,失败时原样放行官方提示词;通过 system-prompt/assemble waterfall 实现,故无需改动安装包) | v0.2.0 |
| dsh-repo-wiki | plugins/dsh-repo-wiki | Qoder Repo Wiki 等价实现(逆向 Qoder CN 1.35.0:18 状态状态机与进度换算、wiki_catalogs/wiki_items/knowledge_relations 四表元数据、分类目录页面路径规则实测 71/71 对齐、wiki_plan.yaml 全部字段与 Qoder 上限、六个 _wiki 工具)。在宿主内用 ctx.llm 跑「目录规划 → 逐页写作」两阶段流水线,产物落进仓库的 .dsh/repowiki,支持暂停/续跑/取消/增量更新/自动更新,可直接读取 Qoder 已导出的 .qoder/repowiki;修复 @deepseek-ai/dsh-agent-preset peer 下界写成从未发布的 0.1.0-rc.6,导致 pnpm 解析失败、CI 与用户安装双双装不上;修复生成调用被 INVALID_PREPARED_CALL 判为配置篡改,导致每次生成必败;修复中文界面菜单/设置项仍显示英文 Repo Wiki) | v0.2.8 |
| dsh-spec | plugins/dsh-spec | 以 Agent 预设形式提供的 Spec 模式(Kiro 兼容的 SPEC 规约模型,逆向 Kiro 1.4.13 的官方文档模板与校验器:.kiro/specs 三文档、EARS 验收标准、Correctness Properties、复选框任务状态机、Task Dependency Graph 波次调度、tasks.meta.json 执行/PBT 记录)。8 个 spec_ 工具与 Kiro 提示词随「Spec 模式」预设挂载,只有选中该预设的会话可见;宿主行只提供 SPEC 抽屉面板与设置页的 RPC 通道) | v0.2.0 |
🚀 插件安装指南 (Installation)
所有插件已发布到 npm registry,scope 为 @weniatall/。用 DSH 官方 CLI 即可在线一键安装:
为什么带 @weniatall/ 前缀:12 个插件里有 9 个的无 scope 包名(dsh-terminal、 dsh-file-viewer 等)已被第三方占用且不可转让,因此统一迁移到 scope 下。scope 包名与 GitHub tag 刻意不同 —— tag 仍是 dsh-terminal@v0.1.16 这样的短名,以便历史 Release 的下载链接和插件管理器的来源白名单继续有效。详见 npm 发布指引。
宿主兼容(dsh 0.2.1-rc.2):下表版本均已针对运行中的 dsh 宿主做过兼容校验,peerDependencies 使用 >=0.1.0-rc.6 这类开放区间,同时接受 0.1.x、0.2.0-rc.N 与 0.2.1-rc.N。2026-09-29 之前发布的旧版本(如 dsh-ai-proxy@0.3.9、dsh-model-roles@0.4.25)声明的是 ^0.1.0-rc.6,其隐含上界 0.2.0-0 把 0.2.0-rc.2 排除在外,dsh 0.2 会在启动时直接拒载:
dsh: warning: Plugin dsh-ai-proxy@0.3.9 is incompatible with dsh 0.2.0-rc.2: peerDependencies ...
dsh: it stays installed but profile startup denies it until you grant an exemption for those exact versions.
修复方式是用下面的安装命令覆盖安装同名插件(dsh plugin add 会替换 profile 里 pin 住的旧 tarball),再重启服务;不要手动往 profile 的 node_modules 里拷文件。
1. 安装插件管理中心 (自有插件更新与社区市场)
dsh plugin --profile web add @weniatall/dsh-plugin-manager
2. 安装模型角色分工插件 (多模型智能路由与识图子代理)
dsh plugin --profile web add @weniatall/dsh-model-roles
3. 安装远程安全通道插件 (推荐所有公网/局域网部署安装)
dsh plugin --profile web add @weniatall/dsh-remote-control
4. 安装 AI Proxy 网关插件
dsh plugin --profile web add @weniatall/dsh-ai-proxy
5. 安装移动端适配插件 (手机浏览器访问必备)
dsh plugin --profile web add @weniatall/dsh-mobile-adapter
6. 安装文件查看器插件 (会话头部抽屉浏览工作区文件)
dsh plugin --profile web add @weniatall/dsh-file-viewer
7. 安装本地终端插件 (跨平台原生终端调用与移动端适配)
dsh plugin --profile web add @weniatall/dsh-terminal
8. 安装会话归档管理器
dsh plugin --profile web add @weniatall/dsh-archive-manager
9. 安装提示词历史与跨端漫游
dsh plugin --profile web add @weniatall/dsh-prompt-history
10. 安装主题工作室(ZCode / 苹果玻璃等多款主题 + 外观自定义)
dsh plugin --profile web add @weniatall/dsh-theme-studio
(旧包 @weniatall/dsh-zcode-theme 已并入上面这个,仅作兼容薄壳保留)
11. 安装决策模型(默认 TypeSafe Jev,也可选 dsh 已配置的服务商)
dsh plugin --profile web add @weniatall/dsh-jev
12. 安装文生图 (生图模型) 插件
dsh plugin --profile web add @weniatall/dsh-image-gen
13. 安装独立子任务模型路由 (按任务类型为子代理选模型)
dsh plugin --profile web add @weniatall/dsh-task-models
14. 安装集成机器人 (企业微信 / 个人微信双向通信与任务完成通知)
dsh plugin --profile web add @weniatall/dsh-im-bot
15. 安装 Kiro 兼容 SPEC 规约模型 (requirements/design/tasks + 校验与任务状态)
dsh plugin --profile web add @weniatall/dsh-spec
16. 安装 Qoder Repo Wiki 等价的仓库知识库 (两阶段生成 + 六个 _wiki 工具)
dsh plugin --profile web add @weniatall/dsh-repo-wiki
从旧版 tarball 安装迁移
如果你的配置档里还 pin 着旧的无 scope 版本或 GitHub tarball,直接执行上面的 dsh plugin add @weniatall/... 即可覆盖安装:dsh plugin add 会替换配置档里 pin 住的旧来源,不需要先卸载。
迁移前,配置档的 package.json 里通常长这样(两种历史形态):
{
// 形态一:插件管理器预下载的本地缓存 "dsh-terminal": "file:/home/you/.dsh/profiles/web/.plugin-manager/downloads/dsh-terminal-0.1.16.tgz", // 形态二:GitHub Release tarball,版本被锁死 "dsh-model-roles": "https://github.com/veildawn/dsh-plugins/releases/download/dsh-model-roles@v0.4.31/dsh-model-roles-0.4.31.tgz" }
迁移后应变成标准的 registry 依赖:
{
"@weniatall/dsh-terminal": "^0.1.17",
"@weniatall/dsh-model-roles": "^0.4.32"
}
注意:包名本身也变了(dsh-terminal → @weniatall/dsh-terminal),旧条目不会自动消失。安装完新版后,需要把 dependencies 与 dsh.profile.bundles 里的旧名手动删掉,否则宿主会因找不到模块而报错。dsh-plugin-manager 已内置新旧名称的双向兼容匹配,能正确识别这种过渡态(不会把已安装的插件显示成「未安装」),但它不会替你改写配置档清单。
插件管理器内的安装与更新
dsh-plugin-manager 的版本检测、安装、更新与「复制指令」都走 npm 渠道:
- 版本检测:优先读 npm registry 的 dist-tags.latest(发布事实本身), GitHub Release 仅作兜底,避免 tag 与 package.json 版本不一致导致的误判;
- 安装 / 更新:向 dsh plugin add 传入 @weniatall/dsh-xxx 包名,而不是锁死版本的 tarball URL;
- 复制指令:复制出来的命令是 dsh plugin --profile web add @weniatall/dsh-xxx。
离线或内网环境可以在插件管理器设置里打开 allowTarball,此时回落到 GitHub Release 的 tarball(仍会校验来源白名单)。
重启 DSH Web 服务生效
注意:@deepseek-ai/dsh 官方命令行本身没有 service 子命令,执行 dsh service restart 会报错。请使用本仓库自带的控制脚本:
- macOS / Linux 用户: ./scripts/dsh-web.sh restart
- Windows 用户: .\scripts\dsh-web.ps1 restart 或 cmd: scripts\dsh-web.cmd restart
🛠️ 独立发布机制 (Independent Release Workflow)
本项目采用业内标准 Monorepo 独立发布策略(Tag 格式:<plugin-name>@v<version>)。
npm 包名带 scope(@weniatall/dsh-terminal),GitHub tag 保持短名(dsh-terminal@v0.1.16)——
两者刻意不同,原因见 npm 发布指引。
⚠️ 新增插件时必须手动做的三步操作(一次性)
下面三件事无法由 CI 完成,每新增一个插件都要人工执行一次。漏做任何一步,后续推 tag 的自动发布会直接失败(E404 或 403)。
第 1 步:本地登录 npm(每个开发者/每台机器一次)
npm login --auth-type=web
Trusted Publishing 只能给已存在的包配置,所以每个新包的首个版本必须先在本地发出去。
第 2 步:首次发布该包(每个新包一次)
cd plugins/dsh-terminal && npm publish --access public
首次发布不要加 --provenance(本地没有 OIDC 身份,加了会报错)。CI 后续发布的新版本才会带上 provenance。发布前记得先跑 npm test 与
node scripts/verify-pack-contents.mjs --plugin <插件目录名>。
第 3 步:给这个包配置一次 trusted publisher(每个新包一次)
打开该包的设置页,例如:
<https://www.npmjs.com/package/@weniatall/dsh-terminal/access>
在 Trusted publishing 区域点 Add trusted publisher,按下表填写:
| 字段 | 值 |
| Publisher | GitHub Actions |
| Organization or user | veildawn |
| Repository | dsh-plugins |
| Workflow filename | release-plugin.yml |
| Environment name | 留空(不使用 environment 保护) |
*Organization or user 填的是 GitHub 仓库归属(veildawn),不是 npm 账号名(weniatall),两者不同是正常的 —— npm 校验的是仓库身份。
工作流文件名必须逐字符一致(release-plugin.yml,含扩展名)。配好后建议同时把 Publishing access 设为 “Require two-factor authentication and disallow tokens”,彻底关掉 token 通道。
三步都完成后,该插件之后的所有版本都可以只靠推 tag 自动发布(见下方方式 1)。
完整背景与故障排查见 npm 发布指引。
方式 1:推送 Tag(推荐,默认即发布 npm)
改好 plugins/<plugin>/package.json 的 version 并推送到 main 后,打并推送 <plugin-name>@v<version> 形式的 Tag,CI 会跑测试、校验打包内容、发布 npm(走 Trusted Publishing,无需任何 token)、再创建 GitHub Release:
git tag -a "dsh-terminal@v0.1.16" -m "dsh-terminal v0.1.16"
git push origin "dsh-terminal@v0.1.16"
版本已存在于 npm 时该步骤会自动跳过而不是让 job 失败(重跑或重推修正后的 tag 都安全),GitHub Release 仍会正常创建。要发新版本必须升 package.json 的 version。
方式 2:GitHub Actions 手动触发
在 Actions → Release Single Plugin → Run workflow 中填写插件名、版本号。
publish_npm 默认已勾选;取消勾选则只建 GitHub Release。执行内容与方式 1 相同。
方式 3:本地一键脚本
格式: ./scripts/release.sh <插件目录名> [版本号(可选)] ./scripts/release.sh dsh-plugin-manager 0.3.38 ./scripts/release.sh dsh-model-roles 0.4.28 ./scripts/release.sh dsh-remote-control 0.1.18 ./scripts/release.sh dsh-ai-proxy 0.3.12 ./scripts/release.sh dsh-mobile-adapter 0.1.41 ./scripts/release.sh dsh-file-viewer 0.1.49 ./scripts/release.sh dsh-terminal 0.1.13 ./scripts/release.sh dsh-task-models 0.3.0 脚本会自动:
1. 运行对应插件的单元测试;
2. 校验宿主兼容性与 npm 发布内容(verify-pack-contents.mjs);
3. 执行 npm pack 并把产物重命名为 <短名>-<版本>.tgz;
4. 打上 plugin@vX.Y.Z 格式的 Git Tag 并推送(因此同样会触发 CI 发布 npm);
5. 再用 gh release create 自己建一次 Release。
⚠️ 第 4 步已经触发 CI,第 5 步与 workflow 的 “Create GitHub Release” 存在竞争,谁先建谁生效。日常发布建议直接用方式 1。
发布前的本地自检:node scripts/verify-pack-contents.mjs 会逐个校验全部插件的 files 白名单,确保既不漏发运行期文件,也不会把 test/、node_modules/ 或历史 .tgz 一起发出去。
设置写入自检(has no volatile fields 回归)
dsh 0.1.7 起(含当前的 0.2.1-rc.2)ctx.settings 是 dsh-settings 的 SettingsForms:任何没有声明 live
(.volatile()) 字段的插件条目,宿主的写入会直接抛
Plugin entry "<id>" has no volatile fields(前端表现为「保存配置失败」),且该条目不会出现在 describe() 里。凡是自己写自己设置节的插件,都要把被写入的字段声明为 live,并在读取时解包 live 引用。
scripts/check-host-settings.mjs 用宿主真实的 Loader/fiber、SettingsForms 与 schemastery 挂载插件的真实 Config,逐字段验证写入被接受、落盘到 profile 补丁且不重载 fiber;机器上没有 dsh 时打印 SKIP 退出 0。受影响插件的 npm test 已串联该检查:
node scripts/check-host-settings.mjs plugins/dsh-archive-manager archive-manager
宿主兼容自检(is incompatible with dsh ... 拒载回归)
dsh 启动时只按 peerDependencies 里的 @deepseek-ai/dsh 区间判断插件能否加载,且带
includePrerelease: true。^0.1.0-rc.6 会被解析成 >=0.1.0-rc.6 <0.2.0-0,上界 0.2.0-0 小于 0.2.0-rc.2,于是 0.1 线上锁死的 caret 区间在宿主升到 0.2.0-rc.N 的那一刻变成硬拒载:插件仍然「安装成功」,但 profile 启动会跳过它,并把 Plugin <name>@<version> is incompatible with dsh <version> 写进安装日志与启动告警。
scripts/check-plugin-compat.mjs 用宿主自己的 evaluatePluginCompatibility() (@deepseek-ai/dsh-app-boot 导出,与启动告警同一段逻辑)逐个校验本仓库插件的 package.json,并额外确认宿主确实提供了清单里声明的每个 @deepseek-ai/dsh 包;机器上没有 dsh 时打印 SKIP 退出 0。scripts/release.sh 已在测试前串联该预检,范围写错的版本不会再被发出去。
0.2.1-rc.2 起的「宿主没有这个包」例外:@deepseek-ai/dsh-client-ui-slots 与 @deepseek-ai/dsh-client-ui-primitives 是宿主前端自己的构建依赖,dsh-web-frontend 用 vite 把它们内联进 dist/assets/.js,再经 window.__ModuleLoader__ 作为共享模块(seed)发给插件 client bundle。宿主 node_modules 里没有同名目录不是不兼容——预检会同时扫描 web bundle 的 seed 表,命中即视为宿主已提供;只有既不在 node_modules、也不在 seed 表里的包才判 FAIL。
node scripts/check-plugin-compat.mjs # 全部插件
node scripts/check-plugin-compat.mjs plugins/dsh-ai-proxy # 单个插件
node scripts/check-plugin-compat.mjs --runtime 0.2.1-rc.2 # 指定宿主版本
宿主 CSS Modules 哈希类名自检(data- 稳定属性回归)
宿主前端的 CSS Modules 类名(如 Sh0Q9G_trigger、FJxK0a_root)由构建生成,宿主每次发版都可能变。
插件里按旧哈希写的样式覆盖不会报错,只会静默失效——0.2.1-rc.2 把统计行从 dsh-client-ui-conversation 迁到 dsh-client-ui-chat(FJxK0a_root → bOPqQW_),把权限选择器迁到 dsh-client-ui-permission-presets(Sh0Q9G_ → iWlSmW_),移动端因此重新冒出两行统计并把 ∨ 箭头带回权限按钮。
新写样式覆盖时优先用宿主渲染时写死的稳定属性(data-composer-stat、data-slot、
data-composer-card、[data-shortcut-modal="settings"] 等),必须用哈希类名时请同时保留
新旧两代前缀,并用下面的脚本确认没有死哈希:
对照当前宿主审计:列出插件里已不存在于宿主 node_modules 的哈希前缀
node -e "
const fs=require('fs'), path=require('path');
const D=process.env.DSH_HOST||'/home/ai_bot/.nvm/versions/node/v22.22.1/lib/node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai';
const isHash=s=>/^[A-Za-z0-9]{5,8}$/.test(s)&&/[A-Z0-9]/.test(s);
const host=new Set();
for(const p of fs.readdirSync(D)){const f=path.join(D,p,'lib/client.js');if(!fs.existsSync(f))continue;
for(const m of fs.readFileSync(f,'utf8').matchAll(/\.([A-Za-z0-9]{5,8})_[a-zA-Z]+\{/g))if(isHash(m[1]))host.add(m[1]);}
for(const plugin of fs.readdirSync('plugins')){const f=path.join('plugins',plugin,'lib/client.js');if(!fs.existsSync(f))continue;
const used=new Set();for(const m of fs.readFileSync(f,'utf8').matchAll(/\.([A-Za-z0-9]{5,8})_[a-zA-Z]+\{/g))if(isHash(m[1]))used.add(m[1]);
const dead=[...used].filter(h=>!host.has(h));if(dead.length)console.log(plugin,'->',dead.join(', '));}
"
宿主加载自检(1 required plugin did not activate 回归)
peerDependencies 只挡住「版本区间」,挡不住「清单没变但宿主 API 变了」这一整类故障: 0.2.1-rc.2 移除了 webRuntime 服务。只要 cordis.patch.yml 还在给 connection 注入它,这一行就会永远停在 pending,profile 启动直接失败:
dsh: startup failed: 1 required plugin did not activate
Plugin Missing services
connection (required) webRuntime
scripts/check-host-load.mjs 会按宿主自己的 node_modules 真实 import 一次插件,并断言:
1. 入口导出 apply()(或默认插件函数);
2. 每个 inject 服务名都能在宿主已装载的插件里找到提供者;
3. cordis.patch.yml 里每条 inject: 只引用宿主确实提供的服务;
4. 若声明了 Config,它是宿主 schemastery 能识别的 schema。
没有 dsh 时同样打印 SKIP 退出 0;scripts/release.sh 已把它排在测试之前:
node scripts/check-host-load.mjs # 全部插件
node scripts/check-host-load.mjs plugins/dsh-ai-proxy # 单个插件
📄 License
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
veildawn/dsh-plugins
集中安装更新与卸载社区插件,一键批量升级
相关插件 · 市场 / 管理
插件精选列表awesome-dsh-plugin/awesome-dsh-plugin
DeepSeek Harness(dsh)插件精选列表
★ 22,025未汉化DSH
73.6
新词雷达zhuyansen/new-term-radar
new-term-radar新词雷达
★ 2,049已汉化MCP
72.8
插件生态导航0xsline/awesome-deepseek-harness
安装 贡献指南 DeepSeek Docs 公开插件目录 Issues
★ 1,188已汉化DSH
72.6
技能注册中心iflytek/skillhub
企业级开源智能体技能注册中心——发布、发现并管理组织内可复用的技能包。
★ 5,358已汉化DSH
71.9
插件市场目录imsai-sh/awesome-deepseek-harness-plugins
面向 DeepSeek Harnessdsh生态的社区插件目录,共收录 13938 个插件含 PR 收录与…
★ 350已汉化DSH
71.8
插件精选清单Anil-matcha/awesome-dsh-plugin
DeepSeek Harnessdsh精选指南——DeepSeek…
★ 1,013已汉化DSH
71.7
这是你的仓库?认领条目