mioku-plugin-chat 3.0.6 → 3.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.
- package/context.ts +5 -5
- package/core/base.ts +20 -20
- package/core/chat-engine.ts +6 -6
- package/core/chat-turn.ts +30 -26
- package/core/media/history-media.ts +13 -13
- package/core/media/segment.ts +2 -2
- package/core/prompt.ts +1 -1
- package/core/tools/info.ts +9 -4
- package/core/tools/web.ts +6 -9
- package/db.ts +13 -13
- package/handlers/idle-debug.ts +7 -7
- package/handlers/message.ts +6 -8
- package/handlers/poke.ts +15 -14
- package/humanize/emotion-agent.ts +5 -5
- package/humanize/expression.ts +6 -6
- package/humanize/index.ts +1 -1
- package/humanize/memory.ts +1 -1
- package/index.ts +30 -22
- package/manage/cooldown.ts +8 -8
- package/manage/group-structured-history.ts +2 -2
- package/manage/idle-check.ts +12 -11
- package/manage/queue-processor.ts +9 -8
- package/manage/rate-limit-guard.ts +2 -2
- package/manage/rate-limiter.ts +21 -21
- package/manage/session.ts +1 -1
- package/manage/types.ts +16 -16
- package/package.json +1 -1
- package/runtime/chat-runtime.ts +4 -4
- package/types.ts +11 -11
- package/utils/config.ts +4 -4
- package/utils/group-config.ts +3 -4
- package/utils/message.ts +21 -21
- package/utils/queue.ts +12 -11
package/context.ts
CHANGED
|
@@ -38,7 +38,7 @@ export interface ChatPluginContext {
|
|
|
38
38
|
ctx: MiokuContext;
|
|
39
39
|
defaultConfig: ChatConfig;
|
|
40
40
|
configProvider: ChatConfigProvider;
|
|
41
|
-
getConfig: (groupId?:
|
|
41
|
+
getConfig: (groupId?: string) => Promise<ChatConfig>;
|
|
42
42
|
db: ChatDatabase;
|
|
43
43
|
aiInstance: AIInstance;
|
|
44
44
|
workAIInstance: AIInstance;
|
|
@@ -75,8 +75,8 @@ export interface ChatPluginContext {
|
|
|
75
75
|
runChat: RunChat;
|
|
76
76
|
startCooldownTimer: (
|
|
77
77
|
groupSessionId: string,
|
|
78
|
-
groupId:
|
|
79
|
-
selfId:
|
|
78
|
+
groupId: string,
|
|
79
|
+
selfId: string,
|
|
80
80
|
) => void;
|
|
81
81
|
recordGroupMessageForLearning: (
|
|
82
82
|
userMsg: ChatMessage,
|
|
@@ -91,12 +91,12 @@ export interface ChatRuntimeState {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
export interface ChatHandlerState {
|
|
94
|
-
getConfig: (groupId?:
|
|
94
|
+
getConfig: (groupId?: string) => Promise<ChatConfig>;
|
|
95
95
|
matchMessageCommands?: (
|
|
96
96
|
text: string,
|
|
97
97
|
) => Array<{ plugin: string; command: string }>;
|
|
98
98
|
runtimeState: ChatRuntimeState;
|
|
99
|
-
pokeCooldowns: Map<
|
|
99
|
+
pokeCooldowns: Map<string, number>;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
export interface ChatRuntime {
|
package/core/base.ts
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
|
|
26
26
|
export interface SendAIResponseOptions {
|
|
27
27
|
ctx: MiokuContext;
|
|
28
|
-
groupId:
|
|
28
|
+
groupId: string;
|
|
29
29
|
messages: string[];
|
|
30
30
|
config: ChatConfig;
|
|
31
31
|
sentIndices?: Set<number>;
|
|
@@ -78,7 +78,7 @@ async function waitTypingDelay(
|
|
|
78
78
|
|
|
79
79
|
export async function sendAIResponse(
|
|
80
80
|
options: SendAIResponseOptions,
|
|
81
|
-
selfId:
|
|
81
|
+
selfId: string,
|
|
82
82
|
): Promise<Array<string | undefined>> {
|
|
83
83
|
const {
|
|
84
84
|
ctx,
|
|
@@ -252,11 +252,11 @@ export async function sendAIResponse(
|
|
|
252
252
|
|
|
253
253
|
export async function sendMessage(
|
|
254
254
|
ctx: MiokuContext,
|
|
255
|
-
groupId:
|
|
256
|
-
userId:
|
|
255
|
+
groupId: string | undefined,
|
|
256
|
+
userId: string,
|
|
257
257
|
text: string,
|
|
258
258
|
config: ChatConfig,
|
|
259
|
-
selfId:
|
|
259
|
+
selfId: string,
|
|
260
260
|
audioService?: AudioServiceApi,
|
|
261
261
|
): Promise<void> {
|
|
262
262
|
const typingDelayEnabled = config.enableTypingDelay ?? false;
|
|
@@ -555,8 +555,8 @@ async function buildMarkdownImage(
|
|
|
555
555
|
|
|
556
556
|
async function dispatchSegments(
|
|
557
557
|
bot: any,
|
|
558
|
-
groupId:
|
|
559
|
-
userId:
|
|
558
|
+
groupId: string | undefined,
|
|
559
|
+
userId: string | undefined,
|
|
560
560
|
buildSegments: (imageSource?: string) => any[],
|
|
561
561
|
fallbackImagePath?: string,
|
|
562
562
|
): Promise<string | undefined> {
|
|
@@ -583,8 +583,8 @@ async function dispatchSegments(
|
|
|
583
583
|
|
|
584
584
|
async function sendByTarget(
|
|
585
585
|
bot: Bot,
|
|
586
|
-
groupId:
|
|
587
|
-
userId:
|
|
586
|
+
groupId: string | undefined,
|
|
587
|
+
userId: string | undefined,
|
|
588
588
|
segments: readonly any[],
|
|
589
589
|
): Promise<import("mioku").SentMessage | undefined> {
|
|
590
590
|
if (groupId) {
|
|
@@ -668,12 +668,12 @@ export interface GroupHistoryResult {
|
|
|
668
668
|
}
|
|
669
669
|
|
|
670
670
|
export async function getGroupHistoryMessages(
|
|
671
|
-
groupId:
|
|
671
|
+
groupId: string,
|
|
672
672
|
groupSessionId: string,
|
|
673
673
|
ctx: MiokuContext,
|
|
674
674
|
historyCount: number,
|
|
675
675
|
db: ChatDatabase,
|
|
676
|
-
selfId:
|
|
676
|
+
selfId: string,
|
|
677
677
|
mediaOptions?: {
|
|
678
678
|
ai?: AIInstance;
|
|
679
679
|
workingModel?: string;
|
|
@@ -710,8 +710,8 @@ export interface GroupInfoResult {
|
|
|
710
710
|
|
|
711
711
|
export async function getGroupInfoData(
|
|
712
712
|
ctx: MiokuContext,
|
|
713
|
-
groupId:
|
|
714
|
-
selfId:
|
|
713
|
+
groupId: string,
|
|
714
|
+
selfId: string,
|
|
715
715
|
fallbackGroupName?: string,
|
|
716
716
|
): Promise<GroupInfoResult> {
|
|
717
717
|
let groupName: string | undefined;
|
|
@@ -746,7 +746,7 @@ export async function getHumanizeContexts(
|
|
|
746
746
|
groupSessionId: string,
|
|
747
747
|
userName: string,
|
|
748
748
|
history: ChatMessage[],
|
|
749
|
-
triggerUserId?:
|
|
749
|
+
triggerUserId?: string,
|
|
750
750
|
): Promise<HumanizeContextsResult> {
|
|
751
751
|
const historyStartAt = history.length > 0 ? history[0].timestamp : undefined;
|
|
752
752
|
|
|
@@ -775,10 +775,10 @@ export async function getHumanizeContexts(
|
|
|
775
775
|
export interface BuildToolContextOptions {
|
|
776
776
|
ctx: MiokuContext;
|
|
777
777
|
event: any;
|
|
778
|
-
selfId:
|
|
778
|
+
selfId: string;
|
|
779
779
|
groupSessionId: string;
|
|
780
|
-
groupId?:
|
|
781
|
-
userId:
|
|
780
|
+
groupId?: string;
|
|
781
|
+
userId: string;
|
|
782
782
|
config: ChatConfig;
|
|
783
783
|
aiService: AIService;
|
|
784
784
|
db: ChatDatabase;
|
|
@@ -867,7 +867,7 @@ export function buildToolContext(
|
|
|
867
867
|
}
|
|
868
868
|
|
|
869
869
|
export function saveBotMessages(
|
|
870
|
-
groupId:
|
|
870
|
+
groupId: string,
|
|
871
871
|
groupSessionId: string,
|
|
872
872
|
messages: string[],
|
|
873
873
|
timestamp: number,
|
|
@@ -891,7 +891,7 @@ export function saveBotMessages(
|
|
|
891
891
|
sessionId: groupSessionId,
|
|
892
892
|
role: "assistant",
|
|
893
893
|
content: msg ?? "",
|
|
894
|
-
userId: selfId ??
|
|
894
|
+
userId: String(selfId ?? ""),
|
|
895
895
|
userName: botNickname ?? "Miku",
|
|
896
896
|
userRole: "member",
|
|
897
897
|
groupId,
|
|
@@ -904,7 +904,7 @@ export function saveBotMessages(
|
|
|
904
904
|
|
|
905
905
|
export async function sendEmoji(
|
|
906
906
|
ctx: MiokuContext,
|
|
907
|
-
groupId:
|
|
907
|
+
groupId: string,
|
|
908
908
|
emojiPath: string | null | undefined,
|
|
909
909
|
bot: Bot | undefined,
|
|
910
910
|
): Promise<void> {
|
package/core/chat-engine.ts
CHANGED
|
@@ -142,7 +142,7 @@ export async function runChat(
|
|
|
142
142
|
const usageContext = {
|
|
143
143
|
usageId,
|
|
144
144
|
source: "chat",
|
|
145
|
-
botId:
|
|
145
|
+
botId: getEventId(toolCtx.event, "self_id"),
|
|
146
146
|
groupId: toolCtx.groupId,
|
|
147
147
|
groupName: getEventString(toolCtx.event, "group_name"),
|
|
148
148
|
userId: toolCtx.userId,
|
|
@@ -960,7 +960,7 @@ ${failedSummary}
|
|
|
960
960
|
],
|
|
961
961
|
usageContext: {
|
|
962
962
|
source: "chat.tool-failure",
|
|
963
|
-
botId:
|
|
963
|
+
botId: getEventId(toolCtx.event, "self_id"),
|
|
964
964
|
groupId: toolCtx.groupId,
|
|
965
965
|
groupName: getEventString(toolCtx.event, "group_name"),
|
|
966
966
|
userId: toolCtx.userId,
|
|
@@ -984,12 +984,12 @@ ${failedSummary}
|
|
|
984
984
|
return "我刚刚查这条信息时出了点问题,你可以换个关键词再试试,或者给我更具体一点的线索。";
|
|
985
985
|
}
|
|
986
986
|
|
|
987
|
-
function
|
|
987
|
+
function getEventId(event: unknown, key: string): string | undefined {
|
|
988
988
|
if (!event || typeof event !== "object") return undefined;
|
|
989
989
|
const value = (event as Record<string, unknown>)[key];
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
990
|
+
if (value == null) return undefined;
|
|
991
|
+
const text = String(value).trim();
|
|
992
|
+
return text.length > 0 ? text : undefined;
|
|
993
993
|
}
|
|
994
994
|
|
|
995
995
|
function getEventString(event: unknown, key: string): string | undefined {
|
package/core/chat-turn.ts
CHANGED
|
@@ -14,9 +14,9 @@ export type RuntimeReplyContextType =
|
|
|
14
14
|
|
|
15
15
|
export interface ExecuteChatRuntimeRequestOptions {
|
|
16
16
|
event?: any;
|
|
17
|
-
selfId?:
|
|
18
|
-
groupId?:
|
|
19
|
-
userId?:
|
|
17
|
+
selfId?: string;
|
|
18
|
+
groupId?: string;
|
|
19
|
+
userId?: string;
|
|
20
20
|
config: ChatConfig;
|
|
21
21
|
targetMessageContent?: string;
|
|
22
22
|
promptInjections?: ChatRuntimePromptInjection[];
|
|
@@ -28,9 +28,9 @@ export interface ExecuteChatRuntimeRequestOptions {
|
|
|
28
28
|
interface ResolvedRuntimeContext {
|
|
29
29
|
event: any;
|
|
30
30
|
isGroup: boolean;
|
|
31
|
-
groupId?:
|
|
32
|
-
userId:
|
|
33
|
-
selfId:
|
|
31
|
+
groupId?: string;
|
|
32
|
+
userId: string;
|
|
33
|
+
selfId: string;
|
|
34
34
|
sessionId: string;
|
|
35
35
|
personalSessionId?: string;
|
|
36
36
|
senderName: string;
|
|
@@ -61,8 +61,12 @@ function resolveRuntimeContext(
|
|
|
61
61
|
if (options.event) {
|
|
62
62
|
const event = options.event;
|
|
63
63
|
const isGroup = event.message_type === "group";
|
|
64
|
-
const groupId:
|
|
65
|
-
|
|
64
|
+
const groupId: string | undefined = isGroup
|
|
65
|
+
? String(event.group_id ?? "").trim() || undefined
|
|
66
|
+
: undefined;
|
|
67
|
+
const userId: string = String(
|
|
68
|
+
event.user_id ?? event.sender?.user_id ?? "",
|
|
69
|
+
).trim();
|
|
66
70
|
return {
|
|
67
71
|
event,
|
|
68
72
|
isGroup,
|
|
@@ -80,18 +84,18 @@ function resolveRuntimeContext(
|
|
|
80
84
|
};
|
|
81
85
|
}
|
|
82
86
|
|
|
83
|
-
|
|
87
|
+
const selfId = String(options.selfId ?? "").trim();
|
|
88
|
+
if (!selfId) {
|
|
84
89
|
throw new Error("Chat runtime requires either event or selfId");
|
|
85
90
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
) {
|
|
91
|
+
const optionGroupId = String(options.groupId ?? "").trim() || undefined;
|
|
92
|
+
const optionUserId = String(options.userId ?? "").trim();
|
|
93
|
+
if (!optionGroupId && !optionUserId) {
|
|
90
94
|
throw new Error("Chat runtime requires groupId or userId");
|
|
91
95
|
}
|
|
92
96
|
|
|
93
|
-
const isGroup =
|
|
94
|
-
const userId =
|
|
97
|
+
const isGroup = Boolean(optionGroupId);
|
|
98
|
+
const userId = optionUserId;
|
|
95
99
|
const event = {
|
|
96
100
|
self_id: options.selfId,
|
|
97
101
|
message_type: isGroup ? "group" : "private",
|
|
@@ -110,15 +114,15 @@ function resolveRuntimeContext(
|
|
|
110
114
|
return {
|
|
111
115
|
event,
|
|
112
116
|
isGroup,
|
|
113
|
-
groupId:
|
|
117
|
+
groupId: optionGroupId,
|
|
114
118
|
userId,
|
|
115
|
-
selfId
|
|
116
|
-
sessionId:
|
|
117
|
-
? `group:${
|
|
119
|
+
selfId,
|
|
120
|
+
sessionId: optionGroupId
|
|
121
|
+
? `group:${optionGroupId}`
|
|
118
122
|
: `personal:${userId}`,
|
|
119
123
|
personalSessionId:
|
|
120
|
-
|
|
121
|
-
senderName:
|
|
124
|
+
optionGroupId && userId ? `personal:${userId}` : undefined,
|
|
125
|
+
senderName: optionGroupId ? "system" : String(userId),
|
|
122
126
|
userRole: "member",
|
|
123
127
|
userTitle: undefined,
|
|
124
128
|
groupName: undefined,
|
|
@@ -133,10 +137,10 @@ export async function finalizeChatTurn(
|
|
|
133
137
|
event: any;
|
|
134
138
|
cfg: ChatConfig;
|
|
135
139
|
result: { messages: string[]; emojiPath?: string | null };
|
|
136
|
-
groupId?:
|
|
140
|
+
groupId?: string;
|
|
137
141
|
groupSessionId: string;
|
|
138
|
-
userId:
|
|
139
|
-
selfId:
|
|
142
|
+
userId: string;
|
|
143
|
+
selfId: string;
|
|
140
144
|
toolCtx: { sentMessageIndices?: Set<number> };
|
|
141
145
|
send: boolean;
|
|
142
146
|
isLive: boolean;
|
|
@@ -247,8 +251,8 @@ export async function processChat(
|
|
|
247
251
|
): Promise<void> {
|
|
248
252
|
const { ctx } = pluginCtx;
|
|
249
253
|
const isGroup = e.message_type === "group";
|
|
250
|
-
const groupId:
|
|
251
|
-
const userId:
|
|
254
|
+
const groupId: string | undefined = isGroup ? e.group_id : undefined;
|
|
255
|
+
const userId: string = e.user_id || e.sender?.user_id;
|
|
252
256
|
const selfId = options.replyBot ? Number(options.replyBot.bot_id) : e.self_id;
|
|
253
257
|
const cfg = await pluginCtx.getConfig(groupId);
|
|
254
258
|
|
|
@@ -70,12 +70,12 @@ export interface HistoryMediaProcessingOptions {
|
|
|
70
70
|
error(message: string): void;
|
|
71
71
|
};
|
|
72
72
|
bot?: Bot;
|
|
73
|
-
groupId?:
|
|
73
|
+
groupId?: string;
|
|
74
74
|
runAIRequest?<T>(request: () => Promise<T>): Promise<T | null>;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
export interface GroupNoticeHistorySummary {
|
|
78
|
-
userId:
|
|
78
|
+
userId: string;
|
|
79
79
|
userName: string;
|
|
80
80
|
userRole: string;
|
|
81
81
|
content: string;
|
|
@@ -701,18 +701,18 @@ function extractNoticeText(notice: any): string {
|
|
|
701
701
|
}
|
|
702
702
|
|
|
703
703
|
function extractNoticeSender(notice: any): {
|
|
704
|
-
userId:
|
|
704
|
+
userId: string;
|
|
705
705
|
userName: string;
|
|
706
706
|
} {
|
|
707
|
-
const userId =
|
|
708
|
-
notice?.user_id
|
|
709
|
-
notice?.sender_id
|
|
710
|
-
notice?.operator_id
|
|
711
|
-
notice?.poster_id
|
|
712
|
-
notice?.publisher_id
|
|
713
|
-
notice?.sender?.user_id
|
|
714
|
-
|
|
715
|
-
);
|
|
707
|
+
const userId = String(
|
|
708
|
+
notice?.user_id ??
|
|
709
|
+
notice?.sender_id ??
|
|
710
|
+
notice?.operator_id ??
|
|
711
|
+
notice?.poster_id ??
|
|
712
|
+
notice?.publisher_id ??
|
|
713
|
+
notice?.sender?.user_id ??
|
|
714
|
+
"",
|
|
715
|
+
).trim();
|
|
716
716
|
const userName =
|
|
717
717
|
notice?.sender?.card ||
|
|
718
718
|
notice?.sender?.nickname ||
|
|
@@ -722,7 +722,7 @@ function extractNoticeSender(notice: any): {
|
|
|
722
722
|
notice?.operator_name ||
|
|
723
723
|
(userId ? String(userId) : "unknown");
|
|
724
724
|
return {
|
|
725
|
-
userId
|
|
725
|
+
userId,
|
|
726
726
|
userName: String(userName),
|
|
727
727
|
};
|
|
728
728
|
}
|
package/core/media/segment.ts
CHANGED
|
@@ -28,7 +28,7 @@ export function buildHistoryMediaProcessingOptions(
|
|
|
28
28
|
saveMediaSummary(summary: MediaSummaryRecord): void;
|
|
29
29
|
},
|
|
30
30
|
bot: Bot,
|
|
31
|
-
groupId:
|
|
31
|
+
groupId: string,
|
|
32
32
|
log: HistoryMediaProcessingOptions["logger"],
|
|
33
33
|
runAIRequest?: <T>(request: () => Promise<T>) => Promise<T | null>,
|
|
34
34
|
): HistoryMediaProcessingOptions {
|
|
@@ -81,7 +81,7 @@ export function getCardData(seg: unknown): string | null {
|
|
|
81
81
|
|
|
82
82
|
export function isMediaAnalysisBlocked(
|
|
83
83
|
config: ChatConfig,
|
|
84
|
-
userId:
|
|
84
|
+
userId: string,
|
|
85
85
|
): boolean {
|
|
86
86
|
return Boolean(config.mediaAnalysisBlacklistUsers?.includes(userId));
|
|
87
87
|
}
|
package/core/prompt.ts
CHANGED
|
@@ -274,7 +274,7 @@ function buildResponseFormatSection(
|
|
|
274
274
|
- For action markers like [] , put them on their own line when they are meant to be a separate action.
|
|
275
275
|
|
|
276
276
|
- **SPECIAL ACTIONS in your text (auto-parsed and removed from message):**
|
|
277
|
-
- Use [at
|
|
277
|
+
- Use [at:<user_id>] in your text to @ someone (<user_id> is the platform user id shown in history)
|
|
278
278
|
- Use [poke:123456] in your text to poke someone. IMPORTANT: when you plan to poke a user, DON't describe your poke actions.
|
|
279
279
|
- Use [reply:message_id] at the START of a line to quote-reply that message (copy the message_id EXACTLY as shown after # in the chat history; it may contain letters, e.g. [reply:P2rW...pMB])
|
|
280
280
|
- **You can use MULTIPLE [reply:xxx] markers in different lines to quote multiple messages!**`);
|
package/core/tools/info.ts
CHANGED
|
@@ -67,7 +67,11 @@ export function createInfoTools(toolCtx: ToolContext): AITool[] {
|
|
|
67
67
|
parameters: {
|
|
68
68
|
type: "object",
|
|
69
69
|
properties: {
|
|
70
|
-
user_id: {
|
|
70
|
+
user_id: {
|
|
71
|
+
type: "string",
|
|
72
|
+
description:
|
|
73
|
+
"Platform user id of the member (QQ number, or openid on QQ official)",
|
|
74
|
+
},
|
|
71
75
|
},
|
|
72
76
|
required: ["user_id"],
|
|
73
77
|
},
|
|
@@ -137,7 +141,7 @@ export function createInfoTools(toolCtx: ToolContext): AITool[] {
|
|
|
137
141
|
type: "object",
|
|
138
142
|
properties: {
|
|
139
143
|
message_id: {
|
|
140
|
-
type: "
|
|
144
|
+
type: "string",
|
|
141
145
|
description:
|
|
142
146
|
"The message ID (message_id) of the image or video. You can get this from the original message that contains the media.",
|
|
143
147
|
},
|
|
@@ -250,8 +254,9 @@ export function createInfoTools(toolCtx: ToolContext): AITool[] {
|
|
|
250
254
|
type: "object",
|
|
251
255
|
properties: {
|
|
252
256
|
user_id: {
|
|
253
|
-
type: "
|
|
254
|
-
description:
|
|
257
|
+
type: "string",
|
|
258
|
+
description:
|
|
259
|
+
"Platform user id of the member whose avatar you want to view",
|
|
255
260
|
},
|
|
256
261
|
},
|
|
257
262
|
required: ["user_id"],
|
package/core/tools/web.ts
CHANGED
|
@@ -23,14 +23,11 @@ function resolveUserHistoryLimit(value: unknown): number {
|
|
|
23
23
|
|
|
24
24
|
function extractTargetUserIdsFromQuestion(
|
|
25
25
|
question: string,
|
|
26
|
-
requesterUserId:
|
|
27
|
-
):
|
|
26
|
+
requesterUserId: string,
|
|
27
|
+
): string[] {
|
|
28
28
|
const matches = question.match(/\b\d{5,12}\b/g) || [];
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
.filter((item) => Number.isFinite(item) && item > 0);
|
|
32
|
-
const ids = [requesterUserId, ...parsed].filter(
|
|
33
|
-
(item) => Number.isFinite(item) && item > 0,
|
|
29
|
+
const ids = [String(requesterUserId ?? "").trim(), ...matches].filter(
|
|
30
|
+
(item) => item.length > 0,
|
|
34
31
|
);
|
|
35
32
|
return [...new Set(ids)].slice(0, 3);
|
|
36
33
|
}
|
|
@@ -138,8 +135,8 @@ async function fetchGroupHistoryByMessageIdPaging(
|
|
|
138
135
|
sessionId: toolCtx.sessionId,
|
|
139
136
|
role: String(raw.user_id) === String(bot.bot_id) ? "assistant" : "user",
|
|
140
137
|
content,
|
|
141
|
-
userId:
|
|
142
|
-
userName: raw.nickname || String(raw.user_id
|
|
138
|
+
userId: String(raw.user_id ?? "").trim(),
|
|
139
|
+
userName: raw.nickname || String(raw.user_id ?? "unknown"),
|
|
143
140
|
userRole: "member",
|
|
144
141
|
groupId: toolCtx.groupId,
|
|
145
142
|
timestamp: ts,
|
package/db.ts
CHANGED
|
@@ -69,14 +69,14 @@ export interface ChatDatabase {
|
|
|
69
69
|
before?: number,
|
|
70
70
|
): ChatMessage[];
|
|
71
71
|
// 获取 bot 发送的消息
|
|
72
|
-
getBotMessages(groupId:
|
|
73
|
-
getStoredGroupNoticeMessages(groupId:
|
|
72
|
+
getBotMessages(groupId: string, limit?: number): ChatMessage[];
|
|
73
|
+
getStoredGroupNoticeMessages(groupId: string, limit?: number): ChatMessage[];
|
|
74
74
|
getMessagesByUser(
|
|
75
|
-
userId:
|
|
75
|
+
userId: string,
|
|
76
76
|
sessionId?: string,
|
|
77
77
|
limit?: number,
|
|
78
78
|
): ChatMessage[];
|
|
79
|
-
getAllMessagesByUser(userId:
|
|
79
|
+
getAllMessagesByUser(userId: string, sessionId?: string): ChatMessage[];
|
|
80
80
|
getMessagesByTimeRange(
|
|
81
81
|
sessionId: string,
|
|
82
82
|
startTimestamp: number,
|
|
@@ -108,9 +108,9 @@ export interface ChatDatabase {
|
|
|
108
108
|
// 表达学习
|
|
109
109
|
saveExpression(expr: ExpressionRecord): void;
|
|
110
110
|
getExpressions(sessionId: string, limit?: number): ExpressionRecord[];
|
|
111
|
-
getExpressionsByUser(userId:
|
|
111
|
+
getExpressionsByUser(userId: string, limit?: number): ExpressionRecord[];
|
|
112
112
|
replaceExpressionsByUser(
|
|
113
|
-
userId:
|
|
113
|
+
userId: string,
|
|
114
114
|
userName: string,
|
|
115
115
|
expressions: Array<
|
|
116
116
|
Pick<ExpressionRecord, "situation" | "style" | "example">
|
|
@@ -473,7 +473,7 @@ export async function initDatabase(): Promise<ChatDatabase> {
|
|
|
473
473
|
.reverse(); // 按时间正序
|
|
474
474
|
},
|
|
475
475
|
|
|
476
|
-
getBotMessages(groupId:
|
|
476
|
+
getBotMessages(groupId: string, limit: number = 50): ChatMessage[] {
|
|
477
477
|
const rows = stmts.getBotMessages.all({ $groupId: groupId, $limit: limit }) as any[];
|
|
478
478
|
return rows
|
|
479
479
|
.map(toChatMessage)
|
|
@@ -481,7 +481,7 @@ export async function initDatabase(): Promise<ChatDatabase> {
|
|
|
481
481
|
},
|
|
482
482
|
|
|
483
483
|
getStoredGroupNoticeMessages(
|
|
484
|
-
groupId:
|
|
484
|
+
groupId: string,
|
|
485
485
|
limit: number = 20,
|
|
486
486
|
): ChatMessage[] {
|
|
487
487
|
const rows = stmts.getStoredGroupNoticeMessages.all(
|
|
@@ -493,7 +493,7 @@ export async function initDatabase(): Promise<ChatDatabase> {
|
|
|
493
493
|
},
|
|
494
494
|
|
|
495
495
|
getMessagesByUser(
|
|
496
|
-
userId:
|
|
496
|
+
userId: string,
|
|
497
497
|
sessionId?: string,
|
|
498
498
|
limit: number = 20,
|
|
499
499
|
): ChatMessage[] {
|
|
@@ -510,7 +510,7 @@ export async function initDatabase(): Promise<ChatDatabase> {
|
|
|
510
510
|
.reverse();
|
|
511
511
|
},
|
|
512
512
|
|
|
513
|
-
getAllMessagesByUser(userId:
|
|
513
|
+
getAllMessagesByUser(userId: string, sessionId?: string): ChatMessage[] {
|
|
514
514
|
const rows = sessionId
|
|
515
515
|
? (stmts.getAllMessagesByUserInSession.all({ $userId: userId, $sessionId: sessionId }) as any[])
|
|
516
516
|
: (stmts.getAllMessagesByUser.all({ $userId: userId }) as any[]);
|
|
@@ -633,7 +633,7 @@ export async function initDatabase(): Promise<ChatDatabase> {
|
|
|
633
633
|
},
|
|
634
634
|
|
|
635
635
|
getExpressionsByUser(
|
|
636
|
-
userId:
|
|
636
|
+
userId: string,
|
|
637
637
|
limit: number = 50,
|
|
638
638
|
): ExpressionRecord[] {
|
|
639
639
|
const rows = stmts.getExpressionsByUser.all({ $userId: userId, $limit: limit }) as any[];
|
|
@@ -641,7 +641,7 @@ export async function initDatabase(): Promise<ChatDatabase> {
|
|
|
641
641
|
},
|
|
642
642
|
|
|
643
643
|
replaceExpressionsByUser(
|
|
644
|
-
userId:
|
|
644
|
+
userId: string,
|
|
645
645
|
userName: string,
|
|
646
646
|
expressions: Array<
|
|
647
647
|
Pick<ExpressionRecord, "situation" | "style" | "example">
|
|
@@ -650,7 +650,7 @@ export async function initDatabase(): Promise<ChatDatabase> {
|
|
|
650
650
|
const now = Date.now();
|
|
651
651
|
const tx = db.transaction(
|
|
652
652
|
(
|
|
653
|
-
targetUserId:
|
|
653
|
+
targetUserId: string,
|
|
654
654
|
targetUserName: string,
|
|
655
655
|
rows: Array<
|
|
656
656
|
Pick<ExpressionRecord, "situation" | "style" | "example">
|
package/handlers/idle-debug.ts
CHANGED
|
@@ -17,10 +17,10 @@ export async function handleIdleCheckDebug(
|
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
const groupIdStr =
|
|
20
|
-
e.message[0]?.text?.replace(
|
|
21
|
-
const targetGroupId =
|
|
20
|
+
e.message[0]?.text?.replace(/^[./]空闲检查/, "")?.trim() || "";
|
|
21
|
+
const targetGroupId = String(groupIdStr).trim();
|
|
22
22
|
if (!targetGroupId) {
|
|
23
|
-
await e.reply("
|
|
23
|
+
await e.reply("请指定群 ID,如:.空闲检查 123456");
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -61,7 +61,7 @@ export async function handleIdleCheckDebug(
|
|
|
61
61
|
|
|
62
62
|
const targetMessage: TargetMessage = {
|
|
63
63
|
userName: "系统",
|
|
64
|
-
userId:
|
|
64
|
+
userId: "",
|
|
65
65
|
userRole: "member",
|
|
66
66
|
content: "[No one in the group is talking? I'll answer!]",
|
|
67
67
|
messageId: "",
|
|
@@ -73,7 +73,7 @@ export async function handleIdleCheckDebug(
|
|
|
73
73
|
event: null,
|
|
74
74
|
groupSessionId,
|
|
75
75
|
groupId: targetGroupId,
|
|
76
|
-
userId:
|
|
76
|
+
userId: "",
|
|
77
77
|
config: cfg,
|
|
78
78
|
aiService: ctx.services!.ai as AIService,
|
|
79
79
|
db: pluginCtx.db,
|
|
@@ -117,8 +117,8 @@ export async function handleIdleCheckDebug(
|
|
|
117
117
|
result,
|
|
118
118
|
groupId: targetGroupId,
|
|
119
119
|
groupSessionId,
|
|
120
|
-
userId:
|
|
121
|
-
selfId: e.self_id,
|
|
120
|
+
userId: "",
|
|
121
|
+
selfId: String(e.self_id ?? "").trim(),
|
|
122
122
|
toolCtx,
|
|
123
123
|
send: true,
|
|
124
124
|
isLive: true,
|
package/handlers/message.ts
CHANGED
|
@@ -35,8 +35,8 @@ export function createMessageHandler(
|
|
|
35
35
|
|
|
36
36
|
return async (e: MessageEvent) => {
|
|
37
37
|
const isGroup = e.message_type === "group";
|
|
38
|
-
const groupId:
|
|
39
|
-
?
|
|
38
|
+
const groupId: string | undefined = isGroup
|
|
39
|
+
? String(e.group_id ?? "").trim() || undefined
|
|
40
40
|
: undefined;
|
|
41
41
|
const cfg = await getConfig(groupId);
|
|
42
42
|
if (!isGroup && cfg.ignorePrivateChat) return;
|
|
@@ -44,13 +44,13 @@ export function createMessageHandler(
|
|
|
44
44
|
if (!e?.message || !Array.isArray(e.message)) return;
|
|
45
45
|
|
|
46
46
|
const text = ctx.text(e) || "";
|
|
47
|
-
const userId:
|
|
47
|
+
const userId: string = String(e.user_id ?? e.sender?.user_id ?? "").trim();
|
|
48
48
|
|
|
49
|
-
if (userId ===
|
|
49
|
+
if (!userId || userId === String(e.self_id ?? "").trim()) return;
|
|
50
50
|
|
|
51
51
|
if (matchMessageCommands && matchMessageCommands(text).length > 0) return;
|
|
52
52
|
|
|
53
|
-
if (text
|
|
53
|
+
if (/^[./]空闲检查\s/.test(text)) {
|
|
54
54
|
await handleIdleCheckDebug(pluginCtx, e, cfg);
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
@@ -204,9 +204,7 @@ export function createMessageHandler(
|
|
|
204
204
|
|
|
205
205
|
const atBot = shouldTrigger(e, text, cfg, ctx);
|
|
206
206
|
const replyBot = ctx.pickReplyBot(e);
|
|
207
|
-
const actorSelfId = replyBot
|
|
208
|
-
? Number(replyBot.bot_id)
|
|
209
|
-
: Number(e.self_id || 0);
|
|
207
|
+
const actorSelfId = String(replyBot?.bot_id ?? e.self_id ?? "").trim();
|
|
210
208
|
const quotedBot = isGroup ? await isQuotingBot(e, ctx) : null;
|
|
211
209
|
const mentionedNickname =
|
|
212
210
|
cfg.nicknames.length > 0 &&
|