@tencent-connect/dsh-qqbot 0.1.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.
Files changed (126) hide show
  1. package/.orange-ci.yml +68 -0
  2. package/LICENSE +21 -0
  3. package/README.md +142 -0
  4. package/README_EN.md +142 -0
  5. package/cordis.patch.yml +32 -0
  6. package/cordis.yml +69 -0
  7. package/dist/commands/help.d.ts +11 -0
  8. package/dist/commands/help.d.ts.map +1 -0
  9. package/dist/commands/help.js +21 -0
  10. package/dist/commands/help.js.map +1 -0
  11. package/dist/commands/index.d.ts +13 -0
  12. package/dist/commands/index.d.ts.map +1 -0
  13. package/dist/commands/index.js +27 -0
  14. package/dist/commands/index.js.map +1 -0
  15. package/dist/commands/misc.d.ts +12 -0
  16. package/dist/commands/misc.d.ts.map +1 -0
  17. package/dist/commands/misc.js +30 -0
  18. package/dist/commands/misc.js.map +1 -0
  19. package/dist/commands/model.d.ts +7 -0
  20. package/dist/commands/model.d.ts.map +1 -0
  21. package/dist/commands/model.js +58 -0
  22. package/dist/commands/model.js.map +1 -0
  23. package/dist/commands/session.d.ts +10 -0
  24. package/dist/commands/session.d.ts.map +1 -0
  25. package/dist/commands/session.js +26 -0
  26. package/dist/commands/session.js.map +1 -0
  27. package/dist/commands/status.d.ts +8 -0
  28. package/dist/commands/status.d.ts.map +1 -0
  29. package/dist/commands/status.js +24 -0
  30. package/dist/commands/status.js.map +1 -0
  31. package/dist/commands/types.d.ts +12 -0
  32. package/dist/commands/types.d.ts.map +1 -0
  33. package/dist/commands/types.js +2 -0
  34. package/dist/commands/types.js.map +1 -0
  35. package/dist/config.d.ts +50 -0
  36. package/dist/config.d.ts.map +1 -0
  37. package/dist/config.js +33 -0
  38. package/dist/config.js.map +1 -0
  39. package/dist/index.d.ts +14 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +154 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/model/index.d.ts +10 -0
  44. package/dist/model/index.d.ts.map +1 -0
  45. package/dist/model/index.js +9 -0
  46. package/dist/model/index.js.map +1 -0
  47. package/dist/model/model-resolver.d.ts +82 -0
  48. package/dist/model/model-resolver.d.ts.map +1 -0
  49. package/dist/model/model-resolver.js +142 -0
  50. package/dist/model/model-resolver.js.map +1 -0
  51. package/dist/model/prefs-store.d.ts +24 -0
  52. package/dist/model/prefs-store.d.ts.map +1 -0
  53. package/dist/model/prefs-store.js +94 -0
  54. package/dist/model/prefs-store.js.map +1 -0
  55. package/dist/model/settings-reader.d.ts +19 -0
  56. package/dist/model/settings-reader.d.ts.map +1 -0
  57. package/dist/model/settings-reader.js +76 -0
  58. package/dist/model/settings-reader.js.map +1 -0
  59. package/dist/model/types.d.ts +15 -0
  60. package/dist/model/types.d.ts.map +1 -0
  61. package/dist/model/types.js +5 -0
  62. package/dist/model/types.js.map +1 -0
  63. package/dist/session/idle-evictor.d.ts +18 -0
  64. package/dist/session/idle-evictor.d.ts.map +1 -0
  65. package/dist/session/idle-evictor.js +31 -0
  66. package/dist/session/idle-evictor.js.map +1 -0
  67. package/dist/session/index.d.ts +9 -0
  68. package/dist/session/index.d.ts.map +1 -0
  69. package/dist/session/index.js +8 -0
  70. package/dist/session/index.js.map +1 -0
  71. package/dist/session/session-manager.d.ts +44 -0
  72. package/dist/session/session-manager.d.ts.map +1 -0
  73. package/dist/session/session-manager.js +341 -0
  74. package/dist/session/session-manager.js.map +1 -0
  75. package/dist/session/types.d.ts +124 -0
  76. package/dist/session/types.d.ts.map +1 -0
  77. package/dist/session/types.js +2 -0
  78. package/dist/session/types.js.map +1 -0
  79. package/dist/setup.d.ts +24 -0
  80. package/dist/setup.d.ts.map +1 -0
  81. package/dist/setup.js +135 -0
  82. package/dist/setup.js.map +1 -0
  83. package/dist/shared/index.d.ts +7 -0
  84. package/dist/shared/index.d.ts.map +1 -0
  85. package/dist/shared/index.js +7 -0
  86. package/dist/shared/index.js.map +1 -0
  87. package/dist/shared/scope.d.ts +14 -0
  88. package/dist/shared/scope.d.ts.map +1 -0
  89. package/dist/shared/scope.js +12 -0
  90. package/dist/shared/scope.js.map +1 -0
  91. package/dist/shared/send-helper.d.ts +11 -0
  92. package/dist/shared/send-helper.d.ts.map +1 -0
  93. package/dist/shared/send-helper.js +13 -0
  94. package/dist/shared/send-helper.js.map +1 -0
  95. package/dist/shared/utils.d.ts +19 -0
  96. package/dist/shared/utils.d.ts.map +1 -0
  97. package/dist/shared/utils.js +66 -0
  98. package/dist/shared/utils.js.map +1 -0
  99. package/dist/transport/chunker.d.ts +14 -0
  100. package/dist/transport/chunker.d.ts.map +1 -0
  101. package/dist/transport/chunker.js +78 -0
  102. package/dist/transport/chunker.js.map +1 -0
  103. package/dist/transport/inbound.d.ts +8 -0
  104. package/dist/transport/inbound.d.ts.map +1 -0
  105. package/dist/transport/inbound.js +223 -0
  106. package/dist/transport/inbound.js.map +1 -0
  107. package/dist/transport/index.d.ts +10 -0
  108. package/dist/transport/index.d.ts.map +1 -0
  109. package/dist/transport/index.js +10 -0
  110. package/dist/transport/index.js.map +1 -0
  111. package/dist/transport/outbound-buffer.d.ts +32 -0
  112. package/dist/transport/outbound-buffer.d.ts.map +1 -0
  113. package/dist/transport/outbound-buffer.js +65 -0
  114. package/dist/transport/outbound-buffer.js.map +1 -0
  115. package/dist/transport/outbound.d.ts +26 -0
  116. package/dist/transport/outbound.d.ts.map +1 -0
  117. package/dist/transport/outbound.js +92 -0
  118. package/dist/transport/outbound.js.map +1 -0
  119. package/dist/types.d.ts +34 -0
  120. package/dist/types.d.ts.map +1 -0
  121. package/dist/types.js +5 -0
  122. package/dist/types.js.map +1 -0
  123. package/install.sh +108 -0
  124. package/package.json +75 -0
  125. package/pnpm-workspace.yaml +16 -0
  126. package/scripts/prepare-test-pkg.js +23 -0
