@zhin.js/adapter-icqq 6.0.2 → 6.0.3

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 (121) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +32 -437
  3. package/adapters/icqq.ts +30 -0
  4. package/agent/tools/announce.ts +2 -2
  5. package/agent/tools/essence.ts +2 -2
  6. package/agent/tools/friend_list.ts +2 -2
  7. package/agent/tools/group_files.ts +2 -2
  8. package/agent/tools/group_invite.ts +2 -2
  9. package/agent/tools/group_list.ts +2 -2
  10. package/agent/tools/group_sign.ts +2 -2
  11. package/agent/tools/list_muted.ts +2 -2
  12. package/agent/tools/poke.ts +2 -2
  13. package/agent/tools/send_user_like.ts +2 -2
  14. package/agent/tools/set_anonymous.ts +2 -2
  15. package/agent/tools/set_title.ts +2 -2
  16. package/lib/agent-prompt.d.ts +2 -0
  17. package/lib/{src/agent-prompt.js → agent-prompt.js} +0 -1
  18. package/lib/cq-message.d.ts +9 -0
  19. package/lib/{src/cq-message.js → cq-message.js} +0 -1
  20. package/lib/endpoint.d.ts +51 -0
  21. package/lib/endpoint.js +483 -0
  22. package/lib/forward-msg.d.ts +26 -0
  23. package/lib/{src/forward-msg.js → forward-msg.js} +0 -1
  24. package/lib/icqq-agent-deps.d.ts +25 -0
  25. package/lib/icqq-agent-deps.js +32 -0
  26. package/lib/icqq-guild.d.ts +47 -0
  27. package/lib/{src/icqq-guild.js → icqq-guild.js} +4 -2
  28. package/lib/icqq-inbound.d.ts +139 -0
  29. package/lib/{src/icqq-inbound.js → icqq-inbound.js} +27 -3
  30. package/lib/index.d.ts +6 -0
  31. package/lib/index.js +6 -0
  32. package/lib/ipc-client.d.ts +73 -0
  33. package/lib/{src/ipc-client.js → ipc-client.js} +0 -1
  34. package/lib/outbound-media.d.ts +13 -0
  35. package/lib/{src/outbound-media.js → outbound-media.js} +0 -1
  36. package/lib/protocol.d.ts +269 -0
  37. package/lib/{src/protocol.js → protocol.js} +124 -2
  38. package/lib/types.d.ts +72 -0
  39. package/lib/{src/types.js → types.js} +0 -1
  40. package/package.json +49 -45
  41. package/plugin.ts +32 -0
  42. package/schema.json +35 -0
  43. package/src/endpoint.ts +407 -796
  44. package/src/icqq-agent-deps.ts +48 -9
  45. package/src/icqq-guild.ts +1 -2
  46. package/src/icqq-inbound.ts +31 -2
  47. package/src/index.ts +35 -69
  48. package/src/protocol.ts +191 -1
  49. package/client/ICQQManagement.tsx +0 -147
  50. package/client/LoginAssistPanel.tsx +0 -300
  51. package/client/index.tsx +0 -11
  52. package/client/tsconfig.json +0 -7
  53. package/client/utils/api.ts +0 -30
  54. package/dist/index.js +0 -34
  55. package/lib/agent/tools/announce.js +0 -21
  56. package/lib/agent/tools/announce.js.map +0 -1
  57. package/lib/agent/tools/essence.js +0 -22
  58. package/lib/agent/tools/essence.js.map +0 -1
  59. package/lib/agent/tools/friend_list.js +0 -19
  60. package/lib/agent/tools/friend_list.js.map +0 -1
  61. package/lib/agent/tools/group_files.js +0 -29
  62. package/lib/agent/tools/group_files.js.map +0 -1
  63. package/lib/agent/tools/group_invite.js +0 -20
  64. package/lib/agent/tools/group_invite.js.map +0 -1
  65. package/lib/agent/tools/group_list.js +0 -20
  66. package/lib/agent/tools/group_list.js.map +0 -1
  67. package/lib/agent/tools/group_sign.js +0 -19
  68. package/lib/agent/tools/group_sign.js.map +0 -1
  69. package/lib/agent/tools/list_muted.js +0 -23
  70. package/lib/agent/tools/list_muted.js.map +0 -1
  71. package/lib/agent/tools/poke.js +0 -20
  72. package/lib/agent/tools/poke.js.map +0 -1
  73. package/lib/agent/tools/send_user_like.js +0 -22
  74. package/lib/agent/tools/send_user_like.js.map +0 -1
  75. package/lib/agent/tools/set_anonymous.js +0 -22
  76. package/lib/agent/tools/set_anonymous.js.map +0 -1
  77. package/lib/agent/tools/set_title.js +0 -25
  78. package/lib/agent/tools/set_title.js.map +0 -1
  79. package/lib/src/adapter.js +0 -128
  80. package/lib/src/adapter.js.map +0 -1
  81. package/lib/src/agent-prompt.js.map +0 -1
  82. package/lib/src/cq-message.js.map +0 -1
  83. package/lib/src/endpoint.js +0 -755
  84. package/lib/src/endpoint.js.map +0 -1
  85. package/lib/src/forward-msg.js.map +0 -1
  86. package/lib/src/get-msg.js +0 -46
  87. package/lib/src/get-msg.js.map +0 -1
  88. package/lib/src/icqq-agent-deps.js +0 -10
  89. package/lib/src/icqq-agent-deps.js.map +0 -1
  90. package/lib/src/icqq-guild.js.map +0 -1
  91. package/lib/src/icqq-inbound.js.map +0 -1
  92. package/lib/src/icqq-login-assist-bridge.js +0 -148
  93. package/lib/src/icqq-login-assist-bridge.js.map +0 -1
  94. package/lib/src/icqq-side-events.js +0 -130
  95. package/lib/src/icqq-side-events.js.map +0 -1
  96. package/lib/src/index.js +0 -50
  97. package/lib/src/index.js.map +0 -1
  98. package/lib/src/ipc-client.js.map +0 -1
  99. package/lib/src/login-assist-routes.js +0 -29
  100. package/lib/src/login-assist-routes.js.map +0 -1
  101. package/lib/src/login-ipc-contract.js +0 -35
  102. package/lib/src/login-ipc-contract.js.map +0 -1
  103. package/lib/src/outbound-media.js.map +0 -1
  104. package/lib/src/protocol.js.map +0 -1
  105. package/lib/src/routes.js +0 -67
  106. package/lib/src/routes.js.map +0 -1
  107. package/lib/src/segment-mapper.js +0 -2
  108. package/lib/src/segment-mapper.js.map +0 -1
  109. package/lib/src/tools/index.js +0 -23
  110. package/lib/src/tools/index.js.map +0 -1
  111. package/lib/src/types.js.map +0 -1
  112. package/plugin.yml +0 -3
  113. package/src/adapter.ts +0 -151
  114. package/src/get-msg.ts +0 -56
  115. package/src/icqq-login-assist-bridge.ts +0 -196
  116. package/src/icqq-side-events.ts +0 -143
  117. package/src/login-assist-routes.ts +0 -39
  118. package/src/login-ipc-contract.ts +0 -52
  119. package/src/routes.ts +0 -83
  120. package/src/segment-mapper.ts +0 -1
  121. package/src/tools/index.ts +0 -31
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Agent tool deps for icqq.
3
+ * Endpoints register themselves on start; tools look up by config name / QQ uin.
4
+ */
5
+ const endpoints = new Map();
6
+ let override = null;
7
+ export function registerIcqqAgentEndpoint(endpointId, endpoint) {
8
+ endpoints.set(endpointId, endpoint);
9
+ return () => {
10
+ if (endpoints.get(endpointId) === endpoint) {
11
+ endpoints.delete(endpointId);
12
+ }
13
+ };
14
+ }
15
+ /** Optional override used by tests / transitional callers. Pass `null` to clear. */
16
+ export function setIcqqAgentDeps(deps) {
17
+ override = deps;
18
+ }
19
+ function lookup(endpointId) {
20
+ const registered = endpoints.get(endpointId);
21
+ if (!registered)
22
+ throw new Error(`Endpoint ${endpointId} 不存在`);
23
+ return registered;
24
+ }
25
+ export function getIcqqAgentDeps() {
26
+ if (override)
27
+ return override;
28
+ return {
29
+ getEndpoint: lookup,
30
+ getAdapter: () => ({ getEndpoint: lookup }),
31
+ };
32
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * ICQQ guild (QQ 频道) catalog sync, inbound normalize, Console channel list.
3
+ */
4
+ import { type MessageSegment } from "zhin.js";
5
+ import { type IpcGuildMessageEventData } from "./protocol.js";
6
+ import type { IpcClient } from "./ipc-client.js";
7
+ export interface IcqqGuildChannelEntry {
8
+ channel_id: string;
9
+ channel_name: string;
10
+ guild_id: string;
11
+ guild_name: string;
12
+ }
13
+ export interface NormalizedIcqqGuildInbound {
14
+ messageId: string;
15
+ channelId: string;
16
+ guildId: string;
17
+ guildName: string;
18
+ channelName: string;
19
+ userId: string;
20
+ nickname: string;
21
+ content: MessageSegment[];
22
+ rawMessage: string;
23
+ timestampMs: number;
24
+ raw: IpcGuildMessageEventData;
25
+ }
26
+ export declare class IcqqGuildCatalog {
27
+ private readonly channels;
28
+ private readonly guilds;
29
+ clear(): void;
30
+ syncAll(ipc: IpcClient): Promise<void>;
31
+ upsertFromInbound(data: IpcGuildMessageEventData): void;
32
+ getGuildChannelList(): Array<{
33
+ id: string;
34
+ name: string;
35
+ parent: {
36
+ type: "guild";
37
+ id: string;
38
+ name: string;
39
+ };
40
+ }>;
41
+ resolveConsoleChannelNames(channelId: string, guildId?: string): {
42
+ channelName?: string;
43
+ parentName?: string;
44
+ };
45
+ }
46
+ export declare function isIcqqGuildIpcEvent(eventName: string | undefined): boolean;
47
+ export declare function normalizeIcqqGuildInboundMessage(data: IpcGuildMessageEventData & Record<string, unknown>): NormalizedIcqqGuildInbound | null;
@@ -1,6 +1,9 @@
1
+ /**
2
+ * ICQQ guild (QQ 频道) catalog sync, inbound normalize, Console channel list.
3
+ */
4
+ import { toCanonicalSegments } from "zhin.js";
1
5
  import { Actions } from "./protocol.js";
2
6
  import { parseCqMessage } from "./cq-message.js";
3
- import { toCanonicalSegments } from "./segment-mapper.js";
4
7
  export class IcqqGuildCatalog {
5
8
  channels = new Map();
6
9
  guilds = new Map();
@@ -112,4 +115,3 @@ export function normalizeIcqqGuildInboundMessage(data) {
112
115
  raw: data,
113
116
  };
114
117
  }
115
- //# sourceMappingURL=icqq-guild.js.map
@@ -0,0 +1,139 @@
1
+ /**
2
+ * icqq 守护进程 IPC 入站事件归一化(post_type / message_type / message 段)
3
+ */
4
+ import { type MessageSegment, type QuotedMessagePayload } from "zhin.js";
5
+ import type { GroupRole } from "./types.js";
6
+ /** 守护进程推送的通用事件壳 */
7
+ export interface IcqqIpcEventBase {
8
+ post_type?: string;
9
+ self_id?: number;
10
+ }
11
+ /** post_type=message 时的消息体(字段随 icqqjs/cli 演进,未知字段保留) */
12
+ export interface IcqqIpcMessageEvent extends IcqqIpcEventBase {
13
+ post_type: "message";
14
+ message_id?: string;
15
+ msg_id?: string;
16
+ user_id: number;
17
+ user_uid?: string;
18
+ time: number;
19
+ seq?: number;
20
+ message_type: string;
21
+ sub_type?: string;
22
+ raw_message?: string;
23
+ message?: IcqqMessageElement[];
24
+ sender?: {
25
+ user_id?: number;
26
+ user_uid?: string;
27
+ nickname?: string;
28
+ card?: string;
29
+ /** 群临时会话来源群号 */
30
+ group_id?: number;
31
+ /** NT/IPC 群成员角色:owner | admin | member */
32
+ role?: GroupRole | string;
33
+ };
34
+ from_id?: number;
35
+ from_uid?: string;
36
+ group_id?: number;
37
+ to_id?: number;
38
+ nickname?: string;
39
+ /** 旧版 IPC 仅有 type 无 message_type */
40
+ type?: "group" | "private";
41
+ /** oicq Message#source:被引用回复的源消息 */
42
+ source?: IcqqMessageSource;
43
+ }
44
+ /** oicq 引用源消息(与 MessageEvent.source 对齐) */
45
+ export interface IcqqMessageSource {
46
+ message_id?: string;
47
+ msg_id?: string;
48
+ seq?: number;
49
+ rand?: number;
50
+ time?: number;
51
+ user_id?: number;
52
+ group_id?: number;
53
+ raw_message?: string;
54
+ /** 元素数组,或 NT 推送的纯文本摘要 */
55
+ message?: IcqqMessageElement[] | string;
56
+ sender?: {
57
+ user_id?: number;
58
+ nickname?: string;
59
+ card?: string;
60
+ };
61
+ [key: string]: unknown;
62
+ }
63
+ export type IcqqMessageElement = {
64
+ type: string;
65
+ text?: string;
66
+ qq?: string | number;
67
+ user_id?: string | number;
68
+ id?: string | number;
69
+ url?: string;
70
+ file?: string;
71
+ [key: string]: unknown;
72
+ };
73
+ /** 归一化后供适配器使用的入站消息 */
74
+ export interface NormalizedIcqqInbound {
75
+ messageId: string;
76
+ idSource: "message_id" | "msg_id" | "seq" | "synthetic";
77
+ channelType: "group" | "private";
78
+ channelId: string;
79
+ /** 群临时会话:来源群号 */
80
+ channelParentGroupId?: string;
81
+ userId: string;
82
+ nickname: string;
83
+ /** 群聊时来自 IPC sender.role(私聊无) */
84
+ senderRole?: GroupRole;
85
+ content: MessageSegment[];
86
+ rawMessage: string;
87
+ timestampMs: number;
88
+ raw: IcqqIpcMessageEvent;
89
+ }
90
+ /** 从 IPC sender.role 解析群成员角色(供 Message.$sender → resolveSenderRoles) */
91
+ export declare function parseIcqqSenderGroupRole(sender: {
92
+ role?: unknown;
93
+ } | undefined): GroupRole | undefined;
94
+ /**
95
+ * 判断入站消息是否 @ 了本机账号(uin = endpoint 配置 name,即 QQ 号)。
96
+ * 新 Plugin Runtime 的 Message.content 为纯文本,at 信息只能经 metadata 传递,
97
+ * endpoint 在 admit 时用本函数标注 `metadata.mentioned`(供 Agent Host 的 @ 触发)。
98
+ */
99
+ export declare function isIcqqBotMentioned(input: {
100
+ readonly uin: string;
101
+ readonly content?: readonly MessageSegment[] | null;
102
+ readonly rawMessage?: string;
103
+ }): boolean;
104
+ /** 从 IPC 事件壳中取出 OneBot/icqq 载荷(兼容 data 嵌套或字段在根级) */
105
+ export declare function unwrapIcqqIpcEventPayload(event: {
106
+ data?: unknown;
107
+ [key: string]: unknown;
108
+ }): unknown;
109
+ export declare function resolveIcqqInboundUserId(data: Record<string, unknown>): number | undefined;
110
+ export declare function isIcqqMessagePostType(data: unknown): data is IcqqIpcMessageEvent;
111
+ export declare function shouldSkipSelfInboundMessage(data: IcqqIpcMessageEvent): boolean;
112
+ /** 群临时会话私聊:icqq message_type=private & sub_type=group */
113
+ export declare function isIcqqGroupTempPrivateMessage(data: IcqqIpcMessageEvent): boolean;
114
+ export declare function resolveChannelFromIcqqMessage(data: IcqqIpcMessageEvent): {
115
+ channelType: "group" | "private";
116
+ channelId: string;
117
+ channelParentGroupId?: string;
118
+ };
119
+ export declare function resolveIcqqInboundMessageId(data: IcqqIpcMessageEvent, channelId: string): {
120
+ id: string;
121
+ source: "message_id" | "msg_id" | "seq" | "synthetic";
122
+ };
123
+ export declare function icqqElementsToSegments(elements: IcqqMessageElement[] | undefined): MessageSegment[] | null;
124
+ /** IPC 载荷可能把 source 嵌在 data / event 等字段,深度查找 */
125
+ export declare function findIcqqNestedMessageSource(root: unknown, maxDepth?: number): IcqqMessageSource | undefined;
126
+ /** 从 oicq MessageEvent.source 解析被引用消息的 message_id */
127
+ export declare function resolveQuoteIdFromIcqqSource(source: unknown): string | undefined;
128
+ /** 将 source 转为 QuotedMessagePayload(供 $getMsg 缓存,避免重复拉取) */
129
+ export declare function quotedPayloadFromIcqqSource(source: unknown): QuotedMessagePayload | null;
130
+ /** 从 IPC 事件顶层字段解析引用 message_id(与 message 段互补) */
131
+ export declare function resolveIcqqQuoteIdFromEvent(data: IcqqIpcMessageEvent): string | undefined;
132
+ export declare function resolveInboundContent(data: IcqqIpcMessageEvent): MessageSegment[];
133
+ export declare function normalizeIcqqInboundMessage(data: IcqqIpcMessageEvent): NormalizedIcqqInbound | null;
134
+ /** 按 message_id 去重(多路 subscribe 会收到同一消息多次) */
135
+ export declare class InboundMessageDeduper {
136
+ private readonly seen;
137
+ shouldProcess(messageId: string): boolean;
138
+ clear(): void;
139
+ }
@@ -1,9 +1,8 @@
1
1
  /**
2
2
  * icqq 守护进程 IPC 入站事件归一化(post_type / message_type / message 段)
3
3
  */
4
- import { Message } from "zhin.js";
4
+ import { Message, toCanonicalSegments } from "zhin.js";
5
5
  import { parseCqMessage } from "./cq-message.js";
6
- import { toCanonicalSegments } from "./segment-mapper.js";
7
6
  import { extractForwardResidFromJsonElement } from "./forward-msg.js";
8
7
  const DEDUPE_TTL_MS = 120_000;
9
8
  const ICQQ_GROUP_ROLES = new Set(["owner", "admin", "member"]);
@@ -15,6 +14,32 @@ export function parseIcqqSenderGroupRole(sender) {
15
14
  const role = raw.trim().toLowerCase();
16
15
  return ICQQ_GROUP_ROLES.has(role) ? role : undefined;
17
16
  }
17
+ /**
18
+ * 判断入站消息是否 @ 了本机账号(uin = endpoint 配置 name,即 QQ 号)。
19
+ * 新 Plugin Runtime 的 Message.content 为纯文本,at 信息只能经 metadata 传递,
20
+ * endpoint 在 admit 时用本函数标注 `metadata.mentioned`(供 Agent Host 的 @ 触发)。
21
+ */
22
+ export function isIcqqBotMentioned(input) {
23
+ const uin = String(input.uin ?? "").trim();
24
+ if (!uin)
25
+ return false;
26
+ for (const seg of input.content ?? []) {
27
+ if (!seg || (seg.type !== "at" && seg.type !== "mention"))
28
+ continue;
29
+ const data = (seg.data ?? {});
30
+ const target = String(data.qq ?? data.user_id ?? data.id ?? data.target ?? "").trim();
31
+ if (target && target !== "all" && Number(target) === Number(uin)) {
32
+ return true;
33
+ }
34
+ }
35
+ const raw = input.rawMessage ?? "";
36
+ if (!raw)
37
+ return false;
38
+ const escaped = uin.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
39
+ // OneBot CQ 码 `[CQ:at,qq=uin]`;QQ 频道 markdown `<@!uin>`
40
+ return new RegExp(`\\[CQ:at,qq=${escaped}\\]`, "u").test(raw)
41
+ || new RegExp(`<@!?${escaped}>`, "u").test(raw);
42
+ }
18
43
  const MESSAGE_POST_TYPES = new Set(["message"]);
19
44
  function isMessagePostType(postType) {
20
45
  if (typeof postType !== "string" || postType === "")
@@ -538,4 +563,3 @@ export class InboundMessageDeduper {
538
563
  this.seen.clear();
539
564
  }
540
565
  }
541
- //# sourceMappingURL=icqq-inbound.js.map
package/lib/index.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export { Actions, formatInboundContent, formatInboundTarget, formatOutboundBody, parseSendTarget, resolveIcqqConfig, type IcqqAdapterConfig, type IcqqInboundMessage, type IcqqWireSegment, type IpcEvent, type IpcMessage, type IpcRequest, type IpcResponse, type ParsedIcqqSendTarget, type ResolvedIcqqConfig, } from './protocol.js';
2
+ export { IcqqIpcEndpoint, type CreateIcqqIpc, type IcqqEndpointOptions, type IcqqIpcTransport, } from './endpoint.js';
3
+ export * from './types.js';
4
+ export { getIcqqAgentDeps, registerIcqqAgentEndpoint, setIcqqAgentDeps, type IcqqAgentDeps, type IcqqAgentEndpoint, } from './icqq-agent-deps.js';
5
+ export { IpcClient } from './ipc-client.js';
6
+ export { resolveIcqqInboundMessageId, } from './icqq-inbound.js';
package/lib/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { Actions, formatInboundContent, formatInboundTarget, formatOutboundBody, parseSendTarget, resolveIcqqConfig, } from './protocol.js';
2
+ export { IcqqIpcEndpoint, } from './endpoint.js';
3
+ export * from './types.js';
4
+ export { getIcqqAgentDeps, registerIcqqAgentEndpoint, setIcqqAgentDeps, } from './icqq-agent-deps.js';
5
+ export { IpcClient } from './ipc-client.js';
6
+ export { resolveIcqqInboundMessageId, } from './icqq-inbound.js';
@@ -0,0 +1,73 @@
1
+ import type { IpcResponse, IpcEvent } from "./protocol.js";
2
+ export declare class IpcClient {
3
+ private socket;
4
+ private buffer;
5
+ private pending;
6
+ private eventHandlers;
7
+ private _closed;
8
+ /** 是否为客户端主动 close()(与对端断线区分) */
9
+ private _userClosed;
10
+ private _remoteDisconnectEmitted;
11
+ private onRemoteDisconnect;
12
+ private constructor();
13
+ get closed(): boolean;
14
+ /**
15
+ * 注册「对端断开 / 连接异常关闭」回调(不含本端 close())。
16
+ * 传入 null 可清除回调。
17
+ */
18
+ setOnRemoteDisconnect(handler: (() => void) | null): void;
19
+ /** 注册数据处理 handler(RPC 模式延迟到 challenge 完成后调用) */
20
+ private attachDataHandler;
21
+ /**
22
+ * 通过 IPC(Unix Socket)连接守护进程并完成认证。
23
+ * @param uin - 目标账号的 QQ 号
24
+ * @returns 已认证的 IpcClient 实例
25
+ * @throws 守护进程未运行或认证失败时抛出错误
26
+ */
27
+ static connect(uin: number): Promise<IpcClient>;
28
+ /**
29
+ * 通过 RPC(TCP)连接守护进程并完成 HMAC 挑战-响应认证。
30
+ *
31
+ * 流程:
32
+ * 1. 服务端连接后发送 { challenge: "<hex>" }
33
+ * 2. 客户端用 HMAC-SHA256(token, challenge) 生成 digest
34
+ * 3. 客户端发送 { action: "auth", params: { digest: "<hex>" } }
35
+ * 4. 服务端验证 digest,通过则认证成功
36
+ *
37
+ * token 不会明文传输,防止中间人嗅探。
38
+ *
39
+ * @param options.host - 远程主机地址
40
+ * @param options.port - 远程端口
41
+ * @param options.token - 认证 token(用于 HMAC 计算,不会明文传输)
42
+ */
43
+ static connectRpc(options: {
44
+ host: string;
45
+ port: number;
46
+ token: string;
47
+ }): Promise<IpcClient>;
48
+ /**
49
+ * 通过 RPC 连接守护进程(自动从 daemon.rpc 文件读取地址)。
50
+ * @param uin - 目标账号的 QQ 号
51
+ */
52
+ static connectRpcByUin(uin: number): Promise<IpcClient>;
53
+ private onData;
54
+ /**
55
+ * 注册 icqq 事件回调。
56
+ * 新版守护进程在认证后会自动广播事件(event.id = "*")。
57
+ */
58
+ onEvent(onEvent: (event: IpcEvent) => void): () => void;
59
+ /**
60
+ * 发送 IPC 请求并等待响应。
61
+ */
62
+ request(action: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<IpcResponse>;
63
+ /**
64
+ * @deprecated 兼容旧调用方式:服务端已自动推送事件,type/id 过滤在客户端完成。
65
+ * @returns 订阅句柄,包含 unsubscribe() 方法
66
+ */
67
+ subscribe(_action: string, params: Record<string, unknown>, onEvent: (event: IpcEvent) => void): {
68
+ id: string;
69
+ unsubscribe: () => Promise<void>;
70
+ };
71
+ /** 关闭连接 */
72
+ close(): void;
73
+ }
@@ -356,4 +356,3 @@ export class IpcClient {
356
356
  this.socket.destroy();
357
357
  }
358
358
  }
359
- //# sourceMappingURL=ipc-client.js.map
@@ -0,0 +1,13 @@
1
+ import type { SendContent } from "zhin.js";
2
+ import type { IcqqEndpointConfig } from "./types.js";
3
+ export type IcqqOutboundMediaMode = "file" | "base64";
4
+ /**
5
+ * 出站媒体模式:file=本机落盘后 CQ [image:path](与 icqq 同机时可用);
6
+ * base64=保留 segment.base64,CQ 编码为 [image:base64://...] 经 IPC 交给守护进程解码(异机 RPC 默认)。
7
+ */
8
+ export declare function resolveIcqqOutboundMediaMode(config: Pick<IcqqEndpointConfig, "rpc" | "outboundMedia">): IcqqOutboundMediaMode;
9
+ /**
10
+ * file 模式:将 segment.data.base64 物化为本机路径。
11
+ * base64 模式:不改动(由 toCqString 生成 base64://,供异机守护进程读取)。
12
+ */
13
+ export declare function materializeOutboundBase64(content: SendContent, mode?: IcqqOutboundMediaMode): SendContent;
@@ -63,4 +63,3 @@ export function materializeOutboundBase64(content, mode = "file") {
63
63
  return seg;
64
64
  });
