aicq-chat-plugin 3.2.2 → 3.4.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
@@ -3,193 +3,77 @@
3
3
  *
4
4
  * Architecture: Channel (in-process, no independent port)
5
5
  * - Runs inside the OpenClaw process
6
- * - Uses createChatChannelPlugin for E2EE chat channel
7
- * - Provides Gateway HTTP routes for the SPA UI
6
+ * - Uses defineChannelPluginEntry from the official Channel Plugin SDK
7
+ * - Provides Gateway RPC methods for the SPA UI and agent tools
8
8
  * - No sidecar process needed
9
+ *
10
+ * ESM module — this file IS the openclaw extension entry.
9
11
  */
10
- const path = require('path');
11
- const fs = require('fs');
12
- const os = require('os');
13
12
 
14
- // ── Configuration ──────────────────────────────────────────────────
15
- const DATA_DIR = process.env.AICQ_DATA_DIR || path.join(os.homedir(), '.aicq-plugin');
16
- const SERVER_URL = process.env.AICQ_SERVER_URL || 'https://aicq.online';
13
+ import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
14
+ import { aicqChatPlugin, runtime } from "./src/channel.js";
15
+ import { createRequire } from "module";
16
+ import path from "path";
17
+ import os from "os";
18
+ import fs from "fs";
19
+
20
+ // ── CJS interop — lib/ modules are CommonJS ──────────────────────────
21
+ const require = createRequire(import.meta.url);
22
+
23
+ // ── Configuration ────────────────────────────────────────────────────
24
+ const DATA_DIR = process.env.AICQ_DATA_DIR || path.join(os.homedir(), ".aicq-plugin");
25
+ const SERVER_URL = process.env.AICQ_SERVER_URL || "https://aicq.online";
17
26
 
18
27
  fs.mkdirSync(DATA_DIR, { recursive: true });
19
28
 
20
- // ── Lazy-loaded modules (require db init) ──────────────────────────
29
+ // ── Lazy-loaded CJS modules (need async db init) ────────────────────
21
30
  let _db = null;
22
31
  let _identity = null;
23
32
  let _serverClient = null;
24
33
  let _handshake = null;
25
34
  let _chat = null;
26
- let _channel = null;
27
- let _uiRoutes = null;
28
- let _initialized = false;
29
35
 
30
36
  /**
31
- * Initialize all plugin components (async, called once)
37
+ * Initialize all plugin components (async, called once from registerFull).
32
38
  */
33
39
  async function ensureInitialized() {
34
- if (_initialized) return;
40
+ if (runtime._initialized) return;
35
41
 
36
- const PluginDatabase = require('./lib/database');
37
- const IdentityManager = require('./lib/identity');
38
- const ServerClient = require('./lib/server-client');
39
- const HandshakeManager = require('./lib/handshake');
40
- const ChatManager = require('./lib/chat');
42
+ const PluginDatabase = require("./lib/database");
43
+ const IdentityManager = require("./lib/identity");
44
+ const ServerClient = require("./lib/server-client");
45
+ const HandshakeManager = require("./lib/handshake");
46
+ const ChatManager = require("./lib/chat");
41
47
 
42
48
  // Initialize database
43
49
  _db = new PluginDatabase(DATA_DIR);
44
50
  await _db.init();
45
- console.log('[AICQ Channel] Database initialized');
51
+ console.log("[AICQ Channel] Database initialized");
46
52
 
47
53
  // Initialize managers
48
54
  _identity = new IdentityManager(_db);
49
55
  _serverClient = new ServerClient(_identity, _db, SERVER_URL);
50
56
  _handshake = new HandshakeManager(_identity, _serverClient, _db);
51
- _chat = new ChatManager(_identity, _serverClient, _db, path.join(DATA_DIR, 'uploads'));
52
-
53
- // Load channel and UI route creators
54
- const { createAicqChannel } = require('./src/channel');
55
- const { createUiRoutes } = require('./src/ui-routes');
57
+ _chat = new ChatManager(_identity, _serverClient, _db, path.join(DATA_DIR, "uploads"));
56
58
 
57
- _channel = createAicqChannel({
58
- db: _db,
59
- identity: _identity,
60
- serverClient: _serverClient,
61
- handshake: _handshake,
62
- chat: _chat,
63
- dataDir: DATA_DIR,
64
- serverUrl: SERVER_URL,
65
- });
66
-
67
- _uiRoutes = createUiRoutes({
68
- db: _db,
69
- identity: _identity,
70
- serverClient: _serverClient,
71
- handshake: _handshake,
72
- chat: _chat,
73
- dataDir: DATA_DIR,
74
- });
59
+ // Populate the shared runtime store so channel adapters can use it
60
+ runtime.db = _db;
61
+ runtime.identity = _identity;
62
+ runtime.serverClient = _serverClient;
63
+ runtime.handshake = _handshake;
64
+ runtime.chat = _chat;
65
+ runtime.dataDir = DATA_DIR;
66
+ runtime.serverUrl = SERVER_URL;
67
+ runtime.handleGateway = handleGatewayMethod;
75
68
 
76
69
  // Periodic cleanup
77
70
  setInterval(() => _db.cleanup(), 3600000);
78
71
 
79
- _initialized = true;
80
- console.log('[AICQ Channel] Plugin components initialized');
72
+ runtime._initialized = true;
73
+ console.log("[AICQ Channel] Plugin runtime initialized");
81
74
  }
