@zhin.js/adapter-icqq 1.0.71 → 1.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.
Files changed (111) hide show
  1. package/CHANGELOG.md +1125 -52
  2. package/README.md +116 -431
  3. package/adapters/icqq.js +31 -0
  4. package/adapters/icqq.ts +42 -0
  5. package/agent/PERMITS.md +24 -0
  6. package/agent/prompt-sections/platform.ts +17 -0
  7. package/commands/endpoint/add/[[id]].js +3 -0
  8. package/commands/endpoint/add/[[id]].ts +3 -0
  9. package/commands/endpoint/list.js +3 -0
  10. package/commands/endpoint/list.ts +3 -0
  11. package/commands/endpoint/remove/[id].js +3 -0
  12. package/commands/endpoint/remove/[id].ts +3 -0
  13. package/lib/client.d.ts +19 -0
  14. package/lib/client.js +3 -0
  15. package/lib/cq-message.d.ts +14 -0
  16. package/lib/cq-message.js +106 -0
  17. package/lib/endpoint.d.ts +31 -0
  18. package/lib/endpoint.js +1046 -0
  19. package/lib/forward-msg.d.ts +6 -0
  20. package/lib/forward-msg.js +107 -0
  21. package/lib/icqq-endpoint-commands.d.ts +1 -0
  22. package/lib/icqq-endpoint-commands.js +26 -0
  23. package/lib/icqq-guild.d.ts +57 -0
  24. package/lib/icqq-guild.js +109 -0
  25. package/lib/icqq-inbound.d.ts +165 -0
  26. package/lib/icqq-inbound.js +651 -0
  27. package/lib/icqq-inbox.d.ts +25 -0
  28. package/lib/icqq-inbox.js +129 -0
  29. package/lib/icqq-login-assist.d.ts +27 -0
  30. package/lib/icqq-login-assist.js +109 -0
  31. package/lib/icqq-runtime-state.d.ts +1 -0
  32. package/lib/icqq-runtime-state.js +6 -0
  33. package/lib/index.d.ts +5 -18
  34. package/lib/index.js +5 -124
  35. package/lib/outbound-media.d.ts +14 -0
  36. package/lib/outbound-media.js +76 -0
  37. package/lib/protocol.d.ts +276 -0
  38. package/lib/protocol.js +425 -0
  39. package/lib/types.d.ts +37 -11
  40. package/lib/types.js +0 -1
  41. package/package.json +80 -32
  42. package/plugin.js +19 -0
  43. package/schema.json +162 -0
  44. package/src/client.ts +29 -0
  45. package/src/cq-message.ts +113 -0
  46. package/src/endpoint.ts +1138 -0
  47. package/src/forward-msg.ts +112 -0
  48. package/src/icqq-endpoint-commands.ts +28 -0
  49. package/src/icqq-guild.ts +154 -0
  50. package/src/icqq-inbound.ts +814 -0
  51. package/src/icqq-inbox.ts +147 -0
  52. package/src/icqq-login-assist.ts +132 -0
  53. package/src/icqq-runtime-state.ts +7 -0
  54. package/src/index.ts +30 -149
  55. package/src/outbound-media.ts +103 -0
  56. package/src/protocol.ts +575 -0
  57. package/src/types.ts +40 -11
  58. package/tools/announce.js +16 -0
  59. package/tools/announce.ts +15 -0
  60. package/tools/essence.js +22 -0
  61. package/tools/essence.ts +20 -0
  62. package/tools/friend_list.js +18 -0
  63. package/tools/friend_list.ts +18 -0
  64. package/tools/group_files.js +22 -0
  65. package/tools/group_files.ts +20 -0
  66. package/tools/group_invite.js +23 -0
  67. package/tools/group_invite.ts +20 -0
  68. package/tools/group_kick.js +26 -0
  69. package/tools/group_kick.ts +22 -0
  70. package/tools/group_list.js +19 -0
  71. package/tools/group_list.ts +19 -0
  72. package/tools/group_member_info.js +24 -0
  73. package/tools/group_member_info.ts +26 -0
  74. package/tools/group_sign.js +19 -0
  75. package/tools/group_sign.ts +17 -0
  76. package/tools/list_muted.js +17 -0
  77. package/tools/list_muted.ts +16 -0
  78. package/tools/poke.js +16 -0
  79. package/tools/poke.ts +15 -0
  80. package/tools/send_user_like.js +25 -0
  81. package/tools/send_user_like.ts +22 -0
  82. package/tools/set_anonymous.js +21 -0
  83. package/tools/set_anonymous.ts +19 -0
  84. package/tools/set_mute.js +24 -0
  85. package/tools/set_mute.ts +21 -0
  86. package/tools/set_title.js +25 -0
  87. package/tools/set_title.ts +22 -0
  88. package/tools/user_info.js +14 -0
  89. package/tools/user_info.ts +13 -0
  90. package/LICENSE +0 -21
  91. package/client/ICQQManagement.tsx +0 -139
  92. package/client/LoginAssistPanel.tsx +0 -293
  93. package/client/index.tsx +0 -11
  94. package/client/tsconfig.json +0 -7
  95. package/client/utils/api.ts +0 -20
  96. package/dist/index.js +0 -1
  97. package/lib/adapter.d.ts +0 -34
  98. package/lib/adapter.d.ts.map +0 -1
  99. package/lib/adapter.js +0 -396
  100. package/lib/adapter.js.map +0 -1
  101. package/lib/bot.d.ts +0 -46
  102. package/lib/bot.d.ts.map +0 -1
  103. package/lib/bot.js +0 -457
  104. package/lib/bot.js.map +0 -1
  105. package/lib/index.d.ts.map +0 -1
  106. package/lib/index.js.map +0 -1
  107. package/lib/types.d.ts.map +0 -1
  108. package/lib/types.js.map +0 -1
  109. package/skills/icqq/SKILL.md +0 -22
  110. package/src/adapter.ts +0 -448
  111. package/src/bot.ts +0 -521
