qidao-openclaw-plugin 1.2.7 → 1.3.2
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/package.json +1 -1
- package/src/index.js +130 -34
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -6,6 +6,19 @@ import { QidaoChannel } from './qidao-channel.js';
|
|
|
6
6
|
import { registerAuthCommand } from './auth-cli.js';
|
|
7
7
|
|
|
8
8
|
let connection = null;
|
|
9
|
+
let pluginApi = null;
|
|
10
|
+
let qidaoRuntime = null;
|
|
11
|
+
|
|
12
|
+
function setQidaoRuntime(r) {
|
|
13
|
+
qidaoRuntime = r;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getQidaoRuntime() {
|
|
17
|
+
if (!qidaoRuntime) {
|
|
18
|
+
throw new Error('Qidao runtime not initialized - plugin not registered');
|
|
19
|
+
}
|
|
20
|
+
return qidaoRuntime;
|
|
21
|
+
}
|
|
9
22
|
|
|
10
23
|
const qidaoChannel = {
|
|
11
24
|
id: 'qidao',
|
|
@@ -19,6 +32,7 @@ const qidaoChannel = {
|
|
|
19
32
|
|
|
20
33
|
capabilities: {
|
|
21
34
|
chatTypes: ['direct', 'group'],
|
|
35
|
+
hasGateway: true,
|
|
22
36
|
},
|
|
23
37
|
|
|
24
38
|
config: {
|
|
@@ -126,32 +140,25 @@ const qidaoChannel = {
|
|
|
126
140
|
}
|
|
127
141
|
},
|
|
128
142
|
},
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
export default function register(api) {
|
|
132
|
-
api.logger.info('栖岛聊天插件加载中...');
|
|
133
143
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
try {
|
|
141
|
-
const cfg = api.getGatewayConfig?.() || {};
|
|
142
|
-
const account = qidaoChannel.config.resolveAccount(cfg);
|
|
144
|
+
gateway: {
|
|
145
|
+
startAccount: async (ctx) => {
|
|
146
|
+
const { account, cfg, runtime, abortSignal } = ctx;
|
|
147
|
+
|
|
148
|
+
runtime.log?.('🚀 栖岛聊天 gateway.startAccount 被调用!');
|
|
149
|
+
runtime.log?.(`账户信息: ${JSON.stringify(account)}`);
|
|
143
150
|
|
|
144
151
|
if (!account.enabled) {
|
|
145
|
-
|
|
152
|
+
runtime.log?.('栖岛聊天未启用');
|
|
146
153
|
return;
|
|
147
154
|
}
|
|
148
155
|
|
|
149
156
|
if (!account.chatId) {
|
|
150
|
-
|
|
157
|
+
runtime.log?.('栖岛聊天缺少chatId配置');
|
|
151
158
|
return;
|
|
152
159
|
}
|
|
153
160
|
|
|
154
|
-
|
|
161
|
+
runtime.log?.(`连接栖岛聊天 (chatId: ${account.chatId})`);
|
|
155
162
|
|
|
156
163
|
connection = new QidaoChannel({
|
|
157
164
|
serverUrl: account.serverUrl,
|
|
@@ -160,38 +167,127 @@ export default function register(api) {
|
|
|
160
167
|
});
|
|
161
168
|
|
|
162
169
|
connection.on('connect', () => {
|
|
163
|
-
|
|
170
|
+
runtime.log?.('栖岛聊天已连接');
|
|
164
171
|
});
|
|
165
172
|
|
|
166
173
|
connection.on('disconnect', () => {
|
|
167
|
-
|
|
174
|
+
runtime.log?.('栖岛聊天已断开');
|
|
168
175
|
});
|
|
169
176
|
|
|
170
177
|
connection.on('error', (error) => {
|
|
171
|
-
|
|
178
|
+
runtime.error?.(`栖岛聊天错误: ${error.message}`);
|
|
172
179
|
});
|
|
173
180
|
|
|
174
|
-
connection.on('message', (message) => {
|
|
181
|
+
connection.on('message', async (message) => {
|
|
175
182
|
if (message.type === 'new_message') {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
183
|
+
try {
|
|
184
|
+
// 过滤掉机器人自己发送的消息,避免循环
|
|
185
|
+
// 栖岛消息中,senderId=1 是畅小猪,otherUserId=175 是机器人
|
|
186
|
+
if (message.senderId === 175 || message.otherUserId === 1) {
|
|
187
|
+
runtime.log?.(`跳过机器人自己的消息`);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
runtime.log?.(`收到栖岛消息: ${message.messageText}`);
|
|
192
|
+
|
|
193
|
+
const core = getQidaoRuntime();
|
|
194
|
+
|
|
195
|
+
const chatId = message.chatId.toString();
|
|
196
|
+
const chatType = message.chatType === 0 ? 'direct' : 'group';
|
|
197
|
+
|
|
198
|
+
// 解析路由信息
|
|
199
|
+
const route = core.channel.routing.resolveAgentRoute({
|
|
200
|
+
cfg,
|
|
201
|
+
channel: 'qidao',
|
|
202
|
+
accountId: account.accountId,
|
|
203
|
+
peer: {
|
|
204
|
+
kind: chatType,
|
|
205
|
+
id: chatId,
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// 构建标准消息上下文(参考企业微信插件)
|
|
210
|
+
const ctxPayload = core.channel.reply.finalizeInboundContext({
|
|
211
|
+
Body: message.messageText,
|
|
212
|
+
RawBody: message.messageText,
|
|
213
|
+
CommandBody: message.messageText,
|
|
214
|
+
MessageSid: message.messageId?.toString() || `${Date.now()}`,
|
|
215
|
+
From: chatType === 'group' ? `qidao:group:${chatId}` : `qidao:${message.senderId}`,
|
|
216
|
+
To: `qidao:${chatId}`,
|
|
217
|
+
SenderId: message.senderId.toString(),
|
|
218
|
+
SessionKey: route.sessionKey,
|
|
219
|
+
AccountId: account.accountId,
|
|
220
|
+
ChatType: chatType,
|
|
221
|
+
ConversationLabel: chatType === 'group' ? `group:${chatId}` : `user:${message.senderId}`,
|
|
222
|
+
Timestamp: message.timestamp || Date.now(),
|
|
223
|
+
Provider: 'qidao',
|
|
224
|
+
Surface: 'qidao',
|
|
225
|
+
OriginatingChannel: 'qidao',
|
|
226
|
+
OriginatingTo: `qidao:${chatId}`,
|
|
227
|
+
CommandAuthorized: true,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// 使用 core.channel.reply.dispatchReplyWithBufferedBlockDispatcher 处理消息
|
|
231
|
+
await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
232
|
+
ctx: ctxPayload,
|
|
233
|
+
cfg,
|
|
234
|
+
dispatcherOptions: {
|
|
235
|
+
deliver: async (payload, info) => {
|
|
236
|
+
runtime.log?.(`发送回复: ${payload.text.substring(0, 50)}...`);
|
|
237
|
+
|
|
238
|
+
// 通过 connection 发送回复
|
|
239
|
+
if (info.kind === 'final') {
|
|
240
|
+
await connection.sendMessage(message.chatId, payload.text);
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
onError: (err, info) => {
|
|
244
|
+
runtime.error?.(`回复失败 (${info.kind}): ${err.message}`);
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
runtime.log?.('✅ 消息处理完成');
|
|
250
|
+
} catch (error) {
|
|
251
|
+
runtime.error?.(`处理消息失败: ${error.message}`);
|
|
252
|
+
}
|
|
186
253
|
}
|
|
187
254
|
});
|
|
188
255
|
|
|
256
|
+
// 处理中止信号
|
|
257
|
+
if (abortSignal) {
|
|
258
|
+
abortSignal.addEventListener('abort', () => {
|
|
259
|
+
runtime.log?.('栖岛聊天连接被中止');
|
|
260
|
+
if (connection) {
|
|
261
|
+
connection.disconnect();
|
|
262
|
+
connection = null;
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
189
267
|
await connection.connect();
|
|
190
268
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
269
|
+
// 返回 Promise,保持连接直到被中止
|
|
270
|
+
return new Promise((resolve) => {
|
|
271
|
+
if (abortSignal) {
|
|
272
|
+
abortSignal.addEventListener('abort', resolve);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
export default function register(api) {
|
|
280
|
+
pluginApi = api;
|
|
281
|
+
|
|
282
|
+
// 设置 runtime(参考企业微信插件)
|
|
283
|
+
setQidaoRuntime(api.runtime);
|
|
284
|
+
|
|
285
|
+
api.logger.info('栖岛聊天插件加载中...');
|
|
286
|
+
|
|
287
|
+
api.registerChannel({ plugin: qidaoChannel });
|
|
288
|
+
|
|
289
|
+
// 注册认证命令
|
|
290
|
+
registerAuthCommand(api);
|
|
195
291
|
|
|
196
292
|
api.logger.info('栖岛聊天插件加载完成');
|
|
197
293
|
}
|