evolclaw 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.
@@ -9,13 +9,14 @@
9
9
  "agentProgressSummaries": true
10
10
  },
11
11
  "openai": {
12
- "apiKey": "your-openai-api-key",
13
- "baseUrl": "https://api.openai.com/v1",
12
+ "apiKey": "",
13
+ "baseUrl": "",
14
14
  "model": "gpt-5.2-codex",
15
15
  "effort": "medium"
16
16
  },
17
17
  "google": {
18
18
  "apiKey": "",
19
+ "baseUrl": "",
19
20
  "model": "gemini-2.5-flash",
20
21
  "cliPath": "",
21
22
  "mode": "cli"
@@ -23,29 +24,25 @@
23
24
  "defaultAgent": "claude"
24
25
  },
25
26
  "channels": {
26
- "defaultChannel": "feishu",
27
+ "defaultChannel": "aun",
27
28
  "feishu": {
28
- "enabled": true,
29
+ "enabled": false,
29
30
  "appId": "",
30
31
  "appSecret": "",
31
- "owner": "",
32
- "flushDelay": 10,
33
- "debounce": 2,
34
- "showActivities": "dm-only"
32
+ "owner": ""
35
33
  },
36
34
  "wechat": {
37
35
  "enabled": false,
38
36
  "baseUrl": "https://ilinkai.weixin.qq.com",
39
37
  "token": "",
40
- "owner": "",
41
- "flushDelay": 3,
42
- "debounce": 2,
43
- "showActivities": "all"
38
+ "owner": ""
44
39
  },
45
40
  "aun": {
46
41
  "enabled": false,
47
- "aid": "your-agent.agentid.pub",
42
+ "aid": "",
48
43
  "owner": "",
44
+ "flushDelay": 4,
45
+ "debounce": 2,
49
46
  "showActivities": "owner-dm-only"
50
47
  }
51
48
  },
@@ -59,11 +56,6 @@
59
56
  "showActivities": "all",
60
57
  "idleMonitor": {
61
58
  "enabled": true,
62
- "timeout": 120,
63
- "safeModeThreshold": 0
64
- },
65
- "debug": {
66
- "flusherDiag": false,
67
- "aunTrace": false
59
+ "timeout": 120
68
60
  }
69
61
  }
@@ -312,11 +312,25 @@ export class AUNChannel {
312
312
  logger.info('[AUN] Agent already initialized, skipping welcome message');
313
313
  return;
314
314
  }
315
+ // Fetch owner's agent.md to derive name and validate type
316
+ const ownerInfo = await this.fetchPeerInfo(owner);
317
+ if (ownerInfo.type !== null && ownerInfo.type !== 'human') {
318
+ logger.warn(`[AUN] Owner ${owner} type is "${ownerInfo.type}" (not human). Consider using a human AID as owner.`);
319
+ }
320
+ // Name: owner agent.md name (first 12 chars) → fallback to owner AID first label (first 12 chars)
321
+ const ownerAidClean = owner.startsWith('@') ? owner.slice(1) : owner;
322
+ let ownerDisplayName;
323
+ if (ownerInfo.name) {
324
+ ownerDisplayName = ownerInfo.name.slice(0, 12);
325
+ }
326
+ else {
327
+ ownerDisplayName = ownerAidClean.split('.')[0].slice(0, 12);
328
+ }
329
+ const agentDisplayName = `${ownerDisplayName}的Evol助手`;
315
330
  // Generate new agent.md with proper fields
316
- const ownerShortId = owner.split('@')[0].slice(0, 8);
317
331
  const newAgentMd = `---
318
332
  aid: "${aid}"
319
- name: "${ownerShortId}的Evol助手"
333
+ name: "${agentDisplayName}"
320
334
  type: "codeagent"
321
335
  version: "1.0.0"
322
336
  description: "EvolClaw AI Agent Gateway - 连接 Claude/Codex 到消息通道"
@@ -327,7 +341,7 @@ tags:
327
341
  initialized: true
328
342
  ---
329
343
 
330
- # ${ownerShortId}的Evol助手
344
+ # ${agentDisplayName}
331
345
 
332
346
  EvolClaw AI Agent 网关,支持多项目会话管理和多 AI 后端切换。
333
347
  `;