@@ -0,0 +1,24 @@
1
+ # ICQQ Platform Permits(QQ 群)
2
+
3
+ ## 入站字段
4
+
5
+ 群成员 `owner` / `admin` / `member` 写入 `$sender.role`(IPC 侧已有)。
6
+
7
+ ## Permit 词汇表
8
+
9
+ 平台范围用工具的 `platforms: ['icqq']`,不要写非法的 `platform(icqq)`(缺 perm 时 PermissionHost 会直接拒绝,工具对模型不可见)。
10
+
11
+ | `platform(icqq,…)` | 含义 |
12
+ |--------------------|------|
13
+ | `scene_owner` | 群主 |
14
+ | `scene_admin` | 群管理员(含群主) |
15
+
16
+ ## 扩展工具示例
17
+
18
+ | 工具 | permit |
19
+ |------|--------|
20
+ | `icqq_set_title` | `scene_owner` |
21
+ | `icqq_announce` / `icqq_essence` / `icqq_list_muted` | `scene_admin` |
22
+ | `icqq_set_anonymous` | `scene_owner` |
23
+
24
+ 工厂群管工具使用默认 `scene_admin` / `scene_owner`。
@@ -0,0 +1,17 @@
1
+ import { defineAgentPromptSection } from '@zhin.js/prompt-section';
2
+
3
+ export default defineAgentPromptSection({
4
+ title: 'ICQQ / QQ',
5
+ content: [
6
+ 'On icqq/QQ: if icqq__send_user_like is in your tool list, call it with { user_id, times }.',
7
+ 'The current IM operation selects the bot Client automatically. user_id is the sender to like. times is 1-20.',
8
+ 'Do not claim the tool is missing until calling it this turn or load_tool("icqq__send_user_like") fails.',
9
+ 'Other social tools include icqq__poke and icqq__friend_list.',
10
+ ].join('\n'),
11
+ layer: 'tools',
12
+ order: 70,
13
+ retention: 'preferred',
14
+ maxChars: 1200,
15
+ profiles: ['interactive'],
16
+ platforms: ['icqq'],
17
+ });
@@ -0,0 +1,3 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { icqqEndpointCommands } from "../../../lib/icqq-endpoint-commands.js";
3
+ export default icqqEndpointCommands.add;
@@ -0,0 +1,3 @@
1
+ import { icqqEndpointCommands } from '../../../src/icqq-endpoint-commands.js';
2
+
3
+ export default icqqEndpointCommands.add;
@@ -0,0 +1,3 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { icqqEndpointCommands } from "../../lib/icqq-endpoint-commands.js";
3
+ export default icqqEndpointCommands.list;
@@ -0,0 +1,3 @@
1
+ import { icqqEndpointCommands } from '../../src/icqq-endpoint-commands.js';
2
+
3
+ export default icqqEndpointCommands.list;
@@ -0,0 +1,3 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { icqqEndpointCommands } from "../../../lib/icqq-endpoint-commands.js";
3
+ export default icqqEndpointCommands.remove;
@@ -0,0 +1,3 @@
1
+ import { icqqEndpointCommands } from '../../../src/icqq-endpoint-commands.js';
2
+
3
+ export default icqqEndpointCommands.remove;
@@ -0,0 +1,19 @@
1
+ import type { Client, EventMap } from '@icqqjs/icqq';
2
+ type EventPayload<TListener> = TListener extends (event: infer TEvent, ...rest: readonly unknown[]) => unknown ? TEvent : never;
3
+ /** The actual ICQQ SDK instance exposed by every ICQQ Endpoint event. */
4
+ export type IcqqClient = Client;
5
+ /** Native ICQQ event-name → first public event payload, derived from the SDK SSOT. */
6
+ export type IcqqClientEventMap = {
7
+ readonly [TName in keyof EventMap]: EventPayload<EventMap[TName]>;
8
+ };
9
+ declare module '@zhin.js/feature-kit' {
10
+ interface AdapterClientRegistry {
11
+ readonly icqq: {
12
+ readonly client: IcqqClient;
13
+ readonly events: IcqqClientEventMap;
14
+ };
15
+ }
16
+ }
17
+ /** Typed, generation-checked identity used by handlers, commands, tools and schedules. */
18
+ export declare const icqqClient: import("@zhin.js/adapter").EndpointClientToken<Client, IcqqClientEventMap>;
19
+ export {};
package/lib/client.js ADDED
@@ -0,0 +1,3 @@
1
+ import { defineEndpointClient } from 'zhin.js/adapter';
2
+ /** Typed, generation-checked identity used by handlers, commands, tools and schedules. */
3
+ export const icqqClient = defineEndpointClient('icqq');
@@ -0,0 +1,14 @@
1
+ /** ICQQ 历史文本视图 → canonical MessageSegment。出站只使用原生 Sendable。 */
2
+ import { type MediaRef } from "@zhin.js/core";
3
+ import type { MessageSegment } from "zhin.js";
4
+ /**
5
+ * CQ 媒体参数 / 入站元素媒体值 → canonical MediaRef:
6
+ * `base64://` → base64;http(s) → url;本机路径 → path;其余视为平台不透明引用(file)。
7
+ */
8
+ export declare function icqqMediaRefFromString(value: string): MediaRef;
9
+ /**
10
+ * canonical MediaRef(`data.media`,唯一媒体来源)→ ICQQ native
11
+ * element 的 file 参数。base64 使用 ICQQ 原生支持的 `base64://` 前缀。
12
+ */
13
+ export declare function resolveIcqqMediaFile(data: Record<string, unknown> | undefined): string | undefined;
14
+ export declare function parseCqMessage(raw: string): MessageSegment[];
@@ -0,0 +1,106 @@
1
+ /** ICQQ 历史文本视图 → canonical MessageSegment。出站只使用原生 Sendable。 */
2
+ import { isMediaRef } from "@zhin.js/core";
3
+ const MAX_CQ_PARSE_LEN = 256_000;
4
+ /**
5
+ * CQ 媒体参数 / 入站元素媒体值 → canonical MediaRef:
6
+ * `base64://` → base64;http(s) → url;本机路径 → path;其余视为平台不透明引用(file)。
7
+ */
8
+ export function icqqMediaRefFromString(value) {
9
+ if (value.startsWith("base64://")) {
10
+ return { kind: "base64", value: value.slice("base64://".length) };
11
+ }
12
+ if (value.startsWith("http://") || value.startsWith("https://")) {
13
+ return { kind: "url", value };
14
+ }
15
+ if (value.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(value)) {
16
+ return { kind: "path", value };
17
+ }
18
+ return { kind: "file", value };
19
+ }
20
+ /**
21
+ * canonical MediaRef(`data.media`,唯一媒体来源)→ ICQQ native
22
+ * element 的 file 参数。base64 使用 ICQQ 原生支持的 `base64://` 前缀。
23
+ */
24
+ export function resolveIcqqMediaFile(data) {
25
+ const media = data?.media;
26
+ if (!isMediaRef(media))
27
+ return undefined;
28
+ if (media.kind === "base64") {
29
+ return media.value.startsWith("base64://") ? media.value : `base64://${media.value}`;
30
+ }
31
+ return media.value;
32
+ }
33
+ function pushCqSegment(segments, type, arg) {
34
+ switch (type) {
35
+ case "face":
36
+ segments.push({ type: "face", data: { id: Number(arg) } });
37
+ break;
38
+ case "image":
39
+ segments.push({ type: "image", data: { media: icqqMediaRefFromString(arg) } });
40
+ break;
41
+ case "at":
42
+ if (arg === "all") {
43
+ segments.push({ type: "at", data: { qq: "all" } });
44
+ }
45
+ else {
46
+ segments.push({ type: "at", data: { qq: arg } });
47
+ }
48
+ break;
49
+ case "dice":
50
+ segments.push({ type: "dice", data: {} });
51
+ break;
52
+ case "rps":
53
+ segments.push({ type: "rps", data: {} });
54
+ break;
55
+ case "record":
56
+ case "audio":
57
+ segments.push({ type: "audio", data: { media: icqqMediaRefFromString(arg) } });
58
+ break;
59
+ case "video":
60
+ segments.push({ type: "video", data: { media: icqqMediaRefFromString(arg) } });
61
+ break;
62
+ case "reply":
63
+ segments.push({ type: "reply", data: { message_id: arg } });
64
+ break;
65
+ case "json":
66
+ segments.push({ type: "json", data: { text: arg } });
67
+ break;
68
+ default:
69
+ segments.push({ type, data: { text: `[${type}:${arg}]` } });
70
+ break;
71
+ }
72
+ }
73
+ export function parseCqMessage(raw) {
74
+ const text = raw.length > MAX_CQ_PARSE_LEN ? raw.slice(0, MAX_CQ_PARSE_LEN) : raw;
75
+ const segments = [];
76
+ let i = 0;
77
+ while (i < text.length) {
78
+ if (text[i] !== "[") {
79
+ const next = text.indexOf("[", i);
80
+ const chunk = next === -1 ? text.slice(i) : text.slice(i, next);
81
+ if (chunk)
82
+ segments.push({ type: "text", data: { text: chunk } });
83
+ if (next === -1)
84
+ break;
85
+ i = next;
86
+ continue;
87
+ }
88
+ const close = text.indexOf("]", i + 1);
89
+ if (close === -1) {
90
+ segments.push({ type: "text", data: { text: text.slice(i) } });
91
+ break;
92
+ }
93
+ const inner = text.slice(i + 1, close);
94
+ const colon = inner.indexOf(":");
95
+ const type = (colon === -1 ? inner : inner.slice(0, colon)).trim().toLowerCase();
96
+ const arg = colon === -1 ? "" : inner.slice(colon + 1);
97
+ if (/^[a-z_]+$/.test(type)) {
98
+ pushCqSegment(segments, type, arg);
99
+ }
100
+ else {
101
+ segments.push({ type: "text", data: { text: text.slice(i, close + 1) } });
102
+ }
103
+ i = close + 1;
104
+ }
105
+ return segments.length ? segments : [{ type: "text", data: { text: raw } }];
106
+ }
@@ -0,0 +1,31 @@
1
+ import { Client } from '@icqqjs/icqq';
2
+ import { Endpoint } from 'zhin.js/adapter';
3
+ import type { EndpointControl, EndpointManagement, EndpointSendRequest } from 'zhin.js/adapter';
4
+ import type { EndpointContentPort } from '@zhin.js/adapter';
5
+ import { type LoginAssist } from '@zhin.js/core';
6
+ import type { CapabilityId } from 'zhin.js';
7
+ import { type IcqqInboundMessage, type ResolvedIcqqConfig } from './protocol.js';
8
+ export interface IcqqEndpointOptions {
9
+ readonly id: CapabilityId;
10
+ readonly config: ResolvedIcqqConfig;
11
+ readonly loginAssist: LoginAssist;
12
+ }
13
+ declare class ManagedIcqqClient extends Client {
14
+ cancelReconnect(): void;
15
+ }
16
+ export declare class IcqqEndpoint extends Endpoint<Client> {
17
+ #private;
18
+ readonly client: ManagedIcqqClient;
19
+ readonly endpointName: string;
20
+ readonly content: EndpointContentPort;
21
+ readonly management: EndpointManagement;
22
+ readonly control: EndpointControl;
23
+ constructor(options: IcqqEndpointOptions);
24
+ start(signal: AbortSignal): Promise<void>;
25
+ open(): void;
26
+ close(): Promise<void>;
27
+ stop(): Promise<void>;
28
+ send({ conversation, payload }: EndpointSendRequest): Promise<string>;
29
+ admit(msg: IcqqInboundMessage): Promise<void>;
30
+ }
31
+ export {};