@zaofan/dsh-qqbot 1.5.1 → 1.5.3
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_EN.md +7 -7
- package/client/qqbot-settings.js +36 -5
- package/dist/channel-tools.d.ts.map +1 -1
- package/dist/channel-tools.js +43 -1
- package/dist/channel-tools.js.map +1 -1
- package/dist/config.d.ts +34 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -1
- package/dist/config.js.map +1 -1
- package/dist/features/agg-score.d.ts +1 -1
- package/dist/features/agg-score.js +1 -1
- package/dist/features/four-source.d.ts +1 -1
- package/dist/features/four-source.js +1 -1
- package/dist/features/local-signals.js +2 -2
- package/dist/features/local-signals.js.map +1 -1
- package/dist/features/people-memo.js +1 -1
- package/dist/features/tendency-samples.js +1 -1
- package/dist/features/value-sample.d.ts +3 -1
- package/dist/features/value-sample.d.ts.map +1 -1
- package/dist/features/value-sample.js +3 -1
- package/dist/features/value-sample.js.map +1 -1
- package/dist/features/value-score.d.ts +27 -0
- package/dist/features/value-score.d.ts.map +1 -1
- package/dist/features/value-score.js +42 -3
- package/dist/features/value-score.js.map +1 -1
- package/dist/gateway/debounce.d.ts.map +1 -1
- package/dist/gateway/debounce.js +28 -6
- package/dist/gateway/debounce.js.map +1 -1
- package/dist/shared/mention-clean.d.ts +13 -0
- package/dist/shared/mention-clean.d.ts.map +1 -1
- package/dist/shared/mention-clean.js +19 -0
- package/dist/shared/mention-clean.js.map +1 -1
- package/dist/transport/inbound.d.ts +10 -0
- package/dist/transport/inbound.d.ts.map +1 -1
- package/dist/transport/inbound.js +121 -50
- package/dist/transport/inbound.js.map +1 -1
- package/dist/transport/markers.d.ts +59 -0
- package/dist/transport/markers.d.ts.map +1 -0
- package/dist/transport/markers.js +97 -0
- package/dist/transport/markers.js.map +1 -0
- package/docs/USER-GUIDE.md +461 -461
- package/package.json +124 -124
- package/settings-host.js +3095 -3071
package/README_EN.md
CHANGED
|
@@ -4,8 +4,8 @@ An **enhanced fork** of the QQ Bot IM plugin for [deepseek-harness](https://gith
|
|
|
4
4
|
|
|
5
5
|
📦 Repo: [gcry13067381632-jpg/dsh-qqbot](https://github.com/gcry13067381632-jpg/dsh-qqbot) (forked from [tencent-connect/dsh-qqbot](https://github.com/tencent-connect/dsh-qqbot))
|
|
6
6
|
|
|
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
|
-
|
|
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
|
+
|
|
9
9
|
[中文文档](./README.md) | English
|
|
10
10
|
|
|
11
11
|
## 🐋 This fork (enhanced edition)
|
|
@@ -290,7 +290,7 @@ Please install the local small model used by the dsh qqbot plugin on this machin
|
|
|
290
290
|
Every inbound message carries a **short message number** (e.g. `#0913a` — month/day + rolling id):
|
|
291
291
|
|
|
292
292
|
```
|
|
293
|
-
[
|
|
293
|
+
[Alice (12AB34…) #0913a] take a look at this
|
|
294
294
|
```
|
|
295
295
|
|
|
296
296
|
- To quote a message, the AI writes `[rf:0913a]` in its reply body → the reply is sent as a **quote bubble** (the other side sees "she quoted this message"). The tag itself is never displayed.
|
|
@@ -410,10 +410,10 @@ export QQBOT_APPID="xxx" QQBOT_SECRET="xxx"
|
|
|
410
410
|
npx @deepseek-ai/dsh web --patch /path/to/dsh-qqbot/cordis.dev.yml
|
|
411
411
|
```
|
|
412
412
|
|
|
413
|
-
## Support
|
|
414
|
-
|
|
415
|
-
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/gcry13067381632-jpg/dsh-qqbot/issues).
|
|
416
|
-
|
|
413
|
+
## Support
|
|
414
|
+
|
|
415
|
+
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/gcry13067381632-jpg/dsh-qqbot/issues).
|
|
416
|
+
|
|
417
417
|
## License
|
|
418
418
|
|
|
419
419
|
[MIT](./LICENSE)
|
package/client/qqbot-settings.js
CHANGED
|
@@ -2125,7 +2125,9 @@ var QQS_CSS = ".qqs-btn{font:inherit;color:#333;background:linear-gradient(180de
|
|
|
2125
2125
|
var q = state.ns ? '?' + outNsQ() : ''
|
|
2126
2126
|
Promise.all([
|
|
2127
2127
|
fetch('/api/qqbot-settings/affinity' + q).then(function (r) { return r.json() }).catch(function () { return {} }),
|
|
2128
|
-
|
|
2128
|
+
// all=1&limit=50: 这张表是"按 key 左连接好感度", 只要 top N 的话排在 N 后面的人永远显示 "—"
|
|
2129
|
+
// (2026-09-15 主人问"小明不是有好感度吗, 怎么显示 0" —— 他 a=0.064 排第 9, 被 top8 截掉)。
|
|
2130
|
+
fetch('/api/qqbot-settings/attitude' + q + (q ? '&' : '?') + 'all=1&limit=50').then(function (r) { return r.json() }).catch(function () { return {} })
|
|
2129
2131
|
]).then(function (rs) {
|
|
2130
2132
|
var aff = (rs[0] && rs[0].items) || []
|
|
2131
2133
|
var att = (rs[1] && rs[1].items) || []
|
|
@@ -2257,11 +2259,21 @@ var QQS_CSS = ".qqs-btn{font:inherit;color:#333;background:linear-gradient(180de
|
|
|
2257
2259
|
valueGate: gateEl ? gateEl.value : 'log',
|
|
2258
2260
|
valueMinScore: minEl ? (parseFloat(minEl.value) || 0.5) : 0.5,
|
|
2259
2261
|
}
|
|
2262
|
+
var apNext = null // 附件唤醒新值(账号级): 保存成功后立刻写回本地缓存, 不等接口回读
|
|
2260
2263
|
if (hint) hint.textContent = '保存中…'
|
|
2261
2264
|
fetch(READ + (state.ns ? '?' + outNsQ() : '')).then(function (r) { return r.json() }).then(function (d) {
|
|
2262
2265
|
var cur = (d && d.value) || {}
|
|
2263
2266
|
var lm = Object.assign({}, cur.localModel || {})
|
|
2264
2267
|
if (dirEl) lm.modelDir = String(dirEl.value || '').trim() // 账号级
|
|
2268
|
+
// 附件唤醒开关(账号级,2026-09-15):勾了 = 该类附件无视分数直接唤醒
|
|
2269
|
+
{
|
|
2270
|
+
var apEls = panel ? panel.querySelectorAll('.dk-lm-ap') : []
|
|
2271
|
+
if (apEls.length) {
|
|
2272
|
+
lm.attachmentPassthrough = {}
|
|
2273
|
+
apEls.forEach(function (el) { lm.attachmentPassthrough[el.getAttribute('data-kind')] = !!el.checked })
|
|
2274
|
+
apNext = lm.attachmentPassthrough
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2265
2277
|
lm.overrides = Object.assign({}, (lm.overrides || {}))
|
|
2266
2278
|
lm.overrides[ovKey] = ovNext // 会话级
|
|
2267
2279
|
var patch = Object.assign({}, cur, { localModel: lm })
|
|
@@ -2277,6 +2289,7 @@ var QQS_CSS = ".qqs-btn{font:inherit;color:#333;background:linear-gradient(180de
|
|
|
2277
2289
|
lm2.overrides = Object.assign({}, (lm2.overrides || {}))
|
|
2278
2290
|
lm2.overrides[ovKey] = ovNext
|
|
2279
2291
|
if (dirEl) lm2.modelDir = String(dirEl.value || '').trim()
|
|
2292
|
+
if (apNext) lm2.attachmentPassthrough = apNext // 附件唤醒(账号级): 保存后立刻回填, 否则重绘又跳回默认勾选
|
|
2280
2293
|
state.lmCfg = lm2
|
|
2281
2294
|
paintBody()
|
|
2282
2295
|
setTimeout(function () { loadLocalModel() }, 2000)
|
|
@@ -3559,6 +3572,24 @@ var QQS_CSS = ".qqs-btn{font:inherit;color:#333;background:linear-gradient(180de
|
|
|
3559
3572
|
+ '<span style="font-size:12px;color:#666">门槛:</span>'
|
|
3560
3573
|
+ '<input class="qqs-inp" id="dk-lm-min" type="number" step="0.01" min="0" max="1" style="width:78px" value="' + minV + '">'
|
|
3561
3574
|
+ '</div>'
|
|
3575
|
+
// 🎬 附件唤醒开关(2026-09-15 主人定):按类型决定"是否**无视分数**直接唤醒"
|
|
3576
|
+
// 勾上 = 该类附件不管分多低都唤醒;没勾 = 交给评分决定(没文字没分 → 不唤醒)
|
|
3577
|
+
{
|
|
3578
|
+
// ⚠️ 2026-09-15 修(主人反馈"关掉图片唤醒, 保存后又跳回勾选"):
|
|
3579
|
+
// 根因=这里只读 status 接口(lm)的字段, 而该接口的 bot.cfg 解析不到实例配置(实测一律
|
|
3580
|
+
// fallback: valueGate=log / 无 attachmentPassthrough) → 永远按默认渲染 → 看着像没保存。
|
|
3581
|
+
// 实际 settings 里早就是 image:false(读接口 ?ns= 已证实)。所以**以 lmCfg(直读配置)为准**,
|
|
3582
|
+
// status 只兜底 —— 与 09-13 修 valueGate 同一个教训: 前端别依赖需要重启才对的 host 字段。
|
|
3583
|
+
var apCfg = ((lmCfg && lmCfg.attachmentPassthrough) || lm.attachmentPassthrough || {})
|
|
3584
|
+
var apDef = { image: true, video: false, voice: false, file: false }
|
|
3585
|
+
body += '<div class="dk-row" style="gap:12px;flex-wrap:wrap;align-items:center;margin:4px 0 2px">'
|
|
3586
|
+
+ '<span style="font-size:12px;color:#666" title="勾上的类型:不管分数都唤醒她;没勾的按评分判(没文字就没分 → 不唤醒)">附件唤醒:</span>'
|
|
3587
|
+
+ [['image', '🖼 图片'], ['video', '🎬 视频'], ['voice', '🎤 语音'], ['file', '📎 文件']].map(function (k) {
|
|
3588
|
+
var on = apCfg[k[0]] === undefined ? apDef[k[0]] : apCfg[k[0]] === true
|
|
3589
|
+
return '<label style="display:inline-flex;align-items:center;gap:4px;font-size:12px;cursor:pointer"><input type="checkbox" class="dk-lm-ap" data-kind="' + k[0] + '"' + (on ? ' checked' : '') + '> ' + k[1] + '</label>'
|
|
3590
|
+
}).join('')
|
|
3591
|
+
+ '</div>'
|
|
3592
|
+
}
|
|
3562
3593
|
body += '<span class="dk-msg" id="dk-lm-hint" style="color:#2f9e44;margin:2px 0"></span>'
|
|
3563
3594
|
// 📊 最近评分(观察期): 让主人直接看到"她是怎么被叫醒的"
|
|
3564
3595
|
// 2026-09-13 二次修: 列表抽成 scoreListHtml + 独立 div, 由 refreshScoreList 做**局部刷新**
|
|
@@ -4266,11 +4297,11 @@ var QQS_CSS = ".qqs-btn{font:inherit;color:#333;background:linear-gradient(180de
|
|
|
4266
4297
|
if (keepScrollOffset == null) box.scrollTop = box.scrollHeight
|
|
4267
4298
|
else box.scrollTop = box.scrollHeight - keepScrollOffset
|
|
4268
4299
|
}
|
|
4269
|
-
// 聊天文本渲染(2026-09-13 引用消息功能):
|
|
4270
|
-
//
|
|
4300
|
+
// 聊天文本渲染(2026-09-13 引用消息功能): 把引用块渲染成"引用样式"气泡(左边框+灰底), 其余正文照常。
|
|
4301
|
+
// 2026-09-15 标记改短([引]…[/引][当前]) —— **新旧都认**, 否则老会话里的英文标记会显示成裸文本。
|
|
4271
4302
|
function chatRenderText(t) {
|
|
4272
|
-
var src = String(t || '')
|
|
4273
|
-
var re = /\[Quoted message begins\]([\s\S]*?)\[Quoted message ends\]/g
|
|
4303
|
+
var src = String(t || '').replace(/\[(?:当前|Current message)\]\s*/g, '')
|
|
4304
|
+
var re = /\[(?:引|Quoted message begins)\]([\s\S]*?)\[\/(?:引|Quoted message ends)\]/g
|
|
4274
4305
|
var parts = []
|
|
4275
4306
|
var m, last = 0
|
|
4276
4307
|
while ((m = re.exec(src)) !== null) {
|
|
@@ -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;AA2ElE,6DAA6D;AAC7D,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,eAAO,MAAM,IAAI,wBAAwB,CAAC;AAC1C,eAAO,MAAM,MAAM,UAAY,CAAC;AAShC,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":"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;AA2ElE,6DAA6D;AAC7D,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,eAAO,MAAM,IAAI,wBAAwB,CAAC;AAC1C,eAAO,MAAM,MAAM,UAAY,CAAC;AAShC,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,CAk3DvD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,GAAG,KAAK,EACtB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAwCvC"}
|
package/dist/channel-tools.js
CHANGED
|
@@ -2194,8 +2194,47 @@ export async function apply(ctx) {
|
|
|
2194
2194
|
|| process.cwd();
|
|
2195
2195
|
const defs = await loadExtensionTools(extRoot, (ctx.logger ?? console));
|
|
2196
2196
|
extDiag(`apply extRoot=${extRoot} defs=${defs.length} qqCh=${!!qqCh} bridge=${!!bridgeCh}`);
|
|
2197
|
+
// ── 同名扩展工具「热替换」(2026-09-15 主人踩坑后加) ──────────────────────
|
|
2198
|
+
// 症状: 改**已有**扩展工具的逻辑 → tools_reload 报"完成",但跑的还是旧实现
|
|
2199
|
+
// (dsh 的 registry 对重名直接抛 'already registered',这里只能 catch 跳过)。
|
|
2200
|
+
// 根因: 上一版只"新增",没有回收入口。而 `ctx.tools.register()` 其实**返回 disposer**
|
|
2201
|
+
// (dsh-tools 的 `register(definition): () => void`)→ 先 dispose 旧的再注册新的即可。
|
|
2202
|
+
// ⚠️ disposer 不能存在模块变量里: 热刷是用 `?hot=<ts>` 重新 import 本模块的,
|
|
2203
|
+
// 新模块的模块级 Map 是空的、认不出上次注册的东西 → 必须存在 **globalThis 上的
|
|
2204
|
+
// WeakMap(ctx)** 才跨模块实例可见(也顺带不污染 ctx 对象)。
|
|
2205
|
+
// 安全边界: 只 dispose"我们自己注册过、且名字对得上"的工具;别人注册的同名工具照旧走
|
|
2206
|
+
// 原来的 catch 跳过分支(行为不变)。
|
|
2207
|
+
const disposeStore = (() => {
|
|
2208
|
+
const g = globalThis;
|
|
2209
|
+
const KEY = Symbol.for('im-qqbot.extToolDisposers');
|
|
2210
|
+
let store = g[KEY];
|
|
2211
|
+
if (!store) {
|
|
2212
|
+
store = new WeakMap();
|
|
2213
|
+
g[KEY] = store;
|
|
2214
|
+
}
|
|
2215
|
+
return store;
|
|
2216
|
+
})();
|
|
2217
|
+
const myDisposers = (() => {
|
|
2218
|
+
const k = ctx;
|
|
2219
|
+
let m = disposeStore.get(k);
|
|
2220
|
+
if (!m) {
|
|
2221
|
+
m = new Map();
|
|
2222
|
+
disposeStore.set(k, m);
|
|
2223
|
+
}
|
|
2224
|
+
return m;
|
|
2225
|
+
})();
|
|
2197
2226
|
for (const def of defs) {
|
|
2198
2227
|
try {
|
|
2228
|
+
// 同一个 ctx 再来一遍(热刷)= 更新已有工具:先摘掉我们自己上次注册的那份
|
|
2229
|
+
const prev = myDisposers.get(def.name);
|
|
2230
|
+
if (prev) {
|
|
2231
|
+
try {
|
|
2232
|
+
prev();
|
|
2233
|
+
}
|
|
2234
|
+
catch { /* 旧句柄已失效,忽略 */ }
|
|
2235
|
+
myDisposers.delete(def.name);
|
|
2236
|
+
extDiag(`热替换: 先注销旧 ${def.name}`);
|
|
2237
|
+
}
|
|
2199
2238
|
const tool = defineTool({
|
|
2200
2239
|
name: def.name,
|
|
2201
2240
|
description: def.description + ' (用户扩展工具)',
|
|
@@ -2227,7 +2266,10 @@ export async function apply(ctx) {
|
|
|
2227
2266
|
}
|
|
2228
2267
|
},
|
|
2229
2268
|
});
|
|
2230
|
-
ctx.tools.register(tool);
|
|
2269
|
+
const dispose = ctx.tools.register(tool);
|
|
2270
|
+
// 收下 disposer —— 下次(热刷/重装配)靠它做同名替换,不然只能重启宿主
|
|
2271
|
+
if (typeof dispose === 'function')
|
|
2272
|
+
myDisposers.set(def.name, dispose);
|
|
2231
2273
|
ctx.logger?.info?.(`[channel-tools] 已注册扩展工具: ${def.name}`);
|
|
2232
2274
|
diag(`扩展工具注册成功: ${def.name}`);
|
|
2233
2275
|
extDiag(`注册成功: ${def.name}`);
|