前言¶
在 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(安装无构建步骤)。可导出三种形态之一:
- 默认导出函数(迷你 React:
api.h+ hooks) setup(api)返回渲染函数(类 Vue)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)。
典型用法¶
- 在工作区创建
.dsh/pluginlets/,新增hello.pluginlet。 - 重启或刷新 DSH Web,在 Conversation View 看到对应标签。
- 首次运行时在标签内完成能力批准(按需缩小路径作用域)。
- 需要写文件时,在代码里调用
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