evolclaw 3.0.0 → 3.1.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.
Files changed (99) hide show
  1. package/README.md +1 -1
  2. package/bin/ec.js +29 -0
  3. package/dist/agents/baseagent-normalize.js +19 -0
  4. package/dist/agents/claude-runner.js +7 -9
  5. package/dist/agents/codex-runner.js +2 -0
  6. package/dist/agents/gemini-runner.js +9 -9
  7. package/dist/agents/kit-renderer.js +281 -0
  8. package/dist/aun/aid/identity.js +28 -0
  9. package/dist/aun/aid/index.js +1 -1
  10. package/dist/aun/aid/lifecycle-log.js +33 -0
  11. package/dist/aun/msg/group.js +3 -1
  12. package/dist/aun/msg/p2p.js +4 -1
  13. package/dist/channels/aun.js +353 -125
  14. package/dist/channels/dingtalk.js +2 -1
  15. package/dist/channels/feishu.js +118 -5
  16. package/dist/channels/qqbot.js +2 -1
  17. package/dist/channels/wechat.js +3 -1
  18. package/dist/channels/wecom.js +2 -1
  19. package/dist/cli/bench.js +1219 -0
  20. package/dist/cli/index.js +279 -19
  21. package/dist/cli/link-rules.js +245 -0
  22. package/dist/cli/net-check.js +640 -0
  23. package/dist/cli/watch-msg.js +589 -0
  24. package/dist/config-store.js +37 -5
  25. package/dist/core/channel-loader.js +23 -10
  26. package/dist/core/command-handler.js +46 -22
  27. package/dist/core/evolagent.js +5 -10
  28. package/dist/core/message/im-renderer.js +50 -44
  29. package/dist/core/message/items-formatter.js +11 -4
  30. package/dist/core/message/message-bridge.js +7 -2
  31. package/dist/core/message/message-log.js +2 -0
  32. package/dist/core/message/message-processor.js +150 -99
  33. package/dist/core/message/message-queue.js +10 -3
  34. package/dist/core/permission.js +95 -3
  35. package/dist/core/session/session-manager.js +98 -64
  36. package/dist/core/trigger/scheduler.js +1 -1
  37. package/dist/data/error-dict.json +118 -0
  38. package/dist/eck/baseagent-caps.js +18 -0
  39. package/dist/eck/detect.js +47 -0
  40. package/dist/eck/init.js +77 -0
  41. package/dist/eck/rules-loader.js +28 -0
  42. package/dist/index.js +137 -16
  43. package/dist/net-check.js +640 -0
  44. package/dist/paths.js +31 -40
  45. package/dist/utils/aid-lifecycle-log.js +33 -0
  46. package/dist/utils/atomic-write.js +10 -0
  47. package/dist/utils/cross-platform.js +17 -8
  48. package/dist/utils/error-utils.js +10 -2
  49. package/dist/utils/instance-registry.js +6 -5
  50. package/dist/utils/log-writer.js +2 -1
  51. package/dist/utils/logger.js +10 -0
  52. package/dist/utils/npm-ops.js +35 -3
  53. package/dist/utils/process-introspect.js +16 -38
  54. package/dist/watch-msg.js +26 -11
  55. package/evolclaw-install-aun.md +14 -2
  56. package/kits/docs/GUIDE.md +20 -0
  57. package/kits/docs/INDEX.md +52 -0
  58. package/kits/docs/aun/CHEATSHEET.md +17 -0
  59. package/kits/docs/aun/SYNC_PROTOCOL.md +15 -0
  60. package/kits/docs/channels/feishu.md +27 -0
  61. package/kits/docs/eck_templates/GUIDE.template.md +22 -0
  62. package/kits/docs/eck_templates/INDEX.template.md +28 -0
  63. package/kits/docs/eck_templates/path-registry.template.md +33 -0
  64. package/kits/docs/eck_templates/runtime.template.md +19 -0
  65. package/kits/docs/evolclaw/MSG_GROUP.md +30 -0
  66. package/kits/docs/evolclaw/MSG_PRIVATE.md +25 -0
  67. package/kits/docs/identity/AID_PROFILE_SPEC.md +27 -0
  68. package/kits/docs/identity/PATH_OPS.md +16 -0
  69. package/kits/docs/identity/ROLE_DETAIL.md +20 -0
  70. package/kits/docs/path-registry.md +43 -0
  71. package/kits/eck_manifest.json +95 -0
  72. package/kits/rules/01-overview.md +120 -0
  73. package/kits/rules/02-navigation.md +75 -0
  74. package/kits/rules/03-identity.md +34 -0
  75. package/kits/rules/04-relation.md +49 -0
  76. package/kits/rules/05-venue.md +45 -0
  77. package/kits/rules/06-channel.md +43 -0
  78. package/kits/templates/system-fragments/baseagent.md +2 -0
  79. package/kits/templates/system-fragments/channel.md +10 -0
  80. package/kits/templates/system-fragments/identity.md +12 -0
  81. package/kits/templates/system-fragments/relation.md +9 -0
  82. package/kits/templates/system-fragments/runtime.md +19 -0
  83. package/kits/templates/system-fragments/venue.md +5 -0
  84. package/package.json +7 -5
  85. package/dist/agents/templates.js +0 -122
  86. package/dist/data/prompts.md +0 -137
  87. package/kits/aun/meta.md +0 -25
  88. package/kits/aun/role.md +0 -25
  89. package/kits/templates/group.md +0 -20
  90. package/kits/templates/private.md +0 -9
  91. package/kits/templates/system-fragments/personal-context.md +0 -3
  92. package/kits/templates/system-fragments/self-intro.md +0 -5
  93. package/kits/templates/system-fragments/speaker-intro.md +0 -5
  94. package/kits/templates/system-fragments/venue-intro.md +0 -5
  95. /package/kits/{channels → docs/channels}/aun.md +0 -0
  96. /package/kits/{evolclaw/commands.md → docs/evolclaw/AGENT_CMD.md} +0 -0
  97. /package/kits/{evolclaw → docs/evolclaw}/self-summary.md +0 -0
  98. /package/kits/{evolclaw → docs/evolclaw}/tools.md +0 -0
  99. /package/kits/{evolclaw → docs/identity}/identity-tools.md +0 -0
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ClaudeSessionFileAdapter } from './core/session/adapters/claude-session-file-adapter.js';
2
2
  import { CodexSessionFileAdapter } from './core/session/adapters/codex-session-file-adapter.js';
