aicq-chat-plugin 2.5.7 → 2.5.9

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/extension.js CHANGED
@@ -5,96 +5,32 @@
5
5
  * It does NOT require native dependencies (better-sqlite3) which need C++ compilation.
6
6
  *
7
7
  * The actual chat server runs as a **sidecar** process (node index.js) on port 6109.
8
- * This extension just registers the plugin and proxies tool calls to the sidecar.
8
+ * This extension registers the plugin and proxies tool calls to the sidecar.
9
+ *
10
+ * OpenClaw expects `register()` and `activate()` exports from extension modules.
11
+ *
12
+ * NOTE: This file intentionally avoids process.env access to pass OpenClaw's
13
+ * security scanner (which flags env access + network send as a dangerous pattern).
14
+ * Configuration comes from OpenClaw's config system via activate(config).
9
15
  */
10
16
  const http = require('http');
17
+ const path = require('path');
11
18
 
12
- const SIDECAR_PORT = parseInt(process.env.AICQ_PORT || '6109', 10);
19
+ // Default port can be overridden via activate(config)
20
+ const DEFAULT_SIDECAR_PORT = 6109;
13
21
  const SIDECAR_HOST = '127.0.0.1';
14
22
 
15
- // ── Plugin metadata ──────────────────────────────────────────────────
16
- module.exports = {
17
- id: 'aicq-chat',
18
- name: 'AICQ Encrypted Chat',
19
- version: '2.5.7',
20
- description: 'End-to-end encrypted chat plugin for OpenClaw agents',
21
-
22
- // Sidecar configuration — OpenClaw starts this process automatically
23
- sidecar: {
24
- command: 'node',
25
- args: ['index.js'],
26
- port: SIDECAR_PORT,
27
- },
28
-
29
- // Tool definitions for OpenClaw agent use
30
- tools: {
31
- 'chat-friend': {
32
- description: 'Manage AICQ friends — list, add by friend code, remove, view requests, accept/reject requests',
33
- parameters: {
34
- type: 'object',
35
- properties: {
36
- action: {
37
- type: 'string',
38
- enum: ['list', 'add', 'remove', 'requests', 'accept', 'reject'],
39
- description: 'The friend management action to perform',
40
- },
41
- friend_code: {
42
- type: 'string',
43
- description: 'Friend code or temp number for adding a friend',
44
- },
45
- friend_id: {
46
- type: 'string',
47
- description: 'Friend ID for remove/accept/reject actions',
48
- },
49
- },
50
- required: ['action'],
51
- },
52
- },
53
- 'chat-send': {
54
- description: 'Send an encrypted message to a friend or group via AICQ',
55
- parameters: {
56
- type: 'object',
57
- properties: {
58
- targetId: {
59
- type: 'string',
60
- description: 'The friend ID or group ID to send the message to',
61
- },
62
- content: {
63
- type: 'string',
64
- description: 'The message content to send',
65
- },
66
- isGroup: {
67
- type: 'boolean',
68
- description: 'Whether the target is a group (default: false)',
69
- },
70
- },
71
- required: ['targetId', 'content'],
72
- },
73
- },
74
- 'chat-export-key': {
75
- description: 'Export your AICQ identity public key and fingerprint for sharing',
76
- parameters: {
77
- type: 'object',
78
- properties: {
79
- format: {
80
- type: 'string',
81
- enum: ['json', 'qr'],
82
- description: 'Output format: json for key data, qr for QR code image (default: json)',
83
- },
84
- },
85
- },
86
- },
87
- },
88
- };
23
+ // Active port set by activate() or falls back to default
24
+ let sidecarPort = DEFAULT_SIDECAR_PORT;
89
25
 
90
26
  // ── Helper: proxy a gateway call to the sidecar ──────────────────────
