aicq-chat-plugin 3.6.1 → 3.7.1

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/index.js CHANGED
@@ -132,7 +132,7 @@ async function handleGatewayMethod(method, kwargs = {}) {
132
132
  return {
133
133
  state: _serverClient.connected ? "connected" : "disconnected",
134
134
  agent_id: currentAgentId,
135
- version: "3.6.0",
135
+ version: "3.7.0",
136
136
  architecture: "channel",
137
137
  };
138
138
  case "aicq.friends.list":
package/lib/package.json CHANGED
File without changes
@@ -2,7 +2,7 @@
2
2
  "kind": "channel",
3
3
  "id": "aicq-chat",
4
4
  "name": "AICQ Encrypted Chat",
5
- "version": "3.6.1",
5
+ "version": "3.7.1",
6
6
  "description": "End-to-end encrypted chat channel via AICQ protocol — in-process Channel plugin using OpenClaw Channel SDK",
7
7
  "entry": "index.js",
8
8
  "activation": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aicq-chat-plugin",
3
- "version": "3.6.1",
3
+ "version": "3.7.1",
4
4
  "description": "AICQ End-to-end Encrypted Chat Channel Plugin for OpenClaw — In-process Channel SDK architecture with friend management, group chat, file transfer, and AI agent communication",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/src/channel.js CHANGED
@@ -347,55 +347,112 @@ _plugin.gateway = {
347
347
  }
348
348
  }
349
349
 
