onebots 1.0.0 → 1.0.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/lib/bin.js CHANGED
@@ -1,39 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- import { createOnebots, App } from "./app.js";
4
- const execArgv = process.argv.splice(2);
5
- const obj = {};
6
- for (let i = 0; i < execArgv.length; i += 2) {
7
- const key = execArgv[i];
8
- const value = execArgv[i + 1];
9
- if (!obj[key])
10
- obj[key] = value;
11
- else {
12
- if (Array.isArray(obj[key]))
13
- obj[key].push(value);
14
- else
15
- obj[key] = [obj[key], value];
16
- }
17
- }
18
- if (obj["-r"]) {
19
- const adapters = [].concat(obj["-r"]);
20
- for (const adapter of adapters) {
21
- const result = await App.loadAdapterFactory(adapter);
22
- if (!result)
23
- console.warn(`[onebots] Failed to load adapter ${adapter}, please check if the adapter is installed`);
24
- }
25
- }
26
- if (!obj['-p'])
27
- obj['-p'] = [];
28
- if (!Array.isArray(obj['-p']))
29
- obj['-p'] = [obj['-p']];
30
- if (obj["-p"]) {
31
- const protocols = [].concat(obj["-p"]);
32
- for (const protocol of protocols) {
33
- await App.loadProtocolFactory(protocol);
34
- }
35
- }
36
- if (Array.isArray(obj['-c']))
37
- obj['-c'] = obj['-c'][obj['-c'].length - 1];
38
- createOnebots(obj["-c"]).start();
3
+ import { runCli } from "./cli.js";
4
+ runCli();
39
5
  //# sourceMappingURL=bin.js.map
