@zhin.js/adapter-icqq 8.0.8 → 8.0.10
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 +34 -0
- package/README.md +36 -28
- package/adapters/icqq.js +4 -9
- package/adapters/icqq.ts +5 -14
- package/agent/PERMITS.md +2 -0
- package/lib/agent-prompt.js +17 -22
- package/lib/cq-message.d.ts +2 -2
- package/lib/cq-message.js +7 -2
- package/lib/endpoint.d.ts +4 -74
- package/lib/endpoint.js +348 -507
- package/lib/forward-msg.d.ts +7 -8
- package/lib/forward-msg.js +11 -24
- package/lib/icqq-agent-deps.d.ts +3 -15
- package/lib/icqq-agent-deps.js +0 -5
- package/lib/icqq-endpoint-commands.js +4 -13
- package/lib/icqq-guild.d.ts +15 -11
- package/lib/icqq-guild.js +9 -17
- package/lib/icqq-inbound.d.ts +20 -20
- package/lib/icqq-inbound.js +9 -9
- package/lib/icqq-inbox.d.ts +2 -10
- package/lib/index.d.ts +2 -3
- package/lib/index.js +2 -3
- package/lib/outbound-media.d.ts +3 -8
- package/lib/outbound-media.js +3 -8
- package/lib/protocol.d.ts +38 -57
- package/lib/protocol.js +67 -21
- package/lib/types.d.ts +4 -40
- package/lib/types.js +0 -5
- package/package.json +26 -14
- package/plugin.js +6 -1
- package/schema.json +119 -61
- package/src/agent-prompt.ts +17 -22
- package/src/cq-message.ts +7 -2
- package/src/endpoint.ts +359 -600
- package/src/forward-msg.ts +12 -26
- package/src/icqq-agent-deps.ts +3 -17
- package/src/icqq-endpoint-commands.ts +4 -13
- package/src/icqq-guild.ts +16 -25
- package/src/icqq-inbound.ts +26 -26
- package/src/icqq-inbox.ts +2 -10
- package/src/icqqjs-icqq.d.ts +88 -0
- package/src/index.ts +2 -9
- package/src/outbound-media.ts +4 -9
- package/src/protocol.ts +108 -66
- package/src/types.ts +4 -41
- package/tools/announce.js +19 -0
- package/tools/announce.ts +18 -0
- package/tools/essence.js +24 -0
- package/{agent/tools → tools}/essence.ts +8 -8
- package/tools/friend_list.js +20 -0
- package/{agent/tools → tools}/friend_list.ts +7 -7
- package/tools/group_files.js +25 -0
- package/tools/group_files.ts +23 -0
- package/tools/group_invite.js +25 -0
- package/tools/group_invite.ts +22 -0
- package/tools/group_kick.js +28 -0
- package/tools/group_kick.ts +24 -0
- package/tools/group_list.js +21 -0
- package/{agent/tools → tools}/group_list.ts +7 -7
- package/tools/group_sign.js +21 -0
- package/tools/group_sign.ts +19 -0
- package/tools/list_muted.js +20 -0
- package/tools/list_muted.ts +19 -0
- package/tools/poke.js +19 -0
- package/tools/poke.ts +18 -0
- package/tools/send_user_like.js +28 -0
- package/tools/send_user_like.ts +25 -0
- package/tools/set_anonymous.js +23 -0
- package/tools/set_anonymous.ts +21 -0
- package/tools/set_mute.js +26 -0
- package/tools/set_mute.ts +23 -0
- package/tools/set_title.js +27 -0
- package/tools/set_title.ts +24 -0
- package/tools/user_info.js +17 -0
- package/tools/user_info.ts +16 -0
- package/agent/tools/announce.ts +0 -21
- package/agent/tools/group_files.ts +0 -27
- package/agent/tools/group_invite.ts +0 -20
- package/agent/tools/group_sign.ts +0 -19
- package/agent/tools/list_muted.ts +0 -22
- package/agent/tools/poke.ts +0 -20
- package/agent/tools/send_user_like.ts +0 -22
- package/agent/tools/set_anonymous.ts +0 -22
- package/agent/tools/set_title.ts +0 -25
- package/lib/ipc-client.d.ts +0 -73
- package/lib/ipc-client.js +0 -358
- package/src/ipc-client.ts +0 -417
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# @zhin.js/adapter-icqq
|
|
2
2
|
|
|
3
|
+
## 8.0.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e4757a8: fix: bump
|
|
8
|
+
- c3c0ebf: fix: jiagouyouhau
|
|
9
|
+
- Updated dependencies [e4757a8]
|
|
10
|
+
- Updated dependencies [c3c0ebf]
|
|
11
|
+
- @zhin.js/command@1.0.13
|
|
12
|
+
- @zhin.js/agent@1.1.10
|
|
13
|
+
- @zhin.js/core@1.5.9
|
|
14
|
+
- @zhin.js/tool@1.0.10
|
|
15
|
+
- @zhin.js/adapter@1.1.9
|
|
16
|
+
- zhin.js@6.0.9
|
|
17
|
+
|
|
18
|
+
## 8.0.9
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [63253bb]
|
|
23
|
+
- Updated dependencies [6fb24dd]
|
|
24
|
+
- Updated dependencies [d162216]
|
|
25
|
+
- Updated dependencies [7427818]
|
|
26
|
+
- Updated dependencies [90da255]
|
|
27
|
+
- Updated dependencies [8e973dc]
|
|
28
|
+
- Updated dependencies [953cfe1]
|
|
29
|
+
- Updated dependencies [0e73866]
|
|
30
|
+
- @zhin.js/plugin-runtime@1.1.6
|
|
31
|
+
- @zhin.js/core@1.5.8
|
|
32
|
+
- @zhin.js/adapter@1.1.8
|
|
33
|
+
- @zhin.js/agent@1.1.9
|
|
34
|
+
- zhin.js@6.0.8
|
|
35
|
+
- @zhin.js/command@1.0.12
|
|
36
|
+
|
|
3
37
|
## 8.0.8
|
|
4
38
|
|
|
5
39
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,22 +1,37 @@
|
|
|
1
1
|
# @zhin.js/adapter-icqq
|
|
2
2
|
|
|
3
|
-
ICQQ Plugin Runtime 适配器 —
|
|
3
|
+
ICQQ Plugin Runtime 适配器 — 进程内直接使用 [@icqqjs/icqq](https://github.com/icqqjs/icqq) `Client`
|
|
4
4
|
|
|
5
5
|
## 功能特性
|
|
6
6
|
|
|
7
7
|
- 群聊 / 私聊 / 群临时会话 / QQ 频道消息
|
|
8
|
-
- 入站:`messageGatewayToken
|
|
9
|
-
- 出站:`send({ conversation, payload })` → `
|
|
10
|
-
-
|
|
11
|
-
-
|
|
8
|
+
- 入站:`messageGatewayToken`,归一为 `gateway.receive({ conversation, message, content, ... })`
|
|
9
|
+
- 出站:`send({ conversation, payload })` → `sendGroupMsg` / `sendPrivateMsg` / …(conversation kind/id/parent 路由)
|
|
10
|
+
- 群聊 reaction:`control.addReaction` / `removeReaction`(协议 ACK 失败不阻塞后续发送)
|
|
11
|
+
- Agent 工具:包根 `tools/`(`@zhin.js/tool` Feature;模型侧名为 `icqq__send_user_like` 等)
|
|
12
|
+
- Console Endpoint 管理:`src/endpoint.ts` 显式实现 `EndpointManagement`(好友/群/群成员列表、请求审批、删好友、踢人、禁言、设管理)
|
|
12
13
|
|
|
13
14
|
## 安装
|
|
14
15
|
|
|
15
16
|
```bash
|
|
16
|
-
pnpm add @zhin.js/adapter-icqq
|
|
17
|
-
|
|
17
|
+
pnpm add @zhin.js/adapter-icqq @icqqjs/icqq
|
|
18
|
+
# 可选:未配置 signApiAddr 时走本地签名
|
|
19
|
+
pnpm add @icqqjs/qqsign
|
|
18
20
|
```
|
|
19
21
|
|
|
22
|
+
`@icqqjs/icqq` 是适配器的**可选对等依赖**(`peerDependencies` + `optional`)。应用侧需自行安装;monorepo 内另在 `devDependencies` 声明以便构建/测试。
|
|
23
|
+
|
|
24
|
+
`@icqqjs/*` 发布在 GitHub Packages,需:
|
|
25
|
+
|
|
26
|
+
```ini
|
|
27
|
+
@icqqjs:registry=https://npm.pkg.github.com
|
|
28
|
+
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
并设置具有 `read:packages` 权限的 `NPM_TOKEN`(CI 使用仓库 secret `PERSONAL_TOKEN`)。
|
|
32
|
+
|
|
33
|
+
签名:未配置 `signApiAddr` 时,若已安装 `@icqqjs/qqsign` 则自动走本地签名。
|
|
34
|
+
|
|
20
35
|
## 配置(Plugin Runtime)
|
|
21
36
|
|
|
22
37
|
```yaml
|
|
@@ -25,29 +40,22 @@ plugins:
|
|
|
25
40
|
master: "1659488338" # 必填,顶层共享(/approve 与 master 角色)
|
|
26
41
|
autoReconnect: true
|
|
27
42
|
endpoints:
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
# - name: "${ICQQ_ACCOUNT_2}"
|
|
31
|
-
# rpc:
|
|
32
|
-
# host: 10.0.0.2
|
|
33
|
-
# port: 9527
|
|
34
|
-
# token: ${ICQQ_RPC_TOKEN}
|
|
43
|
+
- id: "${ICQQ_ACCOUNT}" # QQ 号
|
|
44
|
+
# password: "${ICQQ_PASSWORD}" # 可选;不填则扫码登录
|
|
35
45
|
```
|
|
36
46
|
|
|
37
|
-
多账号:一个插件实例挂多个 endpoint(`endpoints` 数组逐项覆盖顶层字段,`
|
|
47
|
+
多账号:一个插件实例挂多个 endpoint(`endpoints` 数组逐项覆盖顶层字段,`id` 必填):
|
|
38
48
|
|
|
39
49
|
```yaml
|
|
40
50
|
plugins:
|
|
41
51
|
icqq:
|
|
42
|
-
master: "1659488338"
|
|
52
|
+
master: "1659488338"
|
|
43
53
|
endpoints:
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
54
|
+
- id: "${ICQQ_ACCOUNT}"
|
|
55
|
+
- id: "${ICQQ_ACCOUNT_2}"
|
|
56
|
+
- id: "${ICQQ_ACCOUNT_3}"
|
|
47
57
|
```
|
|
48
58
|
|
|
49
|
-
先执行 `icqq login`,再启动 Zhin。
|
|
50
|
-
|
|
51
59
|
## Send conversation
|
|
52
60
|
|
|
53
61
|
| 类型 | conversation |
|
|
@@ -60,17 +68,17 @@ plugins:
|
|
|
60
68
|
## 架构
|
|
61
69
|
|
|
62
70
|
- `plugin.ts` + `adapters/icqq.ts`(`defineAdapter`)
|
|
71
|
+
- Endpoint:`src/endpoint.ts`(继承 icqq `Client`,`start()` 内 `login()`)
|
|
63
72
|
- 协议常量 / 配置:`src/protocol.ts`
|
|
64
|
-
-
|
|
65
|
-
- Console loginAssist / host-router 延期
|
|
66
|
-
- 旧 `usePlugin` / `extends Adapter` / Endpoint 生产入口已删除
|
|
73
|
+
- Agent 工具:`tools/*.ts`;权限说明见 `agent/PERMITS.md`
|
|
67
74
|
|
|
68
75
|
## Plugin Runtime 迁移说明
|
|
69
76
|
|
|
70
|
-
- `
|
|
71
|
-
- `
|
|
72
|
-
-
|
|
73
|
-
- **
|
|
77
|
+
- 不再经过 `@icqqjs/cli` IPC 守护进程;登录态与协议栈都在本进程。
|
|
78
|
+
- `autoReconnect`:Client 断线后按配置自动重连(`stop()` 为主动断开,不触发重连)。
|
|
79
|
+
- `outboundMedia: file | base64`:`file` 把 segment base64 落盘后发本地路径;`base64` 发 CQ `base64://` 内联。
|
|
80
|
+
- **Console 社交/群管 RPC 已接线**:endpoint 把好友/群/群成员列表、请求审批和群管操作归一化为冻结的 `EndpointManagement`。Host 只消费该语义端口。
|
|
81
|
+
- 好友/入群请求与通知写入 unified inbox(有 DatabaseHost 时),不再走已删除的 `notice.receive` / `request.receive` 事件。
|
|
74
82
|
|
|
75
83
|
## License
|
|
76
84
|
|
package/adapters/icqq.js
CHANGED
|
@@ -6,32 +6,27 @@ import { defineAdapter } from '@zhin.js/adapter';
|
|
|
6
6
|
import { messageGatewayToken } from '@zhin.js/core/runtime';
|
|
7
7
|
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
8
8
|
import { databaseHostToken, INBOX_TABLE_NOTICE, INBOX_TABLE_REQUEST, runtimeEventPublisherToken, } from '@zhin.js/plugin-runtime';
|
|
9
|
-
import {
|
|
9
|
+
import { IcqqEndpoint } from "../lib/endpoint.js";
|
|
10
10
|
import { icqqRuntimeStateToken } from "../lib/icqq-runtime-state.js";
|
|
11
11
|
import { resolveIcqqConfig, } from "../lib/protocol.js";
|
|
12
|
-
export {
|
|
12
|
+
export { IcqqEndpoint } from "../lib/endpoint.js";
|
|
13
13
|
const logger = getLogger('icqq');
|
|
14
14
|
export default defineAdapter({
|
|
15
15
|
capabilities: ['inbound', 'outbound'],
|
|
16
16
|
operations: ['recall', 'reaction'],
|
|
17
|
-
// 统一消息元素通道(UNI-Channel):端点可消费 base64(CQ base64:// 守护进程解码)
|
|
18
|
-
// / url(CQ 直发)/ path(同机守护进程读盘;file 模式出站物化产物)媒体;
|
|
19
|
-
// 卡片/按钮等富交互段无原生承载,降级纯文本。
|
|
20
17
|
segments: {
|
|
21
18
|
outboundMedia: ['base64', 'url', 'path'],
|
|
22
19
|
interactive: 'text',
|
|
23
20
|
},
|
|
24
21
|
create(context) {
|
|
25
|
-
// Client-library / IPC daemon path — no httpHostToken.
|
|
26
|
-
// Console loginAssist + host-router routes deferred.
|
|
27
22
|
const config = resolveIcqqConfig(context.config);
|
|
28
23
|
// 注册到插件运行时状态(icqq.endpoint list 的"运行中"数据源)
|
|
29
24
|
context.use(icqqRuntimeStateToken).endpoints.set(config.id, {
|
|
30
25
|
id: config.id,
|
|
31
|
-
mode:
|
|
26
|
+
mode: 'direct',
|
|
32
27
|
});
|
|
33
28
|
const inbox = resolveInboxHooks(context);
|
|
34
|
-
return new
|
|
29
|
+
return new IcqqEndpoint({
|
|
35
30
|
id: context.id,
|
|
36
31
|
gateway: context.use(messageGatewayToken),
|
|
37
32
|
config,
|
package/adapters/icqq.ts
CHANGED
|
@@ -11,43 +11,34 @@ import {
|
|
|
11
11
|
runtimeEventPublisherToken,
|
|
12
12
|
type Token,
|
|
13
13
|
} from '@zhin.js/plugin-runtime';
|
|
14
|
-
import {
|
|
14
|
+
import { IcqqEndpoint, type IcqqInboxHooks } from '../src/endpoint.js';
|
|
15
15
|
import { icqqRuntimeStateToken } from '../src/icqq-runtime-state.js';
|
|
16
16
|
import {
|
|
17
17
|
resolveIcqqConfig,
|
|
18
18
|
type IcqqAdapterConfig,
|
|
19
19
|
} from '../src/protocol.js';
|
|
20
20
|
|
|
21
|
-
export {
|
|
22
|
-
export type {
|
|
23
|
-
CreateIcqqIpc,
|
|
24
|
-
IcqqEndpointOptions,
|
|
25
|
-
IcqqIpcTransport,
|
|
26
|
-
} from '../src/endpoint.js';
|
|
21
|
+
export { IcqqEndpoint } from '../src/endpoint.js';
|
|
22
|
+
export type { IcqqEndpointOptions } from '../src/endpoint.js';
|
|
27
23
|
|
|
28
24
|
const logger = getLogger('icqq');
|
|
29
25
|
|
|
30
26
|
export default defineAdapter<IcqqAdapterConfig>({
|
|
31
27
|
capabilities: ['inbound', 'outbound'],
|
|
32
28
|
operations: ['recall', 'reaction'],
|
|
33
|
-
// 统一消息元素通道(UNI-Channel):端点可消费 base64(CQ base64:// 守护进程解码)
|
|
34
|
-
// / url(CQ 直发)/ path(同机守护进程读盘;file 模式出站物化产物)媒体;
|
|
35
|
-
// 卡片/按钮等富交互段无原生承载,降级纯文本。
|
|
36
29
|
segments: {
|
|
37
30
|
outboundMedia: ['base64', 'url', 'path'],
|
|
38
31
|
interactive: 'text',
|
|
39
32
|
},
|
|
40
33
|
create(context) {
|
|
41
|
-
// Client-library / IPC daemon path — no httpHostToken.
|
|
42
|
-
// Console loginAssist + host-router routes deferred.
|
|
43
34
|
const config = resolveIcqqConfig(context.config);
|
|
44
35
|
// 注册到插件运行时状态(icqq.endpoint list 的"运行中"数据源)
|
|
45
36
|
context.use(icqqRuntimeStateToken).endpoints.set(config.id, {
|
|
46
37
|
id: config.id,
|
|
47
|
-
mode:
|
|
38
|
+
mode: 'direct',
|
|
48
39
|
});
|
|
49
40
|
const inbox = resolveInboxHooks(context);
|
|
50
|
-
return new
|
|
41
|
+
return new IcqqEndpoint({
|
|
51
42
|
id: context.id,
|
|
52
43
|
gateway: context.use(messageGatewayToken),
|
|
53
44
|
config,
|
package/agent/PERMITS.md
CHANGED
package/lib/agent-prompt.js
CHANGED
|
@@ -2,7 +2,7 @@ import { filterTools } from 'zhin.js/ai';
|
|
|
2
2
|
function isIcqqDelegatedTask(query, goal) {
|
|
3
3
|
const text = `${query} ${goal}`;
|
|
4
4
|
const lower = text.toLowerCase();
|
|
5
|
-
if (/\bicqq\b|
|
|
5
|
+
if (/\bicqq\b|icqq__|send_private_msg|friend\s+send/i.test(text))
|
|
6
6
|
return true;
|
|
7
7
|
if (/\bfriend\s+like\b/.test(lower) && /qq|好友|\d{5,}/i.test(text))
|
|
8
8
|
return true;
|
|
@@ -13,27 +13,22 @@ function isIcqqDelegatedTask(query, goal) {
|
|
|
13
13
|
return false;
|
|
14
14
|
}
|
|
15
15
|
function selectIcqqDeferredTools(query, goal, deferredCatalog, maxTools) {
|
|
16
|
-
const pool = deferredCatalog.filter(t => !t.name.startsWith('mcp_filesystem')
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const pool = deferredCatalog.filter(t => !t.name.startsWith('mcp_filesystem')
|
|
17
|
+
&& !t.name.startsWith('mcp_memory_')
|
|
18
|
+
&& !t.name.startsWith('mcp_icqq_'));
|
|
19
|
+
const icqqTools = pool.filter(t => t.name.startsWith('icqq__') || t.name.startsWith('icqq_'));
|
|
19
20
|
const pinned = [];
|
|
20
|
-
const bash = pool.find(t => t.name === 'bash');
|
|
21
|
-
if (bash)
|
|
22
|
-
pinned.push(bash);
|
|
23
21
|
const preferOrder = [
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
'
|
|
27
|
-
'icqq_friend_list',
|
|
28
|
-
'icqq_poke',
|
|
22
|
+
'icqq__send_user_like',
|
|
23
|
+
'icqq__friend_list',
|
|
24
|
+
'icqq__poke',
|
|
29
25
|
];
|
|
30
26
|
for (const name of preferOrder) {
|
|
31
|
-
const t =
|
|
32
|
-
icqqTools.find(x => x.name === name);
|
|
27
|
+
const t = icqqTools.find(x => x.name === name);
|
|
33
28
|
if (t)
|
|
34
29
|
pinned.push(t);
|
|
35
30
|
}
|
|
36
|
-
for (const t of
|
|
31
|
+
for (const t of icqqTools) {
|
|
37
32
|
if (pinned.length >= maxTools)
|
|
38
33
|
break;
|
|
39
34
|
if (!pinned.some(p => p.name === t.name))
|
|
@@ -51,15 +46,15 @@ function selectIcqqDeferredTools(query, goal, deferredCatalog, maxTools) {
|
|
|
51
46
|
return merged.slice(0, maxTools);
|
|
52
47
|
}
|
|
53
48
|
const ORCHESTRATOR_ICQQ = [
|
|
54
|
-
'On icqq/QQ:
|
|
55
|
-
'
|
|
56
|
-
'
|
|
49
|
+
'On icqq/QQ: if icqq__send_user_like is in your tool list, call it now with { endpoint_id, user_id, times }.',
|
|
50
|
+
'endpoint_id is this bot QQ (Session endpoint). user_id is the sender to like. times is 1-20.',
|
|
51
|
+
'Do not tell the user the tool is missing until you have called it this turn (or load_tool("icqq__send_user_like") failed).',
|
|
52
|
+
'Ignore prior turns that said the like tool was unavailable. Other social tools: icqq__poke, icqq__friend_list.',
|
|
57
53
|
].join('\n');
|
|
58
54
|
const WORKER_ICQQ = [
|
|
59
|
-
'
|
|
60
|
-
'
|
|
61
|
-
'
|
|
62
|
-
'Do NOT use mcp_filesystem_* or explore node_modules / package.json to "discover" icqq.',
|
|
55
|
+
'Friend like: load_tool("icqq__send_user_like") then call with { endpoint_id, user_id, times }. endpoint_id is this bot QQ (origin.endpoint).',
|
|
56
|
+
'Poke: icqq__poke. Friend list: icqq__friend_list.',
|
|
57
|
+
'Do NOT use mcp_icqq_*, mcp_filesystem_*, or bash `icqq friend like`.',
|
|
63
58
|
'Do not stop at --help; execute the action the goal describes.',
|
|
64
59
|
].map(line => `- ${line}`).join('\n');
|
|
65
60
|
export function createIcqqAgentPromptContributor() {
|
package/lib/cq-message.d.ts
CHANGED
|
@@ -17,6 +17,6 @@ export declare function icqqMediaRefFromString(value: string): MediaRef;
|
|
|
17
17
|
*/
|
|
18
18
|
export declare function resolveCqMediaArg(type: string, data: Record<string, unknown> | undefined): string | undefined;
|
|
19
19
|
export declare function parseCqMessage(raw: string): MessageSegment[];
|
|
20
|
-
/** 构建 icqq
|
|
21
|
-
export declare function
|
|
20
|
+
/** 构建 icqq send_*_msg 的 message 字符串(非空) */
|
|
21
|
+
export declare function buildIcqqMessage(content: SendContent): string;
|
|
22
22
|
export declare function toCqString(content: SendContent): string;
|
package/lib/cq-message.js
CHANGED
|
@@ -76,6 +76,9 @@ function pushCqSegment(segments, type, arg) {
|
|
|
76
76
|
case "reply":
|
|
77
77
|
segments.push({ type: "reply", data: { message_id: arg } });
|
|
78
78
|
break;
|
|
79
|
+
case "json":
|
|
80
|
+
segments.push({ type: "json", data: { text: arg } });
|
|
81
|
+
break;
|
|
79
82
|
default:
|
|
80
83
|
segments.push({ type, data: { text: `[${type}:${arg}]` } });
|
|
81
84
|
break;
|
|
@@ -115,8 +118,8 @@ export function parseCqMessage(raw) {
|
|
|
115
118
|
}
|
|
116
119
|
return segments.length ? segments : [{ type: "text", data: { text: raw } }];
|
|
117
120
|
}
|
|
118
|
-
/** 构建 icqq
|
|
119
|
-
export function
|
|
121
|
+
/** 构建 icqq send_*_msg 的 message 字符串(非空) */
|
|
122
|
+
export function buildIcqqMessage(content) {
|
|
120
123
|
let message = toCqString(content).trim();
|
|
121
124
|
if (!message)
|
|
122
125
|
message = "\u200b";
|
|
@@ -159,6 +162,8 @@ export function toCqString(content) {
|
|
|
159
162
|
}
|
|
160
163
|
case "reply":
|
|
161
164
|
return `[reply:${data.message_id ?? data.id}]`;
|
|
165
|
+
case "json":
|
|
166
|
+
return `[json:${data.text ?? ''}]`;
|
|
162
167
|
default:
|
|
163
168
|
return segment.toString(seg);
|
|
164
169
|
}
|
package/lib/endpoint.d.ts
CHANGED
|
@@ -1,25 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
* IcqqIpcEndpoint — lifecycle, outbound, IPC subscribe/admit for ICQQ daemon.
|
|
3
|
-
*/
|
|
1
|
+
import { Client } from '@icqqjs/icqq';
|
|
4
2
|
import type { EndpointControl, EndpointInstance, EndpointManagement, EndpointSendRequest } from '@zhin.js/adapter';
|
|
5
3
|
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
6
4
|
import type { CapabilityId } from '@zhin.js/plugin-runtime';
|
|
7
|
-
import { type IcqqInboundMessage, type
|
|
8
|
-
import type { IpcFriendInfo, IpcGroupInfo, IpcMemberInfo } from './types.js';
|
|
9
|
-
/** Minimal IPC surface used by the endpoint (real IpcClient or test mock). */
|
|
10
|
-
export interface IcqqIpcTransport {
|
|
11
|
-
request(action: string, params?: Record<string, unknown>): Promise<IpcResponse>;
|
|
12
|
-
subscribe(action: string, params: Record<string, unknown>, handler: (event: IpcEvent) => void): {
|
|
13
|
-
unsubscribe: () => Promise<void>;
|
|
14
|
-
};
|
|
15
|
-
setOnRemoteDisconnect(handler: (() => void) | null): void;
|
|
16
|
-
close(): void;
|
|
17
|
-
}
|
|
18
|
-
export type CreateIcqqIpc = (config: ResolvedIcqqConfig) => Promise<IcqqIpcTransport>;
|
|
19
|
-
/**
|
|
20
|
-
* 收件箱写/推钩子(由装配层注入,见 adapters/icqq.ts)。
|
|
21
|
-
* record* 写 unified_inbox_request/notice;publish 向 console hub 推送实时事件。
|
|
22
|
-
*/
|
|
5
|
+
import { type IcqqInboundMessage, type ResolvedIcqqConfig } from './protocol.js';
|
|
23
6
|
export interface IcqqInboxHooks {
|
|
24
7
|
recordRequest(row: Record<string, unknown>): void | Promise<void>;
|
|
25
8
|
recordNotice(row: Record<string, unknown>): void | Promise<void>;
|
|
@@ -29,71 +12,18 @@ export interface IcqqEndpointOptions {
|
|
|
29
12
|
readonly id: CapabilityId;
|
|
30
13
|
readonly gateway: MessageGateway;
|
|
31
14
|
readonly config: ResolvedIcqqConfig;
|
|
32
|
-
readonly createIpc?: CreateIcqqIpc;
|
|
33
|
-
/** 未注入时 request/notice 事件仅按非消息载荷忽略(不报错)。 */
|
|
34
15
|
readonly inbox?: IcqqInboxHooks;
|
|
35
16
|
}
|
|
36
|
-
export declare class
|
|
17
|
+
export declare class IcqqEndpoint extends Client implements EndpointInstance {
|
|
37
18
|
#private;
|
|
38
|
-
readonly
|
|
39
|
-
/** Populated after start(); agent tools read this. */
|
|
40
|
-
ipc: IcqqIpcTransport;
|
|
41
|
-
readonly friends: Map<number, IpcFriendInfo>;
|
|
42
|
-
readonly groups: Map<number, IpcGroupInfo>;
|
|
19
|
+
readonly endpointName: string;
|
|
43
20
|
readonly management: EndpointManagement;
|
|
44
21
|
readonly control: EndpointControl;
|
|
45
22
|
constructor(options: IcqqEndpointOptions);
|
|
46
|
-
request(action: string, params?: Record<string, unknown>): Promise<IpcResponse>;
|
|
47
23
|
start(): Promise<void>;
|
|
48
24
|
open(): void;
|
|
49
25
|
close(): void;
|
|
50
26
|
stop(): Promise<void>;
|
|
51
27
|
send({ conversation, payload }: EndpointSendRequest): Promise<string>;
|
|
52
|
-
private static readonly EMOJI_MAP;
|
|
53
|
-
private getEmojiId;
|
|
54
|
-
/** Activity-feedback / OutboundHost reaction surface. */
|
|
55
|
-
addReaction(messageId: string, emoji: string): Promise<string | null>;
|
|
56
|
-
removeReaction(messageId: string, reactionId: string): Promise<void>;
|
|
57
|
-
/** Activity-feedback autoRemove / Console recall. */
|
|
58
|
-
recallMessage(messageId: string): Promise<void>;
|
|
59
|
-
/** EndpointManagement.listFriends —— 好友列表(LIST_FRIENDS,归一为 {user_id, nickname, remark})。 */
|
|
60
|
-
getFriendList(): Promise<Array<{
|
|
61
|
-
user_id: number;
|
|
62
|
-
nickname: string;
|
|
63
|
-
remark: string;
|
|
64
|
-
}>>;
|
|
65
|
-
/** EndpointManagement.listGroups —— 群列表(LIST_GROUPS,归一为 {group_id, name})。 */
|
|
66
|
-
getGroupList(): Promise<Array<{
|
|
67
|
-
group_id: number;
|
|
68
|
-
name: string;
|
|
69
|
-
}>>;
|
|
70
|
-
/** EndpointManagement.listGroupMembers —— 群成员列表(字段对齐 daemon 返回)。 */
|
|
71
|
-
getGroupMemberList(groupId: number | string): Promise<IpcMemberInfo[]>;
|
|
72
|
-
/** getGroupMemberList 别名(console 探测 listMembers / getMemberList)。 */
|
|
73
|
-
listMembers(groupId: number | string): Promise<IpcMemberInfo[]>;
|
|
74
|
-
getMemberList(groupId: number | string): Promise<IpcMemberInfo[]>;
|
|
75
|
-
/**
|
|
76
|
-
* EndpointManagement.resolveRequest —— id 为 inbox 行的 platform_request_id。
|
|
77
|
-
* 先 GET_SYSTEM_MSG 按 flag(回退 seq)定位请求,再按类型路由 handle_friend/group_request。
|
|
78
|
-
*/
|
|
79
|
-
approveRequest(id: string, remark?: string): Promise<void>;
|
|
80
|
-
rejectRequest(id: string, reason?: string): Promise<void>;
|
|
81
|
-
/** EndpointManagement.deleteFriend —— FRIEND_DELETE。 */
|
|
82
|
-
deleteFriend(userId: number | string): Promise<void>;
|
|
83
|
-
/** deleteFriend 别名(console 探测 delete_friend)。 */
|
|
84
|
-
delete_friend(userId: number | string): Promise<void>;
|
|
85
|
-
/** EndpointManagement.kickGroupMember —— GROUP_KICK。 */
|
|
86
|
-
removeMember(groupId: number | string, userId: number | string): Promise<void>;
|
|
87
|
-
kickMember(groupId: number | string, userId: number | string): Promise<void>;
|
|
88
|
-
setGroupKick(groupId: number | string, userId: number | string): Promise<void>;
|
|
89
|
-
/** EndpointManagement.muteGroupMember —— GROUP_MUTE(duration 秒,默认 600)。 */
|
|
90
|
-
muteMember(groupId: number | string, userId: number | string, duration?: number): Promise<void>;
|
|
91
|
-
banMember(groupId: number | string, userId: number | string, duration?: number): Promise<void>;
|
|
92
|
-
setGroupMute(groupId: number | string, userId: number | string, duration?: number): Promise<void>;
|
|
93
|
-
/** EndpointManagement.setGroupAdmin —— SET_GROUP_ADMIN(enable 默认 true)。 */
|
|
94
|
-
setModerator(groupId: number | string, userId: number | string, enable?: boolean): Promise<void>;
|
|
95
|
-
setAdmin(groupId: number | string, userId: number | string, enable?: boolean): Promise<void>;
|
|
96
|
-
setGroupAdmin(groupId: number | string, userId: number | string, enable?: boolean): Promise<void>;
|
|
97
|
-
/** Test / internal: admit when open. */
|
|
98
28
|
admit(msg: IcqqInboundMessage): void;
|
|
99
29
|
}
|