evolclaw 2.4.0 → 2.5.0

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.
@@ -434,6 +434,8 @@ export async function cmdInit() {
434
434
  console.log(' 1. 飞书 (Feishu)');
435
435
  console.log(' 2. 微信 (WeChat)');
436
436
  console.log(' 3. AUN (AgentUnin.Network)');
437
+ console.log(' 4. 钉钉 (DingTalk)');
438
+ console.log(' 5. QQ 机器人 (QQBot)');
437
439
  const channelChoice = (await ask(rl, '请选择 [1]: ')).trim() || '1';
438
440
  if (channelChoice === '1') {
439
441
  console.log('\n飞书配置方式:');
@@ -488,11 +490,40 @@ export async function cmdInit() {
488
490
  config.channels.aun = {
489
491
  enabled: true,
490
492
  aid: result.aid,
491
- ...(result.gatewayPort && { gatewayPort: result.gatewayPort }),
492
493
  };
493
494
  channelConfigured = true;
494
495
  config.channels.defaultChannel = 'aun';
495
496
  }
497
+ else if (channelChoice === '4') {
498
+ const { runDingtalkQrFlowSimple } = await import('./init-channel.js');
499
+ const result = await runDingtalkQrFlowSimple();
500
+ if (!result) {
501
+ console.log('已取消');
502
+ return;
503
+ }
504
+ config.channels.dingtalk = {
505
+ enabled: true,
506
+ clientId: result.clientId,
507
+ clientSecret: result.clientSecret,
508
+ };
509
+ channelConfigured = true;
510
+ config.channels.defaultChannel = 'dingtalk';
511
+ }
512
+ else if (channelChoice === '5') {
513
+ const { runQQBotBindFlowSimple } = await import('./init-channel.js');
514
+ const result = await runQQBotBindFlowSimple();
515
+ if (!result) {
516
+ console.log('已取消');
517
+ return;
518
+ }
519
+ config.channels.qqbot = {
520
+ enabled: true,
521
+ appId: result.appId,
522
+ clientSecret: result.clientSecret,
523
+ };
524
+ channelConfigured = true;
525
+ config.channels.defaultChannel = 'qqbot';
526
+ }
496
527
  else {
497
528
  console.log(' 无效选择,请重新输入');
498
529
  }
@@ -514,7 +545,7 @@ export async function cmdInit() {
514
545
  * Returns the user's choice, or null if cancelled.
515
546
  */
516
547
  export async function selectInstance(rl, channelType, instances) {
517
- const typeLabel = channelType === 'feishu' ? '飞书' : channelType === 'wechat' ? '微信' : 'AUN';
548
+ const typeLabel = channelType === 'feishu' ? '飞书' : channelType === 'wechat' ? '微信' : channelType === 'dingtalk' ? '钉钉' : channelType === 'qqbot' ? 'QQ机器人' : 'AUN';
518
549
  console.log(`\n发现已有 ${typeLabel} 机器人:`);
519
550
  const letters = 'abcdefghijklmnopqrstuvwxyz';
520
551
  for (let i = 0; i < instances.length; i++) {
@@ -24,6 +24,8 @@ const ALLOWED_CDN_HOSTS = new Set([
24
24
  'novac2c.cdn.weixin.qq.com',
25
25
  'open.feishu.cn',
26
26
  'internal-api-lark-file.feishu.cn',
27
+ 'oapi.dingtalk.com',
28
+ 'api.dingtalk.com',
27
29
  ]);
28
30
  /** 私有 IP 段正则(IPv4) */
29
31
  const PRIVATE_IP_RE = /^(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.|127\.|0\.|169\.254\.|::1|fc|fd|fe80)/;
@@ -20,9 +20,6 @@ export class StatsCollector {
20
20
  eventBus.subscribe('message:interrupted', (_event) => {
21
21
  this.recordEvent({ type: 'interrupted', timestamp: Date.now() });
22
22
  });
23
- eventBus.subscribe('session:safe-mode-entered', (_event) => {
24
- this.recordEvent({ type: 'safe-mode-entered', timestamp: Date.now() });
25
- });
26
23
  eventBus.subscribe('tool:result', (event) => {
27
24
  const e = event;
28
25
  if (e.isError) {
@@ -49,7 +46,6 @@ export class StatsCollector {
49
46
  let toolErrors = 0;
50
47
  const toolErrorsByName = {};
51
48
  let interrupts = 0;
52
- let safeModeEntries = 0;
53
49
  let totalDuration = 0;
54
50
  let durationCount = 0;
55
51
  for (const event of this.events) {
@@ -79,9 +75,6 @@ export class StatsCollector {
79
75
  case 'interrupted':
80
76
  interrupts++;
81
77
  break;
82
- case 'safe-mode-entered':
83
- safeModeEntries++;
84
- break;
85
78
  }
86
79
  }
87
80
  return {
@@ -94,7 +87,6 @@ export class StatsCollector {
94
87
  toolErrors,
95
88
  toolErrorsByName,
96
89
  interrupts,
97
- safeModeEntries,
98
90
  avgResponseMs: durationCount > 0 ? totalDuration / durationCount : 0
99
91
  }
100
92
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evolclaw",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
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",
@@ -14,7 +14,7 @@
14
14
  ],
15
15
  "scripts": {
16
16
  "dev": "tsx watch src/index.ts",
17
- "build": "tsc && node -e \"const f='dist/cli.js',c=require('fs').readFileSync(f,'utf8');if(!c.startsWith('#!'))require('fs').writeFileSync(f,'#!/usr/bin/env node\\n'+c)\" && node -e \"try{require('child_process').execFileSync('chmod',['+x','dist/cli.js'])}catch{}\"",
17
+ "build": "tsc && node -e \"const f='dist/cli.js',c=require('fs').readFileSync(f,'utf8');if(!c.startsWith('#!'))require('fs').writeFileSync(f,'#!/usr/bin/env node\\n'+c)\" && node -e \"try{require('child_process').execFileSync('chmod',['+x','dist/cli.js'])}catch{}\" && node -e \"require('fs').cpSync('src/templates','dist/templates',{recursive:true,force:true})\"",
18
18
  "start": "node dist/index.js",
19
19
  "test": "vitest run",
20
20
  "test:watch": "vitest",
@@ -23,10 +23,16 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@anthropic-ai/claude-agent-sdk": "^0.2.100",
26
- "@eleans/aun-core-node": "^0.3.0",
26
+ "@eleans/aun-core-sdk": "^0.2.9",
27
27
  "@larksuiteoapi/node-sdk": "^1.59.0",
28
28
  "@openai/codex-sdk": "^0.118.0",
29
+ "@types/form-data": "^2.2.1",
30
+ "@wecom/aibot-node-sdk": "^1.0.6",
31
+ "dingtalk-stream": "^2.1.6-beta.1",
32
+ "fast-xml-parser": "^5.7.2",
33
+ "form-data": "^4.0.5",
29
34
  "image-type": "^6.0.0",
35
+ "pure-qqbot": "^2.0.0",
30
36
  "qrcode-terminal": "^0.12.0"
31
37
  },
32
38
  "devDependencies": {