aicq-chat-plugin 3.5.1 → 3.5.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.
- package/index.js +1 -0
- package/openclaw.plugin.json +13 -1
- package/package.json +1 -1
- package/setup-entry.js +0 -0
- package/src/channel.js +69 -22
- package/src/ui-routes.js +0 -0
package/index.js
CHANGED
|
@@ -65,6 +65,7 @@ async function ensureInitialized() {
|
|
|
65
65
|
runtime.dataDir = DATA_DIR;
|
|
66
66
|
runtime.serverUrl = SERVER_URL;
|
|
67
67
|
runtime.handleGateway = handleGatewayMethod;
|
|
68
|
+
runtime.ensureInitialized = ensureInitialized;
|
|
68
69
|
|
|
69
70
|
// Periodic cleanup
|
|
70
71
|
setInterval(() => _db.cleanup(), 3600000);
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"kind": "channel",
|
|
3
3
|
"id": "aicq-chat",
|
|
4
4
|
"name": "AICQ Encrypted Chat",
|
|
5
|
-
"version": "3.5.
|
|
5
|
+
"version": "3.5.3",
|
|
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": {
|
|
@@ -49,6 +49,14 @@
|
|
|
49
49
|
"open",
|
|
50
50
|
"disabled"
|
|
51
51
|
]
|
|
52
|
+
},
|
|
53
|
+
"allowFrom": {
|
|
54
|
+
"type": "array",
|
|
55
|
+
"items": {
|
|
56
|
+
"type": "string"
|
|
57
|
+
},
|
|
58
|
+
"default": [],
|
|
59
|
+
"description": "允许发消息的好友 ID 列表(dmPolicy 为 allowlist 时生效)"
|
|
52
60
|
}
|
|
53
61
|
},
|
|
54
62
|
"required": [
|
|
@@ -71,6 +79,10 @@
|
|
|
71
79
|
"dmPolicy": {
|
|
72
80
|
"label": "DM Policy",
|
|
73
81
|
"help": "Who can send direct messages: allowlist (friends only), open, or disabled"
|
|
82
|
+
},
|
|
83
|
+
"allowFrom": {
|
|
84
|
+
"label": "Allow From",
|
|
85
|
+
"help": "Friend IDs allowed to send DMs (used when dmPolicy is allowlist)"
|
|
74
86
|
}
|
|
75
87
|
}
|
|
76
88
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aicq-chat-plugin",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.3",
|
|
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/setup-entry.js
CHANGED
|
File without changes
|
package/src/channel.js
CHANGED
|
@@ -35,18 +35,29 @@ export const runtime = {
|
|
|
35
35
|
// ── Template variable resolver ───────────────────────────────────────
|
|
36
36
|
// OpenClaw stores accountId as-is (e.g. "{{agent.id}}") in config.
|
|
37
37
|
// Plugins must resolve template variables at runtime.
|
|
38
|
+
//
|
|
39
|
+
// The default agent ID in OpenClaw is "main" (DEFAULT_AGENT_ID).
|
|
40
|
+
// When cfg.agents.list is empty/undefined (no explicit agent config),
|
|
41
|
+
// the implicit default agent "main" is used.
|
|
42
|
+
|
|
43
|
+
const OPENCLAW_DEFAULT_AGENT_ID = "main";
|
|
38
44
|
|
|
39
45
|
function resolveTemplateVar(cfg, value) {
|
|
40
46
|
if (typeof value !== "string") return value;
|
|
41
47
|
const match = value.match(/^\{\{(\w[\w.]*)\}\}$/);
|
|
42
48
|
if (!match) return value;
|
|
43
49
|
|
|
44
|
-
const
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
const tmplPath = match[1]; // e.g. "agent.id"
|
|
51
|
+
if (tmplPath === "agent.id") {
|
|
52
|
+
// Strategy: look for explicit agents in config first
|
|
53
|
+
const agents = cfg.agents?.list;
|
|
54
|
+
if (Array.isArray(agents) && agents.length > 0) {
|
|
55
|
+
// Use the default=true agent, or the first one
|
|
56
|
+
const defaultAgent = agents.find((a) => a.default) || agents[0];
|
|
57
|
+
if (defaultAgent?.id) return defaultAgent.id;
|
|
58
|
+
}
|
|
59
|
+
// Fallback: OpenClaw's implicit default agent ID
|
|
60
|
+
return OPENCLAW_DEFAULT_AGENT_ID;
|
|
50
61
|
}
|
|
51
62
|
|
|
52
63
|
return value; // unknown template — return as-is
|
|
@@ -74,13 +85,19 @@ function resolveAccount(cfg, accountId) {
|
|
|
74
85
|
// Resolve template variables like {{agent.id}}
|
|
75
86
|
const resolvedAccountId = resolveTemplateVar(cfg, rawAccountId);
|
|
76
87
|
|
|
88
|
+
// Resolve allowFrom entries (may contain {{agent.id}} or friend IDs)
|
|
89
|
+
const rawAllowFrom = section.allowFrom || [];
|
|
90
|
+
const resolvedAllowFrom = Array.isArray(rawAllowFrom)
|
|
91
|
+
? rawAllowFrom.map((entry) => resolveTemplateVar(cfg, entry))
|
|
92
|
+
: rawAllowFrom;
|
|
93
|
+
|
|
77
94
|
return {
|
|
78
95
|
accountId: resolvedAccountId,
|
|
79
96
|
serverUrl: section.serverUrl || "https://aicq.online",
|
|
80
97
|
autoAcceptFriends: section.autoAcceptFriends ?? true,
|
|
81
98
|
enabled: section.enabled ?? true,
|
|
82
99
|
dmPolicy: section.dmPolicy || "allowlist",
|
|
83
|
-
allowFrom:
|
|
100
|
+
allowFrom: resolvedAllowFrom,
|
|
84
101
|
};
|
|
85
102
|
}
|
|
86
103
|
|
|
@@ -219,24 +236,46 @@ _plugin.gateway = {
|
|
|
219
236
|
* listening for inbound messages.
|
|
220
237
|
*/
|
|
221
238
|
async startAccount(ctx) {
|
|
222
|
-
const { cfg, accountId, account, setStatus } = ctx;
|
|
239
|
+
const { cfg, accountId, account, setStatus, log } = ctx;
|
|
223
240
|
|
|
224
|
-
|
|
241
|
+
const logger = log || console;
|
|
242
|
+
logger.info?.(`[AICQ Channel] startAccount called for ${accountId}`) || console.log(`[AICQ Channel] startAccount called for ${accountId}`);
|
|
225
243
|
|
|
226
|
-
// Ensure the runtime (DB, identity, transport) is initialised
|
|
227
|
-
|
|
228
|
-
|
|
244
|
+
// Ensure the runtime (DB, identity, transport) is initialised.
|
|
245
|
+
// The runtime is populated by registerFull() in index.js, but startAccount
|
|
246
|
+
// may be called before any gateway method is invoked, so we must ensure
|
|
247
|
+
// initialization here too.
|
|
248
|
+
if (!runtime._initialized && typeof runtime.ensureInitialized === "function") {
|
|
249
|
+
try {
|
|
250
|
+
await runtime.ensureInitialized();
|
|
251
|
+
logger.info?.("[AICQ Channel] Runtime initialized via startAccount") || console.log("[AICQ Channel] Runtime initialized via startAccount");
|
|
252
|
+
} catch (e) {
|
|
253
|
+
console.error("[AICQ Channel] Runtime initialization failed:", e.message);
|
|
254
|
+
setStatus({
|
|
255
|
+
accountId,
|
|
256
|
+
enabled: true,
|
|
257
|
+
configured: true,
|
|
258
|
+
running: false,
|
|
259
|
+
lastError: `Initialization failed: ${e.message}`,
|
|
260
|
+
});
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
229
263
|
}
|
|
230
264
|
|
|
231
|
-
// Resolve the agent ID
|
|
232
|
-
|
|
233
|
-
|
|
265
|
+
// Resolve the agent ID: prefer the resolved accountId from
|
|
266
|
+
// resolveAccount (which already handles {{agent.id}}), then
|
|
267
|
+
// fall back to the OpenClaw default agent ID.
|
|
268
|
+
const agents = cfg.agents?.list;
|
|
269
|
+
const agentId = account?.accountId || accountId || OPENCLAW_DEFAULT_AGENT_ID;
|
|
234
270
|
|
|
235
271
|
// Ensure we have an identity in the plugin DB
|
|
236
272
|
if (runtime.identity) {
|
|
237
273
|
const existing = runtime.identity.listAgents();
|
|
238
274
|
if (existing.length === 0) {
|
|
239
|
-
|
|
275
|
+
const agentName = (Array.isArray(agents) && agents.length > 0 && agents[0]?.name)
|
|
276
|
+
? agents[0].name
|
|
277
|
+
: "AICQ Agent";
|
|
278
|
+
runtime.identity.createAgent(agentId, agentName);
|
|
240
279
|
console.log(`[AICQ Channel] Created agent identity: ${agentId}`);
|
|
241
280
|
}
|
|
242
281
|
}
|
|
@@ -248,9 +287,13 @@ _plugin.gateway = {
|
|
|
248
287
|
console.log(`[AICQ Channel] Authenticated as ${agentId}`);
|
|
249
288
|
|
|
250
289
|
// Connect WebSocket for real-time messages
|
|
251
|
-
|
|
252
|
-
|
|
290
|
+
// ServerClient.start() does ensureAuth + connectWS
|
|
291
|
+
if (typeof runtime.serverClient.start === "function") {
|
|
292
|
+
await runtime.serverClient.start(agentId);
|
|
253
293
|
console.log("[AICQ Channel] WebSocket connected");
|
|
294
|
+
} else if (typeof runtime.serverClient.connectWS === "function") {
|
|
295
|
+
runtime.serverClient.connectWS();
|
|
296
|
+
console.log("[AICQ Channel] WebSocket connecting");
|
|
254
297
|
}
|
|
255
298
|
|
|
256
299
|
// Sync friends and groups from server
|
|
@@ -277,7 +320,7 @@ _plugin.gateway = {
|
|
|
277
320
|
if (runtime.serverClient && typeof runtime.serverClient.onMessage === "function") {
|
|
278
321
|
runtime.serverClient.onMessage(async (msg) => {
|
|
279
322
|
try {
|
|
280
|
-
const resolvedAgentId =
|
|
323
|
+
const resolvedAgentId = agentId;
|
|
281
324
|
const routeResult = await routing.resolveAgentRoute({
|
|
282
325
|
channelId: "aicq-chat",
|
|
283
326
|
accountId,
|
|
@@ -340,9 +383,13 @@ _plugin.gateway = {
|
|
|
340
383
|
const { accountId } = ctx;
|
|
341
384
|
console.log(`[AICQ Channel] stopAccount called for ${accountId}`);
|
|
342
385
|
|
|
343
|
-
if (runtime.serverClient
|
|
386
|
+
if (runtime.serverClient) {
|
|
344
387
|
try {
|
|
345
|
-
runtime.serverClient.
|
|
388
|
+
if (typeof runtime.serverClient.stop === "function") {
|
|
389
|
+
runtime.serverClient.stop();
|
|
390
|
+
} else if (typeof runtime.serverClient.disconnect === "function") {
|
|
391
|
+
runtime.serverClient.disconnect();
|
|
392
|
+
}
|
|
346
393
|
console.log("[AICQ Channel] WebSocket disconnected");
|
|
347
394
|
} catch (e) {
|
|
348
395
|
console.warn("[AICQ Channel] Disconnect error:", e.message);
|
|
@@ -391,7 +438,7 @@ _plugin.config = {
|
|
|
391
438
|
if (section.accountId) {
|
|
392
439
|
return resolveTemplateVar(cfg, section.accountId);
|
|
393
440
|
}
|
|
394
|
-
return
|
|
441
|
+
return OPENCLAW_DEFAULT_AGENT_ID;
|
|
395
442
|
},
|
|
396
443
|
|
|
397
444
|
/**
|
package/src/ui-routes.js
CHANGED
|
File without changes
|