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.
- package/README.md +1 -1
- package/data/evolclaw.sample.json +30 -8
- package/dist/agents/claude-runner.js +13 -1
- package/dist/agents/codex-runner.js +22 -13
- package/dist/channels/aun.js +2 -1
- package/dist/channels/dingtalk.js +4 -3
- package/dist/channels/feishu.js +2 -1
- package/dist/channels/qqbot.js +2 -1
- package/dist/channels/wecom.js +2 -1
- package/dist/cli.js +9 -32
- package/dist/config.js +26 -1
- package/dist/core/command-handler.js +76 -14
- package/dist/core/message/message-processor.js +103 -85
- package/dist/core/message/stream-flusher.js +18 -2
- package/dist/core/session/session-manager.js +72 -21
- package/dist/index.js +25 -2
- package/dist/utils/init-channel.js +78 -16
- package/dist/utils/init.js +7 -4
- package/evolclaw-install-aun.md +102 -4
- package/package.json +8 -7
|
@@ -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
|
-
// 最低 @
|
|
568
|
-
const MIN_AUN_CORE_SDK = [0, 2,
|
|
569
|
-
const AUN_CORE_SDK_PKG = '@
|
|
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('@
|
|
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
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
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
|
-
|
|
814
|
-
aid
|
|
815
|
-
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');
|
package/dist/utils/init.js
CHANGED
|
@@ -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('正在安装 @
|
|
412
|
-
await npmInstallGlobal('@
|
|
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('@
|
|
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
|
-
|
|
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}. 添加新机器人`);
|
package/evolclaw-install-aun.md
CHANGED
|
@@ -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.
|
|
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
|
-
"@
|
|
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
|
-
"
|
|
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",
|