350
- // Wire up inbound message handling via channelRuntime if available
351
- if (ctx.channelRuntime) {
352
- const { reply, routing } = ctx.channelRuntime;
353
- if (reply && routing) {
354
- console.log("[AICQ Channel] channelRuntime available AI dispatch enabled");
355
-
356
- if (runtime.serverClient && typeof runtime.serverClient.onMessage === "function") {
357
- runtime.serverClient.onMessage(async (msg) => {
358
- try {
359
- const resolvedAgentId = agentId;
360
- const routeResult = await routing.resolveAgentRoute({
361
- channelId: "aicq-chat",
362
- accountId,
363
- fromId: msg.from || msg.sender_id,
364
- chatType: msg.isGroup ? "group" : "dm",
365
- });
350
+ // Wire up inbound message handling
351
+ // Register handlers for AICQ message types. When an inbound message arrives,
352
+ // we try the OpenClaw channelRuntime first; if that fails we fall back to
353
+ // calling z-ai CLI directly and sending the reply via chat.sendMessage.
354
+ if (runtime.serverClient && typeof runtime.serverClient.onMessage === "function") {
355
+ const inboundHandler = async (msg) => {
356
+ try {
357
+ // AICQ server wraps message content in msg.data for "message" type,
358
+ // but "relay" type may have fields at the top level.
359
+ const data = msg.data || msg;
360
+ const fromId = data.from || data.fromId || data.sender_id || msg.from || msg.fromId;
361
+ const isGroup = !!(data.isGroup || data.groupId || msg.isGroup || msg.groupId);
362
+ const text = data.content || data.text || data.payload || msg.content || msg.text || msg.payload || "";
363
+
364
+ console.log(`[AICQ Channel] Inbound message from=${fromId} isGroup=${isGroup} text=${(text || "").substring(0, 80)}`);
365
+
366
+ if (!fromId || !text) {
367
+ return; // Skip system messages (online_ack, presence, etc.)
368
+ }
366
369
 
367
- if (routeResult?.agentId) {
368
- await reply.dispatchReplyWithBufferedBlockDispatcher({
369
- ctx: {
370
- channelId: "aicq-chat",
371
- accountId,
372
- fromId: msg.from || msg.sender_id,
373
- text: msg.content || msg.text || "",
374
- chatType: msg.isGroup ? "group" : "dm",
375
- },
376
- cfg,
377
- dispatcherOptions: {
378
- deliver: async (payload) => {
379
- if (runtime.chat && payload.text) {
380
- await runtime.chat.sendMessage(
381
- resolvedAgentId,
382
- msg.from || msg.sender_id,
383
- payload.text,
384
- { isGroup: !!msg.isGroup }
385
- );
386
- }
387
- },
388
- },
370
+ // Skip our own messages
371
+ if (fromId === runtime.serverClient?.serverAccountId || fromId === agentId) {
372
+ return;
373
+ }
374
+
375
+ // Try channelRuntime (OpenClaw's built-in agent dispatch) first
376
+ if (ctx.channelRuntime) {
377
+ const { reply, routing } = ctx.channelRuntime;
378
+ if (reply && routing) {
379
+ try {
380
+ const routeResult = await routing.resolveAgentRoute({
381
+ channelId: "aicq-chat",
382
+ accountId,
383
+ fromId,
384
+ chatType: isGroup ? "group" : "dm",
389
385
  });
386
+
387
+ if (routeResult?.agentId) {
388
+ await reply.dispatchReplyWithBufferedBlockDispatcher({
389
+ ctx: {
390
+ channelId: "aicq-chat",
391
+ accountId,
392
+ fromId,
393
+ text,
394
+ chatType: isGroup ? "group" : "dm",
395
+ },
396
+ cfg,
397
+ dispatcherOptions: {
398
+ deliver: async (payload) => {
399
+ if (runtime.chat && payload.text) {
400
+ await runtime.chat.sendMessage(agentId, fromId, payload.text, { isGroup });
401
+ }
402
+ },
403
+ },
404
+ });
405
+ return; // Successfully dispatched via channelRuntime
406
+ }
407
+ } catch (e) {
408
+ console.error("[AICQ Channel] channelRuntime dispatch failed, using fallback:", e.message);
390
409
  }
391
- } catch (e) {
392
- console.error("[AICQ Channel] Inbound message handling error:", e.message);
393
410
  }
394
- });
411
+ }
412
+
413
+ // Fallback: call LLM via z-ai CLI and send reply directly
414
+ console.log("[AICQ Channel] Using fallback: direct z-ai CLI call");
415
+ try {
416
+ const { execFile } = await import('child_process');
417
+ const llmResult = await new Promise((resolve, reject) => {
418
+ execFile('z-ai', ['chat', '--prompt', text], { timeout: 60000 }, (err, stdout) => {
419
+ if (err) reject(err);
420
+ else resolve(stdout);
421
+ });
422
+ });
423
+ let replyText = '';
424
+ const jsonStart = llmResult.indexOf('{');
425
+ if (jsonStart >= 0) {
426
+ try {
427
+ const parsed = JSON.parse(llmResult.substring(jsonStart));
428
+ replyText = parsed.choices?.[0]?.message?.content || llmResult.trim();
429
+ } catch { replyText = llmResult.trim(); }
430
+ } else { replyText = llmResult.trim(); }
431
+
432
+ if (replyText && runtime.chat) {
433
+ await runtime.chat.sendMessage(agentId, fromId, replyText, { isGroup });
434
+ console.log(`[AICQ Channel] Fallback reply sent to ${fromId}: ${replyText.substring(0, 50)}`);
435
+ }
436
+ } catch (fallbackErr) {
437
+ console.error("[AICQ Channel] Fallback LLM also failed:", fallbackErr.message);
438
+ }
439
+ } catch (e) {
440
+ console.error("[AICQ Channel] Inbound message handling error:", e.message);
395
441
  }
442
+ };
443
+
444
+ // Register handler for relevant AICQ message types.
445
+ // ServerClient.onMessage(type, handler) requires a type string.
446
+ runtime.serverClient.onMessage("relay", inboundHandler);
447
+ runtime.serverClient.onMessage("message", inboundHandler);
448
+ runtime.serverClient.onMessage("group_message", inboundHandler);
449
+ console.log("[AICQ Channel] Inbound message handlers registered (relay, message, group_message)");
450
+
451
+ if (ctx.channelRuntime) {
452
+ console.log("[AICQ Channel] channelRuntime available — AI dispatch enabled (with z-ai CLI fallback)");
453
+ } else {
454
+ console.log("[AICQ Channel] channelRuntime not available — using z-ai CLI fallback");
396
455
  }
397
- } else {
398
- console.log("[AICQ Channel] channelRuntime not available — running in standalone mode");
399
456
  }
400
457
 
401
458
  // Update health status