package/dist/config.js CHANGED
@@ -377,11 +377,17 @@ function validateConfig(config) {
377
377
  // Feishu 配置可选,但如果配置了就要完整(支持 array / object 两种格式)
378
378
  const feishuInstances = normalizeChannelInstances(config.channels?.feishu, 'feishu');
379
379
  for (const inst of feishuInstances) {
380
+ if (inst.enabled === false)
381
+ continue;
382
+ const appId = inst.appId || '';
383
+ const appSecret = inst.appSecret || '';
384
+ if (!appId && !appSecret)
385
+ continue;
380
386
  const label = feishuInstances.length > 1 ? ` [${inst.name}]` : '';
381
- if (!inst.appId || inst.appId.startsWith('YOUR_')) {
387
+ if (!appId || appId.startsWith('YOUR_')) {
382
388
  logger.warn(`⚠ Feishu${label} appId not configured (Feishu channel will be disabled)`);
383
389
  }
384
- if (!inst.appSecret || inst.appSecret.startsWith('YOUR_')) {
390
+ if (!appSecret || appSecret.startsWith('YOUR_')) {
385
391
  logger.warn(`⚠ Feishu${label} appSecret not configured (Feishu channel will be disabled)`);
386
392
  }
387
393
  }
@@ -627,6 +627,44 @@ export function resolveAunCoreSdkPkg() {
627
627
  catch { /* not found */ }
628
628
  return null;
629
629
  }
630
+ /**
631
+ * Download AUN CA root certificate to ~/.aun/CA/root/root.crt.
632
+ * Idempotent: skips if file already exists. Returns true if a cert is on disk
633
+ * after the call (either pre-existing or freshly downloaded).
634
+ *
635
+ * Must be called BEFORE constructing any AUNClient that needs to verify
636
+ * gateway-issued certificates (e.g. for uploadAgentMd) — the SDK loads trusted
637
+ * roots from disk at client construction time and won't pick up later writes.
638
+ */
639
+ export async function downloadCaRoot(aunPath, gatewayUrl, indent = '') {
640
+ const caDir = path.join(aunPath, 'CA', 'root');
641
+ const caCertPath = path.join(caDir, 'root.crt');
642
+ if (fs.existsSync(caCertPath))
643
+ return true;
644
+ if (!gatewayUrl)
645
+ return false;
646
+ try {
647
+ fs.mkdirSync(caDir, { recursive: true });
648
+ const gwHttp = gatewayUrl.replace(/^wss?:/, 'https:').replace(/\/aun$/, '');
649
+ const resp = await fetch(`${gwHttp}/pki/chain`, { redirect: 'follow' });
650
+ if (!resp.ok) {
651
+ console.warn(`${indent}⚠ CA 根证书下载失败: HTTP ${resp.status}`);
652
+ return false;
653
+ }
654
+ const body = await resp.text();
655
+ if (!body.includes('BEGIN CERTIFICATE')) {
656
+ console.warn(`${indent}⚠ CA 根证书响应内容无效,跳过写入`);
657
+ return false;
658
+ }
659
+ fs.writeFileSync(caCertPath, body);
660
+ console.log(`${indent}✓ CA 根证书已下载`);
661
+ return true;
662
+ }
663
+ catch (e) {
664
+ console.warn(`${indent}⚠ CA 根证书下载失败: ${e},可稍后手动下载`);
665
+ return false;
666
+ }
667
+ }
630
668
  export async function checkAunEnvironment(rl) {
631
669
  console.log('\n🔍 AUN 环境检查...\n');
632
670
  const minVer = MIN_AUN_CORE_SDK.join('.');
@@ -718,7 +756,7 @@ export async function setupAunAid(rl, _config) {
718
756
  let failed = false;
719
757
  try {
720
758
  const { AUNClient } = await import('@agentunion/aun-node');
721
- const client = new AUNClient({ aun_path: aunPath });
759
+ let client = new AUNClient({ aun_path: aunPath });
722
760
  // 如果用户指定了自定义端口,手动设置 gateway URL;否则让 SDK 自动发现
723
761
  if (gatewayPort) {
724
762
  const domain = aid.split('.').slice(1).join('.');
@@ -727,26 +765,19 @@ export async function setupAunAid(rl, _config) {
727
765
  const result = await client.auth.createAid({ aid });
728
766
  console.log(` ✓ AID ${result.aid} 创建成功`);
729
767
  // 下载 CA 根证书(如果本地不存在),从 SDK 返回的实际网关 URL 派生
730
- const caDir = path.join(aunPath, 'CA', 'root');
731
- const caCertPath = path.join(caDir, 'root.crt');
732
- if (!fs.existsSync(caCertPath) && result.gateway) {
768
+ const caDownloaded = await downloadCaRoot(aunPath, result.gateway || '', ' ');
769
+ // 关键:SDK 默认 rootCaPath=null,只读取包内 bundled certs。
770
+ // 必须显式传 root_ca_path 指向刚下载的 root.crt,uploadAgentMd 才能验证 server cert。
771
+ const caCertPath = path.join(aunPath, 'CA', 'root', 'root.crt');
772
+ if (caDownloaded && fs.existsSync(caCertPath)) {
733
773
  try {
734
- fs.mkdirSync(caDir, { recursive: true });
735
- const gwHttp = result.gateway.replace(/^wss?:/, 'https:').replace(/\/aun$/, '');
736
- const resp = await fetch(`${gwHttp}/pki/chain`, { redirect: 'follow' });
737
- if (resp.ok) {
738
- const body = await resp.text();
739
- if (body.includes('BEGIN CERTIFICATE')) {
740
- fs.writeFileSync(caCertPath, body);
741
- console.log(' ✓ CA 根证书已下载');
742
- }
743
- else {
744
- console.warn(' ⚠ CA 根证书响应内容无效,跳过写入');
745
- }
746
- }
774
+ await client.close();
747
775
  }
748
- catch (e) {
749
- console.warn(` ⚠ CA 根证书下载失败: ${e},可稍后手动下载`);
776
+ catch { /* ignore */ }
777
+ client = new AUNClient({ aun_path: aunPath, root_ca_path: caCertPath });
778
+ if (gatewayPort) {
779
+ const domain = aid.split('.').slice(1).join('.');
780
+ client._gatewayUrl = `wss://gateway.${domain}:${gatewayPort}/aun`;
750
781
  }
751
782
  }
752
783
  // Collect agent.md info and publish
@@ -760,7 +791,7 @@ export async function setupAunAid(rl, _config) {
760
791
  console.log(' ✓ agent.md 已发布');
761
792
  }
762
793
  catch (e) {
763
- console.log(` ⚠ agent.md 发布失败(可稍后用 /agentmd put 重试): ${String(e.message || e).slice(0, 100)}`);
794
+ console.log(` ⚠ agent.md 发布失败(首次连接将自动重试): ${String(e.message || e).slice(0, 100)}`);
764
795
  }
765
796
  fs.writeFileSync(agentMdPath, agentMdContent, 'utf-8');
766
797
  if (!fs.existsSync(agentMdPath)) {
@@ -406,7 +406,7 @@ export async function cmdInit(options) {
406
406
  }
407
407
  if (options.channel === 'aun' && options.aunAid) {
408
408
  // 自动安装 AUN SDK
409
- const { resolveAunCoreSdkPkg, npmInstallGlobal } = await import('./init-channel.js');
409
+ const { resolveAunCoreSdkPkg, npmInstallGlobal, downloadCaRoot } = await import('./init-channel.js');
410
410
  if (!resolveAunCoreSdkPkg()) {
411
411
  console.log('正在安装 @agentunion/aun-node...');
412
412
  await npmInstallGlobal('@agentunion/aun-node@latest');
@@ -416,31 +416,20 @@ export async function cmdInit(options) {
416
416
  const aidDir = path.join(aunPath, 'AIDs', options.aunAid);
417
417
  if (!fs.existsSync(path.join(aidDir, 'private'))) {
418
418
  const { AUNClient } = await import('@agentunion/aun-node');
419
- const client = new AUNClient({ aun_path: aunPath });
419
+ let client = new AUNClient({ aun_path: aunPath });
420
420
  // 让 SDK 通过 well-known 自动发现网关
421
421
  const result = await client.auth.createAid({ aid: options.aunAid });
422
422
  // 下载 CA 根证书(如果本地不存在),从 SDK 返回的实际网关 URL 派生
423
- const caDir = path.join(aunPath, 'CA', 'root');
424
- const caCertPath = path.join(caDir, 'root.crt');
425
- if (!fs.existsSync(caCertPath) && result.gateway) {
423
+ const caDownloaded = await downloadCaRoot(aunPath, result.gateway || '');
424
+ // 关键:SDK 默认 rootCaPath=null,只读取包内 bundled certs。
425
+ // 必须显式传 root_ca_path 指向刚下载的 root.crt,uploadAgentMd 才能验证 server cert。
426
+ const caCertPath = path.join(aunPath, 'CA', 'root', 'root.crt');
427
+ if (caDownloaded && fs.existsSync(caCertPath)) {
426
428
  try {
427
- fs.mkdirSync(caDir, { recursive: true });
428
- const gwHttp = result.gateway.replace(/^wss?:/, 'https:').replace(/\/aun$/, '');
429
- const resp = await fetch(`${gwHttp}/pki/chain`, { redirect: 'follow' });
430
- if (resp.ok) {
431
- const body = await resp.text();
432
- if (body.includes('BEGIN CERTIFICATE')) {
433
- fs.writeFileSync(caCertPath, body);
434
- console.log('✓ CA 根证书已下载');
435
- }
436
- else {
437
- console.warn('⚠ CA 根证书响应内容无效,跳过写入');
438
- }
439
- }
440
- }
441
- catch (e) {
442
- console.warn(`⚠ CA 根证书下载失败: ${e},可稍后手动下载`);
429
+ await client.close();
443
430
  }
431
+ catch { }
432
+ client = new AUNClient({ aun_path: aunPath, root_ca_path: caCertPath });
444
433
  }
445
434
  // 写入初始 agent.md(initialized: false)
446
435
  const agentName = options.aunAid.split('.')[0];
@@ -450,7 +439,7 @@ export async function cmdInit(options) {
450
439
  await client.auth.uploadAgentMd(agentMd);
451
440
  }
452
441
  catch (e) {
453
- console.warn(`⚠ agent.md 网络发布失败(可稍后重试): ${String(e?.message || e).slice(0, 100)}`);
442
+ console.warn(`⚠ agent.md 网络发布失败(首次连接将自动重试): ${String(e?.message || e).slice(0, 100)}`);
454
443
  }
455
444
  fs.writeFileSync(agentMdPath, agentMd, 'utf-8');
456
445
  if (!fs.existsSync(agentMdPath)) {
@@ -70,7 +70,7 @@ evolclaw init --non-interactive \
70
70
 
71
71
  此命令自动完成:
72
72
  1. 创建配置文件 `~/.evolclaw/data/evolclaw.json`
73
- 2. 安装 `@eleans/aun-core-sdk`
73
+ 2. 安装 `@agentunion/aun-node`
74
74
  3. 创建 AID 密钥对(如本地不存在)
75
75
  4. 下载 CA 根证书到 `~/.aun/CA/root/root.crt`
76
76
  5. 写入初始 `agent.md`(`initialized: false`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evolclaw",
3
- "version": "2.5.7",
3
+ "version": "2.5.9",
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",