evolclaw 2.5.4 → 2.5.6

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.
@@ -36,6 +36,22 @@ export async function npmInstallGlobal(pkg) {
36
36
  }
37
37
  }
38
38
  }
39
+ /** Dynamic import with auto-install fallback for optional dependencies */
40
+ export async function requireOptional(pkg, autoInstall = true) {
41
+ try {
42
+ return await import(pkg);
43
+ }
44
+ catch (e) {
45
+ if (e.code !== 'ERR_MODULE_NOT_FOUND' && e.code !== 'MODULE_NOT_FOUND')
46
+ throw e;
47
+ if (!autoInstall)
48
+ throw new Error(`依赖 ${pkg} 未安装。请运行: npm install -g ${pkg}`);
49
+ const { logger } = await import('./logger.js');
50
+ logger.info(`正在安装可选依赖 ${pkg}...`);
51
+ await npmInstallGlobal(pkg);
52
+ return await import(pkg);
53
+ }
54
+ }
39
55
  function ask(rl, question) {
40
56
  return new Promise(resolve => rl.question(question, resolve));
41
57
  }
@@ -564,9 +580,9 @@ export async function cmdInitWechat() {
564
580
  process.exit(1);
565
581
  }
566
582
  // ==================== AUN ====================
567
- // 最低 @eleans/aun-core-sdk 版本要求
568
- const MIN_AUN_CORE_SDK = [0, 2, 9];
569
- const AUN_CORE_SDK_PKG = '@eleans/aun-core-sdk';
583
+ // 最低 @agentunion/aun-node 版本要求
584
+ const MIN_AUN_CORE_SDK = [0, 2, 12];
585
+ const AUN_CORE_SDK_PKG = '@agentunion/aun-node';
570
586
  function compareVersion(a, min) {
571
587
  const parts = a.split('.').map(n => parseInt(n, 10));
572
588
  if (parts.length < 3 || parts.some(isNaN))
@@ -701,7 +717,7 @@ export async function setupAunAid(rl, _config) {
701
717
  console.log(' 正在创建 AID...');
702
718
  let failed = false;
703
719
  try {
704
- const { AUNClient } = await import('@eleans/aun-core-sdk');
720
+ const { AUNClient } = await import('@agentunion/aun-node');
705
721
  const client = new AUNClient({ aun_path: aunPath });
706
722
  // 如果用户指定了自定义端口,手动设置 gateway URL;否则让 SDK 自动发现
707
723
  if (gatewayPort) {
@@ -792,15 +808,29 @@ export async function cmdInitAun() {
792
808
  return;
793
809
  }
794
810
  const config = JSON.parse(fs.readFileSync(p.config, 'utf-8'));
795
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
796
- try {
797
- if (config.channels?.aun?.aid) {
798
- const answer = (await ask(rl, '已有 AUN 配置,是否重新配置?[y/N] ')).trim().toLowerCase();
799
- if (answer !== 'y' && answer !== 'yes') {
800
- console.log('已取消');
811
+ // Normalize existing instances and filter out placeholders
812
+ const allInstances = normalizeChannelInstances(config.channels?.aun, 'aun');
813
+ const validInstances = [];
814
+ for (let i = 0; i < allInstances.length; i++) {
815
+ const inst = allInstances[i];
816
+ if (!inst.aid || inst.aid.includes('your-') || inst.aid.includes('placeholder'))
817
+ continue;
818
+ validInstances.push({ ...inst, originalIndex: i });
819
+ }
820
+ let choice = null;
821
+ if (validInstances.length > 0) {
822
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
823
+ try {
824
+ choice = await selectInstance(rl, 'aun', validInstances);
825
+ if (choice === null)
801
826
  return;
802
- }
803
827
  }
828
+ finally {
829
+ rl.close();
830
+ }
831
+ }
832
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
833
+ try {
804
834
  if (!await checkAunEnvironment(rl)) {
805
835
  return;
806
836
  }
@@ -809,11 +839,43 @@ export async function cmdInitAun() {
809
839
  return;
810
840
  if (!config.channels)
811
841
  config.channels = {};
812
- config.channels.aun = {
813
- enabled: true,
814
- aid: result.aid,
815
- owner: result.owner,
816
- };
842
+ if (choice && choice.action === 'overwrite' && Array.isArray(config.channels.aun)) {
843
+ const idx = validInstances[choice.index]?.originalIndex ?? choice.index;
844
+ config.channels.aun[idx].aid = result.aid;
845
+ config.channels.aun[idx].owner = result.owner;
846
+ config.channels.aun[idx].enabled = true;
847
+ }
848
+ else if (choice && choice.action === 'overwrite' && !Array.isArray(config.channels.aun)) {
849
+ config.channels.aun = config.channels.aun || {};
850
+ config.channels.aun.aid = result.aid;
851
+ config.channels.aun.owner = result.owner;
852
+ config.channels.aun.enabled = true;
853
+ }
854
+ else if (choice && choice.action === 'add') {
855
+ const newInst = {
856
+ name: choice.name,
857
+ enabled: true,
858
+ aid: result.aid,
859
+ owner: result.owner,
860
+ };
861
+ if (Array.isArray(config.channels.aun)) {
862
+ config.channels.aun.push(newInst);
863
+ }
864
+ else if (config.channels.aun) {
865
+ const oldInst = { ...config.channels.aun, name: config.channels.aun.name || 'aun' };
866
+ config.channels.aun = [oldInst, newInst];
867
+ }
868
+ else {
869
+ config.channels.aun = [newInst];
870
+ }
871
+ }
872
+ else {
873
+ config.channels.aun = {
874
+ enabled: true,
875
+ aid: result.aid,
876
+ owner: result.owner,
877
+ };
878
+ }
817
879
  if (!config.channels.defaultChannel)
818
880
  config.channels.defaultChannel = 'aun';
819
881
  fs.writeFileSync(p.config, JSON.stringify(config, null, 2) + '\n');
@@ -408,14 +408,14 @@ export async function cmdInit(options) {
408
408
  // 自动安装 AUN SDK
409
409
  const { resolveAunCoreSdkPkg, npmInstallGlobal } = await import('./init-channel.js');
410
410
  if (!resolveAunCoreSdkPkg()) {
411
- console.log('正在安装 @eleans/aun-core-sdk...');
412
- await npmInstallGlobal('@eleans/aun-core-sdk@latest');
411
+ console.log('正在安装 @agentunion/aun-node...');
412
+ await npmInstallGlobal('@agentunion/aun-node@latest');
413
413
  }
414
414
  // 创建 AID(如果本地不存在)
415
415
  const aunPath = path.join(os.homedir(), '.aun');
416
416
  const aidDir = path.join(aunPath, 'AIDs', options.aunAid);
417
417
  if (!fs.existsSync(path.join(aidDir, 'private'))) {
418
- const { AUNClient } = await import('@eleans/aun-core-sdk');
418
+ const { AUNClient } = await import('@agentunion/aun-node');
419
419
  const client = new AUNClient({ aun_path: aunPath });
420
420
  // 让 SDK 通过 well-known 自动发现网关
421
421
  const result = await client.auth.createAid({ aid: options.aunAid });
@@ -625,7 +625,10 @@ export async function selectInstance(rl, channelType, instances) {
625
625
  console.log(`\n发现已有 ${typeLabel} 机器人:`);
626
626
  const letters = 'abcdefghijklmnopqrstuvwxyz';
627
627
  for (let i = 0; i < instances.length; i++) {
628
- console.log(` ${letters[i]}. ${instances[i].name}`);
628
+ const inst = instances[i];
629
+ const id = inst.aid || inst.appId || inst.botId || inst.clientId || inst.token?.slice(0, 16) || '';
630
+ const suffix = id ? ` (${id})` : '';
631
+ console.log(` ${letters[i]}. ${inst.name}${suffix}`);
629
632
  }
630
633
  const addLetter = letters[instances.length];
631
634
  console.log(` ${addLetter}. 添加新机器人`);
@@ -149,12 +149,110 @@ evolclaw restart
149
149
  evolclaw logs
150
150
  ```
151
151
 
152
- **Q: Windows 上 npm install 报 spawn EINVAL?**
153
- Node.js 24+ 的安全变更(CVE-2024-27980)导致此错误。升级到 evolclaw >= 2.5.4 即可解决。
154
- 临时方案:先手动运行 `npm install -g @eleans/aun-core-sdk`,再执行 init。
155
-
156
152
  **Q: 如何清理损坏的 AID 重新注册?**
157
153
  ```bash
158
154
  rm -rf ~/.aun/AIDs/<aid>
159
155
  evolclaw init --non-interactive --channel aun --aun-aid <aid> --aun-owner <owner>
160
156
  ```
157
+
158
+ ---
159
+
160
+ ## Windows 故障排除(自动诊断)
161
+
162
+ 以下步骤面向 AI Agent 自动执行,按 if-then 格式编写。
163
+
164
+ ### evolclaw 命令不可用
165
+
166
+ 如果 `evolclaw --version` 返回 command not found 或无法识别:
167
+
168
+ **原因**:npm 全局 bin 目录不在系统 PATH 中。
169
+
170
+ **修复**:
171
+
172
+ ```bash
173
+ # 1. 获取 npm 全局 bin 目录
174
+ npm config get prefix
175
+ # Windows 输出示例:C:\Users\<user>\AppData\Roaming\npm
176
+ # Unix 输出示例:/usr/local/
177
+
178
+ # 2. 将该目录加入 PATH
179
+ # Windows (PowerShell, 当前用户永久生效):
180
+ [Environment]::SetEnvironmentVariable("Path", "$([Environment]::GetEnvironmentVariable('Path', 'User'));C:\Users\<user>\AppData\Roaming\npm", "User")
181
+ # Unix:
182
+ echo 'export PATH="$(npm config get prefix)/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc
183
+
184
+ # 3. 验证
185
+ evolclaw --version
186
+ ```
187
+
188
+ ### SDK 找不到 Claude Code 可执行体
189
+
190
+ **症状**:`evolclaw start` 后日志出现 `spawn ENOENT`、`executable not found`、或 SDK 报 `Could not find claude-code executable`。
191
+
192
+ **原因**:Claude Code CLI 未安装,或安装后不在 PATH 中。
193
+
194
+ **修复**:
195
+
196
+ ```bash
197
+ # 1. 检查 claude 是否可用
198
+ # Windows:
199
+ where claude
200
+ # Unix:
201
+ which claude
202
+
203
+ # 2. 如果不存在,安装 Claude Code CLI
204
+ npm install -g @anthropic-ai/claude-code
205
+
206
+ # 3. 如果已安装但不在 PATH,同上一节方法将 npm 全局 bin 目录加入 PATH
207
+
208
+ # 4. 验证
209
+ claude --version
210
+ ```
211
+
212
+ 安装完成后 SDK 会自动发现 `claude` 可执行体,无需额外配置。
213
+
214
+ **备用方案**:如果因 SDK 平台包版本错位(win32-x64 二进制滞后于 SDK 主包)导致 SDK 内置可执行体不可用,但系统已有独立安装的 `claude`,可在 `~/.evolclaw/data/evolclaw.json` 中显式指定路径:
215
+
216
+ ```json
217
+ {
218
+ "agents": {
219
+ "anthropic": {
220
+ "pathToClaudeCodeExecutable": "C:\\Users\\<user>\\AppData\\Roaming\\npm\\claude.cmd"
221
+ }
222
+ }
223
+ }
224
+ ```
225
+
226
+ 此配置仅作为 SDK 自动发现失败时的 escape hatch。
227
+
228
+ ### SDK 平台包版本错位
229
+
230
+ **症状**:`npm install -g evolclaw` 成功,但启动时 SDK 报原生模块加载失败。
231
+
232
+ **诊断**:
233
+ ```bash
234
+ # 检查 SDK 主包版本
235
+ node -e "console.log(require('@anthropic-ai/claude-agent-sdk/package.json').version)"
236
+
237
+ # 检查平台包是否存在
238
+ node -e "try{require('@anthropic-ai/claude-code-win32-x64');console.log('OK')}catch(e){console.log('MISSING:',e.message)}"
239
+ ```
240
+
241
+ **修复**:确保系统有独立安装的 Claude Code CLI(`npm install -g @anthropic-ai/claude-code`),SDK 会优先使用 PATH 中的 `claude`。
242
+
243
+ ### npm install 报 spawn EINVAL
244
+
245
+ **症状**:`npm install -g evolclaw` 过程中报 `spawn EINVAL`。
246
+
247
+ **原因**:Node.js 24+ 的安全变更(CVE-2024-27980)与部分 npm 脚本不兼容。
248
+
249
+ **修复**:
250
+
251
+ ```bash
252
+ # 1. 升级到 evolclaw >= 2.5.4
253
+ npm install -g evolclaw@latest
254
+
255
+ # 2. 如仍报错,先手动安装 AUN SDK 依赖再执行 init
256
+ npm install -g @agentunion/aun-node
257
+ evolclaw init --non-interactive --channel aun --aun-aid <aid> --aun-owner <owner>
258
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evolclaw",
3
- "version": "2.5.4",
3
+ "version": "2.5.6",
4
4
  "description": "Lightweight AI Agent gateway connecting Claude Agent SDK to messaging channels (Feishu, ACP) with multi-project session management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -24,20 +24,21 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@anthropic-ai/claude-agent-sdk": "^0.2.100",
27
- "@eleans/aun-core-sdk": "^0.2.9",
27
+ "@agentunion/aun-node": "^0.2.12",
28
+ "image-type": "^6.0.0",
29
+ "qrcode-terminal": "^0.12.0"
30
+ },
31
+ "optionalDependencies": {
28
32
  "@larksuiteoapi/node-sdk": "^1.59.0",
29
33
  "@openai/codex-sdk": "^0.118.0",
30
- "@types/form-data": "^2.2.1",
31
34
  "@wecom/aibot-node-sdk": "^1.0.6",
32
35
  "dingtalk-stream": "^2.1.6-beta.1",
33
- "fast-xml-parser": "^5.7.2",
34
36
  "form-data": "^4.0.5",
35
- "image-type": "^6.0.0",
36
- "pure-qqbot": "^2.0.0",
37
- "qrcode-terminal": "^0.12.0"
37
+ "pure-qqbot": "^2.0.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^25.5.0",
41
+ "@types/form-data": "^2.2.1",
41
42
  "@types/qrcode-terminal": "^0.12.2",
42
43
  "@vitest/coverage-v8": "^4.1.0",
43
44
  "tsx": "^4.19.0",