3
3
  import { GeminiSessionFileAdapter } from './core/session/adapters/gemini-session-file-adapter.js';
4
- import { ensureDataDirs, resolvePaths, syncKitsFromPackage } from './paths.js';
4
+ import { ensureDataDirs, resolvePaths, getPackageRoot } from './paths.js';
5
5
  import { resolveAnthropicConfig } from './agents/resolve.js';
6
- import { loadDefaults, autoMigrateIfNeeded } from './config-store.js';
6
+ import { loadDefaults, autoMigrateIfNeeded, migrateIdentitiesIfNeeded } from './config-store.js';
7
7
  import { CONFIG_SCHEMA_VERSION } from './types.js';
8
8
  import { SessionManager } from './core/session/session-manager.js';
9
9
  import { ClaudeAgentPlugin } from './agents/claude-runner.js';
@@ -33,14 +33,53 @@ import { IpcServer } from './ipc.js';
33
33
  import { logger, setLogLevel } from './utils/logger.js';
34
34
  import { writeMain, removeAll, isMainWinner, scanInstances } from './utils/instance-registry.js';
35
35
  import { detectDuplicates } from './core/evolagent-registry.js';
36
- import { loadPromptTemplates } from './agents/templates.js';
36
+ import { loadKitManifest, cleanEckDebug, invalidateKitCache } from './agents/kit-renderer.js';
37
+ import { initEck } from './eck/init.js';
37
38
  import { TriggerManager } from './core/trigger/manager.js';