package/.orange-ci.yml ADDED
@@ -0,0 +1,68 @@
1
+ $:
2
+ tag_push:
3
+ - services:
4
+ - docker
5
+ docker:
6
+ image: node:24
7
+ runner:
8
+ network: devnet
9
+ stages:
10
+ - name: 安装依赖
11
+ script: npm install
12
+ - name: 构建项目
13
+ script: npm run build
14
+ - name: 配置 npm 官方源
15
+ script: npm config set registry https://registry.npmjs.org
16
+ - name: 配置 token
17
+ imports: https://git.woa.com/qq-ai/web/secret/blob/master/envs/npm/npmjs.txt
18
+ script: npm config set //registry.npmjs.org/:_authToken=$NPM_TOKEN
19
+ - name: 设置 npm 包版本号
20
+ script: npm version ${ORANGE_BRANCH} --no-git-tag-version --allow-same-version
21
+ - name: 发布 npm 包
22
+ script: npm publish --access public
23
+ - name: 生成通知
24
+ script: echo "@tencent-connect/dsh-qqbot@${ORANGE_BRANCH} 发布成功" > message.txt
25
+ - name: 发送通知
26
+ type: wework:message
27
+ options:
28
+ fromFile: message.txt
29
+
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
42
+
43
+ # ── feat/fix 分支 push:内网发布 dev 版本 ──
44
+ (feat|fix)/**:
45
+ push:
46
+ - docker:
47
+ image: node:24
48
+ runner:
49
+ network: devnet
50
+ stages:
51
+ - name: 安装依赖
52
+ script: npm install
53
+ - name: 构建项目
54
+ script: npm run build
55
+ - name: 设置测试包名
56
+ script: npm run ci:prepare-test-pkg
57
+ - name: 设置测试版本
58
+ script: npm version "0.0.0-dev.${ORANGE_COMMIT_SHORT}" --no-git-tag-version
59
+ - name: 发布 npm 包
60
+ image: tencentcom/npm:latest
61
+ imports: https://git.woa.com/qq-ai/web/secret/blob/master/envs/npm/public.txt
62
+ settings:
63
+ username: $USER
64
+ password: $PWD
65
+ email: $EMAIL
66
+ registry: https://mirrors.tencent.com/npm/
67
+ folder: ./
68
+ tag: dev
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tencent Connect
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # @tencent-connect/dsh-qqbot
2
+
3
+ 基于 [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) (dsh) 的 QQ Bot IM 插件,将 QQ 消息平台作为 dsh agent 的前端协议驱动。
4
+
5
+ 中文 | [English](./README_EN.md)
6
+
7
+ ## 架构
8
+
9
+ ```
10
+ QQ 用户 → QQ WebSocket → dsh-im-qqbot → ctx.agents → dsh agent loop → LLM
11
+ ↑ │
12
+ └── session/event ──────────┘
13
+ (assistant reply → QQ sendMarkdown)
14
+ ```
15
+
16
+ ## 安装
17
+
18
+ ### 方式一:手动执行
19
+
20
+ ```bash
21
+ # 安装到 profile
22
+ dsh plugin --profile qqbot add @tencent-connect/dsh-qqbot
23
+
24
+ # 启动
25
+ dsh --profile qqbot
26
+ ```
27
+
28
+ 首次启动时,插件检测到凭据未配置会自动进入扫码引导:终端输出二维码 → 手机 QQ 扫码绑定 → 凭据自动保存到 profile,后续启动无需再次扫码。
29
+
30
+ ### 方式二:本地路径安装
31
+
32
+ ```bash
33
+ # 构建
34
+ cd /path/to/dsh-qqbot
35
+ pnpm install && pnpm build
36
+
37
+ # 安装到 profile(本地路径)
38
+ dsh plugin --profile qqbot add /path/to/dsh-qqbot
39
+
40
+ # 启动
41
+ export QQBOT_APPID="你的AppID" QQBOT_SECRET="你的AppSecret"
42
+ dsh --profile qqbot
43
+ ```
44
+
45
+ ### 方式三:--patch 开发模式
46
+
47
+ ```bash
48
+ cd /path/to/deepseek-harness
49
+ export QQBOT_APPID="你的AppID" QQBOT_SECRET="你的AppSecret"
50
+ pnpm dsh web --patch /path/to/dsh-qqbot/cordis.dev.yml
51
+ ```
52
+
53
+ ## 配置项
54
+
55
+ | 配置 | 类型 | 默认值 | 说明 |
56
+ |------|------|--------|------|
57
+ | `appId` | string | **必填** | QQ Bot AppID(或通过 `QQBOT_APPID` 环境变量) |
58
+ | `appSecret` | string | **必填** | QQ Bot AppSecret(或通过 `QQBOT_SECRET` 环境变量) |
59
+ | `provider` | string | `deepseek-official` | LLM 提供商名称 |
60
+ | `model` | string | `deepseek-chat` | 模型名称 |
61
+ | `preset` | string | - | Agent preset id |
62
+ | `cwd` | string | `process.cwd()` | Agent 工作目录 |
63
+ | `requireMention` | boolean | `true` | 群聊是否需要 @bot 才触发 |
64
+ | `groupPrompt` | string | - | 群聊额外 system prompt |
65
+ | `directPrompt` | string | - | 私聊额外 system prompt |
66
+ | `textChunkLimit` | number | `4500` | 单条消息最大字符数 |
67
+ | `sessionIdleTimeout` | number | `1800000` | 会话闲置超时(ms),默认 30 分钟 |
68
+ | `debug` | boolean | `false` | 调试模式 |
69
+
70
+ ## 内置命令
71
+
72
+ | 命令 | 说明 |
73
+ |------|------|
74
+ | `/bot-reset` | 重置当前会话(清除上下文) |
75
+ | `/bot-model` | 查看或切换模型 |
76
+ | `/bot-status` | 查看当前会话状态 |
77
+ | `/bot-help` | 查看所有指令 |
78
+
79
+ ## 核心模块
80
+
81
+ ```
82
+ src/
83
+ ├── index.ts # Cordis 插件入口(async apply)
84
+ ├── config.ts # 配置 Schema
85
+ ├── types.ts # 全局类型定义
86
+ ├── setup.ts # 凭据绑定(扫码)
87
+ ├── transport/ # 传输层
88
+ │ ├── inbound.ts # QQ 入站消息 → agent.followup()
89
+ │ ├── outbound.ts # session/event → QQ sendMarkdown
90
+ │ ├── outbound-buffer.ts # 流式缓冲
91
+ │ └── chunker.ts # Markdown 文本切分
92
+ ├── session/ # 会话管理层
93
+ │ ├── session-manager.ts # QQ peer → Agent 映射
94
+ │ └── idle-evictor.ts # 闲置回收
95
+ ├── model/ # 模型路由层
96
+ │ ├── model-resolver.ts # 路由解析
97
+ │ ├── prefs-store.ts # per-peer 偏好持久化
98
+ │ └── settings-reader.ts # settings.yaml 只读
99
+ ├── shared/ # 共享工具
100
+ │ ├── utils.ts # 通用函数
101
+ │ ├── scope.ts # scope/peer 提取
102
+ │ └── send-helper.ts # 分块发送
103
+ ├── commands/ # 斜杠命令
104
+ └── typings/ # 外部模块声明
105
+ ```
106
+
107
+ ## 会话路由
108
+
109
+ sessionKey: `qqbot:${appId}:${scope}:${peerId}`,由 SHA-256 确定性派生 SessionId,重启后可恢复。
110
+
111
+ 解析策略:进程内复用 → 持久化恢复 → 全新创建。
112
+
113
+ ## 设计原则
114
+
115
+ - **纯 Cordis 插件** — 遵循 dsh "Plugins, not loop changes" 原则
116
+ - **声明式依赖** — `inject = ['agents']`,不直接耦合其他插件
117
+ - **会话隔离** — 每个 QQ 私聊用户/群聊各一个独立 Agent
118
+ - **Preset 支持** — 可通过 `agent-presets` 服务挂载预设(工具集、prompt 等)
119
+ - **闲置回收** — 超时自动 dispose Agent,防止内存泄漏
120
+ - **Markdown 输出** — 回复以 Markdown 格式发送,支持代码块/表格感知切分
121
+
122
+ ## 本地开发
123
+
124
+ ```bash
125
+ # 安装依赖
126
+ pnpm install
127
+
128
+ # 构建
129
+ pnpm build
130
+
131
+ # 开发模式(watch)
132
+ pnpm dev
133
+
134
+ # 用 --patch 方式调试(在 dsh monorepo 中)
135
+ cd /path/to/deepseek-harness
136
+ export QQBOT_APPID="xxx" QQBOT_SECRET="xxx"
137
+ pnpm dsh web --patch /path/to/dsh-qqbot/cordis.dev.yml
138
+ ```
139
+
140
+ ## License
141
+
142
+ [MIT](./LICENSE)
package/README_EN.md ADDED
@@ -0,0 +1,142 @@
1
+ # @tencent-connect/dsh-qqbot
2
+
3
+ A QQ Bot IM plugin for [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) (dsh), driving the dsh agent loop with the QQ messaging platform as the frontend protocol.
4
+
5
+ [中文文档](./README.md) | English
6
+
7
+ ## Architecture
8
+
9
+ ```
10
+ QQ User → QQ WebSocket → dsh-im-qqbot → ctx.agents → dsh agent loop → LLM
11
+ ↑ │
12
+ └── session/event ──────────┘
13
+ (assistant reply → QQ sendMarkdown)
14
+ ```
15
+
16
+ ## Installation
17
+
18
+ ### Method 1: Manual
19
+
20
+ ```bash
21
+ # Add to a profile
22
+ dsh plugin --profile qqbot add @tencent-connect/dsh-qqbot
23
+
24
+ # Start
25
+ dsh --profile qqbot
26
+ ```
27
+
28
+ On first launch, the plugin detects missing credentials and automatically starts the QR flow: a QR code is printed in the terminal → scan it with the QQ mobile app → credentials are saved to the profile, so subsequent launches require no re-scan.
29
+
30
+ ### Method 2: Local path
31
+
32
+ ```bash
33
+ # Build
34
+ cd /path/to/dsh-qqbot
35
+ pnpm install && pnpm build
36
+
37
+ # Add to a profile (local path)
38
+ dsh plugin --profile qqbot add /path/to/dsh-qqbot
39
+
40
+ # Start
41
+ export QQBOT_APPID="yourAppID" QQBOT_SECRET="yourAppSecret"
42
+ dsh --profile qqbot
43
+ ```
44
+
45
+ ### Method 3: --patch dev mode
46
+
47
+ ```bash
48
+ cd /path/to/deepseek-harness
49
+ export QQBOT_APPID="yourAppID" QQBOT_SECRET="yourAppSecret"
50
+ pnpm dsh web --patch /path/to/dsh-qqbot/cordis.dev.yml
51
+ ```
52
+
53
+ ## Configuration
54
+
55
+ | Config | Type | Default | Description |
56
+ |------|------|--------|------|
57
+ | `appId` | string | **required** | QQ Bot AppID (or via `QQBOT_APPID` env var) |
58
+ | `appSecret` | string | **required** | QQ Bot AppSecret (or via `QQBOT_SECRET` env var) |
59
+ | `provider` | string | `deepseek-official` | LLM provider name |
60
+ | `model` | string | `deepseek-chat` | Model name |
61
+ | `preset` | string | - | Agent preset id |
62
+ | `cwd` | string | `process.cwd()` | Agent working directory |
63
+ | `requireMention` | boolean | `true` | Whether group messages require @bot to trigger |
64
+ | `groupPrompt` | string | - | Extra system prompt for group chats |
65
+ | `directPrompt` | string | - | Extra system prompt for direct chats |
66
+ | `textChunkLimit` | number | `4500` | Max chars per message |
67
+ | `sessionIdleTimeout` | number | `1800000` | Session idle timeout (ms), default 30 min |
68
+ | `debug` | boolean | `false` | Debug mode |
69
+
70
+ ## Built-in Commands
71
+
72
+ | Command | Description |
73
+ |------|------|
74
+ | `/bot-reset` | Reset the current session (clear context) |
75
+ | `/bot-model` | View or switch model |
76
+ | `/bot-status` | View current session status |
77
+ | `/bot-help` | View all commands |
78
+
79
+ ## Core Modules
80
+
81
+ ```
82
+ src/
83
+ ├── index.ts # Cordis plugin entry (async apply)
84
+ ├── config.ts # Config schema
85
+ ├── types.ts # Global types
86
+ ├── setup.ts # Credential binding (QR)
87
+ ├── transport/ # Transport layer
88
+ │ ├── inbound.ts # QQ inbound message → agent.followup()
89
+ │ ├── outbound.ts # session/event → QQ sendMarkdown
90
+ │ ├── outbound-buffer.ts # Streaming buffer
91
+ │ └── chunker.ts # Markdown chunking
92
+ ├── session/ # Session management
93
+ │ ├── session-manager.ts # QQ peer → Agent mapping
94
+ │ └── idle-evictor.ts # Idle eviction
95
+ ├── model/ # Model routing
96
+ │ ├── model-resolver.ts # Route resolution
97
+ │ ├── prefs-store.ts # Per-peer preference persistence
98
+ │ └── settings-reader.ts # settings.yaml read-only
99
+ ├── shared/ # Shared utilities
100
+ │ ├── utils.ts # Common helpers
101
+ │ ├── scope.ts # scope/peer extraction
102
+ │ └── send-helper.ts # Chunked send
103
+ ├── commands/ # Slash commands
104
+ └── typings/ # External module declarations
105
+ ```
106
+
107
+ ## Session Routing
108
+
109
+ sessionKey: `qqbot:${appId}:${scope}:${peerId}`, with the SessionId derived deterministically via SHA-256 so sessions survive restarts.
110
+
111
+ Resolution strategy: in-process reuse → persisted resume → fresh create.
112
+
113
+ ## Design Principles
114
+
115
+ - **Pure Cordis plugin** — follows the dsh "Plugins, not loop changes" principle
116
+ - **Declarative dependencies** — `inject = ['agents']`, no direct coupling to other plugins
117
+ - **Session isolation** — one independent Agent per QQ direct user / group
118
+ - **Preset support** — mount presets (toolkits, prompts, etc.) via the `agent-presets` service
119
+ - **Idle eviction** — auto-dispose Agents on timeout to prevent memory leaks
120
+ - **Markdown output** — replies sent as Markdown with code-block/table-aware chunking
121
+
122
+ ## Local Development
123
+
124
+ ```bash
125
+ # Install dependencies
126
+ pnpm install
127
+
128
+ # Build
129
+ pnpm build
130
+
131
+ # Dev mode (watch)
132
+ pnpm dev
133
+
134
+ # Debug via --patch (inside the dsh monorepo)
135
+ cd /path/to/deepseek-harness
136
+ export QQBOT_APPID="xxx" QQBOT_SECRET="xxx"
137
+ pnpm dsh web --patch /path/to/dsh-qqbot/cordis.dev.yml
138
+ ```
139
+
140
+ ## License
141
+
142
+ [MIT](./LICENSE)
@@ -0,0 +1,32 @@
1
+ # dsh-im-qqbot bundle patch
2
+ #
3
+ # 当本包通过 `dsh plugin --profile <name> add @tencent-connect/dsh-qqbot` 安装后,
4
+ # dsh 启动时自动加载此 patch。
5
+ #
6
+ # 环境变量:
7
+ # QQBOT_APPID - QQ Bot AppID(必填)
8
+ # QQBOT_SECRET - QQ Bot AppSecret(必填)
9
+ #
10
+ # 叠加顺序:dsh-base → 本 bundle patch → profile cordis.patch.yml → --patch
11
+
12
+ # ── 插入 im-qqbot 插件行 ──
13
+ - insert:
14
+ - id: im-qqbot
15
+ name: '@tencent-connect/dsh-qqbot'
16
+ config:
17
+ appId: __FROM_ENV__
18
+ appSecret: __FROM_ENV__
19
+ # provider/model 留空:从宿主默认模型路由继承
20
+ # 用户可通过 /model 命令在聊天中切换
21
+ requireMention: true
22
+ textChunkLimit: 4500
23
+ sessionIdleTimeout: 1800000
24
+ maxQueue: 20
25
+ processingTimeoutMs: 120000
26
+ historyLimit: 10
27
+ access:
28
+ c2cMode: open
29
+ c2cAllow: []
30
+ groupMode: open
31
+ groupAllow: []
32
+ debug: false
package/cordis.yml ADDED
@@ -0,0 +1,69 @@
1
+ # dsh-im-qqbot 组合配置示例
2
+ #
3
+ # 运行: pnpm dsh --config ./cordis.yml
4
+ #
5
+ # 环境变量:
6
+ # QQBOT_APPID - QQ Bot AppID
7
+ # QQBOT_SECRET - QQ Bot AppSecret
8
+ # DEEPSEEK_API_KEY - DeepSeek API Key
9
+ # DSH_CWD - Agent 工作目录(可选)
10
+
11
+ # ── 核心 spine ──
12
+ - id: sessions
13
+ name: '@deepseek-ai/dsh-session'
14
+
15
+ - id: agent
16
+ name: '@deepseek-ai/dsh-agent'
17
+
18
+ - id: agent-loop
19
+ name: '@deepseek-ai/dsh-agent-loop'
20
+
21
+ - id: system-prompt
22
+ name: '@deepseek-ai/dsh-system-prompt'
23
+
24
+ - id: tools
25
+ name: '@deepseek-ai/dsh-tools'
26
+
27
+ # ── LLM 适配器 ──
28
+ - id: llm-deepseek
29
+ name: '@deepseek-ai/dsh-llm-deepseek'
30
+ config:
31
+ apiKey: ${DEEPSEEK_API_KEY}
32
+
33
+ # ── 执行能力(按需启用) ──
34
+ - id: tool-bash
35
+ name: '@deepseek-ai/dsh-tool-bash'
36
+
37
+ - id: tool-fs
38
+ name: '@deepseek-ai/dsh-tool-fs'
39
+
40
+ - id: tool-web
41
+ name: '@deepseek-ai/dsh-tool-web'
42
+
43
+ # ── 上下文管理 ──
44
+ - id: compaction
45
+ name: '@deepseek-ai/dsh-compaction-basic'
46
+
47
+ - id: token-meter
48
+ name: '@deepseek-ai/dsh-token-meter'
49
+
50
+ # ── 持久化 ──
51
+ - id: session-persistence
52
+ name: '@deepseek-ai/dsh-session-persistence-jsonl'
53
+ config:
54
+ root: ./.dsh-sessions
55
+
56
+ # ── QQ Bot IM 驱动 ──
57
+ - id: im-qqbot
58
+ name: '@deepseek-ai/dsh-im-qqbot'
59
+ config:
60
+ appId: ${QQBOT_APPID}
61
+ appSecret: ${QQBOT_SECRET}
62
+ transport: websocket
63
+ provider: deepseek
64
+ model: deepseek-chat
65
+ cwd: ${DSH_CWD:-/tmp/dsh-qqbot}
66
+ requireMention: false
67
+ textChunkLimit: 4500
68
+ sessionIdleTimeout: 1800000
69
+ debug: false
@@ -0,0 +1,11 @@
1
+ /**
2
+ * /bot-help — 查看所有指令以及用途
3
+ *
4
+ * 参考 openclaw-qqbot 的 bot-help.ts:遍历所有非隐藏命令,
5
+ * 用 <qqbot-cmd-input> 展示为可点击按钮,以 Markdown 格式发送。
6
+ */
7
+ import type { SlashCommand } from '@tencent-connect/qqbot-nodejs';
8
+ import type { CommandDeps } from './types.js';
9
+ /** /bot-help — 查看所有指令以及用途 */
10
+ export declare function helpCommand({ config }: CommandDeps, allCommands: () => SlashCommand[]): SlashCommand;
11
+ //# sourceMappingURL=help.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/commands/help.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,6BAA6B;AAC7B,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,EAAE,GAAG,YAAY,CAkBpG"}
@@ -0,0 +1,21 @@
1
+ import { sendMarkdownChunked } from '../shared/index.js';
2
+ /** /bot-help — 查看所有指令以及用途 */
3
+ export function helpCommand({ config }, allCommands) {
4
+ return {
5
+ name: 'bot-help',
6
+ description: '查看所有指令以及用途',
7
+ handler: async (cmdCtx) => {
8
+ const lines = ['### QQBot插件内置指令', ''];
9
+ for (const cmd of allCommands()) {
10
+ const name = Array.isArray(cmd.name) ? cmd.name[0] : cmd.name;
11
+ if (cmd.hidden)
12
+ continue;
13
+ lines.push(`<qqbot-cmd-input text="/${name}" show="/${name}"/> ${cmd.description ?? ''}`);
14
+ }
15
+ lines.push('', '> dsh-qqbot v0.1.0');
16
+ await sendMarkdownChunked(cmdCtx, lines.join('\n'), config.textChunkLimit);
17
+ return { kind: 'noop' };
18
+ },
19
+ };
20
+ }
21
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/commands/help.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,6BAA6B;AAC7B,MAAM,UAAU,WAAW,CAAC,EAAE,MAAM,EAAe,EAAE,WAAiC;IACpF,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,YAAY;QACzB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YACxB,MAAM,KAAK,GAAG,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;YAEtC,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,EAAE,CAAC;gBAChC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;gBAC9D,IAAI,GAAG,CAAC,MAAM;oBAAE,SAAS;gBACzB,KAAK,CAAC,IAAI,CAAC,2BAA2B,IAAI,YAAY,IAAI,OAAO,GAAG,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC,CAAC;YAC5F,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,oBAAoB,CAAC,CAAC;YACrC,MAAM,mBAAmB,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;YAC3E,OAAO,EAAE,IAAI,EAAE,MAAe,EAAE,CAAC;QACnC,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * 斜杠命令注册中心
3
+ *
4
+ * 每个命令拆分为独立文件,此处仅编排。参考 openclaw-qqbot 的
5
+ * commands/index.ts 模式:工厂函数注入依赖,统一导出命令列表。
6
+ */
7
+ import type { SlashCommand } from '@tencent-connect/qqbot-nodejs';
8
+ import type { CommandDeps } from './types.js';
9
+ /**
10
+ * 构建标准命令列表
11
+ */
12
+ export declare function buildCommandList(deps: CommandDeps): SlashCommand[];
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAO9C;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,YAAY,EAAE,CAmBlE"}
@@ -0,0 +1,27 @@
1
+ import { resetCommand, newCommand } from './session.js';
2
+ import { modelCommand } from './model.js';
3
+ import { statusCommand } from './status.js';
4
+ import { helpCommand } from './help.js';
5
+ import { pingCommand, versionCommand, stopCommand } from './misc.js';
6
+ /**
7
+ * 构建标准命令列表
8
+ */
9
+ export function buildCommandList(deps) {
10
+ const commands = [
11
+ // 会话
12
+ resetCommand(deps),
13
+ newCommand(deps),
14
+ // 模型
15
+ modelCommand(deps),
16
+ // 状态
17
+ statusCommand(deps),
18
+ // 杂项
19
+ pingCommand(),
20
+ versionCommand(deps),
21
+ stopCommand(),
22
+ ];
23
+ // help 需要访问完整列表(含自身),通过闭包惰性引用
24
+ commands.push(helpCommand(deps, () => commands));
25
+ return commands;
26
+ }
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAErE;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAiB;IAChD,MAAM,QAAQ,GAAmB;QAC/B,KAAK;QACL,YAAY,CAAC,IAAI,CAAC;QAClB,UAAU,CAAC,IAAI,CAAC;QAChB,KAAK;QACL,YAAY,CAAC,IAAI,CAAC;QAClB,KAAK;QACL,aAAa,CAAC,IAAI,CAAC;QACnB,KAAK;QACL,WAAW,EAAE;QACb,cAAc,CAAC,IAAI,CAAC;QACpB,WAAW,EAAE;KACd,CAAC;IAEF,8BAA8B;IAC9B,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEjD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 杂项命令:/ping /version /stop
3
+ */
4
+ import type { SlashCommand } from '@tencent-connect/qqbot-nodejs';
5
+ import type { CommandDeps } from './types.js';
6
+ /** /bot-ping — 连通性测试 */
7
+ export declare function pingCommand(): SlashCommand;
8
+ /** /bot-version — 查看版本信息 */
9
+ export declare function versionCommand({ manager }: CommandDeps): SlashCommand;
10
+ /** /bot-stop — 中止当前生成(隐藏) */
11
+ export declare function stopCommand(): SlashCommand;
12
+ //# sourceMappingURL=misc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"misc.d.ts","sourceRoot":"","sources":["../../src/commands/misc.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAwB;AACxB,wBAAgB,WAAW,IAAI,YAAY,CAM1C;AAED,4BAA4B;AAC5B,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,EAAE,WAAW,GAAG,YAAY,CAUrE;AAED,6BAA6B;AAC7B,wBAAgB,WAAW,IAAI,YAAY,CAO1C"}
@@ -0,0 +1,30 @@
1
+ /** /bot-ping — 连通性测试 */
2
+ export function pingCommand() {
3
+ return {
4
+ name: 'bot-ping',
5
+ description: '连通性测试',
6
+ handler: () => 'pong 🏓',
7
+ };
8
+ }
9
+ /** /bot-version — 查看版本信息 */
10
+ export function versionCommand({ manager }) {
11
+ return {
12
+ name: 'bot-version',
13
+ description: '查看版本信息',
14
+ handler: () => {
15
+ const current = manager.getEffectiveModel('c2c', '');
16
+ const modelInfo = current ? `${current.provider}/${current.model}` : '宿主默认';
17
+ return `dsh-qqbot v0.1.0 | model: ${modelInfo}`;
18
+ },
19
+ };
20
+ }
21
+ /** /bot-stop — 中止当前生成(隐藏) */
22
+ export function stopCommand() {
23
+ return {
24
+ name: 'bot-stop',
25
+ description: '中止当前生成',
26
+ hidden: true,
27
+ handler: () => ({ kind: 'noop' }),
28
+ };
29
+ }
30
+ //# sourceMappingURL=misc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"misc.js","sourceRoot":"","sources":["../../src/commands/misc.ts"],"names":[],"mappings":"AAMA,wBAAwB;AACxB,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,OAAO;QACpB,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;KACzB,CAAC;AACJ,CAAC;AAED,4BAA4B;AAC5B,MAAM,UAAU,cAAc,CAAC,EAAE,OAAO,EAAe;IACrD,OAAO;QACL,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,QAAQ;QACrB,OAAO,EAAE,GAAG,EAAE;YACZ,MAAM,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACrD,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;YAC5E,OAAO,6BAA6B,SAAS,EAAE,CAAC;QAClD,CAAC;KACF,CAAC;AACJ,CAAC;AAED,6BAA6B;AAC7B,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,QAAQ;QACrB,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,CAAC;KAC3C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 模型命令:/bot-model — 查看或切换模型
3
+ */
4
+ import type { SlashCommand } from '@tencent-connect/qqbot-nodejs';
5
+ import type { CommandDeps } from './types.js';
6
+ export declare function modelCommand({ manager, config }: CommandDeps): SlashCommand;
7
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/commands/model.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,WAAW,GAAG,YAAY,CAgE3E"}