aicq-chat-plugin 2.6.7 → 3.0.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/README.md +40 -44
- package/SKILL.md +27 -19
- package/cli.js +77 -211
- package/index.js +343 -620
- package/openclaw.plugin.json +42 -33
- package/package.json +11 -7
- package/postinstall.js +17 -346
- package/setup-entry.js +61 -0
- package/src/channel.js +163 -0
- package/src/ui-routes.js +469 -0
- package/extension.js +0 -204
package/cli.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* AICQ Chat Plugin — CLI Entry Point
|
|
3
|
+
* AICQ Chat Plugin — CLI Entry Point (v3.0 Channel)
|
|
4
4
|
*
|
|
5
5
|
* Usage:
|
|
6
6
|
* openclaw plugins install npm:aicq-chat-plugin Install via openclaw CLI
|
|
7
7
|
* openclaw plugins uninstall aicq-chat Uninstall old version
|
|
8
8
|
* openclaw gateway restart Restart gateway
|
|
9
|
-
* aicq-plugin Start plugin server
|
|
10
|
-
* aicq-plugin start Start the plugin server
|
|
9
|
+
* aicq-plugin Start plugin server (standalone mode)
|
|
10
|
+
* aicq-plugin start Start the plugin server (standalone mode)
|
|
11
11
|
* aicq-plugin install Install plugin to OpenClaw only
|
|
12
12
|
* aicq-plugin uninstall Remove plugin from OpenClaw
|
|
13
13
|
* aicq-plugin status Check plugin status
|
|
14
|
-
* aicq-plugin --
|
|
14
|
+
* aicq-plugin --server <url> Specify AICQ server URL
|
|
15
15
|
* aicq-plugin --help Show help
|
|
16
16
|
*/
|
|
17
17
|
const { spawn, execSync } = require('child_process');
|
|
@@ -23,14 +23,9 @@ const args = process.argv.slice(2);
|
|
|
23
23
|
const command = args[0] || 'start';
|
|
24
24
|
|
|
25
25
|
// Parse options
|
|
26
|
-
let port = process.env.AICQ_PORT || '6109';
|
|
27
26
|
let serverUrl = process.env.AICQ_SERVER_URL || 'https://aicq.online';
|
|
28
27
|
|
|
29
28
|
for (let i = 0; i < args.length; i++) {
|
|
30
|
-
if ((args[i] === '--port' || args[i] === '-p') && args[i + 1]) {
|
|
31
|
-
port = args[i + 1];
|
|
32
|
-
i++;
|
|
33
|
-
}
|
|
34
29
|
if ((args[i] === '--server' || args[i] === '-s') && args[i + 1]) {
|
|
35
30
|
serverUrl = args[i + 1];
|
|
36
31
|
i++;
|
|
@@ -40,7 +35,7 @@ for (let i = 0; i < args.length; i++) {
|
|
|
40
35
|
// ── SKILL.md template ─────────────────────────────────────────────
|
|
41
36
|
const SKILL_MD_TEMPLATE = `---
|
|
42
37
|
name: aicq-chat
|
|
43
|
-
description: AICQ End-to-end Encrypted Chat Plugin for OpenClaw —
|
|
38
|
+
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
|
|
44
39
|
license: MIT
|
|
45
40
|
metadata:
|
|
46
41
|
author: AICQ
|
|
@@ -49,61 +44,27 @@ metadata:
|
|
|
49
44
|
|
|
50
45
|
# AICQ Encrypted Chat
|
|
51
46
|
|
|
52
|
-
AICQ
|
|
53
|
-
|
|
54
|
-
## 功能特性
|
|
55
|
-
|
|
56
|
-
- **端到端加密 (E2EE)** — 基于 NaCl (libsodium) 的加密体系,消息仅通信双方可读
|
|
57
|
-
- **Agent 管理** — 支持多 Agent 切换、创建和删除
|
|
58
|
-
- **好友管理** — 好友码添加、QR 码扫描、好友列表同步
|
|
59
|
-
- **群组聊天** — 创建群组、邀请成员、静默模式
|
|
60
|
-
- **消息功能** — Markdown/LaTeX 渲染、图片/文件上传、@提及
|
|
61
|
-
- **密钥管理** — 公钥/私钥显示、密钥轮换、指纹验证
|
|
62
|
-
- **P2P 通信** — 握手、文本传输、文件传输
|
|
47
|
+
AICQ 是一个端到端加密聊天频道插件,基于 OpenClaw Channel 架构。支持好友管理、群组聊天、文件传输和 AI Agent 通信。
|
|
63
48
|
|
|
64
49
|
## 一键启动
|
|
65
50
|
|
|
66
51
|
\`\`\`bash
|
|
67
|
-
# 1. 卸载旧版
|
|
68
|
-
openclaw plugins uninstall aicq-chat
|
|
69
|
-
|
|
70
|
-
# 2. 安装新版
|
|
71
52
|
openclaw plugins install npm:aicq-chat-plugin
|
|
72
|
-
|
|
73
|
-
# 3. 重启 gateway
|
|
74
53
|
openclaw gateway restart
|
|
75
|
-
|
|
76
|
-
# 4. 浏览器访问聊天界面
|
|
77
|
-
open http://localhost:6109
|
|
78
54
|
\`\`\`
|
|
79
55
|
|
|
80
|
-
##
|
|
81
|
-
|
|
82
|
-
插件会自动注册为 OpenClaw sidecar,提供以下工具和网关:
|
|
83
|
-
|
|
84
|
-
### 工具
|
|
85
|
-
- \`chat-friend\` — 好友管理
|
|
86
|
-
- \`chat-send\` — 发送消息
|
|
87
|
-
- \`chat-export-key\` — 导出密钥
|
|
88
|
-
|
|
89
|
-
### 网关方法
|
|
90
|
-
- \`aicq.status\` — 插件状态
|
|
91
|
-
- \`aicq.friends.list/add/remove\` — 好友操作
|
|
92
|
-
- \`aicq.chat.send/history/delete\` — 聊天操作
|
|
93
|
-
- \`aicq.groups.list/create/join\` — 群组操作
|
|
94
|
-
- \`aicq.identity.info\` — 身份信息
|
|
95
|
-
|
|
96
|
-
## 配置
|
|
56
|
+
## 功能特性
|
|
97
57
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
58
|
+
- **端到端加密 (E2EE)** — 基于 NaCl (libsodium) 的加密体系
|
|
59
|
+
- **Channel 架构** — 进程内运行,无独立端口
|
|
60
|
+
- **好友管理** — 好友码添加、QR 码扫描
|
|
61
|
+
- **群组聊天** — 创建群组、邀请成员
|
|
62
|
+
- **流式消息** — 支持 AI 流式输出
|
|
103
63
|
|
|
104
|
-
##
|
|
64
|
+
## UI 路由
|
|
105
65
|
|
|
106
|
-
|
|
66
|
+
- /plugins/aicq-chat/ui/ — 聊天界面
|
|
67
|
+
- /plugins/aicq-chat/api/* — API 端点
|
|
107
68
|
`;
|
|
108
69
|
|
|
109
70
|
// ── Find OpenClaw installation ──────────────────────────────────────
|
|
@@ -122,34 +83,24 @@ function findOpenClawDir() {
|
|
|
122
83
|
return null;
|
|
123
84
|
}
|
|
124
85
|
|
|
125
|
-
// ── Find OpenClaw workspace
|
|
86
|
+
// ── Find OpenClaw workspace ────────────────────────────────────────
|
|
126
87
|
function findOpenClawWorkspace() {
|
|
127
|
-
// Check OPENCLAW_WORKSPACE env var first
|
|
128
88
|
if (process.env.OPENCLAW_WORKSPACE) {
|
|
129
89
|
return process.env.OPENCLAW_WORKSPACE;
|
|
130
90
|
}
|
|
131
|
-
|
|
132
|
-
// Try to find workspace from clawhub or common locations
|
|
133
|
-
// Prefer directories that already have a skills/ directory
|
|
134
91
|
const home = os.homedir();
|
|
135
92
|
const candidates = [
|
|
136
|
-
// Current working directory (most common for clawhub)
|
|
137
93
|
process.cwd(),
|
|
138
|
-
// Common workspace locations
|
|
139
94
|
path.join(home, 'my-project'),
|
|
140
95
|
path.join(home, 'openclaw'),
|
|
141
96
|
path.join(home, '.openclaw'),
|
|
142
97
|
];
|
|
143
|
-
|
|
144
|
-
// Check if any candidate has a skills/ directory (existing)
|
|
145
98
|
for (const dir of candidates) {
|
|
146
99
|
const skillsDir = path.join(dir, 'skills');
|
|
147
100
|
if (fs.existsSync(skillsDir)) {
|
|
148
101
|
return dir;
|
|
149
102
|
}
|
|
150
103
|
}
|
|
151
|
-
|
|
152
|
-
// Also check parent directories of the current working dir
|
|
153
104
|
let current = process.cwd();
|
|
154
105
|
for (let i = 0; i < 3; i++) {
|
|
155
106
|
const skillsDir = path.join(current, 'skills');
|
|
@@ -158,15 +109,10 @@ function findOpenClawWorkspace() {
|
|
|
158
109
|
}
|
|
159
110
|
current = path.dirname(current);
|
|
160
111
|
}
|
|
161
|
-
|
|
162
|
-
// If no existing skills/ found, fall back to the OpenClaw directory itself.
|
|
163
|
-
// This handles the case where ~/.openclaw/ exists but has no skills/ yet.
|
|
164
|
-
// We'll auto-create skills/ inside it during installation.
|
|
165
112
|
const openclawDir = findOpenClawDir();
|
|
166
113
|
if (openclawDir) {
|
|
167
114
|
return openclawDir;
|
|
168
115
|
}
|
|
169
|
-
|
|
170
116
|
return null;
|
|
171
117
|
}
|
|
172
118
|
|
|
@@ -188,19 +134,16 @@ function copyDirRecursive(src, dest) {
|
|
|
188
134
|
|
|
189
135
|
// ── Install plugin files to a target directory ─────────────────────
|
|
190
136
|
function installToDir(sourceDir, targetDir, version) {
|
|
191
|
-
// Files and dirs to copy
|
|
192
137
|
const filesToCopy = [
|
|
193
|
-
'index.js', 'cli.js', 'postinstall.js',
|
|
138
|
+
'index.js', 'setup-entry.js', 'cli.js', 'postinstall.js',
|
|
194
139
|
'openclaw.plugin.json', 'package.json', 'README.md',
|
|
195
140
|
];
|
|
196
|
-
const dirsToCopy = ['lib', 'public'];
|
|
141
|
+
const dirsToCopy = ['lib', 'src', 'public'];
|
|
197
142
|
|
|
198
|
-
// Create target directory if needed
|
|
199
143
|
if (!fs.existsSync(targetDir)) {
|
|
200
144
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
201
145
|
}
|
|
202
146
|
|
|
203
|
-
// Copy files
|
|
204
147
|
for (const file of filesToCopy) {
|
|
205
148
|
const src = path.join(sourceDir, file);
|
|
206
149
|
const dest = path.join(targetDir, file);
|
|
@@ -209,7 +152,6 @@ function installToDir(sourceDir, targetDir, version) {
|
|
|
209
152
|
}
|
|
210
153
|
}
|
|
211
154
|
|
|
212
|
-
// Copy directories
|
|
213
155
|
for (const dir of dirsToCopy) {
|
|
214
156
|
const src = path.join(sourceDir, dir);
|
|
215
157
|
const dest = path.join(targetDir, dir);
|
|
@@ -221,133 +163,91 @@ function installToDir(sourceDir, targetDir, version) {
|
|
|
221
163
|
}
|
|
222
164
|
}
|
|
223
165
|
|
|
224
|
-
// Generate SKILL.md with current version
|
|
225
166
|
const skillMd = SKILL_MD_TEMPLATE.replace('{VERSION}', version);
|
|
226
167
|
fs.writeFileSync(path.join(targetDir, 'SKILL.md'), skillMd, 'utf8');
|
|
227
168
|
}
|
|
228
169
|
|
|
229
|
-
// ──
|
|
170
|
+
// ── Install to OpenClaw ────────────────────────────────────────────
|
|
230
171
|
function installToOpenClaw() {
|
|
231
172
|
const PLUGIN_ID = 'aicq-chat';
|
|
232
173
|
const sourceDir = path.resolve(__dirname);
|
|
233
|
-
let version = '
|
|
174
|
+
let version = '3.0.0';
|
|
234
175
|
|
|
235
|
-
// Read version from package.json
|
|
236
176
|
try {
|
|
237
177
|
const pkg = JSON.parse(fs.readFileSync(path.join(sourceDir, 'package.json'), 'utf8'));
|
|
238
178
|
version = pkg.version;
|
|
239
179
|
} catch (e) {}
|
|
240
180
|
|
|
241
|
-
// ── Step 1: Install to OpenClaw skills/ directory ──────────────
|
|
242
|
-
// This is the primary install location — OpenClaw dashboard discovers
|
|
243
|
-
// skills by scanning skills/ directories for SKILL.md marker files.
|
|
244
181
|
let skillsInstalled = false;
|
|
245
182
|
const workspace = findOpenClawWorkspace();
|
|
246
183
|
if (workspace) {
|
|
247
184
|
const skillsDir = path.join(workspace, 'skills');
|
|
248
185
|
const skillTargetDir = path.join(skillsDir, PLUGIN_ID);
|
|
186
|
+
console.log(`[AICQ] Found workspace at: ${workspace}`);
|
|
187
|
+
console.log(`[AICQ] Installing skill to ${skillTargetDir}...`);
|
|
249
188
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if (fs.existsSync(targetSkillJson)) {
|
|
253
|
-
try {
|
|
254
|
-
const existing = JSON.parse(fs.readFileSync(targetSkillJson, 'utf8'));
|
|
255
|
-
if (existing.version === version) {
|
|
256
|
-
console.log(`[AICQ] Skill already installed at ${skillTargetDir} (v${version})`);
|
|
257
|
-
skillsInstalled = true;
|
|
258
|
-
}
|
|
259
|
-
} catch (e) {}
|
|
189
|
+
if (!fs.existsSync(skillsDir)) {
|
|
190
|
+
fs.mkdirSync(skillsDir, { recursive: true });
|
|
260
191
|
}
|
|
261
192
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
console.log('[AICQ]
|
|
274
|
-
|
|
275
|
-
execSync('npm install --omit=dev', {
|
|
276
|
-
cwd: skillTargetDir,
|
|
277
|
-
stdio: 'pipe',
|
|
278
|
-
timeout: 120000,
|
|
279
|
-
});
|
|
280
|
-
console.log('[AICQ] Skill dependencies installed.');
|
|
281
|
-
} catch (e) {
|
|
282
|
-
console.log('[AICQ] Warning: npm install failed. You may need to run manually:');
|
|
283
|
-
console.log(` cd ${skillTargetDir} && npm install`);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
console.log(`[AICQ] Skill installed to: ${skillTargetDir}`);
|
|
287
|
-
skillsInstalled = true;
|
|
193
|
+
installToDir(sourceDir, skillTargetDir, version);
|
|
194
|
+
|
|
195
|
+
console.log('[AICQ] Installing skill dependencies...');
|
|
196
|
+
try {
|
|
197
|
+
execSync('npm install --omit=dev', {
|
|
198
|
+
cwd: skillTargetDir,
|
|
199
|
+
stdio: 'pipe',
|
|
200
|
+
timeout: 120000,
|
|
201
|
+
});
|
|
202
|
+
console.log('[AICQ] Skill dependencies installed.');
|
|
203
|
+
} catch (e) {
|
|
204
|
+
console.log('[AICQ] Warning: npm install failed. You may need to run manually:');
|
|
205
|
+
console.log(` cd ${skillTargetDir} && npm install`);
|
|
288
206
|
}
|
|
207
|
+
|
|
208
|
+
console.log(`[AICQ] Skill installed to: ${skillTargetDir}`);
|
|
209
|
+
skillsInstalled = true;
|
|
289
210
|
}
|
|
290
211
|
|
|
291
|
-
// ── Step 2: Install to OpenClaw plugins/ directory ─────────────
|
|
292
|
-
// This is the secondary install location for sidecar startup.
|
|
293
|
-
// OpenClaw reads openclaw.plugin.json from plugins/ to launch sidecar.
|
|
294
212
|
let pluginInstalled = false;
|
|
295
213
|
const openclawDir = findOpenClawDir();
|
|
296
214
|
if (openclawDir) {
|
|
297
215
|
const pluginsDir = path.join(openclawDir, 'plugins');
|
|
298
216
|
const pluginTargetDir = path.join(pluginsDir, PLUGIN_ID);
|
|
299
217
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (fs.existsSync(targetPluginJson)) {
|
|
303
|
-
try {
|
|
304
|
-
const existing = JSON.parse(fs.readFileSync(targetPluginJson, 'utf8'));
|
|
305
|
-
if (existing.version === version) {
|
|
306
|
-
console.log(`[AICQ] Plugin already installed at ${pluginTargetDir} (v${version})`);
|
|
307
|
-
pluginInstalled = true;
|
|
308
|
-
}
|
|
309
|
-
} catch (e) {}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
if (!pluginInstalled) {
|
|
313
|
-
console.log(`[AICQ] Found OpenClaw at: ${openclawDir}`);
|
|
314
|
-
console.log(`[AICQ] Installing plugin to ${pluginTargetDir}...`);
|
|
315
|
-
|
|
316
|
-
if (!fs.existsSync(pluginsDir)) {
|
|
317
|
-
fs.mkdirSync(pluginsDir, { recursive: true });
|
|
318
|
-
}
|
|
218
|
+
console.log(`[AICQ] Found OpenClaw at: ${openclawDir}`);
|
|
219
|
+
console.log(`[AICQ] Installing plugin to ${pluginTargetDir}...`);
|
|
319
220
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
console.log('[AICQ] Installing plugin dependencies...');
|
|
324
|
-
try {
|
|
325
|
-
execSync('npm install --omit=dev', {
|
|
326
|
-
cwd: pluginTargetDir,
|
|
327
|
-
stdio: 'pipe',
|
|
328
|
-
timeout: 120000,
|
|
329
|
-
});
|
|
330
|
-
console.log('[AICQ] Plugin dependencies installed.');
|
|
331
|
-
} catch (e) {
|
|
332
|
-
console.log('[AICQ] Warning: npm install failed. You may need to run manually:');
|
|
333
|
-
console.log(` cd ${pluginTargetDir} && npm install`);
|
|
334
|
-
}
|
|
221
|
+
if (!fs.existsSync(pluginsDir)) {
|
|
222
|
+
fs.mkdirSync(pluginsDir, { recursive: true });
|
|
223
|
+
}
|
|
335
224
|
|
|
336
|
-
|
|
337
|
-
|
|
225
|
+
installToDir(sourceDir, pluginTargetDir, version);
|
|
226
|
+
|
|
227
|
+
console.log('[AICQ] Installing plugin dependencies...');
|
|
228
|
+
try {
|
|
229
|
+
execSync('npm install --omit=dev', {
|
|
230
|
+
cwd: pluginTargetDir,
|
|
231
|
+
stdio: 'pipe',
|
|
232
|
+
timeout: 120000,
|
|
233
|
+
});
|
|
234
|
+
console.log('[AICQ] Plugin dependencies installed.');
|
|
235
|
+
} catch (e) {
|
|
236
|
+
console.log('[AICQ] Warning: npm install failed. You may need to run manually:');
|
|
237
|
+
console.log(` cd ${pluginTargetDir} && npm install`);
|
|
338
238
|
}
|
|
239
|
+
|
|
240
|
+
console.log(`[AICQ] Plugin installed to: ${pluginTargetDir}`);
|
|
241
|
+
pluginInstalled = true;
|
|
339
242
|
}
|
|
340
243
|
|
|
341
|
-
// ── Summary ────────────────────────────────────────────────────
|
|
342
244
|
if (!skillsInstalled && !pluginInstalled) {
|
|
343
245
|
console.log('[AICQ] OpenClaw not found, skipping auto-install.');
|
|
344
|
-
console.log('[AICQ]
|
|
345
|
-
console.log('[AICQ] OPENCLAW_HOME=<openclaw-root-dir> (for plugins/ directory)');
|
|
346
|
-
console.log('[AICQ] OPENCLAW_WORKSPACE=<workspace-dir> (for skills/ directory)');
|
|
246
|
+
console.log('[AICQ] Set OPENCLAW_HOME or OPENCLAW_WORKSPACE environment variable.');
|
|
347
247
|
return false;
|
|
348
248
|
}
|
|
349
249
|
|
|
350
|
-
console.log('[AICQ] Restart OpenClaw to activate the plugin.');
|
|
250
|
+
console.log('[AICQ] Restart OpenClaw to activate the plugin (Channel mode).');
|
|
351
251
|
return true;
|
|
352
252
|
}
|
|
353
253
|
|
|
@@ -356,44 +256,38 @@ function uninstallFromOpenClaw() {
|
|
|
356
256
|
const PLUGIN_ID = 'aicq-chat';
|
|
357
257
|
let removed = false;
|
|
358
258
|
|
|
359
|
-
// Remove from skills/ directory
|
|
360
259
|
const workspace = findOpenClawWorkspace();
|
|
361
260
|
if (workspace) {
|
|
362
261
|
const skillDir = path.join(workspace, 'skills', PLUGIN_ID);
|
|
363
262
|
if (fs.existsSync(skillDir)) {
|
|
364
263
|
console.log(`[AICQ] Removing skill from ${skillDir}...`);
|
|
365
264
|
fs.rmSync(skillDir, { recursive: true, force: true });
|
|
366
|
-
console.log('[AICQ] Skill removed.');
|
|
367
265
|
removed = true;
|
|
368
266
|
}
|
|
369
267
|
}
|
|
370
268
|
|
|
371
|
-
// Remove from plugins/ directory
|
|
372
269
|
const openclawDir = findOpenClawDir();
|
|
373
270
|
if (openclawDir) {
|
|
374
271
|
const pluginDir = path.join(openclawDir, 'plugins', PLUGIN_ID);
|
|
375
272
|
if (fs.existsSync(pluginDir)) {
|
|
376
273
|
console.log(`[AICQ] Removing plugin from ${pluginDir}...`);
|
|
377
274
|
fs.rmSync(pluginDir, { recursive: true, force: true });
|
|
378
|
-
console.log('[AICQ] Plugin removed.');
|
|
379
275
|
removed = true;
|
|
380
276
|
}
|
|
381
277
|
}
|
|
382
278
|
|
|
383
279
|
if (!removed) {
|
|
384
280
|
console.log('[AICQ] AICQ plugin not found in any OpenClaw directory.');
|
|
385
|
-
console.log('[AICQ] Nothing to uninstall.');
|
|
386
281
|
} else {
|
|
387
282
|
console.log('[AICQ] Restart OpenClaw to complete the uninstall.');
|
|
388
283
|
}
|
|
389
|
-
|
|
390
284
|
return removed;
|
|
391
285
|
}
|
|
392
286
|
|
|
393
287
|
// ── Help ────────────────────────────────────────────────────────────
|
|
394
288
|
if (command === '--help' || command === '-h') {
|
|
395
289
|
console.log(`
|
|
396
|
-
AICQ Chat Plugin — End-to-End Encrypted Chat for OpenClaw
|
|
290
|
+
AICQ Chat Plugin v3.0 — End-to-End Encrypted Chat for OpenClaw (Channel)
|
|
397
291
|
|
|
398
292
|
Usage:
|
|
399
293
|
openclaw plugins install npm:aicq-chat-plugin Install plugin via openclaw CLI
|
|
@@ -402,63 +296,35 @@ Usage:
|
|
|
402
296
|
aicq-plugin [command] [options] Advanced usage
|
|
403
297
|
|
|
404
298
|
Commands:
|
|
405
|
-
start Install to OpenClaw (if needed) and start
|
|
299
|
+
start Install to OpenClaw (if needed) and start in standalone mode (default)
|
|
406
300
|
install Install plugin to OpenClaw only (don't start server)
|
|
407
301
|
uninstall Remove plugin from OpenClaw (skills/ and plugins/)
|
|
408
302
|
status Check if the plugin is running
|
|
409
303
|
|
|
410
304
|
Options:
|
|
411
|
-
--port, -p <port> Plugin server port (default: 6109)
|
|
412
305
|
--server, -s <url> AICQ server URL (default: https://aicq.online)
|
|
413
306
|
--help, -h Show this help message
|
|
414
307
|
|
|
415
308
|
Environment Variables:
|
|
416
|
-
AICQ_PORT Plugin server port
|
|
417
309
|
AICQ_SERVER_URL AICQ server URL
|
|
418
310
|
AICQ_DATA_DIR Data directory (default: ~/.aicq-plugin)
|
|
419
311
|
OPENCLAW_HOME OpenClaw installation directory (for plugins/)
|
|
420
312
|
OPENCLAW_WORKSPACE OpenClaw workspace directory (for skills/)
|
|
421
313
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
aicq-plugin uninstall # Remove from OpenClaw
|
|
428
|
-
aicq-plugin --port 8080 # Start on port 8080
|
|
429
|
-
aicq-plugin -s http://localhost # Connect to local server
|
|
314
|
+
Architecture:
|
|
315
|
+
v3.0 uses Channel architecture — runs in-process with OpenClaw.
|
|
316
|
+
No independent port needed. UI served via Gateway HTTP routes.
|
|
317
|
+
- UI: /plugins/aicq-chat/ui/
|
|
318
|
+
- API: /plugins/aicq-chat/api/*
|
|
430
319
|
`);
|
|
431
320
|
process.exit(0);
|
|
432
321
|
}
|
|
433
322
|
|
|
434
323
|
// ── Status ──────────────────────────────────────────────────────────
|
|
435
324
|
if (command === 'status') {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
res.on('data', chunk => data += chunk);
|
|
440
|
-
res.on('end', () => {
|
|
441
|
-
try {
|
|
442
|
-
const status = JSON.parse(data);
|
|
443
|
-
console.log('AICQ Plugin Status:');
|
|
444
|
-
console.log(` Version: ${status.version}`);
|
|
445
|
-
console.log(` Status: ${status.status}`);
|
|
446
|
-
console.log(` Connected: ${status.connected ? 'Yes' : 'No'}`);
|
|
447
|
-
console.log(` Agent: ${status.currentAgent || 'None'}`);
|
|
448
|
-
console.log(` Server: ${status.serverUrl}`);
|
|
449
|
-
} catch (e) {
|
|
450
|
-
console.log('Plugin is running but returned invalid status.');
|
|
451
|
-
}
|
|
452
|
-
});
|
|
453
|
-
});
|
|
454
|
-
req.on('error', () => {
|
|
455
|
-
console.log(`AICQ Plugin is not running on port ${port}.`);
|
|
456
|
-
console.log(`Start it with: openclaw plugins install npm:aicq-chat-plugin`);
|
|
457
|
-
});
|
|
458
|
-
req.setTimeout(3000, () => {
|
|
459
|
-
req.destroy();
|
|
460
|
-
console.log(`AICQ Plugin is not responding on port ${port}.`);
|
|
461
|
-
});
|
|
325
|
+
console.log('AICQ Plugin v3.0 (Channel architecture)');
|
|
326
|
+
console.log('In Channel mode, the plugin runs inside OpenClaw process.');
|
|
327
|
+
console.log('Check OpenClaw gateway status for plugin health.');
|
|
462
328
|
process.exit(0);
|
|
463
329
|
}
|
|
464
330
|
|
|
@@ -474,17 +340,17 @@ if (command === 'uninstall' || command === 'remove') {
|
|
|
474
340
|
process.exit(0);
|
|
475
341
|
}
|
|
476
342
|
|
|
477
|
-
// ── Start (default) — auto-install then run
|
|
343
|
+
// ── Start (default) — auto-install then run in standalone mode ──────
|
|
478
344
|
installToOpenClaw();
|
|
479
345
|
|
|
480
|
-
console.log(`[AICQ] Starting plugin
|
|
346
|
+
console.log(`[AICQ] Starting plugin in standalone mode`);
|
|
481
347
|
console.log(`[AICQ] Server: ${serverUrl}`);
|
|
482
348
|
|
|
483
|
-
const env = { ...process.env,
|
|
349
|
+
const env = { ...process.env, AICQ_SERVER_URL: serverUrl };
|
|
484
350
|
const child = spawn('node', [path.join(__dirname, 'index.js')], {
|
|
485
351
|
env,
|
|
486
352
|
stdio: 'inherit',
|
|
487
|
-
detached: false
|
|
353
|
+
detached: false,
|
|
488
354
|
});
|
|
489
355
|
|
|
490
356
|
child.on('error', (err) => {
|