38
- import { TriggerScheduler } from './core/trigger/scheduler.js';
39
+ import { TriggerScheduler, calcNextFireAt } from './core/trigger/scheduler.js';
39
40
  import { agentTriggersDir } from './paths.js';
41
+ import { isLinkedInstall } from './utils/npm-ops.js';
40
42
  import path from 'path';
41
43
  import fs from 'fs';
42
44
  import os from 'os';
43
45
  import crypto from 'crypto';
46
+ import { fileURLToPath } from 'url';
47
+ /** 出站 payload 摘要(用于 channel-out.log) */
48
+ function summarizeOutboundPayload(payload) {
49
+ if (!payload)
50
+ return { kind: 'unknown' };
51
+ const s = { kind: payload.kind };
52
+ switch (payload.kind) {
53
+ case 'activity.batch':
54
+ s.itemCount = payload.items?.length ?? 0;
55
+ s.items = payload.items;
56
+ break;
57
+ case 'result.text':
58
+ s.isFinal = payload.isFinal;
59
+ s.text = payload.text;
60
+ break;
61
+ case 'result.file':
62
+ s.filePath = payload.filePath;
63
+ break;
64
+ case 'system.notice':
65
+ case 'system.error':
66
+ s.subtype = payload.subtype;
67
+ s.text = payload.text;
68
+ break;
69
+ case 'interaction':
70
+ s.interactionId = payload.interaction?.id;
71
+ s.interactionKind = payload.interaction?.kind?.kind;
72
+ break;
73
+ case 'status.started':
74
+ case 'status.completed':
75
+ case 'status.interrupted':
76
+ case 'status.error':
77
+ case 'status.timeout':
78
+ s.metadata = payload.metadata;
79
+ break;
80
+ }
81
+ return s;
82
+ }
44
83
  /**
45
84
  * 通过 adapter.send 发送系统类 payload(system.notice / system.error / 等)。
46
85
  *
@@ -54,6 +93,36 @@ import crypto from 'crypto';
54
93
  export async function sendSystemPayload(adapter, envelope, payload) {
55
94
  await adapter.send(envelope, payload);
56
95
  }
96
+ function readEvolclawVersion() {
97
+ try {
98
+ const pkg = JSON.parse(fs.readFileSync(path.join(getPackageRoot(), 'package.json'), 'utf-8'));
99
+ return pkg.version || 'unknown';
100
+ }
101
+ catch {
102
+ return 'unknown';
103
+ }
104
+ }
105
+ function readFastaunVersion() {
106
+ try {
107
+ const url = import.meta.resolve?.('@agentunion/fastaun');
108
+ if (!url)
109
+ return 'unknown';
110
+ let dir = path.dirname(fileURLToPath(url));
111
+ while (dir !== path.dirname(dir)) {
112
+ const pkgPath = path.join(dir, 'package.json');
113
+ if (fs.existsSync(pkgPath)) {
114
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
115
+ if (pkg.name === '@agentunion/fastaun')
116
+ return pkg.version || 'unknown';
117
+ }
118
+ dir = path.dirname(dir);
119
+ }
120
+ return 'unknown';
121
+ }
122
+ catch {
123
+ return 'unknown';
124
+ }
125
+ }
57
126
  async function main() {
58
127
  // 过滤飞书 SDK 的 info 日志
59
128
  const originalLog = console.log;
@@ -72,11 +141,9 @@ async function main() {
72
141
  return;
73
142
  originalInfo(...args);
74
143
  };
75
- logger.info('EvolClaw starting...');
144
+ logger.info(`EvolClaw v${readEvolclawVersion()} starting... (fastaun v${readFastaunVersion()})`);
76
145
  // 确保数据目录存在
77
146
  ensureDataDirs();
78
- // 同步包内 kits/ 到 EVOLCLAW_HOME/kits/(首次启动或升级时)
79
- syncKitsFromPackage();
80
147
  // ── 单实例保护(pre-check + post-write self-check)──
81
148
  // pre-check:发现已有活 main 直接退出,避免起任何副作用
82
149
  {
@@ -104,16 +171,20 @@ async function main() {
104
171
  process.exit(0);
105
172
  }
106
173
  }
107
- // 加载提示词模板
108
- loadPromptTemplates();
174
+ // ── 自动迁移 ──
175
+ migrateIdentitiesIfNeeded();
176
+ autoMigrateIfNeeded();
177
+ // ── ECK 运行时初始化 ──
178
+ initEck();
179
+ // 加载 ECK manifest + 清理旧调试文件
180
+ cleanEckDebug();
181
+ loadKitManifest();
109
182
  // 加载配置(新结构:defaults.json + per-agent config.json)
110
183
  const defaults = loadDefaults() ?? { $schema_version: CONFIG_SCHEMA_VERSION };
111
184
  // 应用配置中的日志级别(优先于环境变量)
112
185
  // logLevel 现在不在新结构中——若要保留,将来可加 defaults.debug.logLevel
113
186
  // 阶段 2c 暂跳过
114
187
  const paths = resolvePaths();
115
- // ── 自动迁移:旧 data/evolclaw.json → 新结构 ──
116
- autoMigrateIfNeeded();
117
188
  // ── EvolAgent Registry:加载 agents/<aid>/config.json ──
118
189
  const agentRegistry = new EvolAgentRegistry(paths.agentsDir);
119
190
  agentRegistry.loadAll();
@@ -361,6 +432,49 @@ async function main() {
361
432
  if (primaryAgentForTrigger?.triggerScheduler && primaryAgentForTrigger?.triggerManager) {
362
433
  cmdHandler.setTriggerScheduler(primaryAgentForTrigger.triggerScheduler, primaryAgentForTrigger.triggerManager);
363
434
  }
435
+ // Seed default __upgrade-check trigger (daily at random time 3:00~3:59)
436
+ // 用户可通过 /trigger cancel __upgrade-check 永久禁用(不会再自动重建)
437
+ if (!isLinkedInstall() && primaryAgentForTrigger?.triggerManager && primaryAgentForTrigger?.triggerScheduler) {
438
+ const mgr = primaryAgentForTrigger.triggerManager;
439
+ const sched = primaryAgentForTrigger.triggerScheduler;
440
+ const UPGRADE_TRIGGER_NAME = '__upgrade-check';
441
+ if (!mgr.getByName(UPGRADE_TRIGGER_NAME)) {
442
+ // Check history: if user cancelled it before, respect that decision
443
+ const { history } = mgr.listAll();
444
+ const wasCancelled = history.some(h => h.name === UPGRADE_TRIGGER_NAME && h.doneReason === 'cancelled');
445
+ if (!wasCancelled) {
446
+ // Random minute in 3:00~3:59 to avoid all instances hitting registry simultaneously
447
+ const randomMinute = Math.floor(Math.random() * 60);
448
+ const cronExpr = `${randomMinute} 3 * * *`;
449
+ // Use first channel instance as target (command doesn't need real channelId)
450
+ const firstChannel = channelInstances[0]?.adapter?.channelName || 'system';
451
+ const trigger = {
452
+ id: crypto.randomUUID(),
453
+ name: UPGRADE_TRIGGER_NAME,
454
+ scheduleType: 'cron',
455
+ scheduleValue: cronExpr,
456
+ nextFireAt: calcNextFireAt('cron', cronExpr),
457
+ targetChannel: firstChannel,
458
+ targetChannelId: '__system__',
459
+ targetSessionStrategy: 'silent',
460
+ prompt: '检查 evolclaw 是否有新版本可用。执行 `npm view evolclaw version` 获取最新版本,与当前版本(执行 `evolclaw --version`)对比。如果有新版本,执行 /restart 进行升级。如果已是最新版本,无需任何操作。',
461
+ createdByPeerId: '__system__',
462
+ createdByChannel: '__system__',
463
+ fireCount: 0,
464
+ createdAt: Date.now(),
465
+ updatedAt: Date.now(),
466
+ };
467
+ try {
468
+ mgr.register(trigger);
469
+ sched.register(trigger);
470
+ logger.info(`[Trigger] Seeded default trigger: ${UPGRADE_TRIGGER_NAME} (cron ${cronExpr})`);
471
+ }
472
+ catch (e) {
473
+ logger.warn(`[Trigger] Failed to seed ${UPGRADE_TRIGGER_NAME}: ${e}`);
474
+ }
475
+ }
476
+ }
477
+ }
364
478
  // 默认策略
365
479
  const defaultPolicy = {
366
480
  canSwitchProject: (chatType, role) => chatType === 'private' ? (role === 'owner' || role === 'admin') : role === 'owner',
@@ -378,6 +492,12 @@ async function main() {
378
492
  msgBridge.setAgentRegistry(agentRegistry);
379
493
  // ── Channel instance registration (shared by startup and hot-load) ──
380
494
  function registerChannelInstance(inst) {
495
+ // 0. 包装 adapter.send,记录所有出站到 channel-out.log
496
+ const originalSend = inst.adapter.send.bind(inst.adapter);
497
+ inst.adapter.send = async (envelope, payload) => {
498
+ logger.channelOut({ channel: inst.adapter.channelName, channelId: envelope.channelId, taskId: envelope.taskId, payload: summarizeOutboundPayload(payload) });
499
+ return originalSend(envelope, payload);
500
+ };
381
501
  // 1. 项目路径提供器
382
502
  if (inst.onProjectPathRequest && inst.channel.onProjectPathRequest) {
383
503
  inst.channel.onProjectPathRequest(async (channelId) => {
@@ -435,6 +555,10 @@ async function main() {
435
555
  agent.status = 'running';
436
556
  }
437
557
  }
558
+ // 写入 ready 信号(核心服务已就绪,channel 连接不阻塞启动判定)
559
+ const readySignalPath = resolvePaths().readySignal;
560
+ fs.writeFileSync(readySignalPath, String(Date.now()));
561
+ logger.info(`✓ Ready signal written: ${readySignalPath}`);
438
562
  // ── 连接所有渠道(异步,AUN 等 WebSocket 渠道在后台重连)──
439
563
  const connected = await channelLoader.connectAll(channelInstances);
440
564
  // 预填充 Feishu 已知 thread_id(重启后避免误判话题创建)
@@ -631,10 +755,6 @@ async function main() {
631
755
  logger.error('[Restart] Failed to send restart notification:', e);
632
756
  }
633
757
  }
634
- // 写入 ready 信号,供 restart-monitor 检测启动成功
635
- const readySignalPath = resolvePaths().readySignal;
636
- fs.writeFileSync(readySignalPath, String(Date.now()));
637
- logger.info(`✓ Ready signal written: ${readySignalPath}`);
638
758
  // IPC server — 供 CLI 查询实时状态 + Agent ctl 指令执行
639
759
  const ipcServer = new IpcServer(resolvePaths().socket, () => {
640
760
  const channels = {};
@@ -784,7 +904,8 @@ async function main() {
784
904
  results.push(`⚠ ${cfg.aid}: ${e?.message || e}`);
785
905
  }
786
906
  }
787
- // 重建 channel index
907
+ // 重建 channel index + 清除 kit 缓存
908
+ invalidateKitCache();
788
909
  agentRegistry.channelIndex.clear();
789
910
  agentRegistry.buildChannelIndex();
790
911
  logger.info(`[Resync] Done: ${results.length} agent(s) processed`);