dbx-plugin-skill 0.1.2 → 0.1.4

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbx-plugin-skill",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "DBX 插件开发 skill:覆盖插件创建、开发、调试、打包、发布到 dbx-store 上架的全流程,安装到 DSH / Claude Code / agents 技能目录",
5
5
  "type": "module",
6
6
  "bin": {
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,6 +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。需要访问 Kafka `advertised.listeners` 或集群发现等多端点协议时,在 connection-provider 上声明 `proxy_route: true`,通过生命周期请求的 `runtime.proxy` SOCKS5 路由连接广播端点。Sidecar 进程按插件共享、跨标签页复用,后端会话应按 `connection.id` 管理。
107
108
 
108
109
  ### 步骤 3:本地调试
109
110
 
@@ -126,7 +127,7 @@ dbx-plugin package .
126
127
 
127
128
  ### 步骤 5:发布 Release(在自己的插件仓库)
128
129
 
129
- 生成的 `.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**。
130
131
 
131
132
  ### 步骤 6:进入官方商店
132
133
 
@@ -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 }
@@ -49,6 +50,10 @@
49
50
  插件自定义的连接类型标识(如 `ssh`、`example-files`)。**它不会给 DBX 内置数据库枚举添加成员**;保存后存放在 `plugin_connection_type`。
50
51
 
51
52
  ### `fields`
53
+
54
+ #### `connect_timeout_secs`(可选的内置字段键)
55
+
56
+ 如果传输或握手可能超过 DBX 默认的通用超时,可声明一个 `binding: "config"` 且 `key: "connect_timeout_secs"` 的 `number` 字段。DBX 会把用户值(或声明的 `default`)写入类型化连接配置,并让 `connection/test`、`connection/connect` 的请求 deadline 使用这个解析后的值;已保存的 `external_config` 优先于默认值。声明后,连接对话框里的通用超时选项不再覆盖该值。
52
57
  每个字段必须有 `key`(`identifier`)、`label`(非空)、`type`。
53
58
 
54
59
  - `type` 枚举:`text`、`password`、`number`、`boolean`、`select`、`radio`、`textarea`。
@@ -90,6 +95,21 @@
90
95
  ### `capabilities`
91
96
  枚举 `test`、`connect`、`disconnect`,unique。声明什么就要实现什么(见 §2)。
92
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
+
93
113
  ### `workbench` / `filesystem_provider`
94
114
  - `workbench`:指向本插件已声明的 workbench。打开该连接时进入自定义工作台。
95
115
  - `filesystem_provider`:指向本插件已声明的 filesystem-provider。打开该连接时连接生命周期 + 打开 DBX 通用文件管理器。
@@ -133,7 +153,7 @@
133
153
  ```
134
154
 
135
155
  - `connection` 只在**后端生命周期请求**中携带补齐的 Secret;前端只能拿到 `connectionId` 和非敏感导航上下文。
136
- - `runtime.host` / `runtime.port` 是**经过 DBX 隧道/代理转换后的最终端点**。协议插件必须连这里,**不要自己重建 DBX 隧道**。
156
+ - `runtime.host` / `runtime.port` 是**经过 DBX 隧道/代理转换后的最终逻辑端点**。协议插件必须连接这里;声明 `proxy_route` 时,通过 `runtime.proxy` 的 SOCKS5 路由连接广播端点,**不要自己重建 DBX 隧道**。
137
157
  - 后端用 `connection.id` 保存会话。连接/断开应当**幂等**;长任务要有超时、取消与分块确认。
138
158
  - `test` 通常返回 `{ "success": true, "message": "..." }`。
139
159
 
@@ -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-sdk-v1
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: 0.1.6
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`**,保证本地与 CI 用同一套 SDK 契约。
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`(仅首次,**但要先合并到 main**,见 §6 的坑);
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` 说首次 PR 携带 `publishers/<id>.json` 即可 | 签名 overlay 会删除 PR 新增的 publisher 记录 → **必须先在 main 上登记** |
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
  }