package/lib/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function runCli(): void;
2
+ //# sourceMappingURL=cli.d.ts.map
package/lib/cli.js ADDED
@@ -0,0 +1,293 @@
1
+ /**
2
+ * OneBots CLI:gateway 网关控制、config、setup、onboard、send
3
+ */
4
+ import { Command } from "commander";
5
+ import * as path from "path";
6
+ import * as fs from "fs";
7
+ import { createOnebots, App } from "./app.js";
8
+ import { yaml } from "@onebots/core";
9
+ import { getPidPath, readPid, writePid, removePidFile, isProcessRunning, stopProcess, daemonStart, } from "./daemon.js";
10
+ import { serviceInstall, serviceUninstall, serviceStatus, } from "./service-manager.js";
11
+ const program = new Command();
12
+ program
13
+ .name("onebots")
14
+ .description("OneBots CLI - 网关控制与配置管理")
15
+ .version("1.0.1")
16
+ .option("-c, --config <path>", "配置文件路径", "config.yaml")
17
+ .option("-r, --register <adapter>", "注册适配器(可多次)", collect, [])
18
+ .option("-p, --protocol <protocol>", "注册协议(可多次)", collect, []);
19
+ function collect(val, prev) {
20
+ return (prev || []).concat([val]);
21
+ }
22
+ function getConfigPath(configOption) {
23
+ return path.resolve(process.cwd(), configOption);
24
+ }
25
+ async function loadAdaptersAndProtocols(adapters, protocols) {
26
+ for (const adapter of adapters) {
27
+ const ok = await App.loadAdapterFactory(adapter);
28
+ if (!ok) {
29
+ console.warn(`[onebots] 加载适配器 ${adapter} 失败,请检查是否已安装`);
30
+ }
31
+ }
32
+ for (const protocol of protocols) {
33
+ await App.loadProtocolFactory(protocol);
34
+ }
35
+ }
36
+ async function runGatewayStart(configPath, adapters, protocols) {
37
+ await loadAdaptersAndProtocols(adapters, protocols);
38
+ createOnebots(configPath).start();
39
+ }
40
+ // ---------- gateway 子命令 ----------
41
+ const gateway = program.command("gateway").description("网关服务(start/daemon/stop/service)");
42
+ gateway
43
+ .command("start")
44
+ .description("前台启动网关")
45
+ .action(async () => {
46
+ const opts = program.opts();
47
+ const configPath = getConfigPath(opts.config);
48
+ await runGatewayStart(configPath, opts.register || [], opts.protocol || []);
49
+ });
50
+ gateway
51
+ .command("daemon")
52
+ .description("后台启动网关")
53
+ .action(async () => {
54
+ const opts = program.opts();
55
+ const configPath = getConfigPath(opts.config);
56
+ await loadAdaptersAndProtocols(opts.register || [], opts.protocol || []);
57
+ const pid = daemonStart({
58
+ configPath,
59
+ adapters: opts.register || [],
60
+ protocols: opts.protocol || [],
61
+ nodePath: process.execPath,
62
+ binPath: process.argv[1],
63
+ });
64
+ writePid(configPath, pid);
65
+ console.log(`网关已在后台启动,PID: ${pid}`);
66
+ console.log(`PID 文件: ${getPidPath(configPath)}`);
67
+ process.exit(0);
68
+ });
69
+ gateway
70
+ .command("stop")
71
+ .description("停止网关")
72
+ .action(async () => {
73
+ const opts = program.opts();
74
+ const configPath = getConfigPath(opts.config);
75
+ const pid = readPid(configPath);
76
+ if (pid === null) {
77
+ console.error("[onebots] 未找到 PID 文件,网关可能未以后台方式运行");
78
+ process.exit(2);
79
+ }
80
+ if (!isProcessRunning(pid)) {
81
+ console.warn("[onebots] 进程已不存在,清理 PID 文件");
82
+ removePidFile(configPath);
83
+ process.exit(0);
84
+ }
85
+ stopProcess(pid);
86
+ removePidFile(configPath);
87
+ console.log("网关已停止");
88
+ process.exit(0);
89
+ });
90
+ const gatewayService = gateway.command("service").description("系统服务(install/uninstall/status)");
91
+ gatewayService
92
+ .command("install")
93
+ .description("安装网关为系统服务")
94
+ .action(async () => {
95
+ const opts = program.opts();
96
+ const configPath = getConfigPath(opts.config);
97
+ await serviceInstall(configPath);
98
+ });
99
+ gatewayService
100
+ .command("uninstall")
101
+ .description("卸载网关系统服务")
102
+ .action(async () => {
103
+ await serviceUninstall();
104
+ });
105
+ gatewayService
106
+ .command("status")
107
+ .description("查看网关服务状态")
108
+ .action(async () => {
109
+ await serviceStatus();
110
+ });
111
+ // ---------- config 子命令 ----------
112
+ const configCmd = program.command("config").description("命令式修改配置(get/set/list)");
113
+ configCmd
114
+ .command("get <key>")
115
+ .description("获取配置项")
116
+ .action(async (key) => {
117
+ const opts = program.opts();
118
+ const configPath = getConfigPath(opts.config);
119
+ if (!fs.existsSync(configPath)) {
120
+ console.error("[onebots] 配置文件不存在,请先运行 onebots setup");
121
+ process.exit(1);
122
+ }
123
+ const raw = fs.readFileSync(configPath, "utf8");
124
+ const config = yaml.load(raw) || {};
125
+ const keys = key.split(".");
126
+ let cur = config;
127
+ for (const k of keys) {
128
+ cur = cur?.[k];
129
+ if (cur === undefined)
130
+ break;
131
+ }
132
+ console.log(cur === undefined ? "" : String(cur));
133
+ });
134
+ configCmd
135
+ .command("set <key> <value>")
136
+ .description("设置配置项")
137
+ .action(async (key, value) => {
138
+ const opts = program.opts();
139
+ const configPath = getConfigPath(opts.config);
140
+ if (!fs.existsSync(configPath)) {
141
+ console.error("[onebots] 配置文件不存在,请先运行 onebots setup");
142
+ process.exit(1);
143
+ }
144
+ const raw = fs.readFileSync(configPath, "utf8");
145
+ const config = yaml.load(raw) || {};
146
+ const keys = key.split(".");
147
+ let cur = config;
148
+ for (let i = 0; i < keys.length - 1; i++) {
149
+ const k = keys[i];
150
+ if (!(cur[k] instanceof Object))
151
+ cur[k] = {};
152
+ cur = cur[k];
153
+ }
154
+ const last = keys[keys.length - 1];
155
+ const num = Number(value);
156
+ cur[last] = value === "true" ? true : value === "false" ? false : Number.isNaN(num) ? value : num;
157
+ fs.writeFileSync(configPath, yaml.dump(config), "utf8");
158
+ console.log(`已设置 ${key} = ${value}`);
159
+ });
160
+ configCmd
161
+ .command("list")
162
+ .description("列出全部配置")
163
+ .action(async () => {
164
+ const opts = program.opts();
165
+ const configPath = getConfigPath(opts.config);
166
+ if (!fs.existsSync(configPath)) {
167
+ console.error("[onebots] 配置文件不存在,请先运行 onebots setup");
168
+ process.exit(1);
169
+ }
170
+ const raw = fs.readFileSync(configPath, "utf8");
171
+ const config = yaml.load(raw) || {};
172
+ console.log(yaml.dump(config));
173
+ });
174
+ // ---------- setup ----------
175
+ program
176
+ .command("setup")
177
+ .description("初始化 OneBots(创建配置目录与默认配置)")
178
+ .action(async () => {
179
+ const opts = program.opts();
180
+ const configPath = getConfigPath(opts.config);
181
+ const configDir = path.dirname(configPath);
182
+ if (fs.existsSync(configPath)) {
183
+ console.log("配置文件已存在:", configPath);
184
+ process.exit(0);
185
+ }
186
+ if (!fs.existsSync(configDir)) {
187
+ fs.mkdirSync(configDir, { recursive: true });
188
+ }
189
+ const samplePath = path.resolve(import.meta.dirname, "./config.sample.yaml");
190
+ fs.copyFileSync(samplePath, configPath);
191
+ const dataDir = path.join(configDir, "data");
192
+ if (!fs.existsSync(dataDir)) {
193
+ fs.mkdirSync(dataDir, { recursive: true });
194
+ }
195
+ console.log("已初始化,配置文件:", configPath);
196
+ console.log("请修改配置后使用 onebots gateway start 启动");
197
+ process.exit(0);
198
+ });
199
+ // ---------- onboard ----------
200
+ program
201
+ .command("onboard")
202
+ .description("引导式调整配置")
203
+ .action(async () => {
204
+ const opts = program.opts();
205
+ const configPath = getConfigPath(opts.config);
206
+ if (!fs.existsSync(configPath)) {
207
+ console.error("[onebots] 请先运行 onebots setup");
208
+ process.exit(1);
209
+ }
210
+ const readline = await import("readline");
211
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
212
+ const ask = (q) => new Promise((resolve) => rl.question(q, resolve));
213
+ let config = yaml.load(fs.readFileSync(configPath, "utf8")) || {};
214
+ const port = await ask("HTTP 端口 [6727]: ");
215
+ if (port)
216
+ config.port = parseInt(port, 10) || 6727;
217
+ const logLevel = await ask("日志级别 (trace/debug/info/warn/error) [info]: ");
218
+ if (logLevel)
219
+ config.log_level = logLevel || "info";
220
+ fs.writeFileSync(configPath, yaml.dump(config), "utf8");
221
+ console.log("配置已更新:", configPath);
222
+ rl.close();
223
+ process.exit(0);
224
+ });
225
+ // ---------- send ----------
226
+ program
227
+ .command("send <target_id> <message>")
228
+ .description("通过已运行的网关发送消息")
229
+ .requiredOption("--target_type <type>", "private | group | channel")
230
+ .requiredOption("--channel <channel>", "发信 bot,格式 platform.account_id(如 qq.my_bot)")
231
+ .option("--url <baseUrl>", "网关 base URL(默认从 -c 读取 port/path 构造)")
232
+ .action(async (target_id, message, options) => {
233
+ const opts = program.opts();
234
+ let baseUrl = options.url;
235
+ let auth = {};
236
+ if (!baseUrl) {
237
+ const configPath = getConfigPath(opts.config);
238
+ if (!fs.existsSync(configPath)) {
239
+ console.error("[onebots] 配置文件不存在,请指定 -c 或 --url");
240
+ process.exit(1);
241
+ }
242
+ const config = yaml.load(fs.readFileSync(configPath, "utf8"));
243
+ const port = config?.port ?? 6727;
244
+ const pathPrefix = config?.path ?? "";
245
+ baseUrl = `http://127.0.0.1:${port}${pathPrefix}`;
246
+ if (config?.access_token) {
247
+ auth = { Authorization: `Bearer ${config.access_token}` };
248
+ }
249
+ else if (config?.username && config?.password) {
250
+ auth = {
251
+ Authorization: "Basic " + Buffer.from(`${config.username}:${config.password}`).toString("base64"),
252
+ };
253
+ }
254
+ }
255
+ const body = {
256
+ channel: options.channel,
257
+ target_id,
258
+ target_type: options.target_type,
259
+ message: message || "",
260
+ };
261
+ try {
262
+ const res = await fetch(`${baseUrl.replace(/\/$/, "")}/api/send`, {
263
+ method: "POST",
264
+ headers: { "Content-Type": "application/json", ...auth },
265
+ body: JSON.stringify(body),
266
+ });
267
+ const text = await res.text();
268
+ if (!res.ok) {
269
+ console.error("[onebots] 发送失败:", res.status, text);
270
+ process.exit(2);
271
+ }
272
+ console.log(text || "发送成功");
273
+ }
274
+ catch (e) {
275
+ console.error("[onebots] 请求失败,请确认网关已启动(onebots gateway start 或 onebots gateway daemon):", e);
276
+ process.exit(2);
277
+ }
278
+ process.exit(0);
279
+ });
280
+ // 无子命令时默认执行 gateway start(仅当没有未被选项消耗的剩余参数时)
281
+ program.action(async () => {
282
+ // 使用 program.args:Commander 解析后只包含未被 -r/-p/-c 等消耗的剩余参数。
283
+ // 用 process.argv 会把 -r/-p 的值(如 kook、config.yaml)误判为位置参数导致不启动。
284
+ if (program.args.length > 0)
285
+ return; // 有剩余位置参数则交给 Commander 显示 unknown command
286
+ const opts = program.opts();
287
+ const configPath = getConfigPath(opts.config);
288
+ await runGatewayStart(configPath, opts.register || [], opts.protocol || []);
289
+ });
290
+ export function runCli() {
291
+ program.parse();
292
+ }
293
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1,9 @@
1
+ import type { Schema } from '@onebots/core';
2
+ export type ConfigSchemaBundle = {
3
+ base: Schema;
4
+ general: Schema;
5
+ protocols: Record<string, Schema>;
6
+ adapters: Record<string, Schema>;
7
+ };
8
+ export declare const getAppConfigSchema: () => ConfigSchemaBundle;
9
+ //# sourceMappingURL=config-schema.d.ts.map
@@ -0,0 +1,78 @@
1
+ import { BaseAppConfigSchema, AdapterRegistry, ProtocolRegistry } from '@onebots/core';
2
+ /**
3
+ * App 层配置 Schema(可在此扩展)
4
+ */
5
+ const base = BaseAppConfigSchema;
6
+ const withLabel = (key, label, description) => {
7
+ return {
8
+ ...base[key],
9
+ label,
10
+ description,
11
+ };
12
+ };
13
+ const general = {
14
+ 'onebot.v11': {
15
+ use_http: { type: 'boolean', default: true, label: '启用 HTTP' },
16
+ use_ws: { type: 'boolean', default: true, label: '启用 WebSocket' },
17
+ access_token: { type: 'string', default: '', label: 'Access Token' },
18
+ secret: { type: 'string', default: '', label: 'Secret' },
19
+ enable_cors: { type: 'boolean', default: true, label: '启用 CORS' },
20
+ heartbeat_interval: { type: 'number', default: 5, min: 1, label: '心跳间隔(秒)' },
21
+ http_reverse: { type: 'array', default: [], label: 'HTTP 反向上报地址' },
22
+ ws_reverse: { type: 'array', default: [], label: 'WS 反向连接地址' },
23
+ },
24
+ 'onebot.v12': {
25
+ use_http: { type: 'boolean', default: true, label: '启用 HTTP' },
26
+ use_ws: { type: 'boolean', default: true, label: '启用 WebSocket' },
27
+ access_token: { type: 'string', default: '', label: 'Access Token' },
28
+ secret: { type: 'string', default: '', label: 'Secret' },
29
+ enable_cors: { type: 'boolean', default: true, label: '启用 CORS' },
30
+ heartbeat_interval: { type: 'number', default: 5, min: 1, label: '心跳间隔(秒)' },
31
+ webhooks: { type: 'array', default: [], label: 'Webhook 上报地址' },
32
+ ws_reverse: { type: 'array', default: [], label: 'WS 反向连接地址' },
33
+ request_timeout: { type: 'number', default: 15, min: 1, label: '请求超时(秒)' },
34
+ },
35
+ 'satori.v1': {
36
+ use_http: { type: 'boolean', default: true, label: '启用 HTTP' },
37
+ use_ws: { type: 'boolean', default: true, label: '启用 WebSocket' },
38
+ token: { type: 'string', default: '', label: 'Token' },
39
+ platform: { type: 'string', default: 'unknown', label: '平台标识' },
40
+ webhooks: { type: 'array', default: [], label: 'Webhook 上报地址' },
41
+ },
42
+ 'milky.v1': {
43
+ use_http: { type: 'boolean', default: true, label: '启用 HTTP' },
44
+ use_ws: { type: 'boolean', default: true, label: '启用 WebSocket' },
45
+ access_token: { type: 'string', default: '', label: 'Access Token' },
46
+ secret: { type: 'string', default: '', label: 'Secret' },
47
+ heartbeat: { type: 'number', default: 5, min: 1, label: '心跳间隔(秒)' },
48
+ http_reverse: { type: 'array', default: [], label: 'HTTP 反向上报地址' },
49
+ ws_reverse: { type: 'array', default: [], label: 'WS 反向连接地址' },
50
+ },
51
+ };
52
+ const baseWithLabels = {
53
+ port: withLabel('port', '监听端口', '服务监听端口,范围 1-65535'),
54
+ path: withLabel('path', '服务路径前缀', 'HTTP 服务前缀路径,可为空'),
55
+ database: withLabel('database', '数据库文件', '数据库文件名或路径'),
56
+ timeout: withLabel('timeout', '登录超时(秒)', '账号登录超时秒数'),
57
+ username: withLabel('username', '管理端用户名', 'Web 管理端登录用户名(与鉴权码二选一)'),
58
+ password: withLabel('password', '管理端密码', 'Web 管理端登录密码(与鉴权码二选一)'),
59
+ access_token: withLabel('access_token', '管理端鉴权码', 'Bearer 鉴权码,配置后可使用 Authorization: Bearer <鉴权码> 访问 API,无需用户名密码'),
60
+ log_level: withLabel('log_level', '日志等级', 'trace | debug | info | warn | error | fatal | mark | off'),
61
+ public_static_dir: withLabel('public_static_dir', '站点根静态目录', '相对配置文件目录或绝对路径,用于企业微信等可信域名校验文件(站点根路径 GET);留空不启用。Docker:配置 static 并将校验文件放入挂载卷内 /data/static'),
62
+ };
63
+ export const getAppConfigSchema = () => {
64
+ const protocols = {
65
+ ...general,
66
+ ...ProtocolRegistry.getAllSchemas(),
67
+ };
68
+ const adapters = {
69
+ ...AdapterRegistry.getAllSchemas(),
70
+ };
71
+ return {
72
+ base: baseWithLabels,
73
+ general,
74
+ protocols,
75
+ adapters,
76
+ };
77
+ };
78
+ //# sourceMappingURL=config-schema.js.map
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 根据配置路径确定 pid 文件所在目录(与网关进程一致)
3
+ */
4
+ export declare function getPidDir(configPath: string): string;
5
+ export declare function getPidPath(configPath: string): string;
6
+ export declare function writePid(configPath: string, pid: number): void;
7
+ export declare function readPid(configPath: string): number | null;
8
+ export declare function removePidFile(configPath: string): void;
9
+ /**
10
+ * 检查 pid 是否对应存活进程
11
+ */
12
+ export declare function isProcessRunning(pid: number): boolean;
13
+ /**
14
+ * 向网关进程发送 SIGTERM
15
+ */
16
+ export declare function stopProcess(pid: number): boolean;
17
+ /**
18
+ * 在后台启动网关:spawn 子进程执行 onebots gateway start -c <configPath> [-r ...] [-p ...]
19
+ * 返回子进程 pid;父进程写 pid 文件后退出。
20
+ */
21
+ export declare function daemonStart(options: {
22
+ configPath: string;
23
+ adapters: string[];
24
+ protocols: string[];
25
+ /** Node 可执行路径 */
26
+ nodePath: string;
27
+ /** onebots CLI 入口路径(如 lib/bin.js) */
28
+ binPath: string;
29
+ }): number;
30
+ //# sourceMappingURL=daemon.d.ts.map
package/lib/daemon.js ADDED
@@ -0,0 +1,94 @@
1
+ /**
2
+ * 网关 daemon:pid 文件读写与后台进程管理
3
+ */
4
+ import * as fs from "fs";
5
+ import * as path from "path";
6
+ import { spawn } from "child_process";
7
+ const PID_FILE = "onebots-gateway.pid";
8
+ /**
9
+ * 根据配置路径确定 pid 文件所在目录(与网关进程一致)
10
+ */
11
+ export function getPidDir(configPath) {
12
+ const resolved = path.resolve(process.cwd(), configPath);
13
+ return path.dirname(resolved);
14
+ }
15
+ export function getPidPath(configPath) {
16
+ return path.join(getPidDir(configPath), PID_FILE);
17
+ }
18
+ export function writePid(configPath, pid) {
19
+ const file = getPidPath(configPath);
20
+ const dir = path.dirname(file);
21
+ if (!fs.existsSync(dir)) {
22
+ fs.mkdirSync(dir, { recursive: true });
23
+ }
24
+ fs.writeFileSync(file, String(pid), "utf8");
25
+ }
26
+ export function readPid(configPath) {
27
+ const file = getPidPath(configPath);
28
+ if (!fs.existsSync(file))
29
+ return null;
30
+ const content = fs.readFileSync(file, "utf8").trim();
31
+ const pid = parseInt(content, 10);
32
+ return Number.isNaN(pid) ? null : pid;
33
+ }
34
+ export function removePidFile(configPath) {
35
+ const file = getPidPath(configPath);
36
+ if (fs.existsSync(file)) {
37
+ try {
38
+ fs.unlinkSync(file);
39
+ }
40
+ catch {
41
+ // 忽略
42
+ }
43
+ }
44
+ }
45
+ /**
46
+ * 检查 pid 是否对应存活进程
47
+ */
48
+ export function isProcessRunning(pid) {
49
+ try {
50
+ process.kill(pid, 0);
51
+ return true;
52
+ }
53
+ catch {
54
+ return false;
55
+ }
56
+ }
57
+ /**
58
+ * 向网关进程发送 SIGTERM
59
+ */
60
+ export function stopProcess(pid) {
61
+ if (!isProcessRunning(pid))
62
+ return false;
63
+ try {
64
+ process.kill(pid, "SIGTERM");
65
+ return true;
66
+ }
67
+ catch {
68
+ return false;
69
+ }
70
+ }
71
+ /**
72
+ * 在后台启动网关:spawn 子进程执行 onebots gateway start -c <configPath> [-r ...] [-p ...]
73
+ * 返回子进程 pid;父进程写 pid 文件后退出。
74
+ */
75
+ export function daemonStart(options) {
76
+ const args = [
77
+ options.binPath,
78
+ "gateway",
79
+ "start",
80
+ "-c",
81
+ options.configPath,
82
+ ...options.adapters.flatMap((r) => ["-r", r]),
83
+ ...options.protocols.flatMap((p) => ["-p", p]),
84
+ ];
85
+ const child = spawn(options.nodePath, args, {
86
+ cwd: getPidDir(options.configPath),
87
+ stdio: "ignore",
88
+ detached: true,
89
+ env: process.env,
90
+ });
91
+ child.unref();
92
+ return child.pid;
93
+ }
94
+ //# sourceMappingURL=daemon.js.map
package/lib/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './app.js';
2
+ export * from './config-schema.js';
2
3
  export * from '@onebots/core';
3
4
  //# sourceMappingURL=index.d.ts.map
package/lib/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './app.js';
2
+ export * from './config-schema.js';
2
3
  export * from '@onebots/core';
3
4
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,4 @@
1
+ export declare function serviceInstall(configPath: string): Promise<void>;
2
+ export declare function serviceUninstall(): Promise<void>;
3
+ export declare function serviceStatus(): Promise<void>;
4
+ //# sourceMappingURL=service-manager.d.ts.map