@zaofan/dsh-qqbot 1.7.7 → 1.7.9
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 +5 -5
- package/README_EN.md +4 -4
- package/dist/channel-tools.d.ts +20 -0
- package/dist/channel-tools.d.ts.map +1 -1
- package/dist/channel-tools.js +128 -4
- package/dist/channel-tools.js.map +1 -1
- package/dist/features/qq-approval.d.ts.map +1 -1
- package/dist/features/qq-approval.js +13 -4
- package/dist/features/qq-approval.js.map +1 -1
- package/dist/gateway/bootstrap.d.ts.map +1 -1
- package/dist/gateway/bootstrap.js +30 -7
- package/dist/gateway/bootstrap.js.map +1 -1
- package/dist/gateway/debounce.d.ts.map +1 -1
- package/dist/gateway/debounce.js +24 -8
- package/dist/gateway/debounce.js.map +1 -1
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +40 -5
- package/dist/session/session-manager.js.map +1 -1
- package/dist/session/types.d.ts +6 -0
- package/dist/session/types.d.ts.map +1 -1
- package/dist/transport/outbound.d.ts.map +1 -1
- package/dist/transport/outbound.js +2 -0
- package/dist/transport/outbound.js.map +1 -1
- package/package.json +4 -4
- package/settings-host.js +4750 -4717
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
基于 [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) (dsh) 的 QQ Bot IM 插件**增强 fork**:将 QQ 消息平台作为 dsh agent 的前端协议驱动,并加入表情包图库、富媒体收发、定时任务、多实例人格、好感度系统、可视化设置面板等能力。
|
|
6
6
|
|
|
7
|
-
📦 仓库: [
|
|
7
|
+
📦 仓库: [zaofan-make/dsh-qqbot](https://github.com/zaofan-make/dsh-qqbot)(fork 自 [tencent-connect/dsh-qqbot](https://github.com/tencent-connect/dsh-qqbot);改动都在这一侧,升级/重装上游会被冲掉)
|
|
8
8
|
|
|
9
9
|
> ⭐ **用得顺手的话,麻烦点一下右上角的 Star** —— 它是这个项目"有人在用"的唯一可见信号,也是继续更新的动力。
|
|
10
10
|
|
|
@@ -124,7 +124,7 @@ npx @deepseek-ai/dsh plugin --profile web add @zaofan/dsh-qqbot
|
|
|
124
124
|
|
|
125
125
|
> 尚未发布到 npm 前,请用下面的方式二。
|
|
126
126
|
|
|
127
|
-
> ⚠️ **从 GitHub 直装(`github:
|
|
127
|
+
> ⚠️ **从 GitHub 直装(`github:zaofan-make/dsh-qqbot`)需要编译产物 `dist/`,而仓库不提交 `dist`。**
|
|
128
128
|
> 包已声明 `prepare` 脚本,pnpm 安装时会自动编译;
|
|
129
129
|
> 若你的包管理器没自动跑(或报 `failed to import` / 找不到 `dist/index.js`),
|
|
130
130
|
> 手动在插件目录执行一次 `npm run build` 即可。**最省事的做法是用 npm 上的发布版**(`@zaofan/dsh-qqbot`)。
|
|
@@ -134,7 +134,7 @@ npx @deepseek-ai/dsh plugin --profile web add @zaofan/dsh-qqbot
|
|
|
134
134
|
**Windows(一键脚本)**:
|
|
135
135
|
|
|
136
136
|
```powershell
|
|
137
|
-
git clone https://github.com/
|
|
137
|
+
git clone https://github.com/zaofan-make/dsh-qqbot.git
|
|
138
138
|
cd dsh-qqbot
|
|
139
139
|
.\install.ps1 # 自动 install/build → pack → add tarball → 输出重启指引
|
|
140
140
|
```
|
|
@@ -144,7 +144,7 @@ cd dsh-qqbot
|
|
|
144
144
|
**macOS / Linux(手动)**:
|
|
145
145
|
|
|
146
146
|
```bash
|
|
147
|
-
git clone https://github.com/
|
|
147
|
+
git clone https://github.com/zaofan-make/dsh-qqbot.git
|
|
148
148
|
cd dsh-qqbot
|
|
149
149
|
npm install && npm run build
|
|
150
150
|
pnpm pack --pack-destination /tmp
|
|
@@ -434,7 +434,7 @@ AI 侧的工具叫 **`qq_group_admin`**:
|
|
|
434
434
|
|
|
435
435
|
## 支持这个项目
|
|
436
436
|
|
|
437
|
-
如果这个插件帮你省了 token、或者让你家的鲸鱼更活蹦乱跳 —— **给个 ⭐ Star** 就是最实在的支持;有 bug / 想要的功能,欢迎开 [Issue](https://github.com/
|
|
437
|
+
如果这个插件帮你省了 token、或者让你家的鲸鱼更活蹦乱跳 —— **给个 ⭐ Star** 就是最实在的支持;有 bug / 想要的功能,欢迎开 [Issue](https://github.com/zaofan-make/dsh-qqbot/issues)。
|
|
438
438
|
|
|
439
439
|
## License
|
|
440
440
|
|
package/README_EN.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
An **enhanced fork** of the QQ Bot IM plugin for [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) (dsh): it drives the dsh agent loop with the QQ messaging platform as the frontend protocol, adding a local sticker library, rich media send/recall, scheduled tasks, multi-instance personas, and a visual settings panel.
|
|
4
4
|
|
|
5
|
-
📦 Repo: [
|
|
5
|
+
📦 Repo: [zaofan-make/dsh-qqbot](https://github.com/zaofan-make/dsh-qqbot) (forked from [tencent-connect/dsh-qqbot](https://github.com/tencent-connect/dsh-qqbot))
|
|
6
6
|
|
|
7
7
|
> ⭐ **If it works well for you, please star the repo** — it is the only visible signal that someone is using it, and it keeps the project going.
|
|
8
8
|
|
|
@@ -142,7 +142,7 @@ npx @deepseek-ai/dsh plugin --profile web add @zaofan/dsh-qqbot
|
|
|
142
142
|
**Windows (one-click script)**:
|
|
143
143
|
|
|
144
144
|
```powershell
|
|
145
|
-
git clone https://github.com/
|
|
145
|
+
git clone https://github.com/zaofan-make/dsh-qqbot.git
|
|
146
146
|
cd dsh-qqbot
|
|
147
147
|
.\install.ps1 # npm install/build -> pack -> add tarball -> prints restart steps
|
|
148
148
|
```
|
|
@@ -152,7 +152,7 @@ cd dsh-qqbot
|
|
|
152
152
|
**macOS / Linux (manual)**:
|
|
153
153
|
|
|
154
154
|
```bash
|
|
155
|
-
git clone https://github.com/
|
|
155
|
+
git clone https://github.com/zaofan-make/dsh-qqbot.git
|
|
156
156
|
cd dsh-qqbot
|
|
157
157
|
npm install && npm run build
|
|
158
158
|
pnpm pack --pack-destination /tmp
|
|
@@ -463,7 +463,7 @@ npx @deepseek-ai/dsh web --patch /path/to/dsh-qqbot/cordis.dev.yml
|
|
|
463
463
|
|
|
464
464
|
## Support
|
|
465
465
|
|
|
466
|
-
If this plugin saved you some tokens — or made your QQ bot feel alive — a **⭐ Star** is the most concrete way to say thanks. Bugs and feature requests: [Issues](https://github.com/
|
|
466
|
+
If this plugin saved you some tokens — or made your QQ bot feel alive — a **⭐ Star** is the most concrete way to say thanks. Bugs and feature requests: [Issues](https://github.com/zaofan-make/dsh-qqbot/issues).
|
|
467
467
|
|
|
468
468
|
## License
|
|
469
469
|
|
package/dist/channel-tools.d.ts
CHANGED
|
@@ -89,4 +89,24 @@ export declare function syncContextTools(agentCtx: unknown, shouldHave: boolean,
|
|
|
89
89
|
dataRoot?: string;
|
|
90
90
|
sessionKey?: string;
|
|
91
91
|
}, reminderText?: string): void;
|
|
92
|
+
/**
|
|
93
|
+
* 把"三个上下文工具 + QQ 群管理工具"**全局注册一次、永不注销**。
|
|
94
|
+
*
|
|
95
|
+
* 幂等靠 globalThis 记句柄:跨热刷(模块重新 import)依然有效,避免热刷后重复注册被宿主判重名。
|
|
96
|
+
* ⚠️ 可见性不在这里决定 —— 交给 {@link restrictContextTools} 按会话剪枝。
|
|
97
|
+
*/
|
|
98
|
+
export declare function ensureContextToolsGlobal(globalCtx: unknown): void;
|
|
99
|
+
/**
|
|
100
|
+
* 按会话**实时剪枝**三个上下文工具的可见性(2026-10-09,主人要的"实时变更")。
|
|
101
|
+
*
|
|
102
|
+
* 语义:**开了「无上下文模式 + 智能判断」**的会话 → 看得见那三个工具;
|
|
103
|
+
* 否则该会话**连工具名都看不到**(模型清单里没有 = 零 token),而**注册表纹丝不动**。
|
|
104
|
+
* 面板一改开关 → 下一次 pre-step(下一回合/下一 step)即生效;撤销限制是立即的。
|
|
105
|
+
*
|
|
106
|
+
* 幂等:同一作用域状态没变化就直接 return,不重复设/撤 restriction(避免无谓的变更通知与抖动)。
|
|
107
|
+
*/
|
|
108
|
+
export declare function restrictContextTools(agentCtx: unknown, shouldHave: boolean, env?: {
|
|
109
|
+
dataRoot?: string;
|
|
110
|
+
sessionKey?: string;
|
|
111
|
+
}): void;
|
|
92
112
|
//# sourceMappingURL=channel-tools.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel-tools.d.ts","sourceRoot":"","sources":["../src/channel-tools.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AA4FlE,6DAA6D;AAC7D,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,eAAO,MAAM,IAAI,wBAAwB,CAAC;AAI1C,eAAO,MAAM,MAAM,UAAY,CAAC;AAWhC,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,CAAiC;AAkD5F,wCAAwC;AACxC,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAErH;AACD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAE9E;AACD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,CAI/D;AAkFD,mDAAmD;AACnD,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"channel-tools.d.ts","sourceRoot":"","sources":["../src/channel-tools.ts"],"names":[],"mappings":"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"}
|
package/dist/channel-tools.js
CHANGED
|
@@ -2214,10 +2214,15 @@ export async function apply(ctx) {
|
|
|
2214
2214
|
// ⛔ 别再改回 true:那等于给所有会话开后门。
|
|
2215
2215
|
// 代价:插件作用域不再"提前"备一份,开启的会话若在极早期回合看不到工具,等下一个 step
|
|
2216
2216
|
// (pre-step 每个 step 都跑)即出现 —— 比"人人都有"划算得多。
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2217
|
+
// ⚠️ 2026-10-09 **第二次修正**(实测抓到;主人定的"注册不动 + 实时剪枝"要落地必须这样):
|
|
2218
|
+
// ⛔ **不要在这里注册那三个上下文工具** —— 本函数是"每会话"被调用的
|
|
2219
|
+
// (session-manager 传进来的是 **agentCtx**),在这儿 register 等于注册进**该 agent 作用域**;
|
|
2220
|
+
// 而 `restrict({deny})` 按宿主文档**只过滤"继承来的"(全局层 + 祖先层)工具,
|
|
2221
|
+
// 管不到本作用域自己注册的** ⇒ 剪枝永远打空
|
|
2222
|
+
// (trace 原话:`restrict 失败: names unknown global tools "context_memo","context_compact","context_drop"`)。
|
|
2223
|
+
// ✅ 全局注册统一交给 session-manager 的 pre-step 用**插件根 ctx** 做:
|
|
2224
|
+
// `ensureContextToolsGlobal(this.ctx)` —— 它内部用 `ctx.get('tools')` 取服务,绕开 inject 限制。
|
|
2225
|
+
// 这里只保留下面 ②段"QQ 群管理工具"的按会话注册(那本来就是会话级工具)。
|
|
2221
2226
|
const toolDefs = [
|
|
2222
2227
|
{ name: 'send_media', tool: sendMediaTool },
|
|
2223
2228
|
{ name: 'recall_message', tool: recallTool },
|
|
@@ -2960,4 +2965,123 @@ export function syncContextTools(agentCtx, shouldHave, env, reminderText) {
|
|
|
2960
2965
|
traceToolReg('[ctxtool-reg] 异常: ' + String(e?.message ?? e).slice(0, 160));
|
|
2961
2966
|
}
|
|
2962
2967
|
}
|
|
2968
|
+
// ══════════════════════════════════════════════════════════════════════════
|
|
2969
|
+
// 2026-10-09 架构微调(主人定):**注册不动 + 按会话实时剪枝可见性**
|
|
2970
|
+
// ══════════════════════════════════════════════════════════════════════════
|
|
2971
|
+
// 旧做法是 pre-step 每步都 `syncContextTools()`:内部"先注销、再重新注册",
|
|
2972
|
+
// 于是**每一步都动一次工具表** → 宿主每步都发"工具已更新 · 移除/新增"(还进上下文,纯烧 token),
|
|
2973
|
+
// 多会话并存时更是"你挂我卸"来回抖。
|
|
2974
|
+
//
|
|
2975
|
+
// 主人的判断是对的:不该用"注册/注销"表达"这个会话要不要有",而该
|
|
2976
|
+
// **注册只做一次,可见性按会话实时剪枝** —— 宿主正好提供了这个接口:
|
|
2977
|
+
// `ctx.tools.restrict({ allow | deny })`,**per-scope**(只作用于调用方那一个 agent 作用域),
|
|
2978
|
+
// 且"只过滤**继承**来的工具(全局层+祖先层),不动该作用域自己注册的"。
|
|
2979
|
+
//
|
|
2980
|
+
// 于是现在的分工:
|
|
2981
|
+
// · {@link ensureContextToolsGlobal} —— 全局注册一次(永不注销),幂等;
|
|
2982
|
+
// · {@link restrictContextTools} —— 每个会话每次 pre-step 声明"我要不要看得到那三个",
|
|
2983
|
+
// 状态没变就一根手指都不动(不产生任何变更通知)。
|
|
2984
|
+
// =========================================================================
|
|
2985
|
+
/** 三个上下文工具的名字(restrict 用;必须与 ctxToolsRef() 里的 name 完全一致) */
|
|
2986
|
+
const CTX_TOOL_NAMES = ['context_memo', 'context_compact', 'context_drop'];
|
|
2987
|
+
/**
|
|
2988
|
+
* 把"三个上下文工具 + QQ 群管理工具"**全局注册一次、永不注销**。
|
|
2989
|
+
*
|
|
2990
|
+
* 幂等靠 globalThis 记句柄:跨热刷(模块重新 import)依然有效,避免热刷后重复注册被宿主判重名。
|
|
2991
|
+
* ⚠️ 可见性不在这里决定 —— 交给 {@link restrictContextTools} 按会话剪枝。
|
|
2992
|
+
*/
|
|
2993
|
+
export function ensureContextToolsGlobal(globalCtx) {
|
|
2994
|
+
try {
|
|
2995
|
+
if (!globalCtx || typeof globalCtx !== 'object')
|
|
2996
|
+
return;
|
|
2997
|
+
// ⚠️ 2026-10-09 修(实测抓到):apply 的注入列表是 `["settings","webServer"]`,**没有 `tools`** ⇒
|
|
2998
|
+
// 直接读 `ctx.tools` 会被宿主拒(`cannot get property "tools" without inject`),异常被 catch 吞掉,
|
|
2999
|
+
// 表现就是"全局注册压根没发生"(trace 里只有别的报错、没有"全局注册 N 件")。
|
|
3000
|
+
// 正解:**用 cordis 的运行时取服务 `ctx.get('tools')`**(不需要 inject 声明)——
|
|
3001
|
+
// 本插件别处也是这个姿势(见 ext-capabilities 给扩展工具的 kernel 文档:`ctx.get('tools')`)。
|
|
3002
|
+
const ctxObj = globalCtx;
|
|
3003
|
+
let toolsObj;
|
|
3004
|
+
try {
|
|
3005
|
+
toolsObj = ctxObj.tools;
|
|
3006
|
+
}
|
|
3007
|
+
catch { /* 未声明 inject 时会抛 —— 忽略,下面改走 get */ }
|
|
3008
|
+
if (!toolsObj || typeof toolsObj.register !== 'function') {
|
|
3009
|
+
try {
|
|
3010
|
+
toolsObj = ctxObj.get?.('tools');
|
|
3011
|
+
}
|
|
3012
|
+
catch { /* ignore */ }
|
|
3013
|
+
}
|
|
3014
|
+
const reg = toolsObj?.register;
|
|
3015
|
+
if (!toolsObj || typeof reg !== 'function') {
|
|
3016
|
+
traceToolReg('[ctxtool-reg] 全局注册跳过: 拿不到 tools 服务(ctx.tools 被拒 且 ctx.get("tools") 为空)');
|
|
3017
|
+
return;
|
|
3018
|
+
}
|
|
3019
|
+
const g = globalThis;
|
|
3020
|
+
if (Array.isArray(g.__qqbotCtxToolsGlobal) && g.__qqbotCtxToolsGlobal.length > 0)
|
|
3021
|
+
return;
|
|
3022
|
+
const ds = [];
|
|
3023
|
+
for (const t of [...ctxToolsRef(), ...qunAdminRef()]) {
|
|
3024
|
+
try {
|
|
3025
|
+
const d = reg.call(toolsObj, t);
|
|
3026
|
+
if (typeof d === 'function')
|
|
3027
|
+
ds.push(d);
|
|
3028
|
+
}
|
|
3029
|
+
catch { /* 单个失败不影响其它 */ }
|
|
3030
|
+
}
|
|
3031
|
+
g.__qqbotCtxToolsGlobal = ds;
|
|
3032
|
+
traceToolReg(`[ctxtool-reg] 全局注册 ${ds.length} 件(永不注销;可见性改由 per-scope restrict 控制)`);
|
|
3033
|
+
}
|
|
3034
|
+
catch (e) {
|
|
3035
|
+
traceToolReg('[ctxtool-reg] 全局注册异常: ' + String(e?.message ?? e).slice(0, 160));
|
|
3036
|
+
}
|
|
3037
|
+
}
|
|
3038
|
+
/** 每个 agent 作用域当前的可见性状态(幂等用:状态没变就不动) */
|
|
3039
|
+
const ctxRestrictState = new WeakMap();
|
|
3040
|
+
/**
|
|
3041
|
+
* 按会话**实时剪枝**三个上下文工具的可见性(2026-10-09,主人要的"实时变更")。
|
|
3042
|
+
*
|
|
3043
|
+
* 语义:**开了「无上下文模式 + 智能判断」**的会话 → 看得见那三个工具;
|
|
3044
|
+
* 否则该会话**连工具名都看不到**(模型清单里没有 = 零 token),而**注册表纹丝不动**。
|
|
3045
|
+
* 面板一改开关 → 下一次 pre-step(下一回合/下一 step)即生效;撤销限制是立即的。
|
|
3046
|
+
*
|
|
3047
|
+
* 幂等:同一作用域状态没变化就直接 return,不重复设/撤 restriction(避免无谓的变更通知与抖动)。
|
|
3048
|
+
*/
|
|
3049
|
+
export function restrictContextTools(agentCtx, shouldHave, env) {
|
|
3050
|
+
try {
|
|
3051
|
+
if (!agentCtx || typeof agentCtx !== 'object')
|
|
3052
|
+
return;
|
|
3053
|
+
const key = agentCtx;
|
|
3054
|
+
// 会话坐标每次都刷新(工具执行时靠它定位数据根/会话)
|
|
3055
|
+
if (env && env.dataRoot) {
|
|
3056
|
+
ctxEnvMap.set(key, { dataRoot: String(env.dataRoot), sessionKey: String(env.sessionKey ?? '') });
|
|
3057
|
+
}
|
|
3058
|
+
const st = ctxRestrictState.get(key);
|
|
3059
|
+
if (st && st.shouldHave === shouldHave)
|
|
3060
|
+
return; // ← 状态一致:不动(这是"不抖"的关键)
|
|
3061
|
+
if (st?.dispose) {
|
|
3062
|
+
try {
|
|
3063
|
+
st.dispose();
|
|
3064
|
+
}
|
|
3065
|
+
catch { /* ignore */ }
|
|
3066
|
+
}
|
|
3067
|
+
const toolsObj = agentCtx.tools;
|
|
3068
|
+
const restrict = toolsObj?.restrict;
|
|
3069
|
+
let dispose;
|
|
3070
|
+
if (!shouldHave && typeof restrict === 'function') {
|
|
3071
|
+
try {
|
|
3072
|
+
const d = restrict.call(toolsObj, { deny: [...CTX_TOOL_NAMES] });
|
|
3073
|
+
if (typeof d === 'function')
|
|
3074
|
+
dispose = d;
|
|
3075
|
+
}
|
|
3076
|
+
catch (e) {
|
|
3077
|
+
traceToolReg('[ctxtool-reg] restrict 失败: ' + String(e?.message ?? e).slice(0, 160));
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3080
|
+
ctxRestrictState.set(key, dispose ? { shouldHave, dispose } : { shouldHave });
|
|
3081
|
+
traceToolReg(`[ctxtool-reg] ${shouldHave ? '放开(本会话继承全局三个工具)' : '剪枝(本会话看不到三个工具)'} dataRoot=${String(env?.dataRoot ?? '')} sk=${String(env?.sessionKey ?? '')}`);
|
|
3082
|
+
}
|
|
3083
|
+
catch (e) {
|
|
3084
|
+
traceToolReg('[ctxtool-reg] 剪枝异常: ' + String(e?.message ?? e).slice(0, 160));
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
2963
3087
|
//# sourceMappingURL=channel-tools.js.map
|