返回目录
其他 待识别

dsh-panel

jonah791/dsh-panel

独立实时前端面板:宿主托管自包含 HTML + HTTP API,零官方 client 依赖。首版=插件管理(替代官方失效的插件 tab)

Stars
0
Forks
0
Issues
0
更新
3 天前

PROJECT TOPICS

项目标签

PROJECT README

README

dsh-panel — 面板宿主(Panel Host)

version license TypeScript tests

一句话:把「每个插件各写一套前端」收敛成「每个插件提交一份声明」的前端宿主——一个 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 ''(→ <dshHome>/profiles profile 目录(插件管理面板用)
selfPluginsDir ''(→ <workspace>/self-plugins 自研插件目录(插件管理面板用)
defaultProfile web 默认 profile 名
viewTimeoutMs 2000 取视图超时(超时 → 该面板降级,外壳不受阻)
actionTimeoutMs 10000 派发动作超时

落盘与自证(出问题时先看这里)

审计轨:每次派发写一行到 <DSH_HOME>/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:truepanels 为你预期的数量(本机 5 个)+ host.versionpackage.json 一致;
  2. 页面级:浏览器打开 /panel/ 能切到任意面板并看到内容(截图复核,别只看接口——单测全绿时缺陷仍可能只在视觉层暴露);
  3. 生态级:plugin_boot_statusdsh-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 <commit> → 重新构建(含 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 取值非法 / formactionId / 超块数与超嵌套 → 降级;未知 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 自研插件生态。

CLASSIFICATION EVIDENCE

分类依据

项目类型待识别
功能分类其他
规则置信度

系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。