82
75
 
83
- // ── register() Called by OpenClaw when the plugin is discovered ────
84
- function register() {
85
- return {
86
- id: 'aicq-chat',
87
- name: 'AICQ Encrypted Chat',
88
- version: '3.0.0',
89
- description: 'End-to-end encrypted chat channel plugin for OpenClaw agents',
90
- kind: 'channel',
91
-
92
- // Channel configuration
93
- channel: {
94
- id: 'aicq-chat',
95
- label: 'AICQ Encrypted Chat',
96
- },
97
-
98
- // Tool definitions for OpenClaw agent use
99
- tools: {
100
- 'chat-friend': {
101
- description: 'Manage AICQ friends — list, add by friend code, remove, view requests, accept/reject requests',
102
- parameters: {
103
- type: 'object',
104
- properties: {
105
- action: {
106
- type: 'string',
107
- enum: ['list', 'add', 'remove', 'requests', 'accept', 'reject'],
108
- description: 'The friend management action to perform',
109
- },
110
- friend_code: {
111
- type: 'string',
112
- description: 'Friend code or temp number for adding a friend',
113
- },
114
- friend_id: {
115
- type: 'string',
116
- description: 'Friend ID for remove/accept/reject actions',
117
- },
118
- },
119
- required: ['action'],
120
- },
121
- },
122
- 'chat-send': {
123
- description: 'Send an encrypted message to a friend or group via AICQ',
124
- parameters: {
125
- type: 'object',
126
- properties: {
127
- targetId: {
128
- type: 'string',
129
- description: 'The friend ID or group ID to send the message to',
130
- },
131
- content: {
132
- type: 'string',
133
- description: 'The message content to send',
134
- },
135
- isGroup: {
136
- type: 'boolean',
137
- description: 'Whether the target is a group (default: false)',
138
- },
139
- },
140
- required: ['targetId', 'content'],
141
- },
142
- },
143
- 'chat-export-key': {
144
- description: 'Export your AICQ identity public key and fingerprint for sharing',
145
- parameters: {
146
- type: 'object',
147
- properties: {
148
- format: {
149
- type: 'string',
150
- enum: ['json', 'qr'],
151
- description: 'Output format: json for key data, qr for QR code image (default: json)',
152
- },
153
- },
154
- },
155
- },
156
- },
157
- };
158
- }
159
-
160
- // ── activate() — Called by OpenClaw when the plugin is enabled ───────
161
- async function activate(config) {
162
- await ensureInitialized();
163
-
164
- // Channel mode: do NOT auto-create a default agent identity.
165
- // Agent identities are created on-demand via channel.lifecycle.onAccountCreate
166
- // which is triggered when OpenClaw assigns an agent to this channel.
167
- // The resolveAccount method also handles auto-creation if needed.
168
- const agents = _identity.listAgents();
169
- let currentAgentId = agents.length > 0 ? agents[0].agent_id : null;
170
-
171
- // Only connect to AICQ server if we have an existing agent
172
- if (currentAgentId) {
173
- try {
174
- await _serverClient.start(currentAgentId);
175
- await syncFriendsFromServer(currentAgentId);
176
- await syncGroupsFromServer(currentAgentId);
177
- } catch (e) {
178
- console.error('[AICQ Channel] Initial server connection failed:', e.message);
179
- }
180
- } else {
181
- console.log('[AICQ Channel] No existing agent — will connect when an agent is assigned via channel.lifecycle.onAccountCreate');
182
- }
183
-
184
- return {
185
- handleTool,
186
- handleGateway,
187
- channel: _channel,
188
- gatewayRoutes: _uiRoutes,
189
- };
190
- }
191
-
192
- // ── Sync helpers ────────────────────────────────────────────────────
76
+ // ── Sync helpers ─────────────────────────────────────────────────────
193
77
  async function syncFriendsFromServer(agentId) {
194
78
  try {
195
79
  await _serverClient.ensureAuth(agentId);
@@ -201,10 +85,10 @@ async function syncFriendsFromServer(agentId) {
201
85
  _db.addFriend({
202
86
  agent_id: agentId,
203
87
  id: f.id,
204
- public_key: f.public_key || f.publicKey || '',
205
- fingerprint: f.fingerprint || '',
206
- friend_type: f.type || f.friend_type || 'ai',
207
- ai_name: f.agent_name || f.ai_name || f.displayName || '',
88
+ public_key: f.public_key || f.publicKey || "",
89
+ fingerprint: f.fingerprint || "",
90
+ friend_type: f.type || f.friend_type || "ai",
91
+ ai_name: f.agent_name || f.ai_name || f.displayName || "",
208
92
  });
209
93
  } else {
210
94
  _db.updateFriendOnline(agentId, f.id, f.is_online || f.isOnline || false);
@@ -212,7 +96,7 @@ async function syncFriendsFromServer(agentId) {
212
96
  }
213
97
  }
214
98
  } catch (e) {
215
- console.error('[AICQ Channel] Sync friends failed:', e.message);
99
+ console.error("[AICQ Channel] Sync friends failed:", e.message);
216
100
  }
217
101
  }
