@zhin.js/adapter-icqq 1.1.14 → 1.1.16
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/CHANGELOG.md +65 -0
- package/PERMITS.md +14 -18
- package/README.md +12 -0
- package/adapters/icqq/index.js +15 -0
- package/adapters/icqq/index.ts +15 -0
- package/agents/icqq/conversation.js +72 -0
- package/agents/icqq/conversation.ts +67 -0
- package/agents/icqq/messages.js +144 -0
- package/agents/icqq/messages.ts +144 -0
- package/agents/icqq/skills/icqq-conversation/SKILL.md +24 -0
- package/agents/icqq/skills/icqq-conversation/tools/conversation_info/index.js +61 -0
- package/agents/icqq/skills/icqq-conversation/tools/conversation_info/index.ts +61 -0
- package/agents/icqq/skills/icqq-directory/SKILL.md +9 -11
- package/agents/icqq/skills/icqq-directory/tools/user_info/index.js +2 -1
- package/agents/icqq/skills/icqq-directory/tools/user_info/index.ts +2 -1
- package/agents/icqq/skills/icqq-group-admin/SKILL.md +32 -15
- package/agents/icqq/skills/icqq-group-admin/tools/announce/index.js +2 -1
- package/agents/icqq/skills/icqq-group-admin/tools/announce/index.ts +2 -1
- package/agents/icqq/skills/icqq-group-admin/tools/essence/index.js +2 -1
- package/agents/icqq/skills/icqq-group-admin/tools/essence/index.ts +2 -1
- package/agents/icqq/skills/icqq-group-admin/tools/group_invite/index.js +5 -3
- package/agents/icqq/skills/icqq-group-admin/tools/group_invite/index.ts +5 -3
- package/agents/icqq/skills/icqq-group-admin/tools/group_kick/index.js +14 -11
- package/agents/icqq/skills/icqq-group-admin/tools/group_kick/index.ts +13 -9
- package/agents/icqq/skills/icqq-group-admin/tools/group_leave/index.js +33 -0
- package/agents/icqq/skills/icqq-group-admin/tools/group_leave/index.ts +32 -0
- package/agents/icqq/skills/icqq-group-admin/tools/recall_member_message/index.js +33 -0
- package/agents/icqq/skills/icqq-group-admin/tools/recall_member_message/index.ts +32 -0
- package/agents/icqq/skills/icqq-group-admin/tools/set_anonymous/index.js +3 -2
- package/agents/icqq/skills/icqq-group-admin/tools/set_anonymous/index.ts +3 -2
- package/agents/icqq/skills/icqq-group-admin/tools/set_mute/index.js +4 -3
- package/agents/icqq/skills/icqq-group-admin/tools/set_mute/index.ts +4 -3
- package/agents/icqq/skills/icqq-group-admin/tools/set_title/index.js +4 -3
- package/agents/icqq/skills/icqq-group-admin/tools/set_title/index.ts +4 -3
- package/agents/icqq/skills/icqq-group-directory/SKILL.md +16 -0
- package/agents/icqq/skills/{icqq-directory → icqq-group-directory}/tools/group_member_info/index.js +3 -2
- package/agents/icqq/skills/{icqq-directory → icqq-group-directory}/tools/group_member_info/index.ts +3 -2
- package/agents/icqq/skills/icqq-group-interaction/SKILL.md +18 -0
- package/agents/icqq/skills/{icqq-interaction → icqq-group-interaction}/tools/group_sign/index.js +3 -2
- package/agents/icqq/skills/{icqq-interaction → icqq-group-interaction}/tools/group_sign/index.ts +3 -2
- package/agents/icqq/skills/{icqq-interaction → icqq-group-interaction}/tools/poke/index.js +2 -1
- package/agents/icqq/skills/{icqq-interaction → icqq-group-interaction}/tools/poke/index.ts +2 -1
- package/agents/icqq/skills/icqq-group-state/SKILL.md +7 -6
- package/agents/icqq/skills/icqq-group-state/tools/group_files/index.js +2 -1
- package/agents/icqq/skills/icqq-group-state/tools/group_files/index.ts +2 -1
- package/agents/icqq/skills/icqq-interaction/SKILL.md +5 -10
- package/agents/icqq/skills/icqq-interaction/tools/send_user_like/index.js +3 -2
- package/agents/icqq/skills/icqq-interaction/tools/send_user_like/index.ts +3 -2
- package/agents/icqq/skills/icqq-messages/SKILL.md +28 -0
- package/agents/icqq/skills/icqq-messages/tools/forward_messages/index.js +42 -0
- package/agents/icqq/skills/icqq-messages/tools/forward_messages/index.ts +40 -0
- package/agents/icqq/skills/icqq-messages/tools/quote_reply/index.js +24 -0
- package/agents/icqq/skills/icqq-messages/tools/quote_reply/index.ts +24 -0
- package/agents/icqq/skills/icqq-messages/tools/recall_own_message/index.js +18 -0
- package/agents/icqq/skills/icqq-messages/tools/recall_own_message/index.ts +17 -0
- package/agents/icqq/system.md +4 -0
- package/commands/icqq/endpoint/definition.js +9 -7
- package/commands/icqq/endpoint/definition.ts +9 -9
- package/lib/endpoint.d.ts +1 -0
- package/lib/endpoint.js +12 -1
- package/lib/group-moderation.d.ts +5 -0
- package/lib/group-moderation.js +46 -0
- package/lib/i18n.d.ts +1 -0
- package/lib/i18n.js +47 -0
- package/lib/icqq-inbound.js +15 -0
- package/lib/icqq-login-assist.d.ts +2 -0
- package/lib/icqq-login-assist.js +8 -7
- package/lib/protocol.d.ts +1 -0
- package/lib/protocol.js +14 -1
- package/package.json +16 -16
- package/prompt-sections/platform/index.js +1 -2
- package/prompt-sections/platform/index.ts +1 -2
- package/schema.json +250 -42
- package/src/endpoint.ts +14 -1
- package/src/group-moderation.ts +52 -0
- package/src/i18n.ts +48 -0
- package/src/icqq-inbound.ts +14 -0
- package/src/icqq-login-assist.ts +10 -7
- package/src/protocol.ts +13 -1
package/lib/endpoint.js
CHANGED
|
@@ -13,6 +13,7 @@ import { IcqqGuildCatalog, normalizeIcqqGuildInboundMessage, } from './icqq-guil
|
|
|
13
13
|
import { prepareIcqqOutboundMedia, resolveIcqqOutboundMediaMode, } from './outbound-media.js';
|
|
14
14
|
import { formatInboundContent, formatOutboundMessages, normalizeIcqqImageMedia, icqqInboundConversation, icqqOutboundTarget, } from './protocol.js';
|
|
15
15
|
import { ManagedIcqqClient } from './managed-client.js';
|
|
16
|
+
import { inspectGroupMember, moderateGroupMember } from './group-moderation.js';
|
|
16
17
|
const BOUND_EVENTS = [
|
|
17
18
|
'message.private',
|
|
18
19
|
'message.group',
|
|
@@ -55,6 +56,8 @@ export class IcqqEndpoint extends Endpoint {
|
|
|
55
56
|
#contentResolver;
|
|
56
57
|
content;
|
|
57
58
|
management = Object.freeze({
|
|
59
|
+
inspectGroupMember: (group, user, signal) => inspectGroupMember(this.client, group, user, signal),
|
|
60
|
+
moderateGroupMember: (group, user, action, signal) => moderateGroupMember(this.client, group, user, action, signal, () => this.#open && !this.#retiring && !this.#stopped),
|
|
58
61
|
listFriends: async () => Array.from(this.client.fl.values()).map((f) => ({
|
|
59
62
|
user_id: f.user_id,
|
|
60
63
|
nickname: f.nickname,
|
|
@@ -84,12 +87,18 @@ export class IcqqEndpoint extends Endpoint {
|
|
|
84
87
|
deleteFriend: async (userId) => {
|
|
85
88
|
await this.client.deleteFriend(Number(userId));
|
|
86
89
|
},
|
|
90
|
+
sendGroupNotice: async (groupId, content) => {
|
|
91
|
+
if (await this.client.sendGroupNotice(Number(groupId), content) === false) {
|
|
92
|
+
throw new Error('QQ did not confirm the group notice');
|
|
93
|
+
}
|
|
94
|
+
},
|
|
87
95
|
});
|
|
88
96
|
control = Object.freeze({
|
|
89
97
|
recall: async (message) => {
|
|
90
98
|
if (!message.id || message.id.startsWith('outbound:'))
|
|
91
99
|
return;
|
|
92
|
-
await this.client.deleteMsg(message.id)
|
|
100
|
+
if (!await this.client.deleteMsg(message.id))
|
|
101
|
+
throw new Error('QQ did not confirm message recall');
|
|
93
102
|
},
|
|
94
103
|
addReaction: async (message, emoji) => {
|
|
95
104
|
const target = resolveIcqqGroupReactionTarget(message);
|
|
@@ -618,6 +627,7 @@ export class IcqqEndpoint extends Endpoint {
|
|
|
618
627
|
this.#logSystemEvent(`login.${step}`, event);
|
|
619
628
|
void runIcqqLoginAssistStep({
|
|
620
629
|
assist: this.#options.loginAssist,
|
|
630
|
+
locale: this.#options.locale,
|
|
621
631
|
client: this.client,
|
|
622
632
|
adapter: 'icqq',
|
|
623
633
|
endpointKey: this.endpointName,
|
|
@@ -764,6 +774,7 @@ export class IcqqEndpoint extends Endpoint {
|
|
|
764
774
|
metadata: {
|
|
765
775
|
nickname: normalized.nickname,
|
|
766
776
|
senderRole: normalized.senderRole,
|
|
777
|
+
platformSentAt: normalized.timestampMs,
|
|
767
778
|
},
|
|
768
779
|
}, admittedBeforeRetire);
|
|
769
780
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Client } from '@icqqjs/icqq';
|
|
2
|
+
import type { GroupModerationAction, GroupModerationMember } from 'zhin.js/adapter';
|
|
3
|
+
/** Native role/join facts stay in the adapter; the moderation plugin owns policy. */
|
|
4
|
+
export declare function inspectGroupMember(client: Client, groupId: string, userId: string, signal: AbortSignal): Promise<GroupModerationMember>;
|
|
5
|
+
export declare function moderateGroupMember(client: Client, groupId: string, userId: string, action: GroupModerationAction, signal: AbortSignal, isActive: () => boolean): Promise<void>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Native role/join facts stay in the adapter; the moderation plugin owns policy. */
|
|
2
|
+
export async function inspectGroupMember(client, groupId, userId, signal) {
|
|
3
|
+
signal.throwIfAborted();
|
|
4
|
+
const group = numericId(groupId);
|
|
5
|
+
const user = numericId(userId);
|
|
6
|
+
const [self, member] = await Promise.all([
|
|
7
|
+
client.getGroupMemberInfo(group, client.uin, true),
|
|
8
|
+
client.getGroupMemberInfo(group, user, true),
|
|
9
|
+
]);
|
|
10
|
+
signal.throwIfAborted();
|
|
11
|
+
const joinedAt = member.join_time * 1000;
|
|
12
|
+
return {
|
|
13
|
+
canModerate: client.isOnline() && user !== client.uin
|
|
14
|
+
&& self.user_id === client.uin && self.group_id === group
|
|
15
|
+
&& member.user_id === user && member.group_id === group
|
|
16
|
+
&& (self.role === 'owner' || self.role === 'admin') && member.role === 'member',
|
|
17
|
+
...(Number.isSafeInteger(joinedAt) && joinedAt > 0 && joinedAt <= Date.now() ? { joinedAt } : {}),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export async function moderateGroupMember(client, groupId, userId, action, signal, isActive) {
|
|
21
|
+
const member = await inspectGroupMember(client, groupId, userId, signal);
|
|
22
|
+
signal.throwIfAborted();
|
|
23
|
+
if (!isActive() || !member.canModerate)
|
|
24
|
+
throw new Error('Group moderation permission is unavailable');
|
|
25
|
+
if (action.type === 'kick') {
|
|
26
|
+
if (!Number.isSafeInteger(action.maxMembershipAgeMs) || action.maxMembershipAgeMs <= 0
|
|
27
|
+
|| member.joinedAt !== action.joinedAt || !member.joinedAt
|
|
28
|
+
|| Date.now() - member.joinedAt > action.maxMembershipAgeMs) {
|
|
29
|
+
throw new Error('Group membership no longer matches the approved newcomer window');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (!Number.isSafeInteger(action.durationSeconds) || action.durationSeconds <= 0) {
|
|
33
|
+
throw new Error('Invalid group mute duration');
|
|
34
|
+
}
|
|
35
|
+
const ok = action.type === 'kick'
|
|
36
|
+
? await client.setGroupKick(numericId(groupId), numericId(userId))
|
|
37
|
+
: await client.setGroupBan(numericId(groupId), numericId(userId), action.durationSeconds);
|
|
38
|
+
if (!ok)
|
|
39
|
+
throw new Error('Platform did not confirm the moderation action');
|
|
40
|
+
}
|
|
41
|
+
function numericId(value) {
|
|
42
|
+
const id = Number(value);
|
|
43
|
+
if (!/^[1-9]\d*$/.test(value) || !Number.isSafeInteger(id))
|
|
44
|
+
throw new Error('Invalid QQ identifier');
|
|
45
|
+
return id;
|
|
46
|
+
}
|
package/lib/i18n.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const messages: (locale: import("zhin.js").Locale | undefined, key: "direct" | "addUsage" | "uinRequired" | "uinInvalid" | "endpointAdded" | "endpointAddFailed" | "loginQr" | "loginSlider" | "loginSms" | "loginAuth" | "loginOther", values?: import("zhin.js").MessageValues) => string;
|
package/lib/i18n.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createMessages } from 'zhin.js/i18n';
|
|
2
|
+
export const messages = createMessages({
|
|
3
|
+
"direct": {
|
|
4
|
+
"zh-CN": "direct(直连 @icqqjs/icqq)",
|
|
5
|
+
"en": "direct (@icqqjs/icqq)"
|
|
6
|
+
},
|
|
7
|
+
"addUsage": {
|
|
8
|
+
"zh-CN": "用法:{command} <uin>(uin 为纯数字 QQ 号)",
|
|
9
|
+
"en": "Usage: {command} <uin> (a numeric QQ account ID)"
|
|
10
|
+
},
|
|
11
|
+
"uinRequired": {
|
|
12
|
+
"zh-CN": "请提供纯数字 QQ 号(uin)",
|
|
13
|
+
"en": "Provide a numeric QQ account ID (uin)"
|
|
14
|
+
},
|
|
15
|
+
"uinInvalid": {
|
|
16
|
+
"zh-CN": "icqq endpoint 名必须是纯数字 QQ 号(uin)",
|
|
17
|
+
"en": "The ICQQ endpoint name must be a numeric QQ account ID (uin)"
|
|
18
|
+
},
|
|
19
|
+
"endpointAdded": {
|
|
20
|
+
"zh-CN": "✅ endpoint「{id}」已追加到 {file} 的 plugins.icqq.endpoints。\n重启 zhin 后生效。",
|
|
21
|
+
"en": "✅ Endpoint “{id}” added to plugins.icqq.endpoints in {file}.\nRestart zhin to apply."
|
|
22
|
+
},
|
|
23
|
+
"endpointAddFailed": {
|
|
24
|
+
"zh-CN": "添加失败:{error}",
|
|
25
|
+
"en": "Could not add the endpoint: {error}"
|
|
26
|
+
},
|
|
27
|
+
"loginQr": {
|
|
28
|
+
"zh-CN": "扫码登录:请在手机 QQ 扫描二维码,完成后在 Console / 终端确认继续",
|
|
29
|
+
"en": "Scan the QR code in mobile QQ, then confirm in Console or your terminal."
|
|
30
|
+
},
|
|
31
|
+
"loginSlider": {
|
|
32
|
+
"zh-CN": "滑动验证:打开链接完成滑块,将返回的 ticket(可含 randstr)提交继续",
|
|
33
|
+
"en": "Open the link, complete the slider challenge, and submit the returned ticket (with randstr if provided)."
|
|
34
|
+
},
|
|
35
|
+
"loginSms": {
|
|
36
|
+
"zh-CN": "设备锁:已请求短信验证码,请提交短信验证码继续",
|
|
37
|
+
"en": "Device verification: an SMS code was requested. Submit the code to continue."
|
|
38
|
+
},
|
|
39
|
+
"loginAuth": {
|
|
40
|
+
"zh-CN": "身份验证:完成后在 Console / 终端确认继续",
|
|
41
|
+
"en": "Complete identity verification, then confirm in Console or your terminal."
|
|
42
|
+
},
|
|
43
|
+
"loginOther": {
|
|
44
|
+
"zh-CN": "登录辅助({step})",
|
|
45
|
+
"en": "Login assistance ({step})"
|
|
46
|
+
}
|
|
47
|
+
});
|
package/lib/icqq-inbound.js
CHANGED
|
@@ -248,6 +248,21 @@ export function icqqElementsToSegments(elements) {
|
|
|
248
248
|
case "face":
|
|
249
249
|
out.push({ type: "face", data: { id: Number(el.id) } });
|
|
250
250
|
break;
|
|
251
|
+
case "bface": {
|
|
252
|
+
// ICQQ 的原创表情 file 是两个 MD5 加包编号,不是本地文件路径。
|
|
253
|
+
const file = typeof el.file === "string" ? el.file : "";
|
|
254
|
+
if (/^[a-f\d]{64}\d+$/i.test(file)) {
|
|
255
|
+
const md5 = file.slice(0, 32).toLowerCase();
|
|
256
|
+
out.push({
|
|
257
|
+
type: "image",
|
|
258
|
+
data: { media: { kind: "url", value: `https://gxh.vip.qq.com/club/item/parcel/item/${md5.slice(0, 2)}/${md5}/raw300.gif`, mime_type: "image/gif" } },
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
// 保留标签:下载或识图失败时仍能读懂表情的文字含义。
|
|
262
|
+
if (el.text)
|
|
263
|
+
out.push({ type: "text", data: { text: String(el.text) } });
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
251
266
|
case "image": {
|
|
252
267
|
const value = String(el.url ?? el.file ?? "");
|
|
253
268
|
if (!value)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Locale } from 'zhin.js/i18n';
|
|
1
2
|
import type { LoginAssist, LoginAssistType } from '@zhin.js/core';
|
|
2
3
|
type IcqqLoginClient = {
|
|
3
4
|
login(password?: string): Promise<unknown>;
|
|
@@ -23,5 +24,6 @@ export declare function runIcqqLoginAssistStep(input: {
|
|
|
23
24
|
logger: Logger;
|
|
24
25
|
step: LoginAssistType;
|
|
25
26
|
event: unknown;
|
|
27
|
+
locale?: Locale;
|
|
26
28
|
}): Promise<void>;
|
|
27
29
|
export {};
|
package/lib/icqq-login-assist.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { messages as t } from './i18n.js';
|
|
1
2
|
import { formatCompact } from '@zhin.js/logger';
|
|
2
3
|
/**
|
|
3
4
|
* Drive ICQQ login challenges through LoginAssist (refresh-safe pending tasks).
|
|
@@ -7,7 +8,7 @@ import { formatCompact } from '@zhin.js/logger';
|
|
|
7
8
|
export async function runIcqqLoginAssistStep(input) {
|
|
8
9
|
const { assist, client, adapter, endpointKey, owner, logger, step, event } = input;
|
|
9
10
|
assist.cancelOwned(owner, `replaced_by_${step}`);
|
|
10
|
-
const payload = buildPayload(step, event);
|
|
11
|
+
const payload = buildPayload(step, event, input.locale);
|
|
11
12
|
logger.info(formatCompact({
|
|
12
13
|
op: 'login_assist_pending',
|
|
13
14
|
endpoint: endpointKey,
|
|
@@ -56,33 +57,33 @@ export async function runIcqqLoginAssistStep(input) {
|
|
|
56
57
|
}));
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
|
-
function buildPayload(step, event) {
|
|
60
|
+
function buildPayload(step, event, locale) {
|
|
60
61
|
const raw = event && typeof event === 'object' ? event : {};
|
|
61
62
|
switch (step) {
|
|
62
63
|
case 'qrcode':
|
|
63
64
|
return {
|
|
64
|
-
message:
|
|
65
|
+
message: t(locale, 'loginQr'),
|
|
65
66
|
image: bufferToDataUrl(raw.image),
|
|
66
67
|
};
|
|
67
68
|
case 'slider':
|
|
68
69
|
return {
|
|
69
|
-
message:
|
|
70
|
+
message: t(locale, 'loginSlider'),
|
|
70
71
|
url: typeof raw.url === 'string' ? raw.url : undefined,
|
|
71
72
|
};
|
|
72
73
|
case 'device':
|
|
73
74
|
return {
|
|
74
|
-
message: '
|
|
75
|
+
message: t(locale, 'loginSms'),
|
|
75
76
|
url: typeof raw.url === 'string' ? raw.url : undefined,
|
|
76
77
|
phone: raw.phone,
|
|
77
78
|
};
|
|
78
79
|
case 'auth':
|
|
79
80
|
return {
|
|
80
|
-
message:
|
|
81
|
+
message: t(locale, 'loginAuth'),
|
|
81
82
|
url: typeof raw.url === 'string' ? raw.url : undefined,
|
|
82
83
|
device: raw.device,
|
|
83
84
|
};
|
|
84
85
|
default:
|
|
85
|
-
return { message:
|
|
86
|
+
return { message: t(locale, 'loginOther', { step }) };
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
89
|
function normalizeSubmitValue(value) {
|
package/lib/protocol.d.ts
CHANGED
|
@@ -198,6 +198,7 @@ export interface ResolvedIcqqConfig {
|
|
|
198
198
|
export interface IcqqWireSegment {
|
|
199
199
|
readonly type: string;
|
|
200
200
|
readonly data?: Record<string, unknown>;
|
|
201
|
+
readonly platform?: Readonly<Record<string, unknown>>;
|
|
201
202
|
}
|
|
202
203
|
export interface IcqqInboundMessage {
|
|
203
204
|
readonly id: string;
|
package/lib/protocol.js
CHANGED
|
@@ -265,6 +265,7 @@ const ICQQ_STANDALONE_ELEMENTS = new Set([
|
|
|
265
265
|
'json',
|
|
266
266
|
'share',
|
|
267
267
|
'long_msg',
|
|
268
|
+
'multimsg',
|
|
268
269
|
]);
|
|
269
270
|
/** Normalize inline image bytes before either temporary-file or native-base64 delivery. */
|
|
270
271
|
export function normalizeIcqqImageMedia(content) {
|
|
@@ -336,7 +337,7 @@ export function formatOutboundMessages(payload) {
|
|
|
336
337
|
}
|
|
337
338
|
const messages = groups.filter(group => group.some(element => typeof element === 'string'
|
|
338
339
|
? element.trim() !== ''
|
|
339
|
-
: element.type !== 'reply'));
|
|
340
|
+
: element.type !== 'reply' && element.type !== 'quote'));
|
|
340
341
|
if (messages.length === 0)
|
|
341
342
|
return ['\u200b'];
|
|
342
343
|
return messages.map(group => group.length === 1 ? group[0] : group);
|
|
@@ -380,6 +381,14 @@ function formatOutboundElements(payload) {
|
|
|
380
381
|
const id = String(item.data?.message_id ?? item.data?.id ?? '').trim();
|
|
381
382
|
if (!id)
|
|
382
383
|
throw new TypeError('ICQQ reply segment requires message_id');
|
|
384
|
+
const quote = item.platform?.icqqQuote;
|
|
385
|
+
if (quote) {
|
|
386
|
+
const { user_id, seq, rand, time, message } = quote;
|
|
387
|
+
if (typeof user_id !== 'number' || typeof seq !== 'number' || typeof rand !== 'number'
|
|
388
|
+
|| typeof time !== 'number' || typeof message !== 'string')
|
|
389
|
+
throw new TypeError('Invalid ICQQ quote source');
|
|
390
|
+
return { type: 'quote', user_id, seq, rand, time, message };
|
|
391
|
+
}
|
|
383
392
|
return { type: 'reply', id };
|
|
384
393
|
}
|
|
385
394
|
case 'record':
|
|
@@ -410,6 +419,10 @@ function formatOutboundElements(payload) {
|
|
|
410
419
|
const resid = String(item.data?.forward_id ?? item.data?.resid ?? item.data?.id ?? '').trim();
|
|
411
420
|
if (!resid)
|
|
412
421
|
throw new TypeError('ICQQ forward segment requires forward_id');
|
|
422
|
+
// Prepared merged forwards need their filename; a long_msg would expand inline.
|
|
423
|
+
const filename = item.platform?.icqqForwardFilename;
|
|
424
|
+
if (typeof filename === 'string' && filename)
|
|
425
|
+
return { type: 'multimsg', resid, filename };
|
|
413
426
|
return { type: 'long_msg', resid };
|
|
414
427
|
}
|
|
415
428
|
case 'share':
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-icqq",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.16",
|
|
4
4
|
"description": "Zhin.js ICQQ adapter — direct connection to @icqqjs/icqq",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -33,24 +33,24 @@
|
|
|
33
33
|
"directory": "plugins/adapters/icqq"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@zhin.js/adapter": "1.1.
|
|
37
|
-
"@zhin.js/agent-feature": "1.1.
|
|
38
|
-
"@zhin.js/core": "1.1.
|
|
39
|
-
"@zhin.js/feature-kit": "1.1.
|
|
40
|
-
"@zhin.js/im-contract": "1.1.
|
|
36
|
+
"@zhin.js/adapter": "1.1.23",
|
|
37
|
+
"@zhin.js/agent-feature": "1.1.10",
|
|
38
|
+
"@zhin.js/core": "1.1.51",
|
|
39
|
+
"@zhin.js/feature-kit": "1.1.9",
|
|
40
|
+
"@zhin.js/im-contract": "1.1.7",
|
|
41
41
|
"@zhin.js/logger": "1.1.2",
|
|
42
|
-
"@zhin.js/permission": "1.1.
|
|
43
|
-
"@zhin.js/skill": "1.1.
|
|
44
|
-
"@zhin.js/tool": "1.1.
|
|
42
|
+
"@zhin.js/permission": "1.1.9",
|
|
43
|
+
"@zhin.js/skill": "1.1.10",
|
|
44
|
+
"@zhin.js/tool": "1.1.10"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"@icqqjs/icqq": "^1.12.2",
|
|
48
48
|
"zod": "^4.0.0",
|
|
49
|
-
"@zhin.js/adapter": "^1.1.
|
|
50
|
-
"@zhin.js/command": "^1.1.
|
|
51
|
-
"@zhin.js/core": "^1.1.
|
|
52
|
-
"@zhin.js/prompt-section": "^1.1.
|
|
53
|
-
"zhin.js": "^1.1.
|
|
49
|
+
"@zhin.js/adapter": "^1.1.23",
|
|
50
|
+
"@zhin.js/command": "^1.1.11",
|
|
51
|
+
"@zhin.js/core": "^1.1.51",
|
|
52
|
+
"@zhin.js/prompt-section": "^1.1.9",
|
|
53
|
+
"zhin.js": "^1.1.16"
|
|
54
54
|
},
|
|
55
55
|
"peerDependenciesMeta": {
|
|
56
56
|
"@icqqjs/icqq": {
|
|
@@ -75,8 +75,8 @@
|
|
|
75
75
|
"typescript": "^6.0.3",
|
|
76
76
|
"vitest": "^4.1.10",
|
|
77
77
|
"zod": "^4.4.3",
|
|
78
|
-
"@zhin.js/prompt-section": "1.1.
|
|
79
|
-
"zhin.js": "1.1.
|
|
78
|
+
"@zhin.js/prompt-section": "1.1.9",
|
|
79
|
+
"zhin.js": "1.1.16"
|
|
80
80
|
},
|
|
81
81
|
"files": [
|
|
82
82
|
"adapters",
|
|
@@ -3,8 +3,7 @@ import { defineAgentPromptSection } from '@zhin.js/prompt-section';
|
|
|
3
3
|
export default defineAgentPromptSection({
|
|
4
4
|
title: 'ICQQ / QQ',
|
|
5
5
|
content: [
|
|
6
|
-
'
|
|
7
|
-
'Use discover for the user intent, then load only the matching Skill before calling its private Tool.',
|
|
6
|
+
'Use the current Skill catalog; discover the intent and load the matching Skill before its private Tool.',
|
|
8
7
|
'The current IM operation selects the bot Client automatically; never guess user_id or group_id.',
|
|
9
8
|
].join('\n'),
|
|
10
9
|
layer: 'tools',
|
|
@@ -3,8 +3,7 @@ import { defineAgentPromptSection } from '@zhin.js/prompt-section';
|
|
|
3
3
|
export default defineAgentPromptSection({
|
|
4
4
|
title: 'ICQQ / QQ',
|
|
5
5
|
content: [
|
|
6
|
-
'
|
|
7
|
-
'Use discover for the user intent, then load only the matching Skill before calling its private Tool.',
|
|
6
|
+
'Use the current Skill catalog; discover the intent and load the matching Skill before its private Tool.',
|
|
8
7
|
'The current IM operation selects the bot Client automatically; never guess user_id or group_id.',
|
|
9
8
|
].join('\n'),
|
|
10
9
|
layer: 'tools',
|