65
65
  }
66
- //# sourceMappingURL=outbound-media.js.map
@@ -0,0 +1,269 @@
1
+ /**
2
+ * IPC 协议类型定义与 Action 常量 (ported from @icqqjs/cli)
3
+ *
4
+ * CLI 与守护进程通过 Unix Domain Socket 通信,
5
+ * 使用 JSON + 换行符(\n)分隔的文本协议。
6
+ *
7
+ * 通信流程(@icqqjs/cli `src/daemon/protocol.ts`):
8
+ * 1. CLI 连接 Socket → auth(token)
9
+ * 2. 认证通过后发送 IpcRequest → 等待 IpcResponse
10
+ * 3. 认证通过后自动接收 icqq 事件推送(IpcEvent),断开连接自动停止
11
+ *
12
+ * 登录相关:**推送**走 IpcEvent(`system.login.*`)。
13
+ */
14
+ /** CLI → Daemon 请求 */
15
+ export type IpcRequest = {
16
+ id: string;
17
+ action: string;
18
+ params: Record<string, unknown>;
19
+ };
20
+ /** Daemon → CLI 响应 */
21
+ export type IpcResponse = {
22
+ id: string;
23
+ ok: boolean;
24
+ data?: unknown;
25
+ error?: string;
26
+ };
27
+ /**
28
+ * Daemon → CLI 事件推送(icqq client.em 分发的全部事件)
29
+ *
30
+ * 登录/重连时推送 `system.login.*`(如 `system.login.auth` 含 url + device),
31
+ * 语义在 `event` 字段,不在 OneBot 式 `post_type` 里。
32
+ */
33
+ export type IpcEvent = {
34
+ /** 固定为 `"*"`,客户端应忽略,由本地 handler 按 `event` 过滤 */
35
+ id: string;
36
+ /** icqq 事件名,如 `system.login.auth`、`message.group.normal` */
37
+ event: string;
38
+ /** icqq 事件 toJSON 后的 plain object */
39
+ data: unknown;
40
+ };
41
+ export type IpcMessage = IpcResponse | IpcEvent;
42
+ export type { IcqqIpcMessageEvent } from "./icqq-inbound.js";
43
+ /** 从 IPC 入站 payload 解析可用于引用/撤回的消息 ID */
44
+ export { resolveIcqqInboundMessageId } from "./icqq-inbound.js";
45
+ /** Guild 消息事件数据 */
46
+ export interface IpcGuildMessageEventData {
47
+ type: "guild";
48
+ guild_id: string;
49
+ guild_name: string;
50
+ channel_id: string;
51
+ channel_name: string;
52
+ nickname: string;
53
+ tiny_id: string;
54
+ raw_message: string;
55
+ time: number;
56
+ seq: number;
57
+ }
58
+ /**
59
+ * 所有 IPC 操作常量 (from @icqqjs/cli)
60
+ */
61
+ export declare const Actions: {
62
+ readonly PING: "ping";
63
+ readonly LOGOUT: "logout";
64
+ readonly LIST_FRIENDS: "list_friends";
65
+ readonly LIST_GROUPS: "list_groups";
66
+ readonly LIST_GROUP_MEMBERS: "list_group_members";
67
+ readonly LIST_BLACKLIST: "list_blacklist";
68
+ readonly LIST_FRIEND_CLASSES: "list_friend_classes";
69
+ readonly GET_FRIEND_INFO: "get_friend_info";
70
+ readonly GET_GROUP_INFO: "get_group_info";
71
+ readonly GET_GROUP_MEMBER_INFO: "get_group_member_info";
72
+ readonly GET_STRANGER_INFO: "get_stranger_info";
73
+ readonly LIST_STRANGERS: "list_strangers";
74
+ readonly GET_PROFILE: "get_profile";
75
+ readonly GET_STATUS: "get_status";
76
+ readonly GET_ONLINE_STATUS: "get_online_status";
77
+ readonly GET_SELF_PROFILE: "get_self_profile";
78
+ readonly SEND_PRIVATE_MSG: "send_private_msg";
79
+ readonly SEND_GROUP_MSG: "send_group_msg";
80
+ readonly RECALL_MSG: "recall_msg";
81
+ readonly GET_MSG: "get_msg";
82
+ readonly HISTORY_PRIVATE: "history_private";
83
+ readonly HISTORY_GROUP: "history_group";
84
+ readonly HISTORY_BY_MSG_ID: "history_by_msg_id";
85
+ readonly SEND_LONG_MSG: "send_long_msg";
86
+ readonly MARK_READ: "mark_read";
87
+ readonly DELETE_MSG: "delete_msg";
88
+ readonly SET_NICKNAME: "set_nickname";
89
+ readonly SET_GENDER: "set_gender";
90
+ readonly SET_BIRTHDAY: "set_birthday";
91
+ readonly SET_SIGNATURE: "set_signature";
92
+ readonly SET_DESCRIPTION: "set_description";
93
+ readonly SET_AVATAR: "set_avatar";
94
+ readonly SET_ONLINE_STATUS: "set_online_status";
95
+ readonly SET_GROUP_NAME: "set_group_name";
96
+ readonly SET_GROUP_AVATAR: "set_group_avatar";
97
+ readonly SET_GROUP_CARD: "set_group_card";
98
+ readonly SET_GROUP_TITLE: "set_group_title";
99
+ readonly SET_GROUP_ADMIN: "set_group_admin";
100
+ readonly SET_GROUP_REMARK: "set_group_remark";
101
+ readonly GROUP_MUTE: "group_mute";
102
+ readonly GROUP_MUTE_ALL: "group_mute_all";
103
+ readonly GROUP_KICK: "group_kick";
104
+ readonly GROUP_QUIT: "group_quit";
105
+ readonly GROUP_INVITE: "group_invite";
106
+ readonly GROUP_POKE: "group_poke";
107
+ readonly GROUP_ANNOUNCE: "group_announce";
108
+ readonly GROUP_SIGN: "group_sign";
109
+ readonly GROUP_ESSENCE_ADD: "group_essence_add";
110
+ readonly GROUP_ESSENCE_REMOVE: "group_essence_remove";
111
+ readonly GROUP_ALLOW_ANONY: "group_allow_anony";
112
+ readonly GROUP_MUTED_LIST: "group_muted_list";
113
+ readonly GROUP_AT_ALL_REMAIN: "group_at_all_remain";
114
+ readonly FRIEND_POKE: "friend_poke";
115
+ readonly FRIEND_LIKE: "friend_like";
116
+ readonly FRIEND_DELETE: "friend_delete";
117
+ readonly FRIEND_REMARK: "friend_remark";
118
+ readonly FRIEND_CLASS: "friend_class";
119
+ readonly GET_SYSTEM_MSG: "get_system_msg";
120
+ readonly HANDLE_FRIEND_REQUEST: "handle_friend_request";
121
+ readonly HANDLE_GROUP_REQUEST: "handle_group_request";
122
+ readonly ADD_FRIEND_CLASS: "add_friend_class";
123
+ readonly DELETE_FRIEND_CLASS: "delete_friend_class";
124
+ readonly RENAME_FRIEND_CLASS: "rename_friend_class";
125
+ readonly GFS_LIST: "gfs_list";
126
+ readonly GFS_INFO: "gfs_info";
127
+ readonly GFS_MKDIR: "gfs_mkdir";
128
+ readonly GFS_DELETE: "gfs_delete";
129
+ readonly GFS_RENAME: "gfs_rename";
130
+ readonly GFS_STAT: "gfs_stat";
131
+ readonly GFS_MOVE: "gfs_move";
132
+ readonly GFS_DOWNLOAD: "gfs_download";
133
+ readonly IMAGE_OCR: "image_ocr";
134
+ readonly RELOAD_FRIEND_LIST: "reload_friend_list";
135
+ readonly RELOAD_GROUP_LIST: "reload_group_list";
136
+ readonly CLEAN_CACHE: "clean_cache";
137
+ readonly GET_GROUP_SHARE: "get_group_share";
138
+ readonly GROUP_SET_JOIN_TYPE: "group_set_join_type";
139
+ readonly GROUP_SET_RATE_LIMIT: "group_set_rate_limit";
140
+ readonly GROUP_MUTE_ANONY: "group_mute_anony";
141
+ readonly GROUP_ANON_INFO: "group_anon_info";
142
+ readonly ADD_FRIEND: "add_friend";
143
+ readonly SEND_TEMP_MSG: "send_temp_msg";
144
+ readonly GET_ROAMING_STAMP: "get_roaming_stamp";
145
+ readonly DELETE_STAMP: "delete_stamp";
146
+ readonly SEND_PRIVATE_FILE: "send_private_file";
147
+ readonly SEND_GROUP_FILE: "send_group_file";
148
+ readonly FRIEND_RECALL_FILE: "friend_recall_file";
149
+ readonly FRIEND_FORWARD_FILE: "friend_forward_file";
150
+ readonly SEARCH_SAME_GROUP: "search_same_group";
151
+ readonly SEND_CONTACT_SHARE: "send_contact_share";
152
+ readonly GFS_UPLOAD: "gfs_upload";
153
+ readonly GROUP_SET_REACTION: "group_set_reaction";
154
+ readonly GROUP_DEL_REACTION: "group_del_reaction";
155
+ readonly GET_FORWARD_MSG: "get_forward_msg";
156
+ readonly MAKE_FORWARD_MSG: "make_forward_msg";
157
+ readonly GUILD_LIST: "guild_list";
158
+ readonly GUILD_INFO: "guild_info";
159
+ readonly GUILD_CHANNELS: "guild_channels";
160
+ readonly GET_CHANNEL_INFO: "get_channel_info";
161
+ readonly GUILD_MEMBERS: "guild_members";
162
+ readonly GUILD_SEND_MSG: "guild_send_msg";
163
+ readonly GUILD_RECALL_MSG: "guild_recall_msg";
164
+ readonly GET_FILE_INFO: "get_file_info";
165
+ readonly GET_FILE_URL: "get_file_url";
166
+ readonly GET_AVATAR_URL: "get_avatar_url";
167
+ readonly GET_GROUP_AVATAR_URL: "get_group_avatar_url";
168
+ readonly SET_SCREEN_MEMBER_MSG: "set_screen_member_msg";
169
+ readonly GFS_FORWARD: "gfs_forward";
170
+ readonly GFS_FORWARD_OFFLINE: "gfs_forward_offline";
171
+ readonly RELOAD_BLACKLIST: "reload_blacklist";
172
+ readonly RELOAD_STRANGER_LIST: "reload_stranger_list";
173
+ readonly RELOAD_GUILDS: "reload_guilds";
174
+ readonly GET_STATUS_INFO: "get_status_info";
175
+ readonly GET_CLIENT_KEY: "get_client_key";
176
+ readonly GET_PSKEY: "get_pskey";
177
+ readonly UID2UIN: "uid2uin";
178
+ readonly UID2UINS: "uid2uins";
179
+ readonly UIN2UID: "uin2uid";
180
+ readonly UIN2UIDS: "uin2uids";
181
+ readonly GET_COOKIES: "get_cookies";
182
+ readonly GET_CSRF_TOKEN: "get_csrf_token";
183
+ readonly REFRESH_NT_PIC_RKEY: "refresh_nt_pic_rkey";
184
+ readonly SEND_DISCUSS_MSG: "send_discuss_msg";
185
+ readonly GET_VIDEO_URL: "get_video_url";
186
+ readonly GET_ADD_FRIEND_SETTING: "get_add_friend_setting";
187
+ readonly GET_FORUM_URL: "get_forum_url";
188
+ readonly GUILD_CHANNEL_SHARE: "guild_channel_share";
189
+ readonly GET_PIC_URL: "get_pic_url";
190
+ readonly GET_PTT_URL: "get_ptt_url";
191
+ readonly SUBSCRIBE: "subscribe";
192
+ readonly UNSUBSCRIBE: "unsubscribe";
193
+ readonly SET_WEBHOOK: "set_webhook";
194
+ readonly GET_WEBHOOK: "get_webhook";
195
+ readonly SET_NOTIFY: "set_notify";
196
+ readonly GET_NOTIFY: "get_notify";
197
+ };
198
+ /** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
199
+ export interface IcqqAdapterConfig {
200
+ readonly name?: string;
201
+ readonly autoReconnect?: boolean;
202
+ readonly outboundMedia?: 'file' | 'base64';
203
+ readonly rpc?: {
204
+ readonly host?: string;
205
+ readonly port?: number;
206
+ readonly token?: string;
207
+ };
208
+ /** Transitional: legacy root `endpoints[]` with `context: icqq`. */
209
+ readonly endpoints?: ReadonlyArray<{
210
+ readonly context?: string;
211
+ readonly name?: string;
212
+ readonly autoReconnect?: boolean;
213
+ readonly outboundMedia?: 'file' | 'base64';
214
+ readonly rpc?: {
215
+ readonly host?: string;
216
+ readonly port?: number;
217
+ readonly token?: string;
218
+ };
219
+ }>;
220
+ }
221
+ export interface ResolvedIcqqConfig {
222
+ readonly context: 'icqq';
223
+ readonly name: string;
224
+ readonly autoReconnect: boolean;
225
+ readonly outboundMedia?: 'file' | 'base64';
226
+ readonly rpc?: {
227
+ readonly host: string;
228
+ readonly port: number;
229
+ readonly token: string;
230
+ };
231
+ }
232
+ export interface IcqqWireSegment {
233
+ readonly type: string;
234
+ readonly data?: Record<string, unknown>;
235
+ }
236
+ export interface IcqqInboundMessage {
237
+ readonly id: string;
238
+ readonly target: string;
239
+ readonly content: string;
240
+ readonly sender: string;
241
+ readonly channelType: 'private' | 'group' | 'channel';
242
+ readonly metadata?: Record<string, unknown>;
243
+ }
244
+ export type ParsedIcqqSendTarget = {
245
+ readonly kind: 'private';
246
+ readonly userId: number;
247
+ } | {
248
+ readonly kind: 'group';
249
+ readonly groupId: number;
250
+ } | {
251
+ readonly kind: 'temp';
252
+ readonly groupId: number;
253
+ readonly userId: number;
254
+ } | {
255
+ readonly kind: 'channel';
256
+ readonly guildId: string;
257
+ readonly channelId: string;
258
+ };
259
+ export declare function resolveIcqqConfig(config?: IcqqAdapterConfig): ResolvedIcqqConfig;
260
+ /** Gateway reply target: `private:uid` / `group:gid` / `temp:gid:uid` / `channel:guild:channel`. */
261
+ export declare function formatInboundTarget(input: {
262
+ readonly channelType: 'private' | 'group' | 'channel';
263
+ readonly channelId: string;
264
+ readonly channelParentGroupId?: string;
265
+ readonly guildId?: string;
266
+ }): string;
267
+ export declare function parseSendTarget(target: string): ParsedIcqqSendTarget;
268
+ export declare function formatOutboundBody(payload: unknown): string;
269
+ export declare function formatInboundContent(rawMessage: string): string;