qidao-openclaw-plugin 1.2.8 → 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 +129 -38
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,37 +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
|
-
registerAuthCommand(api);
|
|
138
|
-
|
|
139
|
-
// 延迟初始化,确保配置已加载
|
|
140
|
-
setTimeout(async () => {
|
|
141
|
-
try {
|
|
142
|
-
const cfg = api.getGatewayConfig?.() || {};
|
|
143
|
-
|
|
144
|
-
// 调试日志
|
|
145
|
-
api.logger.info(`栖岛聊天配置: ${JSON.stringify(cfg.channels?.qidao || {})}`);
|
|
144
|
+
gateway: {
|
|
145
|
+
startAccount: async (ctx) => {
|
|
146
|
+
const { account, cfg, runtime, abortSignal } = ctx;
|
|
146
147
|
|
|
147
|
-
|
|
148
|
+
runtime.log?.('🚀 栖岛聊天 gateway.startAccount 被调用!');
|
|
149
|
+
runtime.log?.(`账户信息: ${JSON.stringify(account)}`);
|
|
148
150
|
|
|
149
151
|
if (!account.enabled) {
|
|
150
|
-
|
|
152
|
+
runtime.log?.('栖岛聊天未启用');
|
|
151
153
|
return;
|
|
152
154
|
}
|
|
153
155
|
|
|
154
156
|
if (!account.chatId) {
|
|
155
|
-
|
|
157
|
+
runtime.log?.('栖岛聊天缺少chatId配置');
|
|
156
158
|
return;
|
|
157
159
|
}
|
|
158
160
|
|
|
159
|
-
|
|
161
|
+
runtime.log?.(`连接栖岛聊天 (chatId: ${account.chatId})`);
|
|
160
162
|
|
|
161
163
|
connection = new QidaoChannel({
|
|
162
164
|
serverUrl: account.serverUrl,
|
|
@@ -165,38 +167,127 @@ export default function register(api) {
|
|
|
165
167
|
});
|
|
166
168
|
|
|
167
169
|
connection.on('connect', () => {
|
|
168
|
-
|
|
170
|
+
runtime.log?.('栖岛聊天已连接');
|
|
169
171
|
});
|
|
170
172
|
|
|
171
173
|
connection.on('disconnect', () => {
|
|
172
|
-
|
|
174
|
+
runtime.log?.('栖岛聊天已断开');
|
|
173
175
|
});
|
|
174
176
|
|
|
175
177
|
connection.on('error', (error) => {
|
|
176
|
-
|
|
178
|
+
runtime.error?.(`栖岛聊天错误: ${error.message}`);
|
|
177
179
|
});
|
|
178
180
|
|
|
179
|
-
connection.on('message', (message) => {
|
|
181
|
+
connection.on('message', async (message) => {
|
|
180
182
|
if (message.type === 'new_message') {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
+
}
|
|
191
253
|
}
|
|
192
254
|
});
|
|
193
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
|
+
|
|
194
267
|
await connection.connect();
|
|
195
268
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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);
|
|
200
291
|
|
|
201
292
|
api.logger.info('栖岛聊天插件加载完成');
|
|
202
293
|
}
|