dbx-plugin-skill 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skill/SKILL.md +3 -3
- package/skill/references/cli.md +3 -1
- package/skill/references/contributions.md +29 -1
- package/skill/references/packaging.md +7 -3
- package/skill/references/publishing.md +4 -6
- package/skill/references/sidecar-protocol.md +1 -1
- package/skill/scripts/check-project.mjs +5 -0
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dbx-plugin
|
|
3
|
-
description: DBX 插件开发全流程。Use when 创建、开发、调试、打包、签名、发布或上架 DBX 插件;处理 manifest.json、dbx-plugin.toml、.dbxp 包、贡献点(connection-provider / workbench / filesystem-provider / context-menu / result-view)、Host API(window.dbxPlugin 桥接)、Rust/Go Sidecar 协议、dbx-plugin CLI(create / dev / package / keygen)、dbx-store 候选 PR 与 catalog 校验时使用。
|
|
3
|
+
description: DBX 插件开发全流程。Use when 创建、开发、调试、打包、签名、发布或上架 DBX 插件;处理 manifest.json、dbx-plugin.toml、.dbxp 包、贡献点(connection-provider / proxy_route / workbench / filesystem-provider / context-menu / result-view)、Host API(window.dbxPlugin 桥接)、Rust/Go Sidecar 协议、dbx-plugin CLI(create / dev / package / keygen)、dbx-store 候选 PR 与 catalog 校验时使用。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# DBX 插件开发
|
|
@@ -104,7 +104,7 @@ dbx-plugin create my-plugin \
|
|
|
104
104
|
- 所有 UI 必须构建为包内静态资源;**不要把 Vite dev server 或 CDN 地址写进发行包**。
|
|
105
105
|
- 需要原生能力(S3/SSH/系统凭据/长连接/高性能)才写 Sidecar。Sidecar 不是 OS 沙箱,以当前用户权限运行。
|
|
106
106
|
- 连接表单可用 `visible_when` / `required_when` 的 `all_of`、`any_of`、`not` 组合条件,以及 `picker` 提供本地文件选择;依赖这些能力时设置足够新的 `engines.dbx`。
|
|
107
|
-
- 若握手可能超过通用超时,连接表单可声明 `config` 字段 `connect_timeout_secs`;DBX 会用其解析值作为 `connection/test` 与 `connection/connect` 的 deadline
|
|
107
|
+
- 若握手可能超过通用超时,连接表单可声明 `config` 字段 `connect_timeout_secs`;DBX 会用其解析值作为 `connection/test` 与 `connection/connect` 的 deadline。需要访问 Kafka `advertised.listeners` 或集群发现等多端点协议时,在 connection-provider 上声明 `proxy_route: true`,通过生命周期请求的 `runtime.proxy` SOCKS5 路由连接广播端点。Sidecar 进程按插件共享、跨标签页复用,后端会话应按 `connection.id` 管理。
|
|
108
108
|
|
|
109
109
|
### 步骤 3:本地调试
|
|
110
110
|
|
|
@@ -127,7 +127,7 @@ dbx-plugin package .
|
|
|
127
127
|
|
|
128
128
|
### 步骤 5:发布 Release(在自己的插件仓库)
|
|
129
129
|
|
|
130
|
-
生成的 `.github/workflows/plugin-release.yml` 会在发布 GitHub Release 时产出各平台候选包、`.artifact.json` 和合并的 `release-candidates.json`。**不要把 `.dbxp` 提交进 Git**。
|
|
130
|
+
生成的 `.github/workflows/plugin-release.yml` 会在发布 GitHub Release 时产出各平台候选包、`.artifact.json` 和合并的 `release-candidates.json`;它固定到与 CLI 相同的 `plugin-cli-v<version>` reusable workflow tag,并传入相同的 `plugin-cli-version`。**不要把 `.dbxp` 提交进 Git**。
|
|
131
131
|
|
|
132
132
|
### 步骤 6:进入官方商店
|
|
133
133
|
|
package/skill/references/cli.md
CHANGED
|
@@ -91,7 +91,7 @@ dbx-plugin create my-plugin \
|
|
|
91
91
|
| `rust` | `frontend` 的基础文件换成 `common/*`,另加 `backend/Cargo.toml`、`backend/src/main.rs` |
|
|
92
92
|
| `go` | 同上,另加 `backend/go.mod`、`backend/main.go` |
|
|
93
93
|
|
|
94
|
-
生成的 `.gitignore` 已包含 `/dist/`、`/.dbx-dev/`、`.dbx-repository-signing-key.env`。
|
|
94
|
+
生成的 `.gitignore` 已包含 `/dist/`、`/.dbx-dev/`、`.dbx-repository-signing-key.env`。生成的 Release workflow 会固定到与 CLI 相同的 `plugin-cli-v<version>` tag,并把同一版本传给 `plugin-cli-version`;不要把 reusable workflow 改成跟随 `main`。
|
|
95
95
|
|
|
96
96
|
### create 的校验规则
|
|
97
97
|
|
|
@@ -162,6 +162,8 @@ dist/<plugin-id>-<version>-<target>.artifact.json
|
|
|
162
162
|
|
|
163
163
|
**打包行为要点**(详见 `packaging.md`):只打包 `[package].include` 声明的目录;重写包内 `manifest.json` 的 backend executable;拒绝符号链接、`.dbx-dev`、越界路径、过大文件与不安全输出位置。
|
|
164
164
|
|
|
165
|
+
生成的多平台 Release workflow 会按模板选择工具链和缓存:纯前端跳过 Rust/Go,Go 项目跳过 Rust,Rust 项目跳过 Go;npm/pnpm 缓存跟随锁文件,pnpm 使用 `package.json#packageManager`(仅旧锁文件项目回退到 10.27.0),没有锁文件时不恢复依赖缓存;Go 缓存使用工作目录下的 `go.sum`,包括 `backend/go.sum`。Svelte 项目应提交首次 `npm install` 生成的锁文件,工作流使用 `npm ci`。
|
|
166
|
+
|
|
165
167
|
## 5. `dbx-plugin keygen`(仅私有/自定义仓库运营方)
|
|
166
168
|
|
|
167
169
|
```bash
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
],
|
|
39
39
|
"workbench": "com.example.files.main",
|
|
40
40
|
"capabilities": ["test", "connect", "disconnect"],
|
|
41
|
+
"proxy_route": false,
|
|
41
42
|
"actions": [
|
|
42
43
|
{ "id": "refresh", "label": "Refresh metadata", "variant": "outline",
|
|
43
44
|
"when": "edit", "requires_valid_form": true, "timeout_ms": 30000 }
|
|
@@ -94,6 +95,21 @@
|
|
|
94
95
|
### `capabilities`
|
|
95
96
|
枚举 `test`、`connect`、`disconnect`,unique。声明什么就要实现什么(见 §2)。
|
|
96
97
|
|
|
98
|
+
### `proxy_route`
|
|
99
|
+
默认 `false`。Kafka `advertised.listeners`、集群发现等需要连接多个广播端点的协议应设为 `true`。配置传输层后,DBX 会在生命周期请求的 `runtime.proxy` 中提供 SOCKS5 路由,插件保持 `runtime.host` / `runtime.port` 作为逻辑引导端点,并通过该路由连接广播出的其它端点:
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"runtime": {
|
|
104
|
+
"host": "127.0.0.1",
|
|
105
|
+
"port": 49152,
|
|
106
|
+
"proxy": { "type": "socks5", "host": "127.0.0.1", "port": 49153, "username": "", "password": "" }
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
SSH 作为最后一层时,路由是该跳板的动态 SOCKS5 端点;配置 SOCKS5 层时直接使用该代理。代理凭据与连接 Secret 走同一加密通道,绝不要记录日志。未声明该字段时继续使用单一远端端点的静态转发;如果标准 `host` / `port` 为空,DBX 会直接拒绝连接。
|
|
112
|
+
|
|
97
113
|
### `workbench` / `filesystem_provider`
|
|
98
114
|
- `workbench`:指向本插件已声明的 workbench。打开该连接时进入自定义工作台。
|
|
99
115
|
- `filesystem_provider`:指向本插件已声明的 filesystem-provider。打开该连接时连接生命周期 + 打开 DBX 通用文件管理器。
|
|
@@ -137,7 +153,7 @@
|
|
|
137
153
|
```
|
|
138
154
|
|
|
139
155
|
- `connection` 只在**后端生命周期请求**中携带补齐的 Secret;前端只能拿到 `connectionId` 和非敏感导航上下文。
|
|
140
|
-
- `runtime.host` / `runtime.port` 是**经过 DBX
|
|
156
|
+
- `runtime.host` / `runtime.port` 是**经过 DBX 隧道/代理转换后的最终逻辑端点**。协议插件必须连接这里;声明 `proxy_route` 时,通过 `runtime.proxy` 的 SOCKS5 路由连接广播端点,**不要自己重建 DBX 隧道**。
|
|
141
157
|
- 后端用 `connection.id` 保存会话。连接/断开应当**幂等**;长任务要有超时、取消与分块确认。
|
|
142
158
|
- `test` 通常返回 `{ "success": true, "message": "..." }`。
|
|
143
159
|
|
|
@@ -189,6 +205,18 @@
|
|
|
189
205
|
| `filesystem/delete` | `uri`、`recursive` | `{ success, message?, entry? }` |
|
|
190
206
|
| `filesystem/rename` | `sourceUri`、`targetUri`、`overwrite` | `{ success, message?, entry? }` |
|
|
191
207
|
|
|
208
|
+
### 宿主托管下载(`filesystem/download/*`)
|
|
209
|
+
|
|
210
|
+
需要把远端对象保存到用户本地文件时,DBX 桌面宿主会管理保存对话框、临时文件、取消和进度,并调用插件后端的下载生命周期:
|
|
211
|
+
|
|
212
|
+
1. `filesystem/download/open`:接收完整的下载选择参数(其中必须包含 `downloadId`,以及插件所需的 `providerId`、`connectionId` 等字段),返回对象元数据,至少包含 `size`。
|
|
213
|
+
2. `filesystem/download/read`:重复读取分块,返回 `{ dataBase64, done }`。每个分块解码后不得超过 1 MiB;未完成时不能返回空分块。
|
|
214
|
+
3. `filesystem/download/close`:无论成功、取消还是失败都会调用,用于释放插件侧会话。
|
|
215
|
+
|
|
216
|
+
从 DBX `1511f11be1de3060e9ecdc51d86c90a1757a70a0` 的 `src-tauri/src/commands/plugin_download.rs` 变更起,`read` 与 `close` 的控制参数固定为 `{ downloadId, providerId, connectionId }`,不再重复携带 `open` 的完整选择参数。插件应按 `downloadId` 保存会话状态,并允许 `close` 幂等;不要假设每个分块请求都带有对象路径、筛选器或其它大字段。
|
|
217
|
+
|
|
218
|
+
这条宿主托管下载通道与 `stdio-framed` 大文件流不同:它通过 JSON/base64 分块写入用户选择的本地文件;需要双向流、PTY/SFTP 或更大分块时,仍使用 framed 二进制通道和插件自定义的确认、取消、进度协议。
|
|
219
|
+
|
|
192
220
|
### 目录项与分页规则
|
|
193
221
|
|
|
194
222
|
- 每项包含:`name`(**单个文件名**,不含 `/`、`\`,不能是 `.` 或 `..`)、完整 `uri`、`kind`(`file` | `directory` | `symlink` | `other`),可选 `size`、`modifiedAt`、`contentType`。
|
|
@@ -141,22 +141,26 @@ permissions:
|
|
|
141
141
|
contents: write
|
|
142
142
|
jobs:
|
|
143
143
|
release:
|
|
144
|
-
uses: t8y2/dbx/.github/workflows/plugin-release-reusable.yml@plugin-
|
|
144
|
+
uses: t8y2/dbx/.github/workflows/plugin-release-reusable.yml@plugin-cli-v<CLI_VERSION>
|
|
145
145
|
with:
|
|
146
146
|
release-tag: ${{ github.event.release.tag_name }}
|
|
147
147
|
package-command: dbx-plugin package .
|
|
148
148
|
package-path: dist/*.dbxp
|
|
149
149
|
metadata-path: dist/*.artifact.json
|
|
150
|
-
plugin-cli-version:
|
|
150
|
+
plugin-cli-version: <CLI_VERSION>
|
|
151
151
|
# 纯前端插件加这一行,只构建一个 universal 包:
|
|
152
152
|
build-matrix: '{"include":[{"runner":"ubuntu-24.04","target":"universal"}]}'
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
- **同时 pin 住 reusable workflow 的 ref 与 `plugin-cli-version
|
|
155
|
+
- **同时 pin 住 reusable workflow 的 ref 与 `plugin-cli-version`**,并让两者使用同一个已发布的 CLI 版本(例如 `plugin-cli-v0.1.9` + `0.1.9`),保证本地与 CI 用同一套 SDK 契约。不要跟随 `main`;升级已有插件时,先确认对应的 reusable workflow tag 已发布。
|
|
156
156
|
- 原生项目的默认矩阵覆盖 `darwin-arm64`、`darwin-x64`、`windows-x64`、`linux-x64`、`linux-arm64`。
|
|
157
157
|
- 工作流会:安装 pin 的 CLI → 各 target 构建 → 拒绝含 `signature.json` 或含 `signingKeyId` 的候选 → 校验 target/sha256/size/包名与统一 Manifest 身份 → 上传候选包与合并的 `release-candidates.json`。
|
|
158
158
|
- **官方作者不需要配置任何签名 Secret 或 Key ID。**
|
|
159
159
|
|
|
160
|
+
生成的工作流会按模板跳过不需要的工具链:纯前端项目跳过 Rust/Go,Go 项目跳过 Rust,Rust 项目跳过 Go。前端依赖缓存跟随项目锁文件;pnpm 优先使用 `package.json#packageManager` 中的版本,只有已有锁文件但未声明版本时才使用 10.27.0 回退值;没有锁文件就不恢复依赖缓存。Go 模块/构建缓存会检查配置工作目录下的 `go.sum`,包括 `backend/go.sum`。Svelte 项目首次安装后应提交锁文件,发布工作流使用 `npm ci` 构建前端后再打包。
|
|
161
|
+
|
|
162
|
+
源码构建的 CLI 可以生成尚未发布的工作流,但必须先发布匹配的 CLI 与 reusable workflow tag,再让插件仓库使用该工作流。已有插件固定在旧 tag 上时,不会自动获得这些改进;应在新 tag 发布后显式升级。
|
|
163
|
+
|
|
160
164
|
## 10. 打包后自检
|
|
161
165
|
|
|
162
166
|
```bash
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 发布与上架(dbx-store)参考
|
|
2
2
|
|
|
3
|
-
> 本文件的结论来自 `t8y2/dbx-store` 当前源码(`scripts/validate.mjs`、`scripts/sync-release-candidate.mjs`、`scripts/discover-plugin-releases.mjs`、`scripts/finalize-candidates.mjs`、`.github/workflows/*`)与 `t8y2/dbx/plugins/RELEASING.md`。**当文档与脚本冲突时,以脚本为准** —— 文末列出已确认的冲突点。
|
|
3
|
+
> 本文件的结论来自 `t8y2/dbx-store` 当前源码(`CONTRIBUTING.md`、`scripts/validate.mjs`、`scripts/sync-release-candidate.mjs`、`scripts/discover-plugin-releases.mjs`、`scripts/finalize-candidates.mjs`、`.github/workflows/*`)与 `t8y2/dbx/plugins/RELEASING.md`。**当文档与脚本冲突时,以脚本为准** —— 文末列出已确认的冲突点。
|
|
4
4
|
>
|
|
5
5
|
> 上游 `plugins/RELEASING.md` 仍描述「先开 Issue、再开 catalog PR」的两段式流程;**当前实际流程是「一个 PR」**,以 `dbx-store/CONTRIBUTING.md` 为准。
|
|
6
6
|
|
|
@@ -170,15 +170,12 @@ node <skill-root>/scripts/make-candidate.mjs . --release-notes "Initial release.
|
|
|
170
170
|
- **不含联系人/邮箱/URL 要求**,也不含任何密钥。
|
|
171
171
|
- `publisher` 字段引用的是记录的 **`id`**,不是 `name`。
|
|
172
172
|
|
|
173
|
-
> ⚠️ **实测坑(文档未提)**:签名 Workflow 会先把 base 分支的 `publishers/` 覆盖回 PR 分支,**PR 里新增的 `publishers/<新id>.json` 会被删除**,随后校验失败 `publisher '<id>' is not registered`。
|
|
174
|
-
> **实践做法**:新发布者记录必须先落到 `main`(单独提一个只加 publisher 的 PR 并合并,或请维护者登记),**再**在候选 PR 上运行 `/sign`。
|
|
175
|
-
|
|
176
173
|
## 7. 首次上架流程
|
|
177
174
|
|
|
178
175
|
1. 插件源码放在**公开可审阅**的仓库。
|
|
179
176
|
2. 每个支持的 target 构建未签名 `.dbxp`,发布到不可变 HTTPS 地址(Release / 对象存储 / CDN)。
|
|
180
177
|
3. Fork `t8y2/dbx-store`,向 `main` 提**一个** PR:
|
|
181
|
-
- `publishers/<publisher-id>.json
|
|
178
|
+
- `publishers/<publisher-id>.json`(仅首次);
|
|
182
179
|
- `candidates/<plugin-id>.json`。
|
|
183
180
|
4. 按 PR 模板填写:插件 ID/版本/发布者、源码仓库 + 精确 tag、capabilities、**每一项 Manifest 权限**以及数据/网络访问、原生 Sidecar 行为(纯前端写 None)、license、主页/支持地址。
|
|
184
181
|
5. CI 会**故意保持红色**:`open candidate(s) awaiting DBX Store signing` —— 这是为了阻止未签名内容被合并。
|
|
@@ -222,6 +219,7 @@ node <skill-root>/scripts/make-candidate.mjs . --release-notes "Initial release.
|
|
|
222
219
|
- `repository` 必须匹配 `^[^/]+/[A-Za-z0-9._-]+$`;`metadataPath` 不能含 `..`。
|
|
223
220
|
- 同步只在**最新**的(非 draft、非 prerelease)Release 中查找名为 `release-candidates.json` 的资产;找不到就静默跳过(`No published candidate release found for <repo>`)。只拉取最近 30 个 Release。
|
|
224
221
|
- 想让你的仓库加入自动同步,向 `dbx-store` 提一个登记 PR,或请维护者登记。**插件仓库不需要配置任何自动化 Secret。**
|
|
222
|
+
- Store 侧自动同步使用独立 GitHub App,权限只需 Metadata read、Contents read/write、Pull requests read/write;`DBX_STORE_AUTOMATION_APP_ID` 与 `DBX_STORE_AUTOMATION_APP_PRIVATE_KEY` 只配置在 `dbx-store` 的 Actions secrets 中,并且必须与签名密钥 Secret 分离。插件作者无需接触这些凭据。
|
|
225
223
|
|
|
226
224
|
## 11. 审核与签名
|
|
227
225
|
|
|
@@ -328,7 +326,7 @@ https://raw.githubusercontent.com/t8y2/dbx-store/main/catalog/index.json
|
|
|
328
326
|
|
|
329
327
|
| # | 文档说 | 脚本实际 |
|
|
330
328
|
| --- | --- | --- |
|
|
331
|
-
| 1 | `CONTRIBUTING.md`
|
|
329
|
+
| 1 | `CONTRIBUTING.md` 只描述候选内容 | 当前签名 Workflow 会先把 base 分支状态同步到 PR 分支,并保留 PR 新增的 publisher 记录,再校验并签名 |
|
|
332
330
|
| 2 | `CONTRIBUTING.md` 说候选要「把 `verified` 保持 `false`」 | 候选**根本不能含** `verified` 字段 |
|
|
333
331
|
| 3 | 上游 `RELEASING.md` 描述「先开 Issue,再开 catalog PR」 | 当前流程是**一个 PR**,无 Issue |
|
|
334
332
|
| 4 | `README.md` 列的手动签名输入 | 实际还必需 `output-name`(且必须等于 `<id>-<version>-<target>.dbxp`)与 `sdk-ref` |
|
|
@@ -119,7 +119,7 @@ kind: u8 | payload_length: u32 big-endian | payload
|
|
|
119
119
|
| `contextMenu/<contribution-id>` | 连接右键菜单,返回 `{ "message": "..." }` 弹 toast |
|
|
120
120
|
| `filesystem/*` | 声明 filesystem-provider 时实现 |
|
|
121
121
|
|
|
122
|
-
`connection` 只在**后端生命周期请求**中携带补齐的 Secret;`runtime.host` / `runtime.port` 是经过 DBX
|
|
122
|
+
`connection` 只在**后端生命周期请求**中携带补齐的 Secret;`runtime.host` / `runtime.port` 是经过 DBX 隧道/代理后的**最终逻辑端点**,直接连它。多端点协议若在 connection-provider 上声明 `proxy_route: true`,还会收到 `runtime.proxy` SOCKS5 路由,插件应通过它连接广播端点。
|
|
123
123
|
|
|
124
124
|
## 7. 事件
|
|
125
125
|
|
|
@@ -491,11 +491,16 @@ function checkConnectionProvider(contribution, at, declared, usage) {
|
|
|
491
491
|
"workbench",
|
|
492
492
|
"filesystem_provider",
|
|
493
493
|
"capabilities",
|
|
494
|
+
"proxy_route",
|
|
494
495
|
"actions",
|
|
495
496
|
];
|
|
496
497
|
const extra = Object.keys(contribution).filter((k) => !allowed.includes(k));
|
|
497
498
|
if (extra.length) error(`${at} 含未知字段: ${extra.join(", ")}`);
|
|
498
499
|
|
|
500
|
+
if (contribution.proxy_route !== undefined && typeof contribution.proxy_route !== "boolean") {
|
|
501
|
+
error(`${at}.proxy_route 必须是布尔值`);
|
|
502
|
+
}
|
|
503
|
+
|
|
499
504
|
if (typeof contribution.database_type !== "string" || !IDENTIFIER.test(contribution.database_type)) {
|
|
500
505
|
error(`${at}.database_type 是必需字段且必须是小写标识符(如 ssh、example-files)`);
|
|
501
506
|
}
|