218
102
 
@@ -226,132 +110,110 @@ async function syncGroupsFromServer(agentId) {
226
110
  agent_id: agentId,
227
111
  id: g.id,
228
112
  name: g.name,
229
- owner_id: g.owner_id || g.ownerId || '',
230
- members_json: g.members || g.members_json || '[]',
231
- description: g.description || '',
113
+ owner_id: g.owner_id || g.ownerId || "",
114
+ members_json: g.members || g.members_json || "[]",
115
+ description: g.description || "",
232
116
  });
233
117
  }
234
118
  }
235
119
  } catch (e) {
236
- console.error('[AICQ Channel] Sync groups failed:', e.message);
120
+ console.error("[AICQ Channel] Sync groups failed:", e.message);
237
121
  }
238
122
  }
239
123
 
240
- // ── Tool handler ────────────────────────────────────────────────────
241
- async function handleTool(toolName, params) {
242
- await ensureInitialized();
243
- const agents = _identity.listAgents();
244
- const currentAgentId = agents.length > 0 ? agents[0].agent_id : null;
245
-
246
- switch (toolName) {
247
- case 'chat-friend': {
248
- const { action, friend_code, friend_id } = params || {};
249
- switch (action) {
250
- case 'list':
251
- return { friends: _db.listFriends(currentAgentId) };
252
- case 'add':
253
- return await _handshake.addFriendByCode(currentAgentId, friend_code);
254
- case 'remove':
255
- _db.removeFriend(currentAgentId, friend_id);
256
- try { await _serverClient.removeFriend(friend_id); } catch (e) {}
257
- return { success: true };
258
- case 'requests':
259
- return { requests: _db.getPendingRequests(currentAgentId) };
260
- case 'accept':
261
- return await _handshake.acceptRequest(currentAgentId, friend_id);
262
- case 'reject':
263
- return await _handshake.rejectRequest(currentAgentId, friend_id);
264
- default:
265
- return { error: `Unknown friend action: ${action}` };
266
- }
267
- }
268
- case 'chat-send':
269
- return await _chat.sendMessage(
270
- currentAgentId,
271
- params.targetId,
272
- params.content,
273
- { isGroup: params.isGroup || false }
274
- );
275
- case 'chat-export-key':
276
- return _identity.getInfo(currentAgentId) || {};
277
- default:
278
- return { error: `Unknown tool: ${toolName}` };
279
- }
280
- }
281
-
282
- // ── Gateway handler ─────────────────────────────────────────────────
283
- async function handleGateway(method, kwargs = {}) {
284
- await ensureInitialized();
124
+ // ── Gateway method handler ───────────────────────────────────────────
125
+ async function handleGatewayMethod(method, kwargs = {}) {
285
126
  const agents = _identity.listAgents();
286
127
  const currentAgentId = agents.length > 0 ? agents[0].agent_id : null;
287
128
 
288
129
  switch (method) {
289
- case 'aicq.status':
130
+ case "aicq.status":
290
131
  return {
291
- state: _serverClient.connected ? 'connected' : 'disconnected',
132
+ state: _serverClient.connected ? "connected" : "disconnected",
292
133
  agent_id: currentAgentId,
293
- version: '3.0.0',
294
- architecture: 'channel',
134
+ version: "3.2.0",
135
+ architecture: "channel",
295
136
  };
296
- case 'aicq.friends.list':
137
+ case "aicq.friends.list":
297
138
  return { friends: _db.listFriends(currentAgentId) };
298
- case 'aicq.friends.add':
139
+ case "aicq.friends.add":
299
140
  return await _handshake.addFriendByCode(currentAgentId, kwargs.temp_number);
300
- case 'aicq.friends.remove':
141
+ case "aicq.friends.remove":
301
142
  _db.removeFriend(currentAgentId, kwargs.friend_id);
302
143
  return { success: true };
303
- case 'aicq.friends.requests':
144
+ case "aicq.friends.requests":
304
145
  return { requests: _db.getPendingRequests(currentAgentId) };
305
- case 'aicq.friends.acceptRequest':
146
+ case "aicq.friends.acceptRequest":
306
147
  return await _handshake.acceptRequest(currentAgentId, kwargs.request_id);
307
- case 'aicq.friends.rejectRequest':
148
+ case "aicq.friends.rejectRequest":
308
149
  return await _handshake.rejectRequest(currentAgentId, kwargs.request_id);
309
- case 'aicq.identity.info':
150
+ case "aicq.identity.info":
310
151
  return _identity.getInfo(currentAgentId) || {};
311
- case 'aicq.agent.create':
152
+ case "aicq.agent.create":
312
153
  _identity.createAgent(kwargs.agent_id, kwargs.nickname);
313
154
  return { success: true };
314
- case 'aicq.agent.delete':
155
+ case "aicq.agent.delete":
315
156
  _identity.deleteAgent(kwargs.agent_id);
316
157
  return { success: true };
317
- case 'aicq.chat.send':
318
- return await _chat.sendMessage(currentAgentId, kwargs.targetId, kwargs.content, { isGroup: kwargs.isGroup });
319
- case 'aicq.chat.history':
320
- return { messages: _db.getChatHistory(currentAgentId, kwargs.targetId, { limit: kwargs.limit || 50 }) };
321
- case 'aicq.chat.delete':
158
+ case "aicq.chat.send":
159
+ return await _chat.sendMessage(currentAgentId, kwargs.targetId, kwargs.content, {
160
+ isGroup: kwargs.isGroup,
161
+ });
162
+ case "aicq.chat.history":
163
+ return {
164
+ messages: _db.getChatHistory(currentAgentId, kwargs.targetId, {
165
+ limit: kwargs.limit || 50,
166
+ }),
167
+ };
168
+ case "aicq.chat.delete":
322
169
  _db.deleteMessage(currentAgentId, kwargs.message_id);
323
170
  return { success: true };
324
- case 'aicq.chat.streamChunk': {
325
- if (!kwargs.friend_id && !kwargs.targetId) return { error: 'friend_id or targetId is required' };
326
- if (!kwargs.data) return { error: 'data is required' };
327
- const chunkType = kwargs.chunk_type || kwargs.chunkType || 'text';
328
- const ALLOWED_CHUNK_TYPES = ['text', 'reasoning', 'thinking', 'clear_text', 'tool_call', 'tool_result'];
329
- if (!ALLOWED_CHUNK_TYPES.includes(chunkType)) return { error: `Invalid chunk_type: ${chunkType}. Allowed: ${ALLOWED_CHUNK_TYPES.join(', ')}` };
171
+ case "aicq.chat.streamChunk": {
172
+ if (!kwargs.friend_id && !kwargs.targetId)
173
+ return { error: "friend_id or targetId is required" };
174
+ if (!kwargs.data) return { error: "data is required" };
175
+ const chunkType = kwargs.chunk_type || kwargs.chunkType || "text";
176
+ const ALLOWED_CHUNK_TYPES = [
177
+ "text",
178
+ "reasoning",
179
+ "thinking",
180
+ "clear_text",
181
+ "tool_call",
182
+ "tool_result",
183
+ ];
184
+ if (!ALLOWED_CHUNK_TYPES.includes(chunkType))
185
+ return {
186
+ error: `Invalid chunk_type: ${chunkType}. Allowed: ${ALLOWED_CHUNK_TYPES.join(", ")}`,
187
+ };
330
188
  const streamTarget = kwargs.friend_id || kwargs.targetId;
331
189
  const sent = _serverClient.sendWS({
332
- type: 'stream_chunk',
190
+ type: "stream_chunk",
333
191
  to: streamTarget,
334
- chunkType: chunkType,
192
+ chunkType,
335
193
  data: kwargs.data,
336
194
  });
337
- if (!sent) return { error: 'Not connected to server', success: false };
195
+ if (!sent) return { error: "Not connected to server", success: false };
338
196
  return { success: true };
339
197
  }
340
- case 'aicq.chat.streamEnd': {
341
- if (!kwargs.friend_id && !kwargs.targetId) return { error: 'friend_id or targetId is required' };
198
+ case "aicq.chat.streamEnd": {
199
+ if (!kwargs.friend_id && !kwargs.targetId)
200
+ return { error: "friend_id or targetId is required" };
342
201
  const endTarget = kwargs.friend_id || kwargs.targetId;
343
- const msgId = kwargs.message_id || kwargs.messageId || ('msg_' + Date.now() + '_' + Math.random().toString(36).substr(2, 6));
202
+ const msgId =
203
+ kwargs.message_id ||
204
+ kwargs.messageId ||
205
+ "msg_" + Date.now() + "_" + Math.random().toString(36).substr(2, 6);
344
206
  const endSent = _serverClient.sendWS({
345
- type: 'stream_end',
207
+ type: "stream_end",
346
208
  to: endTarget,
347
209
  messageId: msgId,
348
210
  });
349
- if (!endSent) return { error: 'Not connected to server', success: false };
211
+ if (!endSent) return { error: "Not connected to server", success: false };
350
212
  return { success: true, messageId: msgId };
351
213
  }
352
- case 'aicq.groups.list':
214
+ case "aicq.groups.list":
353
215
  return { groups: _db.listGroups(currentAgentId) };
354
- case 'aicq.groups.create': {
216
+ case "aicq.groups.create": {
355
217
  await _serverClient.ensureAuth(currentAgentId);
356
218
  const result = await _serverClient.createGroup(kwargs.name, kwargs.description);
357
219
  if (result.id) {
@@ -360,34 +222,106 @@ async function handleGateway(method, kwargs = {}) {
360
222
  id: result.id,
361
223
  name: kwargs.name,
362
224
  owner_id: currentAgentId,
363
- members_json: result.members || '[]',
364
- description: kwargs.description || '',
225
+ members_json: result.members || "[]",
226
+ description: kwargs.description || "",
365
227
  });
366
228
  }
367
229
  return { success: true, group: result };
368
230
  }
369
- case 'aicq.groups.join':
231
+ case "aicq.groups.join":
370
232
  await _serverClient.ensureAuth(currentAgentId);
371
233
  return await _serverClient.inviteGroupMember(kwargs.group_id, currentAgentId);
372
- case 'aicq.groups.messages': {
234
+ case "aicq.groups.messages": {
373
235
  await _serverClient.ensureAuth(currentAgentId);
374
236
  return await _serverClient.getGroupMessages(kwargs.group_id, kwargs.limit || 50);
375
237
  }
376
- case 'aicq.groups.silent':
238
+ case "aicq.groups.silent":
377
239
  _db.setGroupSilentMode(currentAgentId, kwargs.group_id, !!kwargs.silent);
378
240
  return { success: true, silent: !!kwargs.silent };
379
- case 'aicq.sessions.list':
241
+ case "aicq.sessions.list":
380
242
  return { sessions: [] };
381
243
  default:
382
244
  return { error: `Unknown method: ${method}` };
383
245
  }
384
246
  }
385
247
 
386
- // ── Exports ─────────────────────────────────────────────────────────
387
- module.exports = {
388
- register,
389
- activate,
390
- handleTool,
391
- handleGateway,
392
- ensureInitialized,
393
- };
248
+ // ── CLI metadata registration (lightweight, no runtime init) ─────────
249
+ function registerCliMetadata(api) {
250
+ api.registerCli(
251
+ ({ program }) => {
252
+ program
253
+ .command("aicq-chat")
254
+ .description("AICQ Encrypted Chat management");
255
+ },
256
+ {
257
+ descriptors: [
258
+ {
259
+ name: "aicq-chat",
260
+ description: "AICQ Encrypted Chat management",
261
+ hasSubcommands: false,
262
+ },
263
+ ],
264
+ }
265
+ );
266
+ }
267
+
268
+ // ── Full runtime registration ────────────────────────────────────────
269
+ async function registerFull(api) {
270
+ // Register gateway RPC methods — each wraps handleGatewayMethod
271
+ const GATEWAY_METHODS = [
272
+ "aicq.status",
273
+ "aicq.friends.list",
274
+ "aicq.friends.add",
275
+ "aicq.friends.remove",
276
+ "aicq.friends.requests",
277
+ "aicq.friends.acceptRequest",
278
+ "aicq.friends.rejectRequest",
279
+ "aicq.identity.info",
280
+ "aicq.agent.create",
281
+ "aicq.agent.delete",
282
+ "aicq.chat.send",
283
+ "aicq.chat.history",
284
+ "aicq.chat.delete",
285
+ "aicq.chat.streamChunk",
286
+ "aicq.chat.streamEnd",
287
+ "aicq.groups.list",
288
+ "aicq.groups.create",
289
+ "aicq.groups.join",
290
+ "aicq.groups.messages",
291
+ "aicq.groups.silent",
292
+ "aicq.sessions.list",
293
+ ];
294
+
295
+ for (const method of GATEWAY_METHODS) {
296
+ api.registerGatewayMethod(method, async (opts) => {
297
+ try {
298
+ await ensureInitialized();
299
+ const result = await handleGatewayMethod(method, opts.params || {});
300
+ opts.respond(true, result);
301
+ } catch (e) {
302
+ opts.respond(false, undefined, { message: e.message, code: "AICQ_ERROR" });
303
+ }
304
+ });
305
+ }
306
+
307
+ // Register HTTP routes for the SPA UI and REST API.
308
+ // Lazy-loaded to keep the entry narrow — the ui-routes module pulls in
309
+ // qrcode and multer which are not needed during setup-only registration.
310
+ try {
311
+ const { registerHttpRoutes } = await import("./src/ui-routes.js");
312
+ registerHttpRoutes(api, { ensureInitialized, runtime, DATA_DIR, SERVER_URL });
313
+ } catch (e) {
314
+ console.error("[AICQ Channel] Failed to register HTTP routes:", e.message);
315
+ }
316
+ }
317
+
318
+ // ── Export the entry point ───────────────────────────────────────────
319
+ export default defineChannelPluginEntry({
320
+ id: "aicq-chat",
321
+ name: "AICQ Encrypted Chat",
322
+ description:
323
+ "End-to-end encrypted chat channel plugin for OpenClaw agents — NaCl (X25519 + XSalsa20-Poly1305)",
324
+ plugin: aicqChatPlugin,
325
+ registerCliMetadata,
326
+ registerFull,
327
+ });
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -2,8 +2,8 @@
2
2
  "kind": "channel",
3
3
  "id": "aicq-chat",
4
4
  "name": "AICQ Encrypted Chat",
5
- "version": "3.2.2",
6
- "description": "End-to-end encrypted chat channel via AICQ protocol — in-process Channel plugin",
5
+ "version": "3.4.1",
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": {
9
9
  "onStartup": true
@@ -17,7 +17,6 @@
17
17
  "label": "AICQ Encrypted Chat",
18
18
  "description": "End-to-end encrypted chat channel via AICQ protocol",
19
19
  "schema": {
20
- "$schema": "http://json-schema.org/draft-07/schema#",
21
20
  "type": "object",
22
21
  "additionalProperties": false,
23
22
  "properties": {
package/package.json CHANGED
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "name": "aicq-chat-plugin",
3
- "version": "3.2.2",
4
- "description": "AICQ End-to-end Encrypted Chat Channel Plugin for OpenClaw — In-process Channel architecture with friend management, group chat, file transfer, and AI agent communication",
3
+ "version": "3.4.1",
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
+ "type": "module",
5
6
  "main": "index.js",
6
7
  "bin": {
7
- "aicq-plugin": "cli.js"
8
+ "aicq-plugin": "cli.cjs"
8
9
  },
9
10
  "files": [
10
11
  "index.js",
11
12
  "setup-entry.js",
12
- "cli.js",
13
- "postinstall.js",
13
+ "cli.cjs",
14
+ "postinstall.cjs",
14
15
  "src/",
15
16
  "lib/",
16
17
  "public/",
@@ -20,7 +21,7 @@
20
21
  ],
21
22
  "scripts": {
22
23
  "start": "node index.js",
23
- "postinstall": "node postinstall.js",
24
+ "postinstall": "node postinstall.cjs",
24
25
  "install-deps": "npm install"
25
26
  },
26
27
  "keywords": [
@@ -57,6 +58,14 @@
57
58
  "tweetnacl-util": "^0.15.1",
58
59
  "ws": "^8.16.0"
59
60
  },
61
+ "peerDependencies": {
62
+ "openclaw": ">=2026.3.24-beta.2"
63
+ },
64
+ "peerDependenciesMeta": {
65
+ "openclaw": {
66
+ "optional": true
67
+ }
68
+ },
60
69
  "engines": {
61
70
  "node": ">=18.0.0"
62
71
  },
@@ -64,6 +73,7 @@
64
73
  "extensions": [
65
74
  "./index.js"
66
75
  ],
76
+ "setupEntry": "./setup-entry.js",
67
77
  "channel": {
68
78
  "id": "aicq-chat",
69
79
  "label": "AICQ Encrypted Chat",