dsh-pluginlet:把工作区里的 .pluginlet 变成独立沙箱对话标签页

前言

在 DeepSeek Harness(DSH)里做仓库内的轻量 UI,常见做法是单独写前端、再挂进宿主,或把逻辑塞进一个大插件里。仓库里如果有多份小脚本、小面板,往往难以在对话视图里「一文件一标签」呈现,也难在改动后仍可控地授权读、写和网络。

下面介绍维护者 AlseFum 的 dsh-pluginlet(GitHub:AlseFum/dsh-pluginlet,社区分类 admin-security)。它把工作区中符合规则的每个 *.pluginlet 文件变成 Conversation View 里的独立标签页;运行前按内容哈希绑定能力授权,写入只能通过宿主确认完成。当前 README 标明 experimental, source-only,尚未发布到 npm,需从仓库 Git URL 安装。

这是什么

dsh-pluginlet 是 DSH 的 Web 侧插件:扫描工作区内指定目录下的 *.pluginlet 纯 JavaScript 文件,每个文件对应一个标签(例如 对话 / 轨迹 / hello)。插件随仓库携带的 pluginlet 会随检出一起可用,不依赖按项目再装 npm 包。

设置不在插件 UI 里改,而在宿主插件配置(Plugins → Pluginlet,或该 bundle 对应行的 config:)中完成。

核心功能

发现与标签

默认只扫描工作区根下的 .dsh/pluginlets/(根目录散落的 *.pluginlet 不会变成标签)。可通过 directories 增加搜索路径;extensions 默认 ['.pluginlet']。

示例布局:

repo/
  .dsh/pluginlets/
    app.pluginlet       ->  标签名 "app"
    schema.pluginlet    ->  标签名 "schema"
    hello.pluginlet     ->  标签名 "hello"

发现上限由 maxEditors(默认 64)与单文件 maxEditorBytes(默认 524288)约束。

pluginlet 编写约定

.pluginlet 为纯 JavaScript:无 JSX、无 import(安装无构建步骤)。可导出三种形态之一:

  1. 默认导出函数(迷你 React:api.h + hooks)
  2. setup(api) 返回渲染函数(类 Vue)
  3. mount(el, api) 命令式挂载

api 提供 h、Fragment、常见 hooks、fs.read / fs.list(包装读)、net.fetch(包装网络)、write.request(仅发起确认,不自行写盘)、ui.toast、meta.name / meta.path 等。安装 Host 半部后会注册技能 pluginlet-development,正文在 skills/pluginlet-development.md,供智能体写 pluginlet 前加载。

安全与授权

扫描器是策略门,真正边界是沙箱:pluginlet 在 sandbox="allow-scripts" 的 iframe 中运行,CSP 极严;fs / net 仅通过 postMessage 到宿主,再访问 /api/pluginlet/*,并记入审计。

  • 写入无宿主确认对话框则不可能;帧内只有 write.request。
  • eval、import/require、裸 fetch 等由扫描阻断,不可授予。
  • 授权按内容哈希与路径作用域绑定,批准数据存放在 $DSH_HOME/pluginlet/,不进仓库。
  • 批准发生在该 pluginlet 标签要运行时;对话框可按能力勾选路径子集。
  • devMode: true 时(工作区可见横幅)可接受哈希变更而免重新批准,并放宽可授予能力,被阻断的构造仍被阻断。

主要配置项(节选):

key 默认值 含义
devMode false 变更哈希可不重新批准(仍审计;读写网络仍受控)
extensions ['.pluginlet'] 视为 pluginlet 的后缀
directories ['.dsh/pluginlets'] 相对工作区根的搜索目录
allowRead / allowNetwork / allowWrite true 是否允许提供对应能力
net { perMinute: 20, perHour: 240, maxBytes: 1048576 } 每个 pluginlet 的网络预算

宿主 API

路由均为 POST,路径前缀 /api/pluginlet/,并要求请求头 x-dsh-plugin: pluginlet。包括 discover、scan、source、state / grant / revoke / log、fs/list、fs/read、net/fetch、write 等(网络仅限 http(s)、有超时与大小与速率限制)。

安装与启用

在 profile web 下添加插件(README 原文命令):

dsh plugin --profile web add github:AlseFum/dsh-pluginlet

也可使用完整 Git URL:https://github.com/AlseFum/dsh-pluginlet.git。克隆为完整包,无需 npm install 或构建。

配置示例(cordis.patch.yml 片段):

- id: pluginlet
  config:
    devMode: false
    allowNetwork: false

或在 Plugins 页面安装为 Pluginlet。修改 Host 半部后需重启 dsh web;客户端半部刷新页面生效。

package.json 中版本为 0.1.0,许可证 MIT,要求 Node >= 22.0.0。GitHub 星标数以目录站展示为准(抓取时为 0)。

典型用法

  1. 在工作区创建 .dsh/pluginlets/,新增 hello.pluginlet。
  2. 重启或刷新 DSH Web,在 Conversation View 看到对应标签。
  3. 首次运行时在标签内完成能力批准(按需缩小路径作用域)。
  4. 需要写文件时,在代码里调用 write.request(target, text, version),在宿主对话框确认。

最小计数器示例(README 摘录):

export default function Editor(api) {
  const [count, setCount] = api.useState(0)
  return api.h('div', { style: { padding: '12px' } },
    api.h('button', { onClick: () => setCount(count + 1) }, '+1'),
    ' ' + count)
}

适用场景与注意

适合:需要在同一仓库内维护多个小型、可审查的沙箱 UI(配置预览、Schema 编辑、运维小面板等),且希望授权与源码哈希、路径作用域强绑定。admin-security 分类与此一致:强调宿主侧策略、审计与确认写。

注意:

  • 插件以当前 DSH 进程权限运行;安装前请阅读源码与 MIT 许可证,并理解 devMode 与 allowNetwork 等开关的含义。
  • 网络代理对 DNS 重绑定等仍有残余风险,README 明确其为护栏而非完整出站过滤。
  • DSH 社区插件目录(如 SkillHub 上的条目)为独立生态站点,与 DeepSeek / 幻方无官方从属关系;非 npm 正式发布阶段,升级与变更以 GitHub 仓库为准。

结尾

dsh-pluginlet 把「一文件一标签」和哈希绑定的能力授权结合起来,让仓库自带的 .pluginlet 能在对话视图里安全试运行。进一步细节见仓库 README 与 docs/DESIGN.md。

  • 目录页:https://www.skillhub.cn/plugins/AlseFum/dsh-pluginlet
  • GitHub:https://github.com/AlseFum/dsh-pluginlet
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