91
27
  function proxyToSidecar(method, kwargs) {
92
- return new Promise((resolve, reject) => {
28
+ return new Promise((resolve, _reject) => {
93
29
  const postData = JSON.stringify({ method, kwargs });
94
30
  const req = http.request(
95
31
  {
96
32
  hostname: SIDECAR_HOST,
97
- port: SIDECAR_PORT,
33
+ port: sidecarPort,
98
34
  path: '/api/gateway',
99
35
  method: 'POST',
100
36
  headers: {
@@ -116,7 +52,7 @@ function proxyToSidecar(method, kwargs) {
116
52
  }
117
53
  );
118
54
  req.on('error', (e) => {
119
- resolve({ error: `Sidecar not reachable: ${e.message}. Is the AICQ sidecar running?` });
55
+ resolve({ error: `Sidecar not reachable: ${e.message}. Is the AICQ sidecar running on port ${sidecarPort}?` });
120
56
  });
121
57
  req.on('timeout', () => {
122
58
  req.destroy();
@@ -127,11 +63,11 @@ function proxyToSidecar(method, kwargs) {
127
63
  });
128
64
  }
129
65
 
130
- // ── Tool handlers (proxy to sidecar) ─────────────────────────────────
131
- module.exports.handleTool = async function (toolName, params) {
66
+ // ── Tool handler: dispatch tool calls to sidecar ─────────────────────
67
+ async function handleTool(toolName, params) {
132
68
  switch (toolName) {
133
69
  case 'chat-friend': {
134
- const { action, friend_code, friend_id } = params;
70
+ const { action, friend_code, friend_id } = params || {};
135
71
  switch (action) {
136
72
  case 'list':
137
73
  return proxyToSidecar('aicq.friends.list', {});
@@ -151,18 +87,118 @@ module.exports.handleTool = async function (toolName, params) {
151
87
  }
152
88
  case 'chat-send':
153
89
  return proxyToSidecar('aicq.chat.send', {
154
- targetId: params.targetId,
155
- content: params.content,
156
- isGroup: params.isGroup || false,
90
+ targetId: (params || {}).targetId,
91
+ content: (params || {}).content,
92
+ isGroup: (params || {}).isGroup || false,
157
93
  });
158
94
  case 'chat-export-key':
159
95
  return proxyToSidecar('aicq.identity.info', {});
160
96
  default:
161
97
  return { error: `Unknown tool: ${toolName}` };
162
98
  }
163
- };
99
+ }
164
100
 
165
- // ── Gateway handler (proxy to sidecar via IPC or HTTP) ───────────────
166
- module.exports.handleGateway = async function (method, kwargs) {
101
+ // ── Gateway handler: proxy any gateway method to sidecar ─────────────
102
+ async function handleGateway(method, kwargs) {
167
103
  return proxyToSidecar(method, kwargs || {});
104
+ }
105
+
106
+ // ── register() — called by OpenClaw when the plugin is discovered ────
107
+ // Returns the plugin manifest (tools, sidecar config, etc.)
108
+ function register() {
109
+ return {
110
+ id: 'aicq-chat',
111
+ name: 'AICQ Encrypted Chat',
112
+ version: '2.5.9',
113
+ description: 'End-to-end encrypted chat plugin for OpenClaw agents',
114
+
115
+ // Sidecar configuration — OpenClaw starts this process automatically
116
+ sidecar: {
117
+ command: 'node',
118
+ args: [path.join(__dirname, 'index.js')],
119
+ port: DEFAULT_SIDECAR_PORT,
120
+ },
121
+
122
+ // Tool definitions for OpenClaw agent use
123
+ tools: {
124
+ 'chat-friend': {
125
+ description: 'Manage AICQ friends — list, add by friend code, remove, view requests, accept/reject requests',
126
+ parameters: {
127
+ type: 'object',
128
+ properties: {
129
+ action: {
130
+ type: 'string',
131
+ enum: ['list', 'add', 'remove', 'requests', 'accept', 'reject'],
132
+ description: 'The friend management action to perform',
133
+ },
134
+ friend_code: {
135
+ type: 'string',
136
+ description: 'Friend code or temp number for adding a friend',
137
+ },
138
+ friend_id: {
139
+ type: 'string',
140
+ description: 'Friend ID for remove/accept/reject actions',
141
+ },
142
+ },
143
+ required: ['action'],
144
+ },
145
+ },
146
+ 'chat-send': {
147
+ description: 'Send an encrypted message to a friend or group via AICQ',
148
+ parameters: {
149
+ type: 'object',
150
+ properties: {
151
+ targetId: {
152
+ type: 'string',
153
+ description: 'The friend ID or group ID to send the message to',
154
+ },
155
+ content: {
156
+ type: 'string',
157
+ description: 'The message content to send',
158
+ },
159
+ isGroup: {
160
+ type: 'boolean',
161
+ description: 'Whether the target is a group (default: false)',
162
+ },
163
+ },
164
+ required: ['targetId', 'content'],
165
+ },
166
+ },
167
+ 'chat-export-key': {
168
+ description: 'Export your AICQ identity public key and fingerprint for sharing',
169
+ parameters: {
170
+ type: 'object',
171
+ properties: {
172
+ format: {
173
+ type: 'string',
174
+ enum: ['json', 'qr'],
175
+ description: 'Output format: json for key data, qr for QR code image (default: json)',
176
+ },
177
+ },
178
+ },
179
+ },
180
+ },
181
+ };
182
+ }
183
+
184
+ // ── activate() — called by OpenClaw when the plugin is enabled ───────
185
+ // Receives config from openclaw.json and returns handlers.
186
+ // Port can be configured via the "port" field in configSchema.
187
+ function activate(config) {
188
+ // Read port from OpenClaw config (defined in configSchema)
189
+ if (config && config.port) {
190
+ sidecarPort = config.port;
191
+ }
192
+ return {
193
+ handleTool,
194
+ handleGateway,
195
+ };
196
+ }
197
+
198
+ // ── Exports ──────────────────────────────────────────────────────────
199
+ module.exports = {
200
+ register,
201
+ activate,
202
+ handleTool,
203
+ handleGateway,
168
204
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "aicq-chat",
3
3
  "name": "AICQ Encrypted Chat",
4
- "version": "2.5.7",
4
+ "version": "2.5.9",
5
5
  "description": "End-to-end encrypted chat plugin for OpenClaw agents — Node.js implementation with full UI",
6
6
  "entry": "index.js",
7
7
  "activation": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aicq-chat-plugin",
3
- "version": "2.5.7",
3
+ "version": "2.5.9",
4
4
  "description": "AICQ End-to-end Encrypted Chat Plugin for OpenClaw \u2014 Full UI with friend management, group chat, file transfer, and AI agent communication",
5
5
  "main": "index.js",
6
6
  "bin": {
package/postinstall.js CHANGED
@@ -270,7 +270,7 @@ console.log(' ╚════════════════════
270
270
  console.log('');
271
271
 
272
272
  // Read version from package.json
273
- let version = '2.5.7';
273
+ let version = '2.5.9';
274
274
  try {
275
275
  const pkg = JSON.parse(fs.readFileSync(path.join(PLUGIN_DIR, 'package.json'), 'utf8'));
276
276
  version = pkg.version;