@jsbot-tellus/core 2.0.3 → 2.2.0
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/README.md +23 -27
- package/dist/app.js +14 -40
- package/dist/app.js.map +1 -1
- package/dist/core/config/schema.d.ts +0 -2
- package/dist/core/config/schema.d.ts.map +1 -1
- package/dist/core/config/schema.js +0 -1
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/dispatch/command.d.ts +24 -2
- package/dist/core/dispatch/command.d.ts.map +1 -1
- package/dist/core/dispatch/command.js +297 -60
- package/dist/core/dispatch/command.js.map +1 -1
- package/dist/core/dispatch/router.d.ts +17 -3
- package/dist/core/dispatch/router.d.ts.map +1 -1
- package/dist/core/dispatch/router.js +38 -2
- package/dist/core/dispatch/router.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/kernel.d.ts.map +1 -1
- package/dist/core/kernel.js +5 -1
- package/dist/core/kernel.js.map +1 -1
- package/dist/core/plugin/command-params.d.ts +37 -0
- package/dist/core/plugin/command-params.d.ts.map +1 -0
- package/dist/core/plugin/command-params.js +427 -0
- package/dist/core/plugin/command-params.js.map +1 -0
- package/dist/core/plugin/context.d.ts.map +1 -1
- package/dist/core/plugin/context.js +27 -0
- package/dist/core/plugin/context.js.map +1 -1
- package/dist/core/plugin/install-dir.d.ts +6 -9
- package/dist/core/plugin/install-dir.d.ts.map +1 -1
- package/dist/core/plugin/install-dir.js +99 -79
- package/dist/core/plugin/install-dir.js.map +1 -1
- package/dist/core/plugin/install-validate.d.ts +2 -1
- package/dist/core/plugin/install-validate.d.ts.map +1 -1
- package/dist/core/plugin/install-validate.js +25 -17
- package/dist/core/plugin/install-validate.js.map +1 -1
- package/dist/core/plugin/installer.d.ts +3 -3
- package/dist/core/plugin/installer.d.ts.map +1 -1
- package/dist/core/plugin/installer.js +143 -140
- package/dist/core/plugin/installer.js.map +1 -1
- package/dist/core/plugin/loader.d.ts +13 -1
- package/dist/core/plugin/loader.d.ts.map +1 -1
- package/dist/core/plugin/loader.js +106 -2
- package/dist/core/plugin/loader.js.map +1 -1
- package/dist/core/plugin/types.d.ts +14 -5
- package/dist/core/plugin/types.d.ts.map +1 -1
- package/dist/core/plugin/types.js.map +1 -1
- package/dist/plugins/admin/index.d.ts.map +1 -1
- package/dist/plugins/admin/index.js +119 -86
- package/dist/plugins/admin/index.js.map +1 -1
- package/dist/plugins/core/index.d.ts.map +1 -1
- package/dist/plugins/core/index.js +5 -2
- package/dist/plugins/core/index.js.map +1 -1
- package/docs/architecture.md +22 -24
- package/docs/configuration.md +19 -23
- package/docs/feature-parity.md +4 -4
- package/docs/migration.md +13 -13
- package/docs/plugin-api.md +164 -27
- package/docs/plugin-development.md +400 -0
- package/docs/release.md +2 -2
- package/examples/plugins/hello/README.md +10 -5
- package/examples/plugins/hello/index.js +3 -6
- package/package.json +4 -1
- package/src/app.ts +18 -55
- package/src/core/config/schema.ts +0 -1
- package/src/core/dispatch/command.ts +478 -70
- package/src/core/dispatch/router.ts +77 -3
- package/src/core/index.ts +3 -0
- package/src/core/kernel.ts +8 -1
- package/src/core/plugin/command-params.ts +667 -0
- package/src/core/plugin/context.ts +51 -2
- package/src/core/plugin/install-dir.ts +117 -111
- package/src/core/plugin/install-validate.ts +36 -34
- package/src/core/plugin/installer.ts +228 -184
- package/src/core/plugin/loader.ts +180 -3
- package/src/core/plugin/types.ts +31 -5
- package/src/plugins/admin/index.ts +302 -233
- package/src/plugins/core/index.ts +6 -2
- package/dist/core/plugin/installed.d.ts +0 -9
- package/dist/core/plugin/installed.d.ts.map +0 -1
- package/dist/core/plugin/installed.js +0 -113
- package/dist/core/plugin/installed.js.map +0 -1
- package/src/core/plugin/installed.ts +0 -165
package/docs/configuration.md
CHANGED
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## 路径和优先级
|
|
4
4
|
|
|
5
|
-
| 项目 | CLI
|
|
6
|
-
| -------- |
|
|
7
|
-
| 配置文件 | `--config`
|
|
8
|
-
| 数据目录 | `--data-dir`
|
|
9
|
-
| 日志级别 | `--log-level`
|
|
10
|
-
| 插件目录 | `--plugin-dir` | `BOT_PLUGIN_DIR` | 无 |
|
|
5
|
+
| 项目 | CLI | 环境变量 | 默认值 |
|
|
6
|
+
| -------- | ------------- | --------------- | ------------------- |
|
|
7
|
+
| 配置文件 | `--config` | `BOT_CONFIG` | `./bot.config.json` |
|
|
8
|
+
| 数据目录 | `--data-dir` | `BOT_DATA_DIR` | `./data` |
|
|
9
|
+
| 日志级别 | `--log-level` | `BOT_LOG_LEVEL` | `info` |
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
本地插件目录固定为 `./plugins`,不提供 CLI 或环境变量覆盖;每个插件从 `./plugins/<id>/dist` 加载,缺失时会在启动阶段尝试自动构建,相对路径按 `process.cwd()` 解析。
|
|
13
12
|
|
|
14
13
|
## 完整示例
|
|
15
14
|
|
|
@@ -68,7 +67,6 @@ npm 包会在宿主进程中执行,拥有与内核相同的文件系统、环
|
|
|
68
67
|
{
|
|
69
68
|
"installer": {
|
|
70
69
|
"enabled": true,
|
|
71
|
-
"dir": "data/plugins",
|
|
72
70
|
"registry": "https://registry.npmjs.org/",
|
|
73
71
|
"allowedPackages": ["@scope/*", "another-plugin"],
|
|
74
72
|
"allowScripts": false,
|
|
@@ -80,19 +78,20 @@ npm 包会在宿主进程中执行,拥有与内核相同的文件系统、环
|
|
|
80
78
|
| 字段 | 默认值 | 说明 |
|
|
81
79
|
| ----------------- | ----------------------------- | ------------------------------------------------------------------ |
|
|
82
80
|
| `enabled` | `false` | 为 `false` 时禁用安装、卸载和更新;列表仍可用(仍要求 SuperAdmin) |
|
|
83
|
-
| `dir` | `<data-dir>/plugins` | 安装目录,相对路径按 `process.cwd()` 解析 |
|
|
84
81
|
| `registry` | `https://registry.npmjs.org/` | npm registry,可换成镜像(如 npmmirror) |
|
|
85
82
|
| `allowedPackages` | `[]` | 允许安装的包;空表示不限制,支持精确名和 `@scope/*` |
|
|
86
83
|
| `allowScripts` | `false` | 为 `false` 时 npm 操作带 `--ignore-scripts` |
|
|
87
84
|
| `timeoutMs` | `120000` | 单次 npm/校验操作的超时,最大 600000 |
|
|
88
85
|
|
|
89
|
-
|
|
86
|
+
插件根目录固定为 `plugins/`,不能通过配置修改;旧配置中的 `installer.dir` 已被移除,继续保留会导致配置校验失败。安装器把包直接放到 `plugins/<插件id>/`,和本地插件使用同一个加载器;首次安装时,一个包导出多个插件会使用包名作为目录(例如 `@scope/bundle` 对应 `plugins/@scope__bundle/`)。插件自身在 `plugins/<目录>/dist`,运行时依赖在 `plugins/<目录>/node_modules`,不会放进共享的 `node_modules`。
|
|
90
87
|
|
|
91
|
-
|
|
88
|
+
`plugins/.jsbot-installed.json` 保存安装状态和包名到目录的映射,由内核维护,不要手动修改。安装、更新会先在临时目录完成下载和校验,再原子替换目标目录;失败时保留原目录。状态文件损坏会明确报错,不会静默清空。如果目标目录已存在但没有安装记录,安装会被拒绝,避免覆盖手动放在 `plugins/` 的本地插件。
|
|
89
|
+
|
|
90
|
+
安装器会在每个已安装插件目录创建 `node_modules/@jsbot-tellus/core` 链接,指向当前内核包。`@jsbot-tellus/core` 的入口是 `dist/core/index.js`,所以在线安装和加载已安装插件都需要先执行 `npm run build`;直接从 TypeScript 源码运行(`tsx`)时不要依赖安装器。
|
|
92
91
|
|
|
93
92
|
安装只接受 npm registry 包。以下来源会被拒绝:git/github 地址、`file:`、`http(s):`、`workspace:`、`link:`、本地路径和 semver 范围(`^`、`~`、`1.x`)。版本部分只接受精确版本或 dist-tag。
|
|
94
93
|
|
|
95
|
-
|
|
94
|
+
安装、更新、卸载成功后会自动重建运行时并重新加载插件,不需要手动重启,进程本身不会退出。卸载时如果配置里仍有对应插件 ID,会给出警告并跳过自动重启;如果其它已安装包依赖被卸载的插件 ID,默认拒绝卸载,需要确认后使用 `/plugin remove <目标> --force`。安装和更新会检查完整依赖图,拒绝自依赖、循环依赖和缺失依赖。启动时把内置插件和 `plugins/` 中的全部目录一起加载;出现重复插件 ID 时保留先加载的插件并记录警告。
|
|
96
95
|
|
|
97
96
|
## 插件公共信封
|
|
98
97
|
|
|
@@ -141,19 +140,18 @@ npm 包会在宿主进程中执行,拥有与内核相同的文件系统、环
|
|
|
141
140
|
```
|
|
142
141
|
|
|
143
142
|
- `/utter <文本>`:Admin 权限,发送自动转义的纯文本(CQ 码不会被解析)。
|
|
144
|
-
- `/utter
|
|
143
|
+
- `/utter raw <CQ 消息>`:SuperAdmin 权限,发送原始 CQ 字符串。
|
|
145
144
|
|
|
146
|
-
##
|
|
145
|
+
## 插件目录配置
|
|
147
146
|
|
|
148
|
-
`plugins` 中出现的插件 ID
|
|
147
|
+
`plugins` 中出现的插件 ID 必须对应已加载的插件,否则启动失败。本地插件和在线安装的插件都固定从 `plugins/<目录>/dist` 自动加载:
|
|
149
148
|
|
|
150
149
|
```bash
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
--plugin-dir plugins/llm/dist
|
|
150
|
+
npm run build
|
|
151
|
+
node dist/app.js
|
|
154
152
|
```
|
|
155
153
|
|
|
156
|
-
|
|
154
|
+
没有 `dist` 的本地插件如果带有 `build` 脚本且依赖已安装,启动时会先自动执行 `npm run build` 再加载;没有 `build` 脚本、缺少 `node_modules` 或构建失败时会记录警告并跳过。通过 `/plugin install` 安装的包会直接出现在 `plugins/<插件id>/`,与手动放在 `plugins/` 的本地插件没有区别;安装器管理的包应自带 `dist`,加载器不会为它们自动构建。安装状态、registry 和允许列表见[插件安装器](#插件安装器)。
|
|
157
155
|
|
|
158
156
|
插件自己的配置字段由 `manifest.configSchema` 校验。例如一个 `demo` 插件:
|
|
159
157
|
|
|
@@ -178,12 +176,10 @@ npm install --prefix plugins/poke
|
|
|
178
176
|
npm install --prefix plugins/llm
|
|
179
177
|
npm run build:local
|
|
180
178
|
|
|
181
|
-
npm run dev
|
|
182
|
-
--plugin-dir plugins/poke/dist \
|
|
183
|
-
--plugin-dir plugins/llm/dist
|
|
179
|
+
npm run dev
|
|
184
180
|
```
|
|
185
181
|
|
|
186
|
-
|
|
182
|
+
本地插件从 `plugins/<id>/dist` 自动加载;缺少 `dist` 时会先尝试构建。应用会跳过与内置插件同 ID 的本地插件。
|
|
187
183
|
|
|
188
184
|
## 错误处理
|
|
189
185
|
|
package/docs/feature-parity.md
CHANGED
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
| 群开关 | `PluginGate` | `enabled/private/groups` |
|
|
12
12
|
| 消息发送 | `core/messaging/sender.ts` | reply、长消息 forward |
|
|
13
13
|
| 插件 KV | `core/plugin/kv.ts` | 按插件 ID 隔离的 SQLite KV |
|
|
14
|
-
| 管理发送 | `src/plugins/admin` | `/utter`、`/utter
|
|
14
|
+
| 管理发送 | `src/plugins/admin` | `/utter`、`/utter raw` |
|
|
15
15
|
| 角色查询/帮助 | `src/plugins/core` | `/role`、`/help`、`/status` |
|
|
16
16
|
| 内置插件 | `src/plugins/*` | 普通源码,随内核编译 |
|
|
17
17
|
| 在线安装 | `core/plugin/installer.ts` | `/plugin install/list/remove/update`,重启生效 |
|
|
18
18
|
|
|
19
19
|
## 本地插件
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
以下插件保留在本地,但不进入仓库,从 `plugins/<id>/dist` 自动加载(缺少 `dist` 时会先尝试自动构建):
|
|
22
22
|
|
|
23
23
|
| 能力 | 位置 | 说明 |
|
|
24
24
|
| ---- | -------------- | -------------------------------------------- |
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
## 验收场景
|
|
43
43
|
|
|
44
44
|
- 只注册一个 SDK middleware。
|
|
45
|
+
- 命令支持多级路径,按最长路径匹配;组根未提供 handler 时自动生成用法提示。
|
|
45
46
|
- 命令命中后不会进入普通消息 handler。
|
|
46
47
|
- 禁用命令不会穿透到普通消息 handler。
|
|
47
48
|
- 权限不足不执行 handler,并返回通用提示。
|
|
@@ -49,8 +50,7 @@
|
|
|
49
50
|
- 插件 setup/start 失败可以回滚。
|
|
50
51
|
- 长消息转 forward,短消息默认引用回复。
|
|
51
52
|
- 配置错误包含路径,未知插件 ID 启动失败。
|
|
52
|
-
-
|
|
53
|
-
- 本地插件可以通过 `--plugin-dir` 加载。
|
|
53
|
+
- 本地插件可以从 `plugins/<id>/dist` 自动加载并执行;缺少 `dist` 且带有 `build` 脚本时会先自动构建。
|
|
54
54
|
- 已安装的 npm 插件包可以在自动重启后加载,安装失败会回滚。
|
|
55
55
|
- 非 SuperAdmin 不能使用 `/plugin` 的任何子命令,包括 `help` 和 `list`。
|
|
56
56
|
- `npm run build` 后 `node dist/app.js` 可用。
|
package/docs/migration.md
CHANGED
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
- 安装本地依赖:`npm install --prefix plugins/poke`、`npm install --prefix plugins/llm`
|
|
10
10
|
- 构建本地插件:`npm run build:local`
|
|
11
|
-
-
|
|
11
|
+
- 启动时加载:应用会自动扫描 `plugins/<id>/dist`,不需要路径参数
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
应用会跳过与内置插件同 ID 的本地插件。没有加载的插件不能出现在 `plugins` 配置中,否则会因未知插件 ID 启动失败。
|
|
14
|
+
|
|
15
|
+
管理命令方面,`/utter.raw` 已迁移为 `/utter raw` 指令组子命令。
|
|
14
16
|
|
|
15
17
|
发布到 npm registry 的插件也可以由 SuperAdmin 在聊天中安装:
|
|
16
18
|
|
|
@@ -21,7 +23,7 @@
|
|
|
21
23
|
/plugin remove @scope/plugin
|
|
22
24
|
```
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
包会直接安装到 `plugins/<插件id>/`,和本地插件使用同一个目录、同一个加载器;安装、更新、卸载成功后会自动重启运行时。它不会修改 `plugins` 配置,因此卸载后需要手动删除对应的 `plugins.<id>`;存在残留配置时会跳过自动重启并提示手动处理。旧版本的 `<data-dir>/plugins` 安装目录不再读取,升级后需要用 `/plugin install` 重新安装在线插件;旧配置中的 `installer.dir` 也已移除,继续保留会导致配置校验失败,需要删除该字段。详见[插件 API](plugin-api.md#通过-npm-发布与安装)和[配置](configuration.md#插件安装器)。
|
|
25
27
|
|
|
26
28
|
## 迁移步骤
|
|
27
29
|
|
|
@@ -63,21 +65,19 @@
|
|
|
63
65
|
npm install --prefix plugins/poke
|
|
64
66
|
npm install --prefix plugins/llm
|
|
65
67
|
npm run build:local
|
|
66
|
-
node dist/app.js
|
|
67
|
-
--plugin-dir plugins/poke/dist \
|
|
68
|
-
--plugin-dir plugins/llm/dist
|
|
68
|
+
node dist/app.js
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
6. 验证 `core`、`admin` 和已加载的本地插件。确认后再切换生产进程和反向代理配置。
|
|
72
72
|
|
|
73
73
|
## 目录对照
|
|
74
74
|
|
|
75
|
-
| 项目 | 迁移前 | 迁移后
|
|
76
|
-
| --------------- | -------------------------------------------- |
|
|
77
|
-
| 配置文件 | `bot.config.json` → `bot.config.legacy.json` | 新建 `bot.config.json`
|
|
78
|
-
| 数据目录 | `data/` → `data.legacy/` | 新建 `data/`
|
|
79
|
-
| 旧插件目录 | 保留原样 | 内置 `core`/`admin` +
|
|
80
|
-
| 旧 KV / Session | 保留在 `data.legacy/bot.db` | `data/bot.db`
|
|
75
|
+
| 项目 | 迁移前 | 迁移后 |
|
|
76
|
+
| --------------- | -------------------------------------------- | -------------------------------- |
|
|
77
|
+
| 配置文件 | `bot.config.json` → `bot.config.legacy.json` | 新建 `bot.config.json` |
|
|
78
|
+
| 数据目录 | `data/` → `data.legacy/` | 新建 `data/` |
|
|
79
|
+
| 旧插件目录 | 保留原样 | 内置 `core`/`admin` + `plugins/` |
|
|
80
|
+
| 旧 KV / Session | 保留在 `data.legacy/bot.db` | `data/bot.db` |
|
|
81
81
|
|
|
82
82
|
新版不会读取 `bot.config.legacy.json` 或 `data.legacy/`。备份文件可以保留,方便回退。
|
|
83
83
|
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
- 本地 `llm` 插件按 session 存储上下文,不再整份 KV 重写。
|
|
90
90
|
- 旧 `auth`、`echo`、`like-me` 不重建;权限由 `core` + `roles` 负责,发送文本由 `admin` 负责。
|
|
91
91
|
- 不支持热加载、插件市场界面和旧装饰器;npm 插件安装成功后会重建运行时。
|
|
92
|
-
- 仓库只跟踪 `core`、`admin
|
|
92
|
+
- 仓库只跟踪 `core`、`admin`;其它插件从 `plugins/` 加载,在线安装的插件也在这里。
|
|
93
93
|
|
|
94
94
|
## 回滚
|
|
95
95
|
|
package/docs/plugin-api.md
CHANGED
|
@@ -176,6 +176,7 @@ const result = await ctx.api.call('get_group_list')
|
|
|
176
176
|
const role = ctx.core.roles.roleOf(userId)
|
|
177
177
|
const allowed = ctx.core.roles.can(role, 'Admin')
|
|
178
178
|
const commands = ctx.core.commands.list()
|
|
179
|
+
const visibleCommands = ctx.core.commands.list(event)
|
|
179
180
|
const plugins = ctx.core.plugins.list()
|
|
180
181
|
const uptime = ctx.core.uptime()
|
|
181
182
|
|
|
@@ -183,14 +184,16 @@ const installed = await ctx.core.installer.list()
|
|
|
183
184
|
ctx.core.restart()
|
|
184
185
|
```
|
|
185
186
|
|
|
186
|
-
核心服务由内核注入,适合帮助、状态类插件。`ctx.core.installer` 额外提供 `install` / `remove` / `update` / `list`;它不会检查调用者角色,权限判断由调用方负责(`admin` 的 `/plugin` 命令要求 SuperAdmin)。安装器默认关闭,必须在配置中显式启用。`ctx.core.restart()` 请求应用重建运行时并重新加载插件;第三方插件不应把这些方法暴露给普通用户。
|
|
187
|
+
核心服务由内核注入,适合帮助、状态类插件。`ctx.core.commands.list(event)` 会按当前会话的 `enabled`、`groups`、`private` gating 过滤命令;不传 `event` 时返回全部命令。`ctx.core.installer` 额外提供 `install` / `remove` / `update` / `list`;它不会检查调用者角色,权限判断由调用方负责(`admin` 的 `/plugin` 命令要求 SuperAdmin)。安装器默认关闭,必须在配置中显式启用。`ctx.core.restart()` 请求应用重建运行时并重新加载插件;第三方插件不应把这些方法暴露给普通用户。
|
|
187
188
|
|
|
188
189
|
安装的插件与内置插件运行在同一个宿主进程中,可访问文件系统、网络和 `process.env`,属于完全可信代码,不是安全沙箱。
|
|
189
190
|
|
|
190
|
-
自动重启会在同一个 Node.js 进程内重建 Kernel,不会清空 Node 的 ESM 模块缓存。安装包的入口文件会附加查询参数来绕过缓存,但入口相对导入的辅助模块仍可能复用旧代码;通过
|
|
191
|
+
自动重启会在同一个 Node.js 进程内重建 Kernel,不会清空 Node 的 ESM 模块缓存。安装包的入口文件会附加查询参数来绕过缓存,但入口相对导入的辅助模块仍可能复用旧代码;通过 `plugins/` 加载的本地插件也不会被缓存刷新。更新多文件插件包后,请完整退出并重新启动进程。
|
|
191
192
|
|
|
192
193
|
## 命令
|
|
193
194
|
|
|
195
|
+
### 普通命令
|
|
196
|
+
|
|
194
197
|
```ts
|
|
195
198
|
ctx.commands.register(
|
|
196
199
|
{
|
|
@@ -206,21 +209,151 @@ ctx.commands.register(
|
|
|
206
209
|
)
|
|
207
210
|
```
|
|
208
211
|
|
|
209
|
-
| 字段 | 默认值 | 说明
|
|
210
|
-
| ------------- | -------- |
|
|
211
|
-
| `name` | 必填 | 主命令名,匹配时大小写不敏感
|
|
212
|
-
| `aliases` | `[]` | 别名
|
|
213
|
-
| `prefixes` | `['/']` | 前缀;空字符串表示无前缀
|
|
214
|
-
| `permission` | `'User'` | `User`、`Admin`、`SuperAdmin`
|
|
215
|
-
| `description` | 无 | `/help` 中展示
|
|
212
|
+
| 字段 | 默认值 | 说明 |
|
|
213
|
+
| ------------- | -------- | -------------------------------------------- |
|
|
214
|
+
| `name` | 必填 | 主命令名,匹配时大小写不敏感 |
|
|
215
|
+
| `aliases` | `[]` | 别名 |
|
|
216
|
+
| `prefixes` | `['/']` | 前缀;空字符串表示无前缀 |
|
|
217
|
+
| `permission` | `'User'` | `User`、`Admin`、`SuperAdmin` |
|
|
218
|
+
| `description` | 无 | `/help` 中展示 |
|
|
219
|
+
| `params` | 无 | Koishi 风格参数声明;省略时 handler 行为不变 |
|
|
220
|
+
|
|
221
|
+
`name` 和 `aliases` 的每一项只能是一个路径段;多级命令请使用 `commands.group()`。
|
|
222
|
+
|
|
223
|
+
### 参数
|
|
224
|
+
|
|
225
|
+
`params` 用字符串声明位置参数,解析结果从 handler 的第四个参数开始按位置传入:
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
ctx.commands.register(
|
|
229
|
+
{
|
|
230
|
+
name: 'ask',
|
|
231
|
+
description: '向模型提问',
|
|
232
|
+
params: '<question:string> [count:integer=1]',
|
|
233
|
+
},
|
|
234
|
+
async (_event, context, _match, question, count) => {
|
|
235
|
+
// question: string, count: number
|
|
236
|
+
await context.send(`问题:${question}(${count} 次)`)
|
|
237
|
+
}
|
|
238
|
+
)
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
声明语法:
|
|
242
|
+
|
|
243
|
+
| 写法 | 说明 |
|
|
244
|
+
| -------------------- | ---------------------------------------- |
|
|
245
|
+
| `<arg>` | 必填字符串参数 |
|
|
246
|
+
| `[arg]` | 可选字符串参数 |
|
|
247
|
+
| `<arg:type>` | 指定类型的必填参数 |
|
|
248
|
+
| `[arg:type=default]` | 可选参数及默认值 |
|
|
249
|
+
| `<arg:text>` | 文本参数,消费全部剩余输入,必须放在最后 |
|
|
250
|
+
| `[...rest]` | 变长参数,每个剩余 token 作为一个字符串 |
|
|
216
251
|
|
|
217
|
-
|
|
252
|
+
内置类型:
|
|
253
|
+
|
|
254
|
+
- `string`:默认类型,单个 token。
|
|
255
|
+
- `text`:消费全部剩余输入,保留空格;usage 显示为 `<arg...>`。
|
|
256
|
+
- `number`:有限数字,包括小数。
|
|
257
|
+
- `integer`:整数。
|
|
258
|
+
- `boolean`:`true/false`、`1/0`、`yes/no`、`y/n`、`on/off`,大小写不敏感。
|
|
259
|
+
- `[...rest]`:把剩余 token 依次收集为字符串;只能放在最后,且没有必填形式。
|
|
260
|
+
|
|
261
|
+
固定参数可以用双引号或单引号包裹,例如 `/ask "hello world" 2` 会把 `hello world` 作为一个 token;引号内的反斜杠用于转义。
|
|
262
|
+
|
|
263
|
+
解析规则:
|
|
264
|
+
|
|
265
|
+
- `match.args` 和 `match.rest` 保持原始内容,不会被参数解析结果替换。
|
|
266
|
+
- 声明槽位填完后,多余 token 会被忽略并记录 debug 日志,不会报错。`text` 和 `rest` 会消费全部剩余输入,因此不存在多余 token。
|
|
267
|
+
- 必填参数缺失、已声明槽位类型错误或引号未闭合时,Router 会自动回复错误和用法,handler 不会执行。
|
|
268
|
+
- usage 会自动生成,并显示在 `/help` 和指令组根命令的用法提示中。
|
|
269
|
+
- 必填参数不能出现在可选参数之后;参数名不能重复;`text` 和变长参数必须放在最后;必填参数不能声明默认值。
|
|
270
|
+
- 当 `params` 是字符串字面量时,handler 从第四个参数开始的位置参数类型会自动推导。例如 `<question:string> [count:integer=1]` 会推导为 `(question: string, count: number)`,`[name:string]` 会推导为 `string | undefined`,`[...rest]` 会推导为 `...string[]`。
|
|
271
|
+
- 需要在类型位置复用推导结果时,可以使用导出的 `CommandParamArgs<'<question:string>'>`。
|
|
272
|
+
- 也可以继续手写 handler 参数注解;注解与声明不一致时会在编译期报错。
|
|
273
|
+
- 自动推导只对字面量生效:运行时拼接的字符串,或显式声明为 `string` 的变量会回退为 `any[]`。需要保留字面量类型时,使用 `const` 变量或 `as const`。
|
|
274
|
+
- 类型层解析覆盖上面的声明语法;如果默认值包含 `]` 等会干扰声明边界的字符,可能回退为 `any[]`,但不影响运行时解析。非法声明仍然在注册时抛错,而不是变成类型错误。
|
|
275
|
+
|
|
276
|
+
参数错误示例:
|
|
277
|
+
|
|
278
|
+
```text
|
|
279
|
+
/ask hello abc
|
|
280
|
+
-> 参数 count 需要是整数
|
|
281
|
+
-> 用法:/ask <question> [count]
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### 指令组
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
ctx.commands.group(
|
|
288
|
+
{
|
|
289
|
+
name: 'plugin',
|
|
290
|
+
aliases: ['p'],
|
|
291
|
+
permission: 'SuperAdmin',
|
|
292
|
+
description: '管理已安装的插件包',
|
|
293
|
+
// 可选;省略时自动生成用法提示
|
|
294
|
+
handler: async (_event, context) => {
|
|
295
|
+
await context.send('用法:/plugin <list|install>')
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
(plugin) => {
|
|
299
|
+
plugin.register(
|
|
300
|
+
{
|
|
301
|
+
name: 'list',
|
|
302
|
+
description: '列出插件包',
|
|
303
|
+
},
|
|
304
|
+
async (_event, context) => {
|
|
305
|
+
await context.send('...')
|
|
306
|
+
}
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
plugin.register(
|
|
310
|
+
{
|
|
311
|
+
name: 'install',
|
|
312
|
+
description: '安装插件包',
|
|
313
|
+
params: '<spec:string>',
|
|
314
|
+
},
|
|
315
|
+
async (_event, context, _match, spec: string) => {
|
|
316
|
+
await context.send(`安装:${spec}`)
|
|
317
|
+
}
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
plugin.group({ name: 'cache' }, (cache) => {
|
|
321
|
+
cache.register({ name: 'clear' }, async () => {})
|
|
322
|
+
})
|
|
323
|
+
}
|
|
324
|
+
)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
指令组规则:
|
|
328
|
+
|
|
329
|
+
- `group()` 的 `name` 和 `aliases` 同样是单个路径段;通过嵌套 `group()` 组成任意层级。
|
|
330
|
+
- 子命令自动拼接组路径,例如上面的 `plugin` + `install` 对应 `/plugin install`。
|
|
331
|
+
- 子命令默认继承组的 `prefixes`、`permission`,也可以在子命令上覆盖。
|
|
332
|
+
- 组别名和子命令别名会自动组合;组 `plugin` 别名 `p`、子命令 `install` 别名 `i` 时,`/p i` 也能命中。
|
|
333
|
+
- 组根没有提供 `handler` 时,会自动注册根命令并生成用法提示,列出直接子命令、参数用法和描述。
|
|
334
|
+
- 组根提供了 `handler` 时,未命中子命令的输入(例如 `/plugin`、`/plugin help`、`/plugin unknown`)会进入该 handler。
|
|
335
|
+
- 组根和子命令都可以声明 `params`;子命令的用法会显示在组根提示和 `/help` 中。例如组根声明 `params: '<target:string>'` 时,`/demo alice` 会把 `alice` 传给组根 handler。
|
|
336
|
+
- `group()` 返回 disposer,会注销组根和所有子命令;组 setup 抛错或注册冲突时会自动回滚整组。
|
|
337
|
+
- `/help` 中会显示完整路径,例如 `/plugin install`。
|
|
338
|
+
|
|
339
|
+
同一前缀下按完整路径进行冲突检测。命令命中后会立即 `stopPropagation()`。
|
|
340
|
+
|
|
341
|
+
匹配时前缀最长优先,同一前缀下完整路径最长优先:
|
|
342
|
+
|
|
343
|
+
```text
|
|
344
|
+
/plugin install demo
|
|
345
|
+
-> command: "plugin install"
|
|
346
|
+
-> args: ["demo"]
|
|
347
|
+
-> rest: "demo"
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
`/plugin unknown` 在 `plugin` 组根存在时会回退到组根,`args` 为 `["unknown"]`。
|
|
218
351
|
|
|
219
352
|
`CommandMatch`:
|
|
220
353
|
|
|
221
354
|
```ts
|
|
222
355
|
interface CommandMatch {
|
|
223
|
-
command: string
|
|
356
|
+
command: string // 命中的完整路径,例如 "plugin install"
|
|
224
357
|
prefix: string
|
|
225
358
|
args: string[]
|
|
226
359
|
rest: string
|
|
@@ -304,6 +437,7 @@ await context.send('自动转义 CQ 码', { autoEscape: true })
|
|
|
304
437
|
- `plugins.<id>.enabled` 控制整体启用。
|
|
305
438
|
- `plugins.<id>.groups.allow` / `deny` 只作用于群事件,二者不能同时非空。
|
|
306
439
|
- `plugins.<id>.private` 控制私聊,默认 `true`。
|
|
440
|
+
- `/help` 只列出当前会话中启用的插件命令;群 gating 或 `private: false` 会隐藏对应命令。
|
|
307
441
|
|
|
308
442
|
## 配置校验
|
|
309
443
|
|
|
@@ -334,22 +468,26 @@ manifest: {
|
|
|
334
468
|
|
|
335
469
|
`enabled` 等信封字段会被剥离;`limit` 会传给 `configSchema`。未知字段会报错,错误信息包含 `plugins.demo.limit` 这样的路径。
|
|
336
470
|
|
|
337
|
-
##
|
|
471
|
+
## 本地插件
|
|
472
|
+
|
|
473
|
+
完整的目录约定、创建步骤和本地调试流程见[插件开发指南](plugin-development.md)。
|
|
474
|
+
|
|
475
|
+
本地插件固定放在 `plugins/<id>/dist`,应用启动时自动扫描,不需要路径参数:
|
|
338
476
|
|
|
339
477
|
```bash
|
|
340
478
|
npm run build
|
|
341
|
-
node dist/app.js
|
|
479
|
+
node dist/app.js
|
|
342
480
|
```
|
|
343
481
|
|
|
344
|
-
|
|
482
|
+
应用会跳过与内置插件同 ID 的本地插件。加载器会扫描每个插件 `dist` 目录下所有 `.js`、`.mjs`、`.cjs`、`.ts`、`.mts`、`.cts` 文件,识别:
|
|
345
483
|
|
|
346
484
|
- `export default plugin`
|
|
347
485
|
- `export const plugin = ...`
|
|
348
486
|
- `export const plugins = [...]`
|
|
349
487
|
|
|
350
|
-
没有导出插件定义的 helper
|
|
488
|
+
没有导出插件定义的 helper 模块会被跳过;空目录不会报错,但目录中存在无法导入或无法识别的文件、且最终没有加载到任何有效插件时,启动失败。插件定义必须包含可调用的 `configSchema.safeParse`,非法的 `dependencies` 类型也会被拒绝。
|
|
351
489
|
|
|
352
|
-
TypeScript 插件必须在生产运行前编译为 JavaScript
|
|
490
|
+
TypeScript 插件必须在生产运行前编译为 JavaScript。本地插件和内置插件共用同一个 `PluginContext` API。
|
|
353
491
|
|
|
354
492
|
推荐把插件做成独立包,至少包含 `package.json`、`tsconfig.json` 和 `src/index.ts`。`package.json` 的入口指向构建后的 `dist/index.js`:
|
|
355
493
|
|
|
@@ -368,7 +506,7 @@ TypeScript 插件必须在生产运行前编译为 JavaScript。外部插件和
|
|
|
368
506
|
}
|
|
369
507
|
```
|
|
370
508
|
|
|
371
|
-
`@jsbot-tellus/core` 只用于类型和 `definePlugin
|
|
509
|
+
`@jsbot-tellus/core` 只用于类型和 `definePlugin`。通过 `/plugin install` 安装时由宿主提供;从 `plugins/` 加载的本地插件需要在插件自己的 `node_modules` 中安装 core(`npm install` 会安装 `devDependencies`)。在本仓库内联调也可以改用 `file:` 或 workspace 链接。发布到 npm 时不要把 `@jsbot-tellus/core` 写进 `dependencies` 或 `peerDependencies`。仅在本机使用的包可以加 `"private": true`。插件自己的第三方依赖放在 `dependencies`,npm 安装插件时会一并安装。
|
|
372
510
|
|
|
373
511
|
内置插件 `core`、`admin` 是 `src/plugins/` 下的普通源码。其他插件放在 `plugins/`,该目录整体被 `.gitignore` 排除。每个本地插件都是独立包,独立安装依赖:
|
|
374
512
|
|
|
@@ -377,24 +515,23 @@ npm install --prefix plugins/poke
|
|
|
377
515
|
npm install --prefix plugins/llm
|
|
378
516
|
npm run build:local
|
|
379
517
|
|
|
380
|
-
node dist/app.js
|
|
381
|
-
--plugin-dir plugins/poke/dist \
|
|
382
|
-
--plugin-dir plugins/llm/dist
|
|
518
|
+
node dist/app.js
|
|
383
519
|
```
|
|
384
520
|
|
|
385
|
-
|
|
521
|
+
应用会自动扫描 `plugins/<id>/dist`;没有 `dist` 的本地插件如果带有 `build` 脚本且依赖已安装,会先自动构建再加载,构建失败则记录警告并跳过。示例见 [`examples/plugins/hello`](../examples/plugins/hello)。
|
|
386
522
|
|
|
387
523
|
## 通过 npm 发布与安装
|
|
388
524
|
|
|
525
|
+
打包结构、发布清单和本地开发流程见[插件开发指南](plugin-development.md)。
|
|
526
|
+
|
|
389
527
|
发布到 npm registry 的插件包必须是可直接运行的构建产物,安装后不再执行编译。要求:
|
|
390
528
|
|
|
391
|
-
- ESM 包(`"type": "module"`),发布 `dist/` 中的 JavaScript 和 `.d.ts
|
|
392
|
-
-
|
|
393
|
-
-
|
|
394
|
-
- `manifest.id` 必须匹配 `[a-z0-9][a-z0-9._-]*`,且不能与内置插件、`--plugin-dir` 插件或其它已安装插件重复。
|
|
529
|
+
- ESM 包(`"type": "module"`),发布 `dist/` 中的 JavaScript 和 `.d.ts`;安装后从 `plugins/<目录>/dist` 加载,不再执行编译。
|
|
530
|
+
- `dist/` 中导出的插件定义会被加载:`export default plugin`、`export const plugin = ...` 或 `export const plugins = [...]`。
|
|
531
|
+
- `manifest.id` 必须匹配 `[a-z0-9][a-z0-9._-]*`,且不能与内置插件、`plugins/` 本地插件或其它已安装插件重复。
|
|
395
532
|
- 插件之间的依赖写在 `manifest.dependencies`,依赖必须由同一个包导出,或已由其它已安装包提供。
|
|
396
533
|
- 不要依赖源码仓库或相对的 `file:` 依赖;第三方运行时依赖写入 `dependencies`。
|
|
397
|
-
- 不要把 `@jsbot-tellus/core` 写进 `dependencies` 或 `peerDependencies
|
|
534
|
+
- 不要把 `@jsbot-tellus/core` 写进 `dependencies` 或 `peerDependencies`。宿主会在 `plugins/<目录>/node_modules/@jsbot-tellus/core` 创建链接,运行时直接解析到当前内核。
|
|
398
535
|
- 不要依赖 `postinstall` 构建。安装器默认使用 `--ignore-scripts`,只有 `installer.allowScripts=true` 才会执行 npm 脚本。
|
|
399
536
|
|
|
400
537
|
发布后在聊天中安装:
|
|
@@ -407,7 +544,7 @@ node dist/app.js \
|
|
|
407
544
|
/plugin remove @yourscope/plugin-demo
|
|
408
545
|
```
|
|
409
546
|
|
|
410
|
-
安装、更新和卸载成功后会自动重启运行时并重新加载插件,进程不会退出。`/plugin` 的所有子命令(包括 `help` 和 `list`)都要求 SuperAdmin。安装器默认关闭;启用后只接受 npm registry 包,拒绝 git、file、URL、workspace、link
|
|
547
|
+
安装、更新和卸载成功后会自动重启运行时并重新加载插件,进程不会退出。`/plugin` 的所有子命令(包括 `help` 和 `list`)都要求 SuperAdmin。安装器默认关闭;启用后只接受 npm registry 包,拒绝 git、file、URL、workspace、link 和版本范围。包会直接安装到 `plugins/<插件id>/` 并从 `dist` 加载,配置见[插件安装器](configuration.md#插件安装器)。
|
|
411
548
|
|
|
412
549
|
安装和更新会检查完整依赖图;自依赖、循环依赖和缺失依赖会被拒绝。卸载被其它包依赖的插件时默认失败,确认后可使用 `/plugin remove <目标> --force`。
|
|
413
550
|
|