mioku-plugin-chat 2.6.0 → 2.7.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.
- package/configs/personalization.ts +1 -1
- package/context.ts +2 -0
- package/core/base.ts +1 -1
- package/core/chat-engine.ts +18 -7
- package/core/chat-turn.ts +26 -9
- package/core/media/image-analyzer.ts +63 -397
- package/core/prompt.ts +11 -20
- package/db.ts +8 -12
- package/handlers/idle-debug.ts +96 -97
- package/handlers/message.ts +35 -34
- package/handlers/poke.ts +102 -124
- package/humanize/emoji-agent.ts +208 -332
- package/humanize/index.ts +2 -3
- package/index.ts +32 -44
- package/manage/cooldown.ts +60 -100
- package/manage/idle-check.ts +163 -70
- package/manage/queue-processor.ts +73 -30
- package/manage/session-turn-scheduler.ts +130 -0
- package/package.json +1 -1
- package/runtime/chat-runtime.ts +14 -2
- package/types.ts +2 -19
- package/utils/config.ts +57 -0
- package/utils/message.ts +4 -7
- package/utils/queue.ts +5 -0
package/db.ts
CHANGED
|
@@ -381,6 +381,11 @@ export async function initDatabase(): Promise<ChatDatabase> {
|
|
|
381
381
|
VALUES ($hash, $url, $type, $description, $emotion, $character, $filePath, $createdAt)
|
|
382
382
|
ON CONFLICT(hash) DO UPDATE SET
|
|
383
383
|
url = excluded.url,
|
|
384
|
+
type = excluded.type,
|
|
385
|
+
description = excluded.description,
|
|
386
|
+
emotion = excluded.emotion,
|
|
387
|
+
character = excluded.character,
|
|
388
|
+
file_path = excluded.file_path,
|
|
384
389
|
created_at = excluded.created_at
|
|
385
390
|
`),
|
|
386
391
|
getImageByHash: db.prepare(`SELECT * FROM images WHERE hash = $hash`),
|
|
@@ -710,9 +715,9 @@ export async function initDatabase(): Promise<ChatDatabase> {
|
|
|
710
715
|
$url: image.url,
|
|
711
716
|
$type: image.type,
|
|
712
717
|
$description: image.description,
|
|
713
|
-
$emotion:
|
|
714
|
-
$character:
|
|
715
|
-
$filePath:
|
|
718
|
+
$emotion: null,
|
|
719
|
+
$character: null,
|
|
720
|
+
$filePath: null,
|
|
716
721
|
$createdAt: image.createdAt,
|
|
717
722
|
});
|
|
718
723
|
},
|
|
@@ -726,9 +731,6 @@ export async function initDatabase(): Promise<ChatDatabase> {
|
|
|
726
731
|
url: row.url,
|
|
727
732
|
type: row.type,
|
|
728
733
|
description: row.description,
|
|
729
|
-
emotion: row.emotion,
|
|
730
|
-
character: row.character,
|
|
731
|
-
filePath: row.file_path,
|
|
732
734
|
createdAt: row.created_at,
|
|
733
735
|
};
|
|
734
736
|
},
|
|
@@ -742,9 +744,6 @@ export async function initDatabase(): Promise<ChatDatabase> {
|
|
|
742
744
|
url: row.url,
|
|
743
745
|
type: row.type,
|
|
744
746
|
description: row.description,
|
|
745
|
-
emotion: row.emotion,
|
|
746
|
-
character: row.character,
|
|
747
|
-
filePath: row.file_path,
|
|
748
747
|
createdAt: row.created_at,
|
|
749
748
|
};
|
|
750
749
|
},
|
|
@@ -757,9 +756,6 @@ export async function initDatabase(): Promise<ChatDatabase> {
|
|
|
757
756
|
url: row.url,
|
|
758
757
|
type: row.type,
|
|
759
758
|
description: row.description,
|
|
760
|
-
emotion: row.emotion,
|
|
761
|
-
character: row.character,
|
|
762
|
-
filePath: row.file_path,
|
|
763
759
|
createdAt: row.created_at,
|
|
764
760
|
}));
|
|
765
761
|
},
|
package/handlers/idle-debug.ts
CHANGED
|
@@ -2,8 +2,8 @@ import type { MiokiContext } from "mioki";
|
|
|
2
2
|
import type { AIService } from "mioku";
|
|
3
3
|
import type { ChatPluginContext } from "../context";
|
|
4
4
|
import type { ChatConfig, TargetMessage } from "../types";
|
|
5
|
+
import { finalizeChatTurn } from "../core/chat-turn";
|
|
5
6
|
import { getBotRole } from "../utils";
|
|
6
|
-
import { buildStructuredUserInputFromTarget } from "../manage/group-structured-history";
|
|
7
7
|
|
|
8
8
|
export async function handleIdleCheckDebug(
|
|
9
9
|
pluginCtx: ChatPluginContext,
|
|
@@ -16,7 +16,8 @@ export async function handleIdleCheckDebug(
|
|
|
16
16
|
await e.reply("只有主人才能使用这个指令~");
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
-
const groupIdStr =
|
|
19
|
+
const groupIdStr =
|
|
20
|
+
e.message[0]?.text?.replace("/空闲检查", "")?.trim() || "";
|
|
20
21
|
const targetGroupId = parseInt(groupIdStr, 10);
|
|
21
22
|
if (!targetGroupId) {
|
|
22
23
|
await e.reply("请指定群号,如:/空闲检查 123456");
|
|
@@ -25,108 +26,106 @@ export async function handleIdleCheckDebug(
|
|
|
25
26
|
|
|
26
27
|
const groupSessionId = `group:${targetGroupId}`;
|
|
27
28
|
try {
|
|
28
|
-
|
|
29
|
-
const botNickname =
|
|
30
|
-
cfg.nicknames[0] || ctx.pickBot(e.self_id).nickname || "Bot";
|
|
31
|
-
ctx.logger.info(`[Debug] Manual idle check: group ${targetGroupId}`);
|
|
32
|
-
|
|
33
|
-
const { history } = await pluginCtx.getGroupHistoryMessages(
|
|
34
|
-
targetGroupId,
|
|
35
|
-
groupSessionId,
|
|
36
|
-
ctx,
|
|
37
|
-
cfg.historyCount,
|
|
38
|
-
pluginCtx.db,
|
|
39
|
-
e.self_id,
|
|
40
|
-
pluginCtx.buildHistoryMediaOptions(pluginCtx.aiInstance, cfg),
|
|
41
|
-
);
|
|
42
|
-
const planResult = await pluginCtx.humanize.actionPlanner.plan(
|
|
29
|
+
await pluginCtx.sessionTurnScheduler.run(
|
|
43
30
|
groupSessionId,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
31
|
+
"idle-debug",
|
|
32
|
+
async () => {
|
|
33
|
+
const now = Date.now();
|
|
34
|
+
const botNickname =
|
|
35
|
+
cfg.nicknames[0] || ctx.pickBot(e.self_id).nickname || "Bot";
|
|
36
|
+
ctx.logger.info(`[Debug] Manual idle check: group ${targetGroupId}`);
|
|
49
37
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
38
|
+
const { history } = await pluginCtx.getGroupHistoryMessages(
|
|
39
|
+
targetGroupId,
|
|
40
|
+
groupSessionId,
|
|
41
|
+
ctx,
|
|
42
|
+
cfg.historyCount,
|
|
43
|
+
pluginCtx.db,
|
|
44
|
+
e.self_id,
|
|
45
|
+
pluginCtx.buildHistoryMediaOptions(pluginCtx.aiInstance, cfg),
|
|
46
|
+
);
|
|
47
|
+
const planResult = await pluginCtx.humanize.actionPlanner.plan(
|
|
48
|
+
groupSessionId,
|
|
49
|
+
botNickname,
|
|
50
|
+
history,
|
|
51
|
+
"[Check if you want to answer the call]",
|
|
52
|
+
true,
|
|
53
|
+
);
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
timestamp: now,
|
|
64
|
-
};
|
|
65
|
-
const botRole = await getBotRole(targetGroupId, ctx, e.self_id);
|
|
66
|
-
const toolCtx = pluginCtx.buildToolContext({
|
|
67
|
-
ctx,
|
|
68
|
-
event: null,
|
|
69
|
-
groupSessionId,
|
|
70
|
-
groupId: targetGroupId,
|
|
71
|
-
userId: 0,
|
|
72
|
-
config: cfg,
|
|
73
|
-
aiService: ctx.services!.ai as AIService,
|
|
74
|
-
db: pluginCtx.db,
|
|
75
|
-
botRole,
|
|
76
|
-
humanize: pluginCtx.humanize,
|
|
77
|
-
targetMessage,
|
|
78
|
-
selfId: e.self_id,
|
|
79
|
-
});
|
|
55
|
+
if (planResult.action !== "reply") {
|
|
56
|
+
await e.reply(
|
|
57
|
+
`[空闲检测] 群 ${targetGroupId}\n决定: ${planResult.action}\n原因: ${planResult.reason}`,
|
|
58
|
+
);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
80
61
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
62
|
+
const targetMessage: TargetMessage = {
|
|
63
|
+
userName: "系统",
|
|
64
|
+
userId: 0,
|
|
65
|
+
userRole: "member",
|
|
66
|
+
content: "[No one in the group is talking? I'll answer!]",
|
|
67
|
+
messageId: 0,
|
|
68
|
+
timestamp: now,
|
|
69
|
+
};
|
|
70
|
+
const botRole = await getBotRole(targetGroupId, ctx, e.self_id);
|
|
71
|
+
const toolCtx = pluginCtx.buildToolContext({
|
|
72
|
+
ctx,
|
|
73
|
+
event: null,
|
|
74
|
+
groupSessionId,
|
|
75
|
+
groupId: targetGroupId,
|
|
76
|
+
userId: 0,
|
|
77
|
+
config: cfg,
|
|
78
|
+
aiService: ctx.services!.ai as AIService,
|
|
79
|
+
db: pluginCtx.db,
|
|
80
|
+
botRole,
|
|
81
|
+
humanize: pluginCtx.humanize,
|
|
87
82
|
targetMessage,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
botNickname,
|
|
91
|
-
botRole: toolCtx.botRole,
|
|
92
|
-
aiService: ctx.services!.ai as AIService,
|
|
93
|
-
isGroup: true,
|
|
94
|
-
plannerThoughts: `You stumbled upon some message in this group and decided to reply.\nQuote messages from group friends appropriately (using [reply:message ID] format).\nDon't mention your intentions like "I'm here to answer".`,
|
|
95
|
-
replyContext: { type: "idle" },
|
|
96
|
-
},
|
|
97
|
-
pluginCtx.humanize,
|
|
98
|
-
pluginCtx.skillManager,
|
|
99
|
-
),
|
|
100
|
-
{ groupId: targetGroupId, label: "idle-check" },
|
|
101
|
-
);
|
|
102
|
-
if (!result) {
|
|
103
|
-
await e.reply(`[空闲检测] 群 ${targetGroupId} 因限流被跳过`);
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
83
|
+
selfId: e.self_id,
|
|
84
|
+
});
|
|
106
85
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
86
|
+
const result = await pluginCtx.runWithRateLimitGuard(
|
|
87
|
+
() =>
|
|
88
|
+
pluginCtx.runChat(
|
|
89
|
+
pluginCtx.aiInstance,
|
|
90
|
+
toolCtx,
|
|
91
|
+
history,
|
|
92
|
+
targetMessage,
|
|
93
|
+
{
|
|
94
|
+
config: cfg,
|
|
95
|
+
botNickname,
|
|
96
|
+
botRole: toolCtx.botRole,
|
|
97
|
+
aiService: ctx.services!.ai as AIService,
|
|
98
|
+
isGroup: true,
|
|
99
|
+
plannerThoughts:
|
|
100
|
+
'You stumbled upon some message in this group and decided to reply.\nQuote messages from group friends appropriately (using [reply:message ID] format).\nDon\'t mention your intentions like "I\'m here to answer".',
|
|
101
|
+
replyContext: { type: "idle" },
|
|
102
|
+
},
|
|
103
|
+
pluginCtx.humanize,
|
|
104
|
+
pluginCtx.skillManager,
|
|
105
|
+
),
|
|
106
|
+
{ groupId: targetGroupId, label: "idle-check" },
|
|
107
|
+
);
|
|
108
|
+
if (!result) {
|
|
109
|
+
await e.reply(`[空闲检测] 群 ${targetGroupId} 因限流被跳过`);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
await finalizeChatTurn(pluginCtx, {
|
|
114
|
+
event: null,
|
|
115
|
+
cfg,
|
|
116
|
+
result,
|
|
117
|
+
groupId: targetGroupId,
|
|
118
|
+
groupSessionId,
|
|
119
|
+
userId: 0,
|
|
120
|
+
selfId: e.self_id,
|
|
121
|
+
toolCtx,
|
|
122
|
+
send: true,
|
|
123
|
+
isLive: true,
|
|
124
|
+
});
|
|
125
|
+
await e.reply(
|
|
126
|
+
`[空闲检测] 群 ${targetGroupId} 已发送回复: ${planResult.reason}`,
|
|
127
|
+
);
|
|
114
128
|
},
|
|
115
|
-
e.self_id,
|
|
116
|
-
);
|
|
117
|
-
const now2 = Date.now();
|
|
118
|
-
pluginCtx.saveBotMessages(
|
|
119
|
-
targetGroupId,
|
|
120
|
-
groupSessionId,
|
|
121
|
-
result.messages,
|
|
122
|
-
now2,
|
|
123
|
-
cfg,
|
|
124
|
-
pluginCtx.db,
|
|
125
|
-
ctx,
|
|
126
|
-
e.self_id,
|
|
127
|
-
);
|
|
128
|
-
await e.reply(
|
|
129
|
-
`[空闲检测] 群 ${targetGroupId} 已发送回复: ${planResult.reason}`,
|
|
130
129
|
);
|
|
131
130
|
} catch (err) {
|
|
132
131
|
ctx.logger.error(`[Debug] Idle check failed: ${err}`);
|
package/handlers/message.ts
CHANGED
|
@@ -104,10 +104,6 @@ export function createMessageHandler(
|
|
|
104
104
|
groupId,
|
|
105
105
|
label: "image-analysis",
|
|
106
106
|
}),
|
|
107
|
-
allowedCharacters:
|
|
108
|
-
cfg.emoji?.characters && cfg.emoji.characters.length > 0
|
|
109
|
-
? cfg.emoji.characters
|
|
110
|
-
: undefined,
|
|
111
107
|
}).catch((err) =>
|
|
112
108
|
ctx.logger.error(`[image-analyzer] Failed: ${err}`),
|
|
113
109
|
);
|
|
@@ -232,24 +228,7 @@ export function createMessageHandler(
|
|
|
232
228
|
}
|
|
233
229
|
}
|
|
234
230
|
|
|
235
|
-
|
|
236
|
-
const processingSet = runtimeState.processingSet;
|
|
237
|
-
if (isGroup && groupId && groupSessionId) {
|
|
238
|
-
if (processingSet.has(groupSessionId)) {
|
|
239
|
-
if ((atBot || mentionedNickname) && !runtimeState.isRateLimitBlocked()) {
|
|
240
|
-
pluginCtx.queueManager.enqueue(groupSessionId, e, cfg);
|
|
241
|
-
pluginCtx.rateLimiter.recordInteraction(groupId, userId);
|
|
242
|
-
}
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
processingSet.add(groupSessionId);
|
|
246
|
-
} else {
|
|
247
|
-
const triggerKey = `personal:${userId}`;
|
|
248
|
-
if (processingSet.has(triggerKey)) return;
|
|
249
|
-
processingSet.add(triggerKey);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
try {
|
|
231
|
+
const runTriggeredMessage = async (): Promise<void> => {
|
|
253
232
|
if (atBot) {
|
|
254
233
|
if (!pluginCtx.rateLimiter.canProcess(userId, groupId, text)) return;
|
|
255
234
|
|
|
@@ -279,9 +258,10 @@ export function createMessageHandler(
|
|
|
279
258
|
}
|
|
280
259
|
|
|
281
260
|
if (quotedBot || mentionedNickname) {
|
|
261
|
+
if (!groupId || !groupSessionId) return;
|
|
282
262
|
const { history } = await pluginCtx.getGroupHistoryMessages(
|
|
283
|
-
groupId
|
|
284
|
-
groupSessionId
|
|
263
|
+
groupId,
|
|
264
|
+
groupSessionId,
|
|
285
265
|
ctx,
|
|
286
266
|
cfg.historyCount,
|
|
287
267
|
pluginCtx.db,
|
|
@@ -291,7 +271,7 @@ export function createMessageHandler(
|
|
|
291
271
|
const botNickname =
|
|
292
272
|
cfg.nicknames[0] || ctx.pickBot(e.self_id).nickname || "Bot";
|
|
293
273
|
const planResult = await pluginCtx.humanize.actionPlanner.plan(
|
|
294
|
-
groupSessionId
|
|
274
|
+
groupSessionId,
|
|
295
275
|
botNickname,
|
|
296
276
|
history,
|
|
297
277
|
text,
|
|
@@ -300,18 +280,39 @@ export function createMessageHandler(
|
|
|
300
280
|
if (!pluginCtx.rateLimiter.canProcess(userId, groupId, text)) return;
|
|
301
281
|
pluginCtx.rateLimiter.record(userId, groupId, text);
|
|
302
282
|
await processChat(e, pluginCtx, runtimeState);
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
if (isGroup && groupId && groupSessionId) {
|
|
287
|
+
if (!atBot && !quotedBot && !mentionedNickname) return;
|
|
288
|
+
if (pluginCtx.sessionTurnScheduler.isBusy(groupSessionId)) {
|
|
289
|
+
if (!runtimeState.isRateLimitBlocked()) {
|
|
290
|
+
pluginCtx.queueManager.enqueue(groupSessionId, e, cfg);
|
|
291
|
+
pluginCtx.rateLimiter.recordInteraction(groupId, userId);
|
|
292
|
+
pluginCtx.queueProcessor.scheduleQueuedMessages(
|
|
293
|
+
groupSessionId,
|
|
294
|
+
e.self_id,
|
|
295
|
+
);
|
|
296
|
+
}
|
|
303
297
|
return;
|
|
304
298
|
}
|
|
299
|
+
|
|
300
|
+
await pluginCtx.sessionTurnScheduler.run(
|
|
301
|
+
groupSessionId,
|
|
302
|
+
"message",
|
|
303
|
+
runTriggeredMessage,
|
|
304
|
+
);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const triggerKey = `personal:${userId}`;
|
|
309
|
+
const processingSet = runtimeState.processingSet;
|
|
310
|
+
if (processingSet.has(triggerKey)) return;
|
|
311
|
+
processingSet.add(triggerKey);
|
|
312
|
+
try {
|
|
313
|
+
await runTriggeredMessage();
|
|
305
314
|
} finally {
|
|
306
|
-
|
|
307
|
-
processingSet.delete(groupSessionId);
|
|
308
|
-
await pluginCtx.queueProcessor.processQueuedMessages(
|
|
309
|
-
groupSessionId,
|
|
310
|
-
e.self_id,
|
|
311
|
-
);
|
|
312
|
-
} else {
|
|
313
|
-
processingSet.delete(`personal:${userId}`);
|
|
314
|
-
}
|
|
315
|
+
processingSet.delete(triggerKey);
|
|
315
316
|
}
|
|
316
317
|
};
|
|
317
318
|
}
|
package/handlers/poke.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { ChatPluginContext, ChatHandlerState } from "../context";
|
|
|
2
2
|
import type { TargetMessage } from "../types";
|
|
3
3
|
import { getBotRole, isGroupAllowed } from "../utils";
|
|
4
4
|
import { buildStructuredUserInputFromTarget } from "../manage/group-structured-history";
|
|
5
|
+
import { finalizeChatTurn } from "../core/chat-turn";
|
|
5
6
|
import { POKE_COOLDOWN_MS } from "./message";
|
|
6
7
|
|
|
7
8
|
export function createPokeHandler(
|
|
@@ -25,141 +26,118 @@ export function createPokeHandler(
|
|
|
25
26
|
const groupSessionId = `group:${groupId}`;
|
|
26
27
|
if (runtimeState.isRateLimitBlocked()) return;
|
|
27
28
|
|
|
28
|
-
const processingSet = runtimeState.processingSet;
|
|
29
|
-
if (processingSet.has(groupSessionId)) {
|
|
30
|
-
if (!runtimeState.isRateLimitBlocked()) {
|
|
31
|
-
pluginCtx.queueManager.enqueue(groupSessionId, e, cfg);
|
|
32
|
-
}
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
processingSet.add(groupSessionId);
|
|
37
|
-
pluginCtx.sessionManager.getOrCreate(groupSessionId, "group", groupId);
|
|
38
|
-
|
|
39
29
|
try {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
String(userId);
|
|
54
|
-
} catch {}
|
|
30
|
+
await pluginCtx.sessionTurnScheduler.run(
|
|
31
|
+
groupSessionId,
|
|
32
|
+
"poke",
|
|
33
|
+
async () => {
|
|
34
|
+
pluginCtx.sessionManager.getOrCreate(
|
|
35
|
+
groupSessionId,
|
|
36
|
+
"group",
|
|
37
|
+
groupId,
|
|
38
|
+
);
|
|
39
|
+
const userId = e.user_id || e.operator_id;
|
|
40
|
+
const botRole = await getBotRole(groupId, ctx, e.self_id);
|
|
41
|
+
const botNickname =
|
|
42
|
+
cfg.nicknames[0] || ctx.pickBot(e.self_id).nickname || "Bot";
|
|
55
43
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
44
|
+
let senderName = String(userId);
|
|
45
|
+
try {
|
|
46
|
+
const memberInfo = await ctx
|
|
47
|
+
.pickBot(e.self_id)
|
|
48
|
+
.getGroupMemberInfo(groupId, userId);
|
|
49
|
+
senderName =
|
|
50
|
+
(memberInfo as any).card ||
|
|
51
|
+
(memberInfo as any).nickname ||
|
|
52
|
+
String(userId);
|
|
53
|
+
} catch {}
|
|
63
54
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
pluginCtx.buildHistoryMediaOptions(pluginCtx.aiInstance, cfg),
|
|
72
|
-
);
|
|
73
|
-
const { groupName, memberCount } = await pluginCtx.getGroupInfoData(
|
|
74
|
-
ctx,
|
|
75
|
-
groupId,
|
|
76
|
-
e.self_id,
|
|
77
|
-
);
|
|
55
|
+
const targetMessage: TargetMessage = {
|
|
56
|
+
userName: senderName,
|
|
57
|
+
userId,
|
|
58
|
+
userRole: "member",
|
|
59
|
+
content: `[${senderName} poked you]`,
|
|
60
|
+
timestamp: Date.now(),
|
|
61
|
+
};
|
|
78
62
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
targetMessage,
|
|
91
|
-
selfId: e.self_id,
|
|
92
|
-
});
|
|
63
|
+
const { history } = await pluginCtx.getGroupHistoryMessages(
|
|
64
|
+
groupId,
|
|
65
|
+
groupSessionId,
|
|
66
|
+
ctx,
|
|
67
|
+
cfg.historyCount,
|
|
68
|
+
pluginCtx.db,
|
|
69
|
+
e.self_id,
|
|
70
|
+
pluginCtx.buildHistoryMediaOptions(pluginCtx.aiInstance, cfg),
|
|
71
|
+
);
|
|
72
|
+
const { groupName, memberCount } =
|
|
73
|
+
await pluginCtx.getGroupInfoData(ctx, groupId, e.self_id);
|
|
93
74
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
75
|
+
const toolCtx = pluginCtx.buildToolContext({
|
|
76
|
+
ctx,
|
|
77
|
+
event: e,
|
|
78
|
+
groupSessionId,
|
|
79
|
+
groupId,
|
|
80
|
+
userId,
|
|
81
|
+
config: cfg,
|
|
82
|
+
aiService: pluginCtx.aiService,
|
|
83
|
+
db: pluginCtx.db,
|
|
84
|
+
botRole,
|
|
85
|
+
humanize: pluginCtx.humanize,
|
|
100
86
|
targetMessage,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
groupName,
|
|
104
|
-
memberCount,
|
|
105
|
-
botNickname,
|
|
106
|
-
botRole,
|
|
107
|
-
aiService: pluginCtx.aiService,
|
|
108
|
-
isGroup: true,
|
|
109
|
-
replyContext: {
|
|
110
|
-
type: "poked",
|
|
111
|
-
targetUser: targetMessage.userName,
|
|
112
|
-
targetMessage: targetMessage.content,
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
pluginCtx.humanize,
|
|
116
|
-
pluginCtx.skillManager,
|
|
117
|
-
{
|
|
118
|
-
manager: pluginCtx.groupStructuredHistory,
|
|
119
|
-
ttlMs: cfg.groupStructuredHistoryTtlMs,
|
|
120
|
-
currentUserInputs: [
|
|
121
|
-
buildStructuredUserInputFromTarget(targetMessage),
|
|
122
|
-
],
|
|
123
|
-
},
|
|
124
|
-
),
|
|
125
|
-
{ userId, groupId, label: "poke" },
|
|
126
|
-
);
|
|
127
|
-
if (!result) return;
|
|
87
|
+
selfId: e.self_id,
|
|
88
|
+
});
|
|
128
89
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
90
|
+
const result = await pluginCtx.runWithRateLimitGuard(
|
|
91
|
+
() =>
|
|
92
|
+
pluginCtx.runChat(
|
|
93
|
+
pluginCtx.aiInstance,
|
|
94
|
+
toolCtx,
|
|
95
|
+
history,
|
|
96
|
+
targetMessage,
|
|
97
|
+
{
|
|
98
|
+
config: cfg,
|
|
99
|
+
groupName,
|
|
100
|
+
memberCount,
|
|
101
|
+
botNickname,
|
|
102
|
+
botRole,
|
|
103
|
+
aiService: pluginCtx.aiService,
|
|
104
|
+
isGroup: true,
|
|
105
|
+
replyContext: {
|
|
106
|
+
type: "poked",
|
|
107
|
+
targetUser: targetMessage.userName,
|
|
108
|
+
targetMessage: targetMessage.content,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
pluginCtx.humanize,
|
|
112
|
+
pluginCtx.skillManager,
|
|
113
|
+
{
|
|
114
|
+
manager: pluginCtx.groupStructuredHistory,
|
|
115
|
+
ttlMs: cfg.groupStructuredHistoryTtlMs,
|
|
116
|
+
currentUserInputs: [
|
|
117
|
+
buildStructuredUserInputFromTarget(targetMessage),
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
),
|
|
121
|
+
{ userId, groupId, label: "poke" },
|
|
122
|
+
);
|
|
123
|
+
if (!result) return;
|
|
139
124
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
result.messages.length,
|
|
154
|
-
e.self_id,
|
|
125
|
+
await finalizeChatTurn(pluginCtx, {
|
|
126
|
+
event: e,
|
|
127
|
+
cfg,
|
|
128
|
+
result,
|
|
129
|
+
groupId,
|
|
130
|
+
groupSessionId,
|
|
131
|
+
userId,
|
|
132
|
+
selfId: e.self_id,
|
|
133
|
+
toolCtx,
|
|
134
|
+
send: true,
|
|
135
|
+
isLive: true,
|
|
136
|
+
});
|
|
137
|
+
},
|
|
155
138
|
);
|
|
156
|
-
|
|
157
|
-
await pluginCtx.sendEmoji(ctx, groupId, result.emojiPath, e.self_id);
|
|
158
|
-
pluginCtx.sessionManager.touch(groupSessionId);
|
|
159
139
|
} catch (err) {
|
|
160
140
|
ctx.logger.error(`Poke processing failed: ${err}`);
|
|
161
|
-
} finally {
|
|
162
|
-
processingSet.delete(groupSessionId);
|
|
163
141
|
}
|
|
164
142
|
};
|
|
165
143
|
}
|