集中托管插件前端,统一渲染派发并记录审计
30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/18 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查有告警:npm 同名包「dsh-panel」归属 dushaobindoudou/dsh-panel,装到的可能不是本插件。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add jonah791/dsh-panel该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · ui
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 47 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
⚠︎ 实装验证未通过(unknown · 2026/11/4) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意npm 同名包「dsh-panel」归属 dushaobindoudou/dsh-panel,装到的可能不是本插件
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-panel @ 0.0.1
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/8 06:34:24
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件
查看扫描证据(共 78 处,展示前 48 条)
- 写入本地文件src/audit.ts:43
mkdirSync(dir, { recursive: true }) - 写入本地文件src/audit.ts:44
appendFileSync(join(dir, 'audit.jsonl'), JSON.stringify(record) + '\n', 'utf8') - 读取本地文件src/index.ts:109
if (existsSync(file)) { - 读取本地文件src/index.ts:110
try { return readFileSync(file, 'utf8') } catch { } - 读取本地文件src/index.ts:344
if (!existsSync(target)) continue - 读取本地文件src/index.ts:346
const body = readFileSync(target) - 读取本地文件src/index.ts:393
if (!existsSync(target.file)) { - 读取本地文件src/index.ts:398
if (!statSync(target.file).isFile()) { - 读取本地文件src/panels/agent-teams.ts:79
if (!existsSync(file)) return undefined - 读取本地文件src/panels/agent-teams.ts:81
return JSON.parse(readFileSync(file, 'utf8')) as T - 读取本地文件src/panels/agent-teams.ts:106
if (!existsSync(dir)) return { files, messages, detail } - 读取本地文件src/panels/agent-teams.ts:107
for (const name of readdirSync(dir)) { - 读取本地文件src/panels/agent-teams.ts:110
if (!statSync(file).isFile()) continue - 读取本地文件src/panels/agent-teams.ts:115
n = readFileSync(file, 'utf8').split(/ ? /).filter((l) => l.trim() !== '').length - 读取本地文件src/panels/audit.ts:52
if (!existsSync(file)) return { records: [], corrupt: 0, truncated: false, bytes: 0 } - 读取本地文件src/panels/audit.ts:57
bytes = statSync(file).size - 读取本地文件src/panels/audit.ts:77
raw = readFileSync(file, 'utf8') - 读取本地文件src/panels/growth-profile.ts:71
if (!existsSync(file)) return undefined - 读取本地文件src/panels/growth-profile.ts:73
return JSON.parse(readFileSync(file, 'utf8')) as T - 读取本地文件src/panels/growth-profile.ts:103
if (!existsSync(root)) return out - 读取本地文件src/panels/growth-profile.ts:104
for (const name of readdirSync(root)) { - 读取本地文件src/panels/growth-profile.ts:107
if (!statSync(dir).isDirectory()) continue - 读取本地文件src/panels/growth-profile.ts:159
if (!existsSync(root)) continue - 读取本地文件src/panels/plugin-manager.ts:40
if (!existsSync(patchFile)) return out - 读取本地文件src/panels/plugin-manager.ts:41
const lines = readFileSync(patchFile, 'utf8').split(/ ? /) - 读取本地文件src/panels/plugin-manager.ts:67
for (const entry of readdirSync(dir)) { - 读取本地文件src/panels/plugin-manager.ts:70
if (statSync(full).isDirectory()) collectSources(full, out) - 读取本地文件src/panels/plugin-manager.ts:80
for (const entry of readdirSync(d)) { - 读取本地文件src/panels/plugin-manager.ts:83
const st = statSync(full) - 写入本地文件src/panels/plugin-manager.ts:170
writeFileSync(tmp, content, 'utf8') - 写入本地文件src/panels/plugin-manager.ts:171
renameSync(tmp, file) - 写入本地文件src/panels/plugin-manager.ts:213
writeFileSync(join(dshHomeDir, '.hot-reload-flag'), JSON.stringify({ workspace: join(dshHomeDir, '..'), note }, null, 2), 'utf8') - 写入本地文件src/panels/taskboard.ts:94
writeFileSync(tmp, content, 'utf8') - 写入本地文件src/panels/taskboard.ts:95
renameSync(tmp, file) - 读取本地文件src/panels/taskboard.ts:100
if (!existsSync(file)) return { tasks: [], note: `任务板文件缺失:${file}` } - 读取本地文件src/panels/taskboard.ts:102
const parsed = JSON.parse(readFileSync(file, 'utf8')) as { tasks?: unknown } - 读取本地文件src/panels/taskboard.ts:114
if (!existsSync(dir)) return out - 读取本地文件src/panels/taskboard.ts:115
for (const name of readdirSync(dir)) { - 读取本地文件src/panels/taskboard.ts:119
const parsed = JSON.parse(readFileSync(file, 'utf8')) as ArchiveRecord - 读取本地文件src/panels/taskboard.ts:310
if (!existsSync(boardFile)) { - 写入本地文件src/panels/taskboard.ts:329
mkdirSync(archiveDir, { recursive: true }) - 写入本地文件src/panels/taskboard.ts:336
renameSync(target, `${target}.corrupt-${localClock(now)}`) - 读取本地文件src/panels/tavern.ts:215
const st = statSync(file) - 读取本地文件src/panels/tavern.ts:231
if (!existsSync(dir)) return [] - 读取本地文件src/panels/tavern.ts:234
names = readdirSync(dir) - 读取本地文件src/panels/tavern.ts:266
if (!existsSync(dir)) return { exists: false, files: 0, bytes: 0 } - 读取本地文件src/panels/tavern.ts:272
entries = readdirSync(current, { withFileTypes: true }) - 读取本地文件src/panels/tavern.ts:290
bytes += statSync(full).size
扫描于 2026/11/4(0 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/schemastery@deepseek-ai/dsh-tools@deepseek-ai/dsh-host-webserver给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 托管插件前端
- 统一渲染派发
- 记录审计
独立实时前端面板:宿主托管自包含 HTML + HTTP API,零官方 client 依赖。首版=插件管理(替代官方失效的插件 tab)
README
由 DeepSeek 最新模型翻译生成dsh-panel — 面板宿主(Panel Host)
一句话:把「每个插件各写一套前端」收敛成「每个插件提交一份声明」的前端宿主——一个 URL(http://127.0.0.1:3080/panel/)、一套外壳、一张注册表;贡献方只提供视图规格(ViewSpec)+ 动作表(Action ABI),宿主负责渲染、派发、审计、实测健康与降级。
为什么值得用:自研前端散落各处时,没有人能回答「谁在什么时候对哪个页面做了什么」——安全机制不可观测就等于不存在。本插件把「渲染 / 派发 / 审计 / 实测健康」四件事收进一个宿主:贡献方声明即 effect(插件卸载面板立刻消失,无幽灵),未知动作零副作用,破坏性动作要二次确认,触及「须请示三类」的动作宿主直接拒绝并转请示通道。而且它零官方 client 依赖——官方前端坏了,面板照常可用。
能力
宿主职责:托管外壳与静态资源 · 维护注册表(含实测健康)· 把贡献方的 view() 渲染成视图规格 · 按动作 ABI 派发并每次落一条审计 · 施加超时与降级。
展开完整文档(README 剩余 1 节)
dsh-panel — 面板宿主(Panel Host)
一句话:把「每个插件各写一套前端」收敛成「每个插件提交一份声明」的前端宿主——一个 URL(http://127.0.0.1:3080/panel/)、一套外壳、一张注册表;贡献方只提供视图规格(ViewSpec)+ 动作表(Action ABI),宿主负责渲染、派发、审计、实测健康与降级。
为什么值得用:自研前端散落各处时,没有人能回答「谁在什么时候对哪个页面做了什么」——安全机制不可观测就等于不存在。本插件把「渲染 / 派发 / 审计 / 实测健康」四件事收进一个宿主:贡献方声明即 effect(插件卸载面板立刻消失,无幽灵),未知动作零副作用,破坏性动作要二次确认,触及「须请示三类」的动作宿主直接拒绝并转请示通道。而且它零官方 client 依赖——官方前端坏了,面板照常可用。
能力
宿主职责:托管外壳与静态资源 · 维护注册表(含实测健康)· 把贡献方的 view() 渲染成视图规格 · 按动作 ABI 派发并每次落一条审计 · 施加超时与降级。
接入契约(消费方视角;完整签名见 docs/semantic.md §4):
// 必须用 ctx.inject 等待宿主(不得用 ctx.get('panel') 一次性探测——加载顺序会让它拿到 undefined 且永不重试)
ctx.inject(['panel'], (panelCtx) => {
panelCtx.panel.register({
id: 'my-panel', // 全局唯一 [a-z0-9-]+,重复注册 fail-loud title: '我的面板', order: 100, // 导航排序(小→前) icon: 'plug', // 宿主图标白名单键(非自由 SVG) description: '一句话用途', // 自检面板展示
view: async (params) => ViewSpec,
actions: { /* 动作表 / },
style: { accent: '#f472b6' }, // 可选:自带视觉(宿主只认 token,不认自由 CSS)
}) // 返回 disposer;注册即 effect })
HTTP 面(全部 JSON 响应统一信封 {ok, ...}):
| 方法 | 路径 | 语义 |
| GET | /panel/ | 外壳 HTML(独立资源文件;cache-control: no-store) |
| GET | /panel/assets/ | 宿主静态资源(prefix 路由,白名单目录,禁路径穿越) |
| GET | /api/panel/registry | 注册表投影:[{id,title,order,icon,description,health}](不含视图规格) |
| GET | /api/panel/view?id= | {ok, spec, generatedAt, durationMs, degraded?} |
| POST | /api/panel/action | 派发动作(校验 panelId/actionId,写审计) |
| GET | /api/panel/selfcheck | 宿主自检:贡献健康实测 + 宿主版本 + 计时统计 |
内置面板(宿主自带,随宿主注册):
| id | 标题 | order | 说明 |
| plugin-manager | 插件管理 | 10 | 自研插件清单/构建态与挂载态(启停经 patch + 哨兵生效) |
| taskboard | 任务板 | 20 | 板面与流转:计数、分布图、新建/认领/完成、终态归档 |
| growth-profile | 养成档案 | 30 | 自我模型 + 记忆规模 + 周目存档 + 技能/插件规模(只读) |
| agent-teams | 分身 | 40 | 成员状态、任务清单与 inbox 积压(只读) |
| audit | 面板审计 | 50 | 宿主自己的派发审计(只读,不提供改写通道) |
降级语义:贡献方 view() 抛错 → 该面板显示错误原文,外壳与其余面板不受影响;view() 超过 viewTimeoutMs → 标记超时;未知 panelId/actionId → 400/404 且零副作用(但仍写一条审计)。
快速开始
1) 装依赖:
"dsh-panel": "link:/self-plugins/dsh-panel"
2) 挂组合(零配置可用;下列项按需覆盖):
- id: panel
name: dsh-panel
config:
defaultProfile: web
3) 30 秒验证:
curl -s http://127.0.0.1:3080/api/panel/registry | head -c 300
期望:{"ok":true,"host":{"version":"0.4.0","startedAt":"…"},"panels":[…5 个面板…]}
curl -s http://127.0.0.1:3080/api/panel/selfcheck
期望:ok:true + 各贡献健康度实测 + 宿主版本
浏览器打开 http://127.0.0.1:3080/panel/ → 期望左侧导航 5 项、点任意一项能出内容(而非空壳或 404)。
配置
| 项 | 默认 | 说明 |
| enabled | true | 宿主开关 |
| dshHome | ''(→ $DSH_HOME → ~/.dsh) | DSH 主目录解析起点 |
| profilesDir | ''(→ /profiles) | profile 目录(插件管理面板用) |
| selfPluginsDir | ''(→ /self-plugins) | 自研插件目录(插件管理面板用) |
| defaultProfile | web | 默认 profile 名 |
| viewTimeoutMs | 2000 | 取视图超时(超时 → 该面板降级,外壳不受阻) |
| actionTimeoutMs | 10000 | 派发动作超时 |
落盘与自证(出问题时先看这里)
审计轨:每次派发写一行到 /panel/audit.jsonl(写盘吞错不反噬派发):
{"at":"2026-09-13T09:41:30.712Z","panelId":"taskboard","actionId":"claim","level":"write",
"paramsDigest":"83b51b5ad28488cd","outcome":"ok","durationMs":1,"message":"已认领 t-2a6731ae(claimed,负责人 alice)"}
| 字段 | 含义 |
| at / panelId / actionId | 何时、对哪个面板的哪个动作 |
| level | 动作分级(read/write/destructive)——决定是否要二次确认 |
| paramsDigest | 参数摘要(不落原文,避免把敏感值写进日志) |
| outcome | ok / denied / error(被拦下也有行——这才是审计的意义) |
| durationMs / message | 耗时与人类可读结果/拒绝理由 |
本机实测(2026-09-14):audit.jsonl 4 行,末行即上例。
一条命令答五问(本插件是生态里的正面样板——五问全可答):
tail -3 "$DSH_HOME/panel/audit.jsonl"; curl -s http://127.0.0.1:3080/api/panel/registry
① 线上跑的是哪个构建 → registry 的 host.version + host.startedAt(实测 0.4.0 / 2026-09-14T07:06:07Z) ② 谁发起 / 投给谁 → audit 的 panelId + actionId + at ③ 断在哪一段 → audit 的 outcome(ok/denied/error)+ message;view 断点看 view 响应的 degraded ④ 结果质量 → /api/panel/selfcheck 的实测健康 + 该面板是否 degraded ⑤ 耗时与预算 → audit 的 durationMs(动作)与 view 响应的 durationMs(视图,对照 viewTimeoutMs=2000)
生效判据与回退
生效判据(三选一,按可靠性排序):
1. 行为级:GET /api/panel/registry 返回 ok:true 且 panels 为你预期的数量(本机 5 个)+ host.version 与 package.json 一致;
2. 页面级:浏览器打开 /panel/ 能切到任意面板并看到内容(截图复核,别只看接口——单测全绿时缺陷仍可能只在视觉层暴露);
3. 生态级:plugin_boot_status(dsh-plugin-bootreport)的 liveNow 含本插件。
注意:重新构建 ≠ 生效——产物 mtime 新只证明「构建过」,进程启动时间晚于产物 mtime 才算「在跑它」。本插件构建含两步(tsc + copy-assets.mjs,客户端另有 bundle-client.mjs),只跑 tsc 会得到一个没有外壳资源的宿主。
回退(三档):
- 组合级:preset 给 panel 行加 disabled: true → 面板整体下线,官方 Web GUI 完全不受影响(本插件从不修改官方界面);
- 源码级:git -C self-plugins/dsh-panel revert → 重新构建(含 assets/client)→ 预检 → 哨兵重启;
- 数据级:audit.jsonl 可随时删除(纯审计,无业务状态);贡献方数据不归宿主,宿主从不持久化它们。
测试
npm test # = node --test "tests/*.test.mjs"
51 例离线测试(8 个文件):
| 文件 | 例数 | 覆盖 |
| registry.test.mjs | 12 | 注册表核心:非法 id / 重复 id fail-loud(不静默覆盖)、dispose 后消失(无幽灵)、排序与投影形状、健康度迁移(含恢复) |
| taskboard-write.test.mjs | 9 | 写入通道:板面解析失败 → 拒绝写入、写前写后字节相同(只读可宽容、写入必须苛刻)、并发写、终态归档 |
| taskboard.test.mjs | 6 | 板面视图:计数/分布形状、空板与坏行降级 |
| viewspec-validation.test.mjs | 6 | 视图规格校验:已知 kind 缺必备字段 / chart 取值非法 / form 缺 actionId / 超块数与超嵌套 → 降级;未知 kind 放行 |
| audit-panel.test.mjs | 5 | 审计页:坏行逐行跳过并计数、limit 边界(非法→默认、越界→夹到 500)、>512KB 只读尾部并如实标注 |
| client-bundle.test.mjs | 5 | 零官方 client 依赖:产物 grep + 外壳体积 + 无公网请求断言 |
| panel-style.test.mjs | 5 | 皮肤层:?theme= 优先级、非法 accent 注册 fail-loud、切主题不丢标签页选择 |
| panels-expressiveness.test.mjs | 3 | 表现力块族:块组合渲染、超块数上限降级 |
无网络依赖:视图/动作/审计全在离线夹具上断言(临时目录 + 桩贡献方)。
设计要点
- 注册即 effect,卸载即消失:面板身份是合成级契约——宿主不持久化贡献方数据,插件禁用后面板立刻从注册表消失,绝不出现「幽灵面板」。
- 重复 id 必须 fail-loud:第二个同 id 注册抛错而不是覆盖——撞车 = 配置错误,静默覆盖会让「谁在渲染」变成不可知的谜。
- 必须用 ctx.inject(['panel'], …) 等待宿主,不得 ctx.get('panel'):加载顺序会让一次性探测拿到 undefined 且永不重试,表现为「插件健康但面板 404」——这是实践踩出来的接入纪律。
- 只读可宽容,写入必须苛刻:板面解析失败时拒绝写入(写前写后字节相同),否则空板会覆盖真实数据;读取时坏行跳过并计数即可。
- 审批门优先于确认门:触及「须请示三类」(删数据/动凭据/动核心引擎)的动作,即使调用方带了 confirm:true 也拒绝派发(requires-approval)——宿主不得成为绕过主体性铁律的通道。
- 审计是安全机制的可观测面:被拦下的动作也写行(denied),并且参数只落摘要(paramsDigest)不落原文——记录了「做过什么」又不制造新的泄露面。
- 零官方 client 依赖:外壳是自包含资源(本机实测 lib/assets/shell.html 79,729 字节,/panel/ 一次返回 72,949 字符、cache-control: no-store),构建期才需要 Node 脚本——官方前端坏了面板照常可用,代价是自带一套资源与构建步骤。
相关文档
| 文档 | 内容 |
| docs/semantic.md | 权威契约(284 行):定位与负边界、术语、概念模型、注册契约 / 视图规格 / 动作 ABI / HTTP 面 / 失效降级 / 皮肤层(逐条 [MUST])、信任与安全边界(含能力诚实声明)、与官方 GUI 的关系、迁移路径、可证伪验收 15 条(已证 11 · 待线上 4)、未决问题 Q1–Q6 |
| alice-digital-life | 本插件所属生态的中心索引(全部自研插件) |
| 技能 ui-visual-verification | 界面视觉与交互验收(几何/对比度/跨刷新状态/真实副作用四类断言 + 截图复核清单)——单测全绿时三个缺陷全靠看图发现的教训 |
| 技能 dsh-panel-plugin | 面板插件开发方法论(webServer 托管 + 独立资源 + 同源 fetch + 命名规范),本插件的前身 |
| 技能 semantic-doc-first | 先写「是什么」再让实现逼近它、用实践回修文档的方法(本插件是该方法的第一号实践) |
License
MIT © jonah791
本插件属于我的数字生命爱丽丝(alice-digital-life)的 DSH 自研插件生态。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
jonah791/dsh-panel
集中托管插件前端,统一渲染派发并记录审计
相关插件 · UI / 主题
破甲增强版JeffKeeping/dsh-purge-plus
dsh-purge 的非官方分支fork:适配 DeepSeek Harness 0.2.1-rc.2、破甲内核…
★ 387已汉化DeepSeek 客户端
71.9
无代码业务系统平台nocobase/nocobase
NocoBase 是什么
★ 24,804已汉化DSH
71.8
1Panel 服务器面板1Panel-dev/1Panel
全球 250 万+ 自托管用户共同喜爱。
★ 37,350已汉化DSH
71.5
工作状态行动态ccch1mneyyy/working-activity
作者:chimney@ccch1mneyyy。社区项目,非 DeepSeek 官方项目。
★ 664已汉化DSH
71.2
多模型配置管家farion1231/cc-switch
跨平台桌面一体化助手,支持 Claude Code、Codex、OpenCode、DeepSeek Harness 等工具,唯一官网 ccswitch.io
★ 151,506已汉化DSH
71.1
AI 矢量设计工具ZSeven-W/openpencil
全球首个 AI 原生开源矢量设计工具。
★ 7,027已汉化DSH
71.1
这是你的仓库?认领条目