@cxyhhhhh/dsh-qqbot 0.1.0-dev.202608141548 → 0.1.0-dev.202608141700

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/cordis.patch.yml CHANGED
@@ -21,4 +21,12 @@
21
21
  requireMention: true
22
22
  textChunkLimit: 4500
23
23
  sessionIdleTimeout: 1800000
24
+ maxQueue: 20
25
+ processingTimeoutMs: 120000
26
+ historyLimit: 10
27
+ access:
28
+ c2cMode: open
29
+ c2cAllow: []
30
+ groupMode: open
31
+ groupAllow: []
24
32
  debug: false
package/dist/config.d.ts CHANGED
@@ -2,6 +2,16 @@
2
2
  * dsh-im-qqbot 插件配置 Schema
3
3
  */
4
4
  import Schema from '@deepseek-ai/schemastery';
5
+ export interface AccessControlConfig {
6
+ /** C2C 访问模式 */
7
+ c2cMode: 'open' | 'allowlist' | 'disabled';
8
+ /** C2C 白名单(user openid) */
9
+ c2cAllow: string[];
10
+ /** 群聊访问模式 */
11
+ groupMode: 'open' | 'allowlist' | 'disabled';
12
+ /** 群聊白名单(group openid) */
13
+ groupAllow: string[];
14
+ }
5
15
  export interface ImQQBotConfig {
6
16
  /** QQ Bot AppID */
7
17
  appId: string;
@@ -25,6 +35,14 @@ export interface ImQQBotConfig {
25
35
  textChunkLimit: number;
26
36
  /** 每会话最大闲置时长(ms),超时自动回收 */
27
37
  sessionIdleTimeout: number;
38
+ /** 并发队列最大长度 */
39
+ maxQueue: number;
40
+ /** 处理超时(ms),超时中断当前 LLM 调用 */
41
+ processingTimeoutMs: number;
42
+ /** 群历史缓冲条数 */
43
+ historyLimit: number;
44
+ /** 访问控制 */
45
+ access: AccessControlConfig;
28
46
  /** 调试模式 */
29
47
  debug: boolean;
30
48
  }
@@ -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,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,iBAAiB;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,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,2BAA2B;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW;IACX,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,aAAa,CAa7C,CAAC"}
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,iBAAiB;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,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,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,WAAW;IACX,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,aAAa,CA2B7C,CAAC"}
package/dist/config.js CHANGED
@@ -14,6 +14,20 @@ export const ConfigSchema = Schema.object({
14
14
  directPrompt: Schema.string().description('私聊额外system prompt'),
15
15
  textChunkLimit: Schema.number().default(4500).description('单条消息最大字符数'),
16
16
  sessionIdleTimeout: Schema.number().default(30 * 60 * 1000).description('会话闲置超时(ms)'),
17
+ maxQueue: Schema.number().default(20).description('并发队列最大长度'),
18
+ processingTimeoutMs: Schema.number().default(120000).description('处理超时(ms)'),
19
+ historyLimit: Schema.number().default(10).description('群历史缓冲条数'),
20
+ access: Schema.object({
21
+ c2cMode: Schema.union(['open', 'allowlist', 'disabled']).default('open').description('C2C访问模式'),
22
+ c2cAllow: Schema.array(Schema.string()).default([]).description('C2C白名单'),
23
+ groupMode: Schema.union(['open', 'allowlist', 'disabled']).default('open').description('群聊访问模式'),
24
+ groupAllow: Schema.array(Schema.string()).default([]).description('群聊白名单'),
25
+ }).default({
26
+ c2cMode: 'open',
27
+ c2cAllow: [],
28
+ groupMode: 'open',
29
+ groupAllow: [],
30
+ }).description('访问控制'),
17
31
  debug: Schema.boolean().default(false),
18
32
  });
19
33
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,MAAM,MAAM,0BAA0B,CAAC;AA6B9C,MAAM,CAAC,MAAM,YAAY,GAA0B,MAAM,CAAC,MAAM,CAAC;IAC/D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC;IAC9D,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC;IACtE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,mBAAmB,CAAC;IAC1D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,YAAY,CAAC;IAChD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,iBAAiB,CAAC;IACtD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,yBAAyB,CAAC;IACxE,cAAc,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC;IAC1E,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,mBAAmB,CAAC;IAC7D,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,mBAAmB,CAAC;IAC9D,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC;IACtE,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC;IACrF,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CACvC,CAAC,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,MAAM,MAAM,0BAA0B,CAAC;AAgD9C,MAAM,CAAC,MAAM,YAAY,GAA0B,MAAM,CAAC,MAAM,CAAC;IAC/D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC;IAC9D,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC;IACtE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,mBAAmB,CAAC;IAC1D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,YAAY,CAAC;IAChD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,iBAAiB,CAAC;IACtD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,yBAAyB,CAAC;IACxE,cAAc,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC;IAC1E,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,mBAAmB,CAAC;IAC7D,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,mBAAmB,CAAC;IAC9D,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC;IACtE,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC;IACrF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC;IAC7D,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC;IAC5E,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC;IAChE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC;QAC/F,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC;QACzE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC;QAChG,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC;KAC3E,CAAC,CAAC,OAAO,CAAC;QACT,OAAO,EAAE,MAAM;QACf,QAAQ,EAAE,EAAE;QACZ,SAAS,EAAE,MAAM;QACjB,UAAU,EAAE,EAAE;KACf,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CACvC,CAAC,CAAC"}
package/dist/inbound.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { SessionManager } from './session-manager.js';
2
2
  import type { ImQQBotConfig } from './config.js';
3
3
  import type { Logger } from './types.js';
4
4
  /**
5
- * 处理 QQ 入站消息
5
+ * 处理 QQ 入站消息(已经过 SDK 中间件链)
6
6
  */
7
- export declare function handleInbound(rawMsg: unknown, manager: SessionManager, config: ImQQBotConfig, logger: Logger): Promise<void>;
7
+ export declare function handleInbound(rawMsg: unknown, manager: SessionManager, _config: ImQQBotConfig, logger: Logger, state?: Record<string, unknown>): Promise<void>;
8
8
  //# sourceMappingURL=inbound.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../src/inbound.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAa,MAAM,EAAe,MAAM,YAAY,CAAC;AAkBjE;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAuDf"}
1
+ {"version":3,"file":"inbound.d.ts","sourceRoot":"","sources":["../src/inbound.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAa,MAAM,EAAe,MAAM,YAAY,CAAC;AAsEjE;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,IAAI,CAAC,CA8Cf"}
package/dist/inbound.js CHANGED
@@ -1,36 +1,27 @@
1
1
  import { createUserMessage } from '@deepseek-ai/dsh-llm';
2
- import { detectMention, stripMention } from './mention.js';
2
+ // ── 主处理函数 ──
3
3
  /**
4
- * 处理 QQ 入站消息
4
+ * 处理 QQ 入站消息(已经过 SDK 中间件链)
5
5
  */
6
- export async function handleInbound(rawMsg, manager, config, logger) {
6
+ export async function handleInbound(rawMsg, manager, _config, logger, state) {
7
7
  const msg = rawMsg;
8
- // 从 SDK 消息中提取关键字段
8
+ const mwState = (state ?? {});
9
9
  const scope = msg.kind === 'group' ? 'group' : 'c2c';
10
10
  const peerId = scope === 'group' ? (msg.groupOpenid ?? msg.senderId) : msg.senderId;
11
- // 构造 replyTarget(用于出站回复)
12
11
  const replyTarget = {
13
12
  scope,
14
13
  targetId: peerId,
15
14
  msgId: msg.messageId,
16
15
  };
17
- console.log(`[im-qqbot] Processing: scope=${scope} peerId=${peerId} content="${msg.content}"`);
18
- // ── 群消息 @mention 门控 ──
19
- if (scope === 'group' && config.requireMention) {
20
- if (!detectMention(msg.content)) {
21
- return;
22
- }
23
- }
24
- // ── 提取并清理文本 ──
25
- let text = msg.content?.trim() ?? '';
26
- if (scope === 'group') {
27
- text = stripMention(text);
28
- }
29
- if (!text)
16
+ // ── 组装 agentBody(对齐 openclaw-qqbot body-assembler) ──
17
+ const agentBody = assembleAgentBody(msg, mwState, scope, logger);
18
+ if (!agentBody)
30
19
  return;
31
- // ── 命令处理 ──
20
+ console.log(`[im-qqbot] Processing: scope=${scope} peerId=${peerId} body="${agentBody.slice(0, 120000)}"`);
21
+ // ── 命令兜底(SDK slashCommand 已处理大部分) ──
22
+ const text = (msg.content ?? '').trim();
32
23
  if (text.startsWith('/')) {
33
- const handled = handleCommand(text, scope, peerId, manager, logger);
24
+ const handled = handleCommand(text, scope, peerId, manager);
34
25
  if (handled)
35
26
  return;
36
27
  }
@@ -44,18 +35,230 @@ export async function handleInbound(rawMsg, manager, config, logger) {
44
35
  return;
45
36
  }
46
37
  // ── 构建 UserMessage → followup ──
47
- const content = [{ type: 'text', text }];
38
+ const content = [{ type: 'text', text: agentBody }];
48
39
  const message = createUserMessage({
49
40
  content,
50
41
  source: { kind: 'user' },
51
42
  });
52
43
  record.agent.followup(message);
53
- console.log(`[im-qqbot] → followup sent: key=${scope}:${peerId} text="${text}"`);
44
+ console.log(`[im-qqbot] → followup sent: key=${scope}:${peerId}`);
45
+ }
46
+ // ══════════════════════════════════════════════════════════════
47
+ // Body Assembly(对齐 openclaw-qqbot 5 层组装)
48
+ // ══════════════════════════════════════════════════════════════
49
+ /**
50
+ * 组装 agentBody — AI 实际看到的完整上下文
51
+ */
52
+ function assembleAgentBody(msg, state, scope, logger) {
53
+ // Layer 1: userContent — 用户文本 + 语音转录 + 附件描述
54
+ const userContent = buildUserContent(msg, state, logger);
55
+ // 无任何可处理内容时跳过
56
+ if (!userContent && (!msg.attachments || msg.attachments.length === 0))
57
+ return null;
58
+ // Layer 2: quotePart — 引用消息块
59
+ const quotePart = buildQuotePart(state.quote);
60
+ // Layer 3: userMessage — 带发送者标签的用户消息
61
+ const isGroup = scope === 'group';
62
+ const wasMentioned = state.mention?.wasMentioned ?? false;
63
+ const userMessage = buildUserMessage(userContent, quotePart, msg.senderId, isGroup, wasMentioned);
64
+ // Layer 4: dynamicCtx — 媒体元数据块
65
+ const dynamicCtx = buildDynamicCtx(msg, state);
66
+ // Layer 5: agentBody — history + base 拼合
67
+ const base = dynamicCtx ? `${dynamicCtx}${userMessage}` : userMessage;
68
+ const agentBody = buildAgentBody(base, state.history, isGroup, wasMentioned);
69
+ return agentBody;
54
70
  }
55
71
  /**
56
- * 处理内置命令
72
+ * Layer 1: 用户文本内容 + 语音 + 附件
57
73
  */
58
- function handleCommand(text, scope, peerId, manager, _logger) {
74
+ function buildUserContent(msg, state, logger) {
75
+ const parts = [];
76
+ // 清洗后的文本内容
77
+ const text = (msg.content ?? '').trim();
78
+ if (text) {
79
+ parts.push(text);
80
+ }
81
+ // 语音消息处理
82
+ const voiceTexts = extractVoiceTexts(msg.attachments, state.processedAttachments, logger);
83
+ if (voiceTexts.length > 0) {
84
+ for (const vt of voiceTexts) {
85
+ const durationTag = vt.duration ? ` (${vt.duration}s)` : '';
86
+ parts.push(`[Voice message${durationTag}] ${vt.text}`);
87
+ }
88
+ }
89
+ // 其他附件描述
90
+ const otherAttachments = describeAttachments(msg.attachments, state.processedAttachments);
91
+ if (otherAttachments) {
92
+ parts.push(otherAttachments);
93
+ }
94
+ return parts.join('\n');
95
+ }
96
+ /**
97
+ * Layer 2: 引用消息块
98
+ */
99
+ function buildQuotePart(quote) {
100
+ if (!quote?.text && !quote?.entry?.content)
101
+ return '';
102
+ const quoteText = quote.text || quote.entry?.content || 'Original content unavailable';
103
+ return `[Quoted message begins]\n${quoteText}\n[Quoted message ends]\n[Current message]\n`;
104
+ }
105
+ /**
106
+ * Layer 3: 带发送者标签的用户消息
107
+ */
108
+ function buildUserMessage(userContent, quotePart, senderId, isGroup, wasMentioned) {
109
+ if (!isGroup) {
110
+ // 私聊:无发送者标签
111
+ return `${quotePart}${userContent}`;
112
+ }
113
+ // 群聊:[Sender (openid)] content (@you)
114
+ const mentionTag = wasMentioned ? ' (@you)' : '';
115
+ const senderTag = `[${senderId.slice(0, 8)} (${senderId})]`;
116
+ return `${quotePart}${senderTag} ${userContent}${mentionTag}`;
117
+ }
118
+ /**
119
+ * Layer 4: 媒体元数据上下文
120
+ */
121
+ function buildDynamicCtx(msg, state) {
122
+ const lines = [];
123
+ if (!msg.attachments || msg.attachments.length === 0)
124
+ return '';
125
+ // 图片 URL
126
+ const images = msg.attachments.filter(a => a.content_type === 'image');
127
+ if (images.length > 0) {
128
+ const urls = images.map(a => a.url).filter(Boolean);
129
+ if (urls.length > 0) {
130
+ lines.push(`- Images: ${urls.join(', ')}`);
131
+ }
132
+ }
133
+ // 语音文件
134
+ const voices = msg.attachments.filter(a => a.content_type === 'voice');
135
+ if (voices.length > 0) {
136
+ const urls = voices.map(a => a.url).filter(Boolean);
137
+ if (urls.length > 0) {
138
+ lines.push(`- Voice: ${urls.join(', ')}`);
139
+ }
140
+ // ASR 原始文本
141
+ const asrTexts = voices.map(a => a.asr_refer_text).filter(Boolean);
142
+ if (asrTexts.length > 0) {
143
+ lines.push(`- ASR: ${asrTexts.join(' | ')}`);
144
+ }
145
+ }
146
+ // 视频
147
+ const videos = msg.attachments.filter(a => a.content_type === 'video');
148
+ if (videos.length > 0) {
149
+ lines.push(`- Videos: ${videos.map(a => a.filename).join(', ')}`);
150
+ }
151
+ // 文件
152
+ const files = msg.attachments.filter(a => a.content_type === 'file');
153
+ if (files.length > 0) {
154
+ lines.push(`- Files: ${files.map(a => `${a.filename} (${formatFileSize(a.size)})`).join(', ')}`);
155
+ }
156
+ if (lines.length === 0)
157
+ return '';
158
+ // 引用消息中的附件
159
+ const quoteAttachments = state.quote?.attachments;
160
+ if (quoteAttachments && quoteAttachments.length > 0) {
161
+ lines.push('[Reference attachments]');
162
+ for (const qa of quoteAttachments) {
163
+ const label = qa.asrText ? `Voice: ${qa.asrText}` : (qa.filename ?? qa.contentType ?? 'attachment');
164
+ lines.push(` - ${label}`);
165
+ }
166
+ }
167
+ return lines.join('\n') + '\n\n';
168
+ }
169
+ /**
170
+ * Layer 5: 最终 agentBody 拼合
171
+ */
172
+ function buildAgentBody(base, history, isGroup, wasMentioned) {
173
+ // 非群聊或未被@或无历史:直接返回 base
174
+ if (!isGroup || !wasMentioned || !history || history.length === 0) {
175
+ return base;
176
+ }
177
+ // 群聊被@且有历史:前置 history
178
+ const historyLines = history.map(h => {
179
+ const name = h.senderName ?? h.senderId.slice(0, 8);
180
+ return `[${name} (${h.senderId})] ${h.content}`;
181
+ });
182
+ return [
183
+ '[Chat history begins]',
184
+ ...historyLines,
185
+ '',
186
+ '[Chat history ends]',
187
+ '[Current message]',
188
+ base,
189
+ ].join('\n');
190
+ }
191
+ /**
192
+ * 提取语音转录文本
193
+ * 优先级:processedAttachments.voiceText > attachment.asr_refer_text
194
+ */
195
+ function extractVoiceTexts(attachments, processed, _logger) {
196
+ const results = [];
197
+ // 优先使用中间件处理后的结果(含 STT)
198
+ if (processed) {
199
+ for (const pa of processed) {
200
+ if (pa.type === 'voice' && pa.voiceText) {
201
+ results.push({
202
+ text: pa.voiceText,
203
+ duration: pa.duration,
204
+ source: pa.voiceSource ?? 'stt',
205
+ });
206
+ }
207
+ }
208
+ }
209
+ // 回退到原始附件的 ASR 文本
210
+ if (results.length === 0 && attachments) {
211
+ for (const att of attachments) {
212
+ if (att.content_type === 'voice' && att.asr_refer_text) {
213
+ results.push({
214
+ text: att.asr_refer_text.trim(),
215
+ source: 'asr',
216
+ });
217
+ }
218
+ }
219
+ }
220
+ return results;
221
+ }
222
+ /**
223
+ * 描述非语音附件
224
+ */
225
+ function describeAttachments(attachments, _processed) {
226
+ if (!attachments || attachments.length === 0)
227
+ return '';
228
+ const parts = [];
229
+ for (const att of attachments) {
230
+ switch (att.content_type) {
231
+ case 'voice':
232
+ // 语音已在 voiceTexts 中处理
233
+ break;
234
+ case 'image': {
235
+ const dim = att.width && att.height ? ` ${att.width}×${att.height}` : '';
236
+ parts.push(`[Image: ${att.filename}${dim}]`);
237
+ break;
238
+ }
239
+ case 'video':
240
+ parts.push(`[Video: ${att.filename}]`);
241
+ break;
242
+ case 'file':
243
+ parts.push(`[File: ${att.filename} (${formatFileSize(att.size)})]`);
244
+ break;
245
+ default:
246
+ parts.push(`[Attachment: ${att.filename ?? att.content_type}]`);
247
+ break;
248
+ }
249
+ }
250
+ return parts.join('\n');
251
+ }
252
+ /** 格式化文件大小 */
253
+ function formatFileSize(bytes) {
254
+ if (bytes < 1024)
255
+ return `${bytes}B`;
256
+ if (bytes < 1024 * 1024)
257
+ return `${(bytes / 1024).toFixed(1)}KB`;
258
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
259
+ }
260
+ // ── 命令兜底 ──
261
+ function handleCommand(text, scope, peerId, manager) {
59
262
  const cmd = text.split(/\s+/)[0]?.toLowerCase();
60
263
  switch (cmd) {
61
264
  case '/reset':
@@ -1 +1 @@
1
- {"version":3,"file":"inbound.js","sourceRoot":"","sources":["../src/inbound.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inbound.js","sourceRoot":"","sources":["../src/inbound.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  * dsh-im-qqbot — QQ Bot IM channel plugin for deepseek-harness
3
3
  *
4
4
  * Cordis 插件入口。将 QQ 消息平台作为 dsh 的前端协议驱动。
5
+ * 复用 @tencent-connect/qqbot-nodejs SDK 全套中间件链。
5
6
  */
6
7
  import type { Context } from '@deepseek-ai/cordis';
7
8
  import { type ImQQBotConfig } from './config.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAO/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,CAiB9E"}
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;AAqBnD,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAkB/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;AAKjD,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC9E"}
package/dist/index.js CHANGED
@@ -1,22 +1,47 @@
1
- import { QQBot } from '@tencent-connect/qqbot-nodejs';
1
+ import { fileURLToPath } from 'node:url';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { QQBot, errorHandler, messageFilter, accessPolicy, mentionGate, contentSanitizer, rateLimiter, slashCommand, concurrencyGuard, typingIndicator, quoteRef, historyBuffer, envelopeFormatter, MemoryHistoryStore, } from '@tencent-connect/qqbot-nodejs';
2
4
  import { ConfigSchema } from './config.js';
3
5
  import { SessionManager } from './session-manager.js';
4
6
  import { handleInbound } from './inbound.js';
5
7
  import { createOutboundHandler } from './outbound.js';
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ const PLUGIN_ROOT = resolve(__dirname, '..');
11
+ /** 从插件安装路径推导 profile 目录(node_modules 的父目录) */
12
+ function getProfileDir() {
13
+ const nmIdx = PLUGIN_ROOT.lastIndexOf('/node_modules/');
14
+ if (nmIdx > 0)
15
+ return PLUGIN_ROOT.slice(0, nmIdx);
16
+ return null;
17
+ }
6
18
  // ── Cordis 插件元数据 ──
7
19
  export const name = 'im-qqbot';
8
20
  export const inject = ['agents'];
9
21
  export const Config = ConfigSchema;
22
+ import { runQrSetup, persistCredentialsToProfile } from './setup.js';
10
23
  // ── 插件主体 ──
11
24
  export async function apply(ctx, config) {
12
25
  const agents = ctx.agents;
13
26
  const logger = ctx.logger ?? console;
14
27
  console.log('[im-qqbot] apply() called');
15
- const appId = resolveEnv(config.appId, 'QQBOT_APPID');
16
- const appSecret = resolveEnv(config.appSecret, 'QQBOT_SECRET');
28
+ let appId = resolveEnv(config.appId, 'QQBOT_APPID');
29
+ let appSecret = resolveEnv(config.appSecret, 'QQBOT_SECRET');
30
+ // ── 凭据缺失时唤起扫码绑定 ──
17
31
  if (!appId || !appSecret) {
18
- console.error('[im-qqbot] ERROR: Missing QQBOT_APPID or QQBOT_SECRET');
19
- return;
32
+ console.log('[im-qqbot] 凭据未配置,尝试扫码绑定...');
33
+ const credentials = await runQrSetup();
34
+ if (!credentials) {
35
+ console.error('[im-qqbot] ERROR: 无法获取 QQ Bot 凭据,插件未启动');
36
+ return;
37
+ }
38
+ appId = credentials.appId;
39
+ appSecret = credentials.appSecret;
40
+ // 持久化到 profile 配置
41
+ persistCredentialsToProfile(credentials, getProfileDir() ?? undefined);
42
+ // 同时写入环境变量,使本次运行的其他组件也能读取
43
+ process.env.QQBOT_APPID = appId;
44
+ process.env.QQBOT_SECRET = appSecret;
20
45
  }
21
46
  const resolvedConfig = { ...config, appId, appSecret };
22
47
  await bootstrap(ctx, agents, resolvedConfig, logger);
@@ -31,10 +56,84 @@ async function bootstrap(ctx, agents, config, logger) {
31
56
  logger,
32
57
  });
33
58
  console.log('[im-qqbot] QQBot SDK initialized');
34
- // ── 入站 ──
35
- bot.on('message', async (_mqCtx, msg) => {
36
- console.log('[im-qqbot] ← message received:', JSON.stringify(msg, null, 2).slice(0, 500));
37
- await handleInbound(msg, manager, config, logger);
59
+ // ══════════════════════════════════════════════════════════════
60
+ // SDK 中间件链(洋葱模型,按执行顺序编排)
61
+ // ══════════════════════════════════════════════════════════════
62
+ // 1. 错误兜底(最外层洋葱皮)
63
+ bot.use(errorHandler());
64
+ // 2. 消息过滤:bot 回声 + 消息去重
65
+ bot.use(messageFilter({ skipSelfEcho: false }));
66
+ // 3. 访问控制(白名单/开放/禁用)
67
+ bot.use(accessPolicy({
68
+ c2c: {
69
+ mode: config.access.c2cMode,
70
+ allow: config.access.c2cAllow.length > 0 ? config.access.c2cAllow : ['*'],
71
+ },
72
+ group: {
73
+ mode: config.access.groupMode,
74
+ allow: config.access.groupAllow.length > 0 ? config.access.groupAllow : ['*'],
75
+ },
76
+ onBlock: (_mCtx, reason) => {
77
+ if (config.debug) {
78
+ console.log(`[im-qqbot] Access blocked: ${reason}`);
79
+ }
80
+ },
81
+ }));
82
+ // 4. 群历史缓冲 — 放在门控之前,确保所有消息(含未 @bot)都计入上下文
83
+ const historyStore = new MemoryHistoryStore();
84
+ bot.use(historyBuffer({
85
+ limit: config.historyLimit,
86
+ store: historyStore,
87
+ recordOnSkip: true,
88
+ }));
89
+ // 5. 群聊 @bot 门控
90
+ bot.use(mentionGate({
91
+ requireMentionInGroup: config.requireMention,
92
+ }));
93
+ // 6. 内容清洗(去 @marker、表情标签、多余空白)
94
+ bot.use(contentSanitizer({
95
+ parseFaceTags: true,
96
+ }));
97
+ // 7. 三层限流(sender / group / global)
98
+ bot.use(rateLimiter());
99
+ // 8. 斜杠命令(在 concurrencyGuard 之前,命令匹配后不排队直接响应)
100
+ const slash = slashCommand({
101
+ autoHelp: true,
102
+ commands: buildCommands(manager, config),
103
+ });
104
+ bot.use(slash.middleware);
105
+ // 9. 并发串行 + 消息合并(同 peer 排队,避免 session 冲突)
106
+ bot.use(concurrencyGuard({
107
+ strategy: 'merge',
108
+ maxQueue: config.maxQueue,
109
+ maxProcessingMs: config.processingTimeoutMs,
110
+ urgentPredicate: (mCtx) => {
111
+ return (mCtx.message.content ?? '').trim() === '/stop';
112
+ },
113
+ }));
114
+ // 10. C2C 输入状态指示
115
+ bot.use(typingIndicator());
116
+ // 11. 引用消息解析(记录 + 解析被引用原文)
117
+ bot.use(quoteRef({
118
+ maxSize: 500,
119
+ preferMsgElements: true,
120
+ }));
121
+ // 12. 上下文组装(将 history + quote + sender 组成 envelope)
122
+ bot.use(envelopeFormatter({
123
+ historyLimit: config.historyLimit,
124
+ includeQuote: true,
125
+ includeSender: true,
126
+ }));
127
+ // ══════════════════════════════════════════════════════════════
128
+ // 最终处理:经过中间件链后的消息交给 dsh agent
129
+ // ══════════════════════════════════════════════════════════════
130
+ bot.on('message', async (mCtx) => {
131
+ const msg = mCtx.message;
132
+ if (config.debug) {
133
+ console.log('[im-qqbot] ← message (post-middleware):', JSON.stringify(msg, null, 2).slice(0, 500));
134
+ }
135
+ // 将中间件 state 中的 envelope/quote/history 传递给 inbound handler
136
+ await handleInbound(msg, manager, config, logger, mCtx.state);
38
137
  });
39
138
  // ── 出站 ──
40
139
  const outboundHandler = createOutboundHandler(manager, bot, config, logger);
@@ -58,6 +157,41 @@ async function bootstrap(ctx, agents, config, logger) {
58
157
  };
59
158
  }, 'im-qqbot.lifecycle');
60
159
  }
160
+ // ── 斜杠命令定义 ──
161
+ function buildCommands(manager, config) {
162
+ return [
163
+ {
164
+ name: ['reset', 'clear'],
165
+ description: '重置当前会话(清除上下文)',
166
+ handler: (cmdCtx) => {
167
+ const msg = cmdCtx.message;
168
+ const scope = msg.kind === 'group' ? 'group' : 'c2c';
169
+ const peerId = scope === 'group'
170
+ ? (msg.groupOpenid ?? msg.senderId)
171
+ : msg.senderId;
172
+ void manager.remove(scope, peerId);
173
+ return '会话已重置 ✓';
174
+ },
175
+ },
176
+ {
177
+ name: 'ping',
178
+ description: '连通性测试',
179
+ handler: () => 'pong 🏓',
180
+ },
181
+ {
182
+ name: 'version',
183
+ description: '查看版本信息',
184
+ handler: () => `dsh-qqbot v0.1.0 | model: ${config.model ?? 'deepseek-chat'}`,
185
+ },
186
+ {
187
+ name: 'stop',
188
+ description: '中止当前生成',
189
+ hidden: true,
190
+ handler: () => ({ kind: 'noop' }),
191
+ },
192
+ ];
193
+ }
194
+ // ── 工具函数 ──
61
195
  function resolveEnv(configValue, envKey) {
62
196
  if (configValue && configValue !== '__FROM_ENV__' && !configValue.startsWith('process.env')) {
63
197
  return configValue;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /** 凭据结果 */
2
+ export interface SetupCredentials {
3
+ appId: string;
4
+ appSecret: string;
5
+ }
6
+ /**
7
+ * 执行 QR 扫码绑定,获取 QQ Bot 凭据
8
+ *
9
+ * 使用动态 import 加载 qqbot-connector(可能未安装),
10
+ * 在终端打印二维码等待用户扫码。
11
+ */
12
+ export declare function runQrSetup(source?: string): Promise<SetupCredentials | null>;
13
+ /**
14
+ * 将凭据写入 dsh profile 的 cordis.patch.yml
15
+ *
16
+ * 在已有 `id: im-qqbot` 条目的 config 段中写入 appId/appSecret。
17
+ * 写入后下次启动无需再次扫码。
18
+ */
19
+ export declare function persistCredentialsToProfile(credentials: SetupCredentials, profileDir?: string): boolean;
20
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAUA,WAAW;AACX,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,MAAM,SAAc,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAwCvF;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,gBAAgB,EAC7B,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAsDT"}
package/dist/setup.js ADDED
@@ -0,0 +1,117 @@
1
+ /**
2
+ * QQ Bot 凭据初始化 — 扫码绑定
3
+ *
4
+ * 当 appId/appSecret 未配置时,通过 @tencent-connect/qqbot-connector
5
+ * 唤起终端扫码流程获取凭据,并写入 dsh profile 配置。
6
+ */
7
+ import { resolve } from 'node:path';
8
+ import { readFileSync, writeFileSync, existsSync } from 'node:fs';
9
+ import { qrConnect } from '@tencent-connect/qqbot-connector';
10
+ /**
11
+ * 执行 QR 扫码绑定,获取 QQ Bot 凭据
12
+ *
13
+ * 使用动态 import 加载 qqbot-connector(可能未安装),
14
+ * 在终端打印二维码等待用户扫码。
15
+ */
16
+ export async function runQrSetup(source = 'dsh-qqbot') {
17
+ console.log('\n══════════════════════════════════════════════════════');
18
+ console.log(' QQ Bot 凭据未配置,启动扫码绑定');
19
+ console.log('══════════════════════════════════════════════════════\n');
20
+ try {
21
+ console.log('请使用手机 QQ 扫描下方二维码完成绑定...\n');
22
+ const credentials = await qrConnect({ source });
23
+ if (!credentials || credentials.length === 0) {
24
+ console.error('[im-qqbot] 扫码未返回凭据');
25
+ return null;
26
+ }
27
+ const cred = credentials[0];
28
+ if (!cred) {
29
+ console.error('[im-qqbot] 扫码未返回有效凭据');
30
+ return null;
31
+ }
32
+ console.log(`\n✔ 绑定成功!AppID: ${cred.appId}\n`);
33
+ return {
34
+ appId: cred.appId,
35
+ appSecret: cred.appSecret,
36
+ };
37
+ }
38
+ catch (err) {
39
+ const msg = err instanceof Error ? err.message : String(err);
40
+ if (msg.includes('Cannot find') || msg.includes('ERR_MODULE_NOT_FOUND')) {
41
+ console.error('[im-qqbot] @tencent-connect/qqbot-connector 未安装,无法扫码绑定');
42
+ console.error('[im-qqbot] 请通过环境变量配置:');
43
+ console.error(' export QQBOT_APPID="你的AppID"');
44
+ console.error(' export QQBOT_SECRET="你的AppSecret"');
45
+ }
46
+ else {
47
+ console.error(`[im-qqbot] 扫码绑定失败: ${msg}`);
48
+ }
49
+ return null;
50
+ }
51
+ }
52
+ /**
53
+ * 将凭据写入 dsh profile 的 cordis.patch.yml
54
+ *
55
+ * 在已有 `id: im-qqbot` 条目的 config 段中写入 appId/appSecret。
56
+ * 写入后下次启动无需再次扫码。
57
+ */
58
+ export function persistCredentialsToProfile(credentials, profileDir) {
59
+ const dir = profileDir;
60
+ if (!dir) {
61
+ printManualInstructions(credentials);
62
+ return false;
63
+ }
64
+ const patchPath = resolve(dir, 'cordis.patch.yml');
65
+ try {
66
+ let content;
67
+ if (existsSync(patchPath)) {
68
+ content = readFileSync(patchPath, 'utf8');
69
+ if (content.trim() === '[]' || content.trim() === '') {
70
+ // 空文件,写入完整条目
71
+ content = buildPatchContent(credentials);
72
+ }
73
+ else if (content.includes('id: im-qqbot')) {
74
+ // 已有 im-qqbot 条目
75
+ if (content.includes('appId:')) {
76
+ // 替换已有的 appId/appSecret
77
+ content = content.replace(/appId:\s*.*/, `appId: '${credentials.appId}'`);
78
+ content = content.replace(/appSecret:\s*.*/, `appSecret: '${credentials.appSecret}'`);
79
+ }
80
+ else {
81
+ // config 段存在但没有 appId,在 config: 后插入
82
+ content = content.replace(/(id: im-qqbot\s*\n\s*config:\s*\n)/, `$1 appId: '${credentials.appId}'\n appSecret: '${credentials.appSecret}'\n`);
83
+ }
84
+ }
85
+ else {
86
+ // 没有 im-qqbot 条目,追加
87
+ content = content.trimEnd() + '\n' + buildPatchContent(credentials);
88
+ }
89
+ }
90
+ else {
91
+ content = buildPatchContent(credentials);
92
+ }
93
+ writeFileSync(patchPath, content, 'utf8');
94
+ console.log(`[im-qqbot] ✔ 凭据已写入: ${patchPath}`);
95
+ console.log(`[im-qqbot] 下次启动将自动使用保存的凭据\n`);
96
+ return true;
97
+ }
98
+ catch (err) {
99
+ console.warn(`[im-qqbot] 写入配置失败: ${err instanceof Error ? err.message : String(err)}`);
100
+ printManualInstructions(credentials);
101
+ return false;
102
+ }
103
+ }
104
+ function printManualInstructions(credentials) {
105
+ console.warn('[im-qqbot] 无法自动保存凭据,请手动设置环境变量:');
106
+ console.warn(` export QQBOT_APPID="${credentials.appId}"`);
107
+ console.warn(` export QQBOT_SECRET="${credentials.appSecret}"`);
108
+ }
109
+ function buildPatchContent(creds) {
110
+ return `# QQ Bot 凭据(扫码绑定自动生成)
111
+ - id: im-qqbot
112
+ config:
113
+ appId: '${creds.appId}'
114
+ appSecret: '${creds.appSecret}'
115
+ `;
116
+ }
117
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cxyhhhhh/dsh-qqbot",
3
- "version": "0.1.0-dev.202608141548",
3
+ "version": "0.1.0-dev.202608141700",
4
4
  "description": "QQ Bot IM channel plugin for deepseek-harness (dsh)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -32,7 +32,8 @@
32
32
  }
33
33
  },
34
34
  "dependencies": {
35
- "@tencent-connect/qqbot-nodejs": "^1.0.4"
35
+ "@tencent-connect/qqbot-nodejs": "^1.0.4",
36
+ "@tencent-connect/qqbot-connector": "^1.2.0"
36
37
  },
37
38
  "peerDependencies": {
38
39
  "@deepseek-ai/cordis": ">=4.0.1",
package/dist/mention.d.ts DELETED
@@ -1,15 +0,0 @@
1
- /**
2
- * @mention 检测和清理工具
3
- *
4
- * QQ 群消息中 @bot 的格式为: <@OPENID> (十六进制字符串)
5
- * 例如: <@BD9386750A680BA80CB124E27A7B8089>
6
- */
7
- /**
8
- * 检测消息是否包含 @mention
9
- */
10
- export declare function detectMention(content: string | undefined): boolean;
11
- /**
12
- * 移除消息中的 @mention,返回干净的用户意图文本
13
- */
14
- export declare function stripMention(content: string): string;
15
- //# sourceMappingURL=mention.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mention.d.ts","sourceRoot":"","sources":["../src/mention.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAGlE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIpD"}
package/dist/mention.js DELETED
@@ -1,25 +0,0 @@
1
- /**
2
- * @mention 检测和清理工具
3
- *
4
- * QQ 群消息中 @bot 的格式为: <@OPENID> (十六进制字符串)
5
- * 例如: <@BD9386750A680BA80CB124E27A7B8089>
6
- */
7
- /** QQ @mention 格式: <@OPENID> 或 <@!OPENID>,OPENID 是十六进制或数字字符串 */
8
- const MENTION_PATTERN = /<@!?[A-Fa-f0-9]+>/g;
9
- /**
10
- * 检测消息是否包含 @mention
11
- */
12
- export function detectMention(content) {
13
- if (!content)
14
- return false;
15
- return MENTION_PATTERN.test(content);
16
- }
17
- /**
18
- * 移除消息中的 @mention,返回干净的用户意图文本
19
- */
20
- export function stripMention(content) {
21
- return content
22
- .replace(MENTION_PATTERN, '')
23
- .trim();
24
- }
25
- //# sourceMappingURL=mention.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mention.js","sourceRoot":"","sources":["../src/mention.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,gEAAgE;AAChE,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAE7C;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAA2B;IACvD,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,OAAO,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO,OAAO;SACX,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;SAC5B,IAAI,EAAE,CAAC;AACZ,CAAC"}