@cxyhhhhh/dsh-qqbot 0.1.0-dev.202608142135 → 0.1.0-dev.202608150353
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/.orange-ci.yml +14 -22
- package/CHANGELOG.md +39 -0
- package/a.txt +14 -0
- package/dist/commands/model.js +1 -1
- package/dist/commands/model.js.map +1 -1
- package/dist/config.d.ts +6 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -1
- package/dist/config.js.map +1 -1
- package/dist/features/history-store.d.ts +8 -0
- package/dist/features/history-store.d.ts.map +1 -0
- package/dist/features/history-store.js +24 -0
- package/dist/features/history-store.js.map +1 -0
- package/dist/gateway/bootstrap.d.ts +12 -0
- package/dist/gateway/bootstrap.d.ts.map +1 -0
- package/dist/gateway/bootstrap.js +71 -0
- package/dist/gateway/bootstrap.js.map +1 -0
- package/dist/gateway/index.d.ts +3 -0
- package/dist/gateway/index.d.ts.map +1 -0
- package/dist/gateway/index.js +3 -0
- package/dist/gateway/index.js.map +1 -0
- package/dist/gateway/middleware-setup.d.ts +12 -0
- package/dist/gateway/middleware-setup.d.ts.map +1 -0
- package/dist/gateway/middleware-setup.js +80 -0
- package/dist/gateway/middleware-setup.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -120
- package/dist/index.js.map +1 -1
- package/dist/middleware/attachment.d.ts +11 -0
- package/dist/middleware/attachment.d.ts.map +1 -0
- package/dist/middleware/attachment.js +17 -0
- package/dist/middleware/attachment.js.map +1 -0
- package/dist/model/model-resolver.d.ts +11 -5
- package/dist/model/model-resolver.d.ts.map +1 -1
- package/dist/model/model-resolver.js +15 -6
- package/dist/model/model-resolver.js.map +1 -1
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +4 -5
- package/dist/session/session-manager.js.map +1 -1
- package/dist/setup.js +6 -6
- package/dist/setup.js.map +1 -1
- package/dist/transport/attachment.d.ts +18 -0
- package/dist/transport/attachment.d.ts.map +1 -0
- package/dist/transport/attachment.js +106 -0
- package/dist/transport/attachment.js.map +1 -0
- package/dist/transport/events.d.ts +80 -0
- package/dist/transport/events.d.ts.map +1 -0
- package/dist/transport/events.js +62 -0
- package/dist/transport/events.js.map +1 -0
- package/dist/transport/inbound.d.ts +1 -1
- package/dist/transport/inbound.d.ts.map +1 -1
- package/dist/transport/inbound.js +39 -14
- package/dist/transport/inbound.js.map +1 -1
- package/dist/transport/outbound-buffer.d.ts +12 -7
- package/dist/transport/outbound-buffer.d.ts.map +1 -1
- package/dist/transport/outbound-buffer.js +20 -22
- package/dist/transport/outbound-buffer.js.map +1 -1
- package/dist/transport/outbound.d.ts +11 -7
- package/dist/transport/outbound.d.ts.map +1 -1
- package/dist/transport/outbound.js +118 -69
- package/dist/transport/outbound.js.map +1 -1
- package/dist/transport/streaming-writer.d.ts +47 -0
- package/dist/transport/streaming-writer.d.ts.map +1 -0
- package/dist/transport/streaming-writer.js +110 -0
- package/dist/transport/streaming-writer.js.map +1 -0
- package/dist/transport/tool-presenter.d.ts +38 -0
- package/dist/transport/tool-presenter.d.ts.map +1 -0
- package/dist/transport/tool-presenter.js +117 -0
- package/dist/transport/tool-presenter.js.map +1 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -5
- package/scripts/prepare-test-pkg.js +23 -0
- package/tiezi.md +34 -0
package/.orange-ci.yml
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
# dsh-qqbot OCI 配置
|
|
2
|
-
# 参考 qqbot-nodejs/.orange-ci.yml
|
|
3
|
-
#
|
|
4
|
-
# 发布约定:
|
|
5
|
-
# tag 名即 npm 版本号(不带 v 前缀),例如:
|
|
6
|
-
# git tag 0.1.0 → 发布 0.1.0 到 latest
|
|
7
|
-
# git tag 0.1.0-beta.1 → 发布 0.1.0-beta.1(dist-tag 由版本号推断)
|
|
8
|
-
# feat/fix 分支 push → 内网 mirrors 发布 dev 版本
|
|
9
|
-
|
|
10
|
-
# ── 打 tag 触发发布(核心:打 tags + 发布) ──
|
|
11
1
|
$:
|
|
12
2
|
tag_push:
|
|
13
3
|
- services:
|
|
@@ -37,18 +27,18 @@ $:
|
|
|
37
27
|
options:
|
|
38
28
|
fromFile: message.txt
|
|
39
29
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
merge_request:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
30
|
+
# ── master 分支:MR 检查 ──
|
|
31
|
+
master:
|
|
32
|
+
merge_request:
|
|
33
|
+
- docker:
|
|
34
|
+
image: node:24
|
|
35
|
+
wework:
|
|
36
|
+
silent: true
|
|
37
|
+
stages:
|
|
38
|
+
- name: 安装依赖
|
|
39
|
+
script: npm install
|
|
40
|
+
- name: TypeScript 类型检查
|
|
41
|
+
script: npx tsc --noEmit
|
|
52
42
|
|
|
53
43
|
# ── feat/fix 分支 push:内网发布 dev 版本 ──
|
|
54
44
|
(feat|fix)/**:
|
|
@@ -62,6 +52,8 @@ merge_request:
|
|
|
62
52
|
script: npm install
|
|
63
53
|
- name: 构建项目
|
|
64
54
|
script: npm run build
|
|
55
|
+
- name: 设置测试包名
|
|
56
|
+
script: npm run ci:prepare-test-pkg
|
|
65
57
|
- name: 设置测试版本
|
|
66
58
|
script: npm version "0.0.0-dev.${ORANGE_COMMIT_SHORT}" --no-git-tag-version
|
|
67
59
|
- name: 发布 npm 包
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
本文件从产品视角记录 dsh-qqbot 的重要更新,聚焦用户可感知的变化。
|
|
4
|
+
|
|
5
|
+
格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/)。
|
|
6
|
+
|
|
7
|
+
## [0.3.0] - 2026-08-15
|
|
8
|
+
|
|
9
|
+
### 新功能
|
|
10
|
+
|
|
11
|
+
- **文件理解**:给机器人发送文件,它会自动下载并理解文件内容,支持解压、读取、分析等操作。
|
|
12
|
+
- **流式回复**:回复内容实时逐段显示,无需等待全部生成,体验更流畅自然。
|
|
13
|
+
- **过程可见**:机器人执行任务(运行命令、读写文件)时,用户可以看到它在做什么,不再是一个"黑盒"。
|
|
14
|
+
- **出错提示**:任务异常结束时,机器人会明确告知错误原因,不再出现"半截回复"或"毫无反应"。
|
|
15
|
+
|
|
16
|
+
### 体验优化
|
|
17
|
+
|
|
18
|
+
- 群聊中正确显示发言者昵称,不再显示一串看不懂的字符。
|
|
19
|
+
- 群聊回复后自动清理历史上下文,避免多轮对话相互干扰。
|
|
20
|
+
- 语音消息识别后只保留文字,不再附带无效链接。
|
|
21
|
+
- 机器人现在会"真正动手"了:面对「下载、解压、安装」这类请求,会用工具实际执行,而不是只复述操作步骤。
|
|
22
|
+
|
|
23
|
+
### 问题修复
|
|
24
|
+
|
|
25
|
+
- 修复机器人无法读写文件的问题(此前工作目录配置错误)。
|
|
26
|
+
- 修复流式回复中可能出现的重复内容、分片过少等显示问题。
|
|
27
|
+
|
|
28
|
+
## [0.1.0] - 2026-08-14
|
|
29
|
+
|
|
30
|
+
### 新功能
|
|
31
|
+
|
|
32
|
+
- **首个版本**:QQ 机器人接入 AI 助手,支持私聊与群聊对话。
|
|
33
|
+
- **模型切换**:支持切换不同的 AI 模型。
|
|
34
|
+
- **常用指令**:内置帮助、状态查询、会话管理等指令。
|
|
35
|
+
- **扫码绑定**:首次使用扫码即可完成机器人绑定,配置简单。
|
|
36
|
+
|
|
37
|
+
### 问题修复
|
|
38
|
+
|
|
39
|
+
- 修复配置解析问题。
|
package/a.txt
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
一个让 QQ 机器人秒变 AI 智能体的插件,基于 DeepSeek Harness(dsh)构建。
|
|
2
|
+
为什么值得一试
|
|
3
|
+
零配置接入:首次启动扫码即可绑定机器人,无需折腾密钥
|
|
4
|
+
专属会话:每个用户 / 群聊独立上下文,互不串扰,重启自动恢复
|
|
5
|
+
随时切换模型:聊天里发条指令就能换模型,对话还不丢
|
|
6
|
+
群聊不打扰:支持"@机器人 才响应",安静地待着
|
|
7
|
+
|
|
8
|
+
三步上手
|
|
9
|
+
开始前,请先根据 DeepSeek Harness 官方指引完成 dsh 的初始化和模型配置,确保环境就绪。
|
|
10
|
+
|
|
11
|
+
1. 安装到 dsh profile
|
|
12
|
+
npx @deepseek-ai/dsh plugin --profile qqbot add @tencent-connect/dsh-qqbot
|
|
13
|
+
2. 启动
|
|
14
|
+
npx @deepseek-ai/dsh --profile qqbot
|
package/dist/commands/model.js
CHANGED
|
@@ -48,7 +48,7 @@ export function modelCommand({ manager, config }) {
|
|
|
48
48
|
model = args;
|
|
49
49
|
}
|
|
50
50
|
if (!provider || !model) {
|
|
51
|
-
return '用法: /bot-model provider/model\n示例: /bot-model deepseek-official/deepseek-
|
|
51
|
+
return '用法: /bot-model provider/model\n示例: /bot-model deepseek-official/deepseek-v4-flash';
|
|
52
52
|
}
|
|
53
53
|
await manager.setModelOverride(scope, peerId, { provider, model });
|
|
54
54
|
return `✅ 模型已切换: ${provider}/${model}\n立即生效,对话上下文保留。`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/commands/model.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/commands/model.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -23,8 +23,8 @@ export interface ImQQBotConfig {
|
|
|
23
23
|
model?: string;
|
|
24
24
|
/** Agent preset id */
|
|
25
25
|
preset?: string;
|
|
26
|
-
/** Agent
|
|
27
|
-
cwd
|
|
26
|
+
/** Agent 工作目录(缺省回落到进程 cwd) */
|
|
27
|
+
cwd?: string;
|
|
28
28
|
/** 是否启用群消息 @mention 门控 */
|
|
29
29
|
requireMention: boolean;
|
|
30
30
|
/** 群聊额外 system prompt */
|
|
@@ -33,6 +33,8 @@ export interface ImQQBotConfig {
|
|
|
33
33
|
directPrompt?: string;
|
|
34
34
|
/** 单条消息最大长度(QQ 限制约 5000 字符) */
|
|
35
35
|
textChunkLimit: number;
|
|
36
|
+
/** 是否启用流式输出(群聊始终不启用) */
|
|
37
|
+
streaming: boolean;
|
|
36
38
|
/** 每会话最大闲置时长(ms),超时自动回收 */
|
|
37
39
|
sessionIdleTimeout: number;
|
|
38
40
|
/** 并发队列最大长度 */
|
|
@@ -43,6 +45,8 @@ export interface ImQQBotConfig {
|
|
|
43
45
|
historyLimit: number;
|
|
44
46
|
/** 访问控制 */
|
|
45
47
|
access: AccessControlConfig;
|
|
48
|
+
/** 是否展示工具调用成功结果(工具错误始终展示) */
|
|
49
|
+
showToolResults: boolean;
|
|
46
50
|
/** 调试模式 */
|
|
47
51
|
debug: boolean;
|
|
48
52
|
}
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,MAAM,MAAM,0BAA0B,CAAC;AAE9C,MAAM,WAAW,mBAAmB;IAClC,eAAe;IACf,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;IAC3C,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa;IACb,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;IAC7C,0BAA0B;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,MAAM,MAAM,0BAA0B,CAAC;AAE9C,MAAM,WAAW,mBAAmB;IAClC,eAAe;IACf,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;IAC3C,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa;IACb,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;IAC7C,0BAA0B;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,cAAc,EAAE,OAAO,CAAC;IACxB,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,wBAAwB;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,2BAA2B;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,MAAM,EAAE,mBAAmB,CAAC;IAC5B,6BAA6B;IAC7B,eAAe,EAAE,OAAO,CAAC;IACzB,WAAW;IACX,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,aAAa,CA6B7C,CAAC"}
|
package/dist/config.js
CHANGED
|
@@ -8,11 +8,12 @@ export const ConfigSchema = Schema.object({
|
|
|
8
8
|
provider: Schema.string().description('LLM provider name'),
|
|
9
9
|
model: Schema.string().description('Model name'),
|
|
10
10
|
preset: Schema.string().description('Agent preset id'),
|
|
11
|
-
cwd: Schema.string().
|
|
11
|
+
cwd: Schema.string().description('Agent working directory'),
|
|
12
12
|
requireMention: Schema.boolean().default(true).description('群聊是否需要@bot触发'),
|
|
13
13
|
groupPrompt: Schema.string().description('群聊额外system prompt'),
|
|
14
14
|
directPrompt: Schema.string().description('私聊额外system prompt'),
|
|
15
15
|
textChunkLimit: Schema.number().default(4500).description('单条消息最大字符数'),
|
|
16
|
+
streaming: Schema.boolean().default(true).description('是否启用流式输出(群聊始终不启用)'),
|
|
16
17
|
sessionIdleTimeout: Schema.number().default(30 * 60 * 1000).description('会话闲置超时(ms)'),
|
|
17
18
|
maxQueue: Schema.number().default(20).description('并发队列最大长度'),
|
|
18
19
|
processingTimeoutMs: Schema.number().default(120000).description('处理超时(ms)'),
|
|
@@ -28,6 +29,7 @@ export const ConfigSchema = Schema.object({
|
|
|
28
29
|
groupMode: 'open',
|
|
29
30
|
groupAllow: [],
|
|
30
31
|
}).description('访问控制'),
|
|
32
|
+
showToolResults: Schema.boolean().default(false).description('是否展示工具调用成功结果(错误始终展示)'),
|
|
31
33
|
debug: Schema.boolean().default(false),
|
|
32
34
|
});
|
|
33
35
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,MAAM,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { HistoryStore } from '@tencent-connect/qqbot-nodejs';
|
|
2
|
+
/** 获取共享历史存储(单例) */
|
|
3
|
+
export declare function getHistoryStore(): HistoryStore;
|
|
4
|
+
/** 用 appId 前缀隔离群历史(单账号下等价于 groupOpenid,保留多账号扩展) */
|
|
5
|
+
export declare function historyGroupKey(appId: string, groupId: string): string;
|
|
6
|
+
/** 清空群历史(回复后调用,避免下次 @ 时重复组包) */
|
|
7
|
+
export declare function clearGroupHistory(appId: string, groupId: string): void;
|
|
8
|
+
//# sourceMappingURL=history-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-store.d.ts","sourceRoot":"","sources":["../../src/features/history-store.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAIlE,mBAAmB;AACnB,wBAAgB,eAAe,IAAI,YAAY,CAG9C;AAED,mDAAmD;AACnD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,gCAAgC;AAChC,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAEtE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 群历史存储共享模块
|
|
3
|
+
*
|
|
4
|
+
* historyBuffer 中间件需要一个跨调用可访问的 HistoryStore 实例,
|
|
5
|
+
* 以便在回复完成后清空某群的历史缓存(避免下次 @ 时重复组包)。
|
|
6
|
+
* 对齐 openclaw-qqbot 的 features/history-store。
|
|
7
|
+
*/
|
|
8
|
+
import { MemoryHistoryStore } from '@tencent-connect/qqbot-nodejs';
|
|
9
|
+
let _store = null;
|
|
10
|
+
/** 获取共享历史存储(单例) */
|
|
11
|
+
export function getHistoryStore() {
|
|
12
|
+
if (!_store)
|
|
13
|
+
_store = new MemoryHistoryStore();
|
|
14
|
+
return _store;
|
|
15
|
+
}
|
|
16
|
+
/** 用 appId 前缀隔离群历史(单账号下等价于 groupOpenid,保留多账号扩展) */
|
|
17
|
+
export function historyGroupKey(appId, groupId) {
|
|
18
|
+
return `${appId}:${groupId}`;
|
|
19
|
+
}
|
|
20
|
+
/** 清空群历史(回复后调用,避免下次 @ 时重复组包) */
|
|
21
|
+
export function clearGroupHistory(appId, groupId) {
|
|
22
|
+
_store?.clear?.(historyGroupKey(appId, groupId));
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=history-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-store.js","sourceRoot":"","sources":["../../src/features/history-store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,IAAI,MAAM,GAAwB,IAAI,CAAC;AAEvC,mBAAmB;AACnB,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,MAAM;QAAE,MAAM,GAAG,IAAI,kBAAkB,EAAE,CAAC;IAC/C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,OAAe;IAC5D,OAAO,GAAG,KAAK,IAAI,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED,gCAAgC;AAChC,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,OAAe;IAC9D,MAAM,EAAE,KAAK,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 网关组装 — 创建 bot、编排中间件、注册事件、出站、生命周期
|
|
3
|
+
*
|
|
4
|
+
* 将 QQ 消息平台作为 dsh 前端协议驱动:入站消息 → handleInbound → dsh agent,
|
|
5
|
+
* dsh session/event → createOutboundHandler → QQ 出站。
|
|
6
|
+
*/
|
|
7
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
8
|
+
import { type DshAgentRegistry } from '../session/index.js';
|
|
9
|
+
import type { ImQQBotConfig } from '../config.js';
|
|
10
|
+
import type { Logger } from '../types.js';
|
|
11
|
+
export declare function bootstrapGateway(ctx: Context, agents: DshAgentRegistry, config: ImQQBotConfig, logger: Logger): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=bootstrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/gateway/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAK5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAyEf"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { QQBot } from '@tencent-connect/qqbot-nodejs';
|
|
2
|
+
import { SessionManager } from '../session/index.js';
|
|
3
|
+
import { handleInbound, createOutboundHandler } from '../transport/index.js';
|
|
4
|
+
import { buildUserAgent } from '../shared/index.js';
|
|
5
|
+
import { setupMiddlewares } from './middleware-setup.js';
|
|
6
|
+
export async function bootstrapGateway(ctx, agents, config, logger) {
|
|
7
|
+
const manager = new SessionManager(ctx, agents, config, logger);
|
|
8
|
+
// ── 初始化 QQ Bot SDK ──
|
|
9
|
+
const userAgent = buildUserAgent();
|
|
10
|
+
const bot = new QQBot({
|
|
11
|
+
appId: config.appId,
|
|
12
|
+
appSecret: config.appSecret,
|
|
13
|
+
transport: 'websocket',
|
|
14
|
+
userAgent,
|
|
15
|
+
logger,
|
|
16
|
+
});
|
|
17
|
+
logger.info(`QQBot SDK initialized (UA: ${userAgent})`);
|
|
18
|
+
// ── 中间件链 ──
|
|
19
|
+
setupMiddlewares(bot, config, manager, logger);
|
|
20
|
+
// ── 入站:经过中间件链后的消息交给 dsh agent ──
|
|
21
|
+
bot.on('message', async (mCtx) => {
|
|
22
|
+
const msg = mCtx.message;
|
|
23
|
+
if (config.debug) {
|
|
24
|
+
logger.debug(`← message (post-middleware): ${JSON.stringify(msg, null, 2).slice(0, 500)}`);
|
|
25
|
+
}
|
|
26
|
+
await handleInbound(msg, manager, config, logger, mCtx.state);
|
|
27
|
+
});
|
|
28
|
+
// ── 出站:dsh session/event → QQ 消息 ──
|
|
29
|
+
// 获取 tools 服务(工具结果结构化展示,参考 dsh-TUI presentResult),可选
|
|
30
|
+
let toolsRegistry;
|
|
31
|
+
try {
|
|
32
|
+
toolsRegistry = ctx.get('tools');
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
toolsRegistry = undefined;
|
|
36
|
+
}
|
|
37
|
+
// 发送适配器:将 QQBot 实例适配为 QQBotSender(openStream 参数形态不同)
|
|
38
|
+
const sender = {
|
|
39
|
+
sendMarkdown: (target, content) => bot.sendMarkdown(target, content),
|
|
40
|
+
openStream: (target) => bot.openStream({
|
|
41
|
+
target: {
|
|
42
|
+
scope: target.scope,
|
|
43
|
+
targetId: target.targetId,
|
|
44
|
+
msgId: target.msgId,
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
};
|
|
48
|
+
const outboundHandler = createOutboundHandler(manager, sender, config, logger, toolsRegistry);
|
|
49
|
+
ctx
|
|
50
|
+
.on('session/event', outboundHandler);
|
|
51
|
+
bot.on('error', (err) => {
|
|
52
|
+
logger.error(`bot error: ${err instanceof Error ? err.message : String(err)}`);
|
|
53
|
+
});
|
|
54
|
+
bot.on('ready', () => {
|
|
55
|
+
console.log(`[im-qqbot] Bot ready! appId=${config.appId}`);
|
|
56
|
+
});
|
|
57
|
+
// ── 生命周期 ──
|
|
58
|
+
ctx
|
|
59
|
+
.effect(() => {
|
|
60
|
+
logger.info(`Starting bot (appId=${config.appId})`);
|
|
61
|
+
bot.start().catch((err) => {
|
|
62
|
+
logger.error(`Bot start failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
63
|
+
});
|
|
64
|
+
return async () => {
|
|
65
|
+
logger.info('Shutting down');
|
|
66
|
+
await manager.disposeAll();
|
|
67
|
+
bot.stop();
|
|
68
|
+
};
|
|
69
|
+
}, 'im-qqbot.lifecycle');
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/gateway/bootstrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gateway/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gateway/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK 中间件编排
|
|
3
|
+
*
|
|
4
|
+
* 根据插件配置组装 SDK 内置中间件链(洋葱模型)。
|
|
5
|
+
* 中间件负责过滤与上下文富化;最终消息统一由 bot.on('message') 处理转发。
|
|
6
|
+
*/
|
|
7
|
+
import type { QQBot } from '@tencent-connect/qqbot-nodejs';
|
|
8
|
+
import type { ImQQBotConfig } from '../config.js';
|
|
9
|
+
import type { SessionManager } from '../session/index.js';
|
|
10
|
+
import type { Logger } from '../types.js';
|
|
11
|
+
export declare function setupMiddlewares(bot: QQBot, config: ImQQBotConfig, manager: SessionManager, logger: Logger): void;
|
|
12
|
+
//# sourceMappingURL=middleware-setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware-setup.d.ts","sourceRoot":"","sources":["../../src/gateway/middleware-setup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,KAAK,EAAqB,MAAM,+BAA+B,CAAC;AAe9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAK1C,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,KAAK,EACV,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,MAAM,GACb,IAAI,CAqFN"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { errorHandler, messageFilter, accessPolicy, mentionGate, contentSanitizer, rateLimiter, slashCommand, concurrencyGuard, typingIndicator, quoteRef, historyBuffer, envelopeFormatter, } from '@tencent-connect/qqbot-nodejs';
|
|
2
|
+
import { buildCommandList } from '../commands/index.js';
|
|
3
|
+
import { attachmentProcessor } from '../middleware/attachment.js';
|
|
4
|
+
import { getHistoryStore, historyGroupKey } from '../features/history-store.js';
|
|
5
|
+
export function setupMiddlewares(bot, config, manager, logger) {
|
|
6
|
+
// 1. 错误兜底(最外层洋葱皮)
|
|
7
|
+
bot.use(errorHandler());
|
|
8
|
+
// 2. 消息过滤:bot 回声 + 消息去重
|
|
9
|
+
bot.use(messageFilter({ skipSelfEcho: false }));
|
|
10
|
+
// 3. 访问控制(白名单/开放/禁用)
|
|
11
|
+
bot.use(accessPolicy({
|
|
12
|
+
c2c: {
|
|
13
|
+
mode: config.access.c2cMode,
|
|
14
|
+
allow: config.access.c2cAllow.length > 0 ? config.access.c2cAllow : ['*'],
|
|
15
|
+
},
|
|
16
|
+
group: {
|
|
17
|
+
mode: config.access.groupMode,
|
|
18
|
+
allow: config.access.groupAllow.length > 0 ? config.access.groupAllow : ['*'],
|
|
19
|
+
},
|
|
20
|
+
onBlock: (_mCtx, reason) => {
|
|
21
|
+
if (config.debug) {
|
|
22
|
+
logger.debug(`Access blocked: ${reason}`);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
}));
|
|
26
|
+
// 4. 群历史缓冲 — 放在门控之前,确保所有消息(含未 @bot)都计入上下文
|
|
27
|
+
// store 走共享单例(getHistoryStore),groupKey 带 appId 前缀,供回复后清空
|
|
28
|
+
bot.use(historyBuffer({
|
|
29
|
+
limit: config.historyLimit,
|
|
30
|
+
store: getHistoryStore(),
|
|
31
|
+
recordOnSkip: true,
|
|
32
|
+
groupKey: (ctx) => {
|
|
33
|
+
const gid = ctx.message.groupOpenid;
|
|
34
|
+
if (ctx.message.kind !== 'group' || !gid)
|
|
35
|
+
return undefined;
|
|
36
|
+
return historyGroupKey(config.appId, gid);
|
|
37
|
+
},
|
|
38
|
+
}));
|
|
39
|
+
// 5. 群聊 @bot 门控
|
|
40
|
+
bot.use(mentionGate({
|
|
41
|
+
requireMentionInGroup: config.requireMention,
|
|
42
|
+
}));
|
|
43
|
+
// 6. 内容清洗(去 @marker、表情标签、多余空白)
|
|
44
|
+
bot.use(contentSanitizer({
|
|
45
|
+
parseFaceTags: true,
|
|
46
|
+
}));
|
|
47
|
+
// 7. 三层限流(sender / group / global)
|
|
48
|
+
bot.use(rateLimiter());
|
|
49
|
+
// 8. 斜杠命令(在 concurrencyGuard 之前,命令匹配后不排队直接响应)
|
|
50
|
+
const slash = slashCommand({
|
|
51
|
+
autoHelp: true,
|
|
52
|
+
commands: buildCommandList({ manager, config }),
|
|
53
|
+
});
|
|
54
|
+
bot.use(slash.middleware);
|
|
55
|
+
// 9. 并发串行 + 消息合并(同 peer 排队,避免 session 冲突)
|
|
56
|
+
bot.use(concurrencyGuard({
|
|
57
|
+
strategy: 'merge',
|
|
58
|
+
maxQueue: config.maxQueue,
|
|
59
|
+
maxProcessingMs: config.processingTimeoutMs,
|
|
60
|
+
urgentPredicate: (mCtx) => {
|
|
61
|
+
return (mCtx.message.content ?? '').trim() === '/bot-stop';
|
|
62
|
+
},
|
|
63
|
+
}));
|
|
64
|
+
// 10. C2C 输入状态指示
|
|
65
|
+
bot.use(typingIndicator());
|
|
66
|
+
// 11. 引用消息解析(记录 + 解析被引用原文)
|
|
67
|
+
bot.use(quoteRef({
|
|
68
|
+
maxSize: 500,
|
|
69
|
+
preferMsgElements: true,
|
|
70
|
+
}));
|
|
71
|
+
// 11.5. 附件下载(file 附件下载到本地,供 @提及 / 工具访问)
|
|
72
|
+
bot.use(attachmentProcessor(config, logger));
|
|
73
|
+
// 12. 上下文组装(将 history + quote + sender 组成 envelope)
|
|
74
|
+
bot.use(envelopeFormatter({
|
|
75
|
+
historyLimit: config.historyLimit,
|
|
76
|
+
includeQuote: true,
|
|
77
|
+
includeSender: true,
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=middleware-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware-setup.js","sourceRoot":"","sources":["../../src/gateway/middleware-setup.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* dsh-im-qqbot — QQ Bot IM channel plugin for deepseek-harness
|
|
3
3
|
*
|
|
4
4
|
* Cordis 插件入口。将 QQ 消息平台作为 dsh 的前端协议驱动。
|
|
5
|
-
*
|
|
5
|
+
* 网关组装(中间件编排 + 事件 + 出站 + 生命周期)见 src/gateway/。
|
|
6
6
|
*/
|
|
7
7
|
import type { Context } from '@deepseek-ai/cordis';
|
|
8
8
|
import { type ImQQBotConfig } from './config.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAQ/D,eAAO,MAAM,IAAI,aAAa,CAAC;AAC/B,eAAO,MAAM,MAAM,UAAa,CAAC;AACjC,eAAO,MAAM,MAAM,2DAAe,CAAC;AAEnC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAmC9E"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import { QQBot, errorHandler, messageFilter, accessPolicy, mentionGate, contentSanitizer, rateLimiter, slashCommand, concurrencyGuard, typingIndicator, quoteRef, historyBuffer, envelopeFormatter, MemoryHistoryStore, } from '@tencent-connect/qqbot-nodejs';
|
|
2
1
|
import { ConfigSchema } from './config.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { buildCommandList } from './commands/index.js';
|
|
6
|
-
import { getProfileDir, resolveEnv, buildUserAgent } from './shared/index.js';
|
|
2
|
+
import { bootstrapGateway } from './gateway/index.js';
|
|
3
|
+
import { getProfileDir, resolveEnv } from './shared/index.js';
|
|
7
4
|
import { runQrSetup, persistCredentialsToProfile } from './setup.js';
|
|
8
5
|
// ── Cordis 插件元数据 ──
|
|
9
6
|
export const name = 'im-qqbot';
|
|
@@ -35,120 +32,6 @@ export async function apply(ctx, config) {
|
|
|
35
32
|
return;
|
|
36
33
|
}
|
|
37
34
|
const resolvedConfig = { ...config, appId, appSecret };
|
|
38
|
-
await
|
|
39
|
-
}
|
|
40
|
-
async function bootstrap(ctx, agents, config, logger) {
|
|
41
|
-
const manager = new SessionManager(ctx, agents, config, logger);
|
|
42
|
-
// ── 初始化 QQ Bot SDK ──
|
|
43
|
-
const userAgent = buildUserAgent();
|
|
44
|
-
const bot = new QQBot({
|
|
45
|
-
appId: config.appId,
|
|
46
|
-
appSecret: config.appSecret,
|
|
47
|
-
transport: 'websocket',
|
|
48
|
-
userAgent,
|
|
49
|
-
logger,
|
|
50
|
-
});
|
|
51
|
-
logger.info(`QQBot SDK initialized (UA: ${userAgent})`);
|
|
52
|
-
// ══════════════════════════════════════════════════════════════
|
|
53
|
-
// SDK 中间件链(洋葱模型,按执行顺序编排)
|
|
54
|
-
// ══════════════════════════════════════════════════════════════
|
|
55
|
-
// 1. 错误兜底(最外层洋葱皮)
|
|
56
|
-
bot.use(errorHandler());
|
|
57
|
-
// 2. 消息过滤:bot 回声 + 消息去重
|
|
58
|
-
bot.use(messageFilter({ skipSelfEcho: false }));
|
|
59
|
-
// 3. 访问控制(白名单/开放/禁用)
|
|
60
|
-
bot.use(accessPolicy({
|
|
61
|
-
c2c: {
|
|
62
|
-
mode: config.access.c2cMode,
|
|
63
|
-
allow: config.access.c2cAllow.length > 0 ? config.access.c2cAllow : ['*'],
|
|
64
|
-
},
|
|
65
|
-
group: {
|
|
66
|
-
mode: config.access.groupMode,
|
|
67
|
-
allow: config.access.groupAllow.length > 0 ? config.access.groupAllow : ['*'],
|
|
68
|
-
},
|
|
69
|
-
onBlock: (_mCtx, reason) => {
|
|
70
|
-
if (config.debug) {
|
|
71
|
-
logger.debug(`Access blocked: ${reason}`);
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
}));
|
|
75
|
-
// 4. 群历史缓冲 — 放在门控之前,确保所有消息(含未 @bot)都计入上下文
|
|
76
|
-
const historyStore = new MemoryHistoryStore();
|
|
77
|
-
bot.use(historyBuffer({
|
|
78
|
-
limit: config.historyLimit,
|
|
79
|
-
store: historyStore,
|
|
80
|
-
recordOnSkip: true,
|
|
81
|
-
}));
|
|
82
|
-
// 5. 群聊 @bot 门控
|
|
83
|
-
bot.use(mentionGate({
|
|
84
|
-
requireMentionInGroup: config.requireMention,
|
|
85
|
-
}));
|
|
86
|
-
// 6. 内容清洗(去 @marker、表情标签、多余空白)
|
|
87
|
-
bot.use(contentSanitizer({
|
|
88
|
-
parseFaceTags: true,
|
|
89
|
-
}));
|
|
90
|
-
// 7. 三层限流(sender / group / global)
|
|
91
|
-
bot.use(rateLimiter());
|
|
92
|
-
// 8. 斜杠命令(在 concurrencyGuard 之前,命令匹配后不排队直接响应)
|
|
93
|
-
const slash = slashCommand({
|
|
94
|
-
autoHelp: true,
|
|
95
|
-
commands: buildCommandList({ manager, config }),
|
|
96
|
-
});
|
|
97
|
-
bot.use(slash.middleware);
|
|
98
|
-
// 9. 并发串行 + 消息合并(同 peer 排队,避免 session 冲突)
|
|
99
|
-
bot.use(concurrencyGuard({
|
|
100
|
-
strategy: 'merge',
|
|
101
|
-
maxQueue: config.maxQueue,
|
|
102
|
-
maxProcessingMs: config.processingTimeoutMs,
|
|
103
|
-
urgentPredicate: (mCtx) => {
|
|
104
|
-
return (mCtx.message.content ?? '').trim() === '/bot-stop';
|
|
105
|
-
},
|
|
106
|
-
}));
|
|
107
|
-
// 10. C2C 输入状态指示
|
|
108
|
-
bot.use(typingIndicator());
|
|
109
|
-
// 11. 引用消息解析(记录 + 解析被引用原文)
|
|
110
|
-
bot.use(quoteRef({
|
|
111
|
-
maxSize: 500,
|
|
112
|
-
preferMsgElements: true,
|
|
113
|
-
}));
|
|
114
|
-
// 12. 上下文组装(将 history + quote + sender 组成 envelope)
|
|
115
|
-
bot.use(envelopeFormatter({
|
|
116
|
-
historyLimit: config.historyLimit,
|
|
117
|
-
includeQuote: true,
|
|
118
|
-
includeSender: true,
|
|
119
|
-
}));
|
|
120
|
-
// ══════════════════════════════════════════════════════════════
|
|
121
|
-
// 最终处理:经过中间件链后的消息交给 dsh agent
|
|
122
|
-
// ══════════════════════════════════════════════════════════════
|
|
123
|
-
bot.on('message', async (mCtx) => {
|
|
124
|
-
const msg = mCtx.message;
|
|
125
|
-
if (config.debug) {
|
|
126
|
-
logger.debug(`← message (post-middleware): ${JSON.stringify(msg, null, 2).slice(0, 500)}`);
|
|
127
|
-
}
|
|
128
|
-
await handleInbound(msg, manager, config, logger, mCtx.state);
|
|
129
|
-
});
|
|
130
|
-
// ── 出站 ──
|
|
131
|
-
const outboundHandler = createOutboundHandler(manager, bot, config, logger);
|
|
132
|
-
ctx
|
|
133
|
-
.on('session/event', outboundHandler);
|
|
134
|
-
bot.on('error', (err) => {
|
|
135
|
-
logger.error(`bot error: ${err instanceof Error ? err.message : String(err)}`);
|
|
136
|
-
});
|
|
137
|
-
bot.on('ready', () => {
|
|
138
|
-
console.log(`[im-qqbot] Bot ready! appId=${config.appId}`);
|
|
139
|
-
});
|
|
140
|
-
// ── 生命周期 ──
|
|
141
|
-
ctx
|
|
142
|
-
.effect(() => {
|
|
143
|
-
logger.info(`Starting bot (appId=${config.appId})`);
|
|
144
|
-
bot.start().catch((err) => {
|
|
145
|
-
logger.error(`Bot start failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
146
|
-
});
|
|
147
|
-
return async () => {
|
|
148
|
-
logger.info('Shutting down');
|
|
149
|
-
await manager.disposeAll();
|
|
150
|
-
bot.stop();
|
|
151
|
-
};
|
|
152
|
-
}, 'im-qqbot.lifecycle');
|
|
35
|
+
await bootstrapGateway(ctx, agents, resolvedConfig, logger);
|
|
153
36
|
}
|
|
154
37
|
//# sourceMappingURL=index.js.map
|