evolclaw 2.8.3 → 3.0.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 (105) hide show
  1. package/README.md +21 -12
  2. package/dist/agents/claude-runner.js +102 -38
  3. package/dist/agents/codex-runner.js +11 -14
  4. package/dist/agents/gemini-runner.js +10 -12
  5. package/dist/agents/resolve.js +134 -0
  6. package/dist/agents/templates.js +3 -3
  7. package/dist/aun/aid/agentmd.js +186 -0
  8. package/dist/aun/aid/client.js +134 -0
  9. package/dist/aun/aid/identity.js +131 -0
  10. package/dist/aun/aid/index.js +3 -0
  11. package/dist/aun/aid/types.js +1 -0
  12. package/dist/aun/aid/validation.js +21 -0
  13. package/dist/aun/msg/group.js +291 -0
  14. package/dist/aun/msg/index.js +4 -0
  15. package/dist/aun/msg/p2p.js +144 -0
  16. package/dist/aun/msg/payload-type.js +27 -0
  17. package/dist/aun/msg/upload.js +98 -0
  18. package/dist/aun/outbox.js +138 -0
  19. package/dist/aun/rpc/caller.js +42 -0
  20. package/dist/aun/rpc/connection.js +34 -0
  21. package/dist/aun/rpc/index.js +2 -0
  22. package/dist/aun/storage/download.js +29 -0
  23. package/dist/aun/storage/index.js +3 -0
  24. package/dist/aun/storage/manage.js +10 -0
  25. package/dist/aun/storage/upload.js +35 -0
  26. package/dist/channels/aun.js +1051 -288
  27. package/dist/channels/dingtalk.js +58 -5
  28. package/dist/channels/feishu.js +266 -30
  29. package/dist/channels/qqbot.js +67 -12
  30. package/dist/channels/wechat.js +61 -4
  31. package/dist/channels/wecom.js +58 -5
  32. package/dist/cli/agent.js +800 -0
  33. package/dist/cli/index.js +4253 -0
  34. package/dist/{utils → cli}/init-channel.js +211 -621
  35. package/dist/cli/init.js +178 -0
  36. package/dist/config-store.js +613 -0
  37. package/dist/core/{agent-loader.js → baseagent-loader.js} +6 -12
  38. package/dist/core/channel-loader.js +162 -11
  39. package/dist/core/command-handler.js +858 -847
  40. package/dist/core/evolagent-registry.js +191 -371
  41. package/dist/core/evolagent.js +203 -234
  42. package/dist/core/interaction-router.js +52 -5
  43. package/dist/core/message/im-renderer.js +480 -0
  44. package/dist/core/message/items-formatter.js +61 -0
  45. package/dist/core/message/message-bridge.js +104 -56
  46. package/dist/core/message/message-log.js +91 -0
  47. package/dist/core/message/message-processor.js +309 -142
  48. package/dist/core/message/message-queue.js +3 -3
  49. package/dist/core/permission.js +21 -8
  50. package/dist/core/session/adapters/codex-session-file-adapter.js +24 -2
  51. package/dist/core/session/session-fs-store.js +230 -0
  52. package/dist/core/session/session-manager.js +704 -775
  53. package/dist/core/session/session-mapper.js +87 -0
  54. package/dist/core/trigger/manager.js +122 -0
  55. package/dist/core/trigger/parser.js +128 -0
  56. package/dist/core/trigger/scheduler.js +224 -0
  57. package/dist/{templates → data}/prompts.md +34 -1
  58. package/dist/index.js +431 -275
  59. package/dist/ipc.js +49 -0
  60. package/dist/paths.js +82 -9
  61. package/dist/types.js +8 -2
  62. package/dist/utils/atomic-write.js +79 -0
  63. package/dist/utils/channel-helpers.js +46 -0
  64. package/dist/utils/cross-platform.js +0 -18
  65. package/dist/utils/instance-registry.js +433 -0
  66. package/dist/utils/log-writer.js +216 -0
  67. package/dist/utils/logger.js +24 -77
  68. package/dist/utils/media-cache.js +23 -0
  69. package/dist/utils/{upgrade.js → npm-ops.js} +52 -21
  70. package/dist/utils/process-introspect.js +144 -0
  71. package/dist/utils/stats.js +192 -0
  72. package/dist/watch-msg.js +529 -0
  73. package/evolclaw-install-aun.md +114 -46
  74. package/kits/aun/meta.md +25 -0
  75. package/kits/aun/role.md +25 -0
  76. package/kits/channels/aun.md +25 -0
  77. package/kits/evolclaw/commands.md +31 -0
  78. package/kits/evolclaw/identity-tools.md +26 -0
  79. package/kits/evolclaw/self-summary.md +29 -0
  80. package/kits/evolclaw/tools.md +25 -0
  81. package/kits/templates/group.md +20 -0
  82. package/kits/templates/private.md +9 -0
  83. package/kits/templates/system-fragments/personal-context.md +3 -0
  84. package/kits/templates/system-fragments/self-intro.md +5 -0
  85. package/kits/templates/system-fragments/speaker-intro.md +5 -0
  86. package/kits/templates/system-fragments/venue-intro.md +5 -0
  87. package/package.json +7 -5
  88. package/data/evolclaw.sample.json +0 -60
  89. package/dist/channels/aun-ops.js +0 -275
  90. package/dist/cli.js +0 -2178
  91. package/dist/config.js +0 -591
  92. package/dist/core/agent-registry.js +0 -450
  93. package/dist/core/evolagent-schema.js +0 -72
  94. package/dist/core/message/stream-flusher.js +0 -238
  95. package/dist/core/message/thought-emitter.js +0 -162
  96. package/dist/core/reload-hooks.js +0 -87
  97. package/dist/prompts/templates.js +0 -122
  98. package/dist/templates/skills.md +0 -66
  99. package/dist/utils/channel-fingerprint.js +0 -59
  100. package/dist/utils/error-dict.js +0 -63
  101. package/dist/utils/format.js +0 -32
  102. package/dist/utils/init.js +0 -645
  103. package/dist/utils/migrate-project.js +0 -122
  104. package/dist/utils/reload-hooks.js +0 -87
  105. package/dist/utils/stats-collector.js +0 -99
@@ -20,6 +20,50 @@ export class ChannelLoader {
20
20
  this.plugins.set(plugin.name, plugin);
21
21
  logger.debug(`Registered channel plugin: ${plugin.name}`);
22
22
  }
23
+ /**
24
+ * 新结构入口:从 EvolAgent 的 channels[] 列表创建 channel 实例。
25
+ *
26
+ * 内部把 ChannelInstance[] 翻成各 plugin 期望的 dict 形态(`{ type: [instances...] }`),
27
+ * 然后调用现有 plugin.createChannels / createChannel。
28
+ *
29
+ * 当所有 channel plugin 重写为直接吃 ChannelInstance[] 后,本方法可简化。
30
+ */
31
+ async createForAgent(agent) {
32
+ const rewrittenChannels = {};
33
+ // AUN channel 从 agent.aid 隐式创建——不需要在 channels[] 里显式声明
34
+ const aunEffName = agent.effectiveChannelName('aun', 'main');
35
+ rewrittenChannels['aun'] = [{
36
+ type: 'aun',
37
+ name: aunEffName,
38
+ aid: agent.aid,
39
+ enabled: true,
40
+ agentName: agent.aid,
41
+ // agent 顶层 owners[0] 透传给 AUN channel.owner(用于首次连接发欢迎消息)
42
+ owner: agent.config.owners?.[0],
43
+ }];
44
+ // 其它 channels(非 AUN)从 config.channels[] 取
45
+ for (const inst of agent.config.channels) {
46
+ if (inst.type === 'aun')
47
+ continue; // 跳过显式声明的 AUN(已隐式处理)
48
+ const effName = agent.effectiveChannelName(inst.type, inst.name);
49
+ const rewritten = { ...inst, name: effName, agentName: agent.aid };
50
+ (rewrittenChannels[inst.type] ??= []).push(rewritten);
51
+ }
52
+ // syntheticConfig 是老 Config schema(channel plugin 沿用旧接口),
53
+ // 新 schema 字段命名为 snake_case,这里转 camelCase 透传。
54
+ const syntheticConfig = {
55
+ agents: agent.config.baseagents,
56
+ channels: rewrittenChannels,
57
+ projects: agent.config.projects,
58
+ chatmode: agent.config.chatmode,
59
+ debug: agent.config.debug,
60
+ showActivities: agent.config.show_activities,
61
+ flushDelay: agent.config.flush_delay,
62
+ debounce: agent.config.debounce,
63
+ enableRichContent: agent.config.enable_rich_content,
64
+ };
65
+ return this.createAll(syntheticConfig);
66
+ }
23
67
  async createAll(config) {
24
68
  const instances = [];
25
69
  for (const [name, plugin] of this.plugins) {
@@ -45,17 +89,21 @@ export class ChannelLoader {
45
89
  }
46
90
  return instances;
47
91
  }
48
- async connectAll(instances) {
49
- const results = await Promise.allSettled(instances.map(async (inst) => {
50
- await inst.connect();
51
- return inst.adapter.channelName;
52
- }));
53
- const connected = results
54
- .filter((r) => r.status === 'fulfilled')
55
- .map((r) => r.value);
56
- const failed = results
57
- .filter((r) => r.status === 'rejected')
58
- .map((r) => r.reason);
92
+ async connectAll(instances, delayMs = 150) {
93
+ const connected = [];
94
+ const failed = [];
95
+ for (const inst of instances) {
96
+ try {
97
+ await inst.connect();
98
+ connected.push(inst.adapter.channelName);
99
+ }
100
+ catch (e) {
101
+ failed.push(e);
102
+ }
103
+ if (delayMs > 0 && inst !== instances[instances.length - 1]) {
104
+ await new Promise(r => setTimeout(r, delayMs));
105
+ }
106
+ }
59
107
  if (failed.length > 0) {
60
108
  logger.warn(`Some channels failed to connect:`, failed);
61
109
  }
@@ -65,3 +113,106 @@ export class ChannelLoader {
65
113
  await Promise.allSettled(instances.map((inst) => inst.disconnect()));
66
114
  }
67
115
  }
116
+ const SEP = '#';
117
+ export function formatChannelKey(k) {
118
+ return `${k.aid}${SEP}${k.type}${SEP}${k.name}`;
119
+ }
120
+ export function parseChannelKey(key) {
121
+ const parts = key.split(SEP);
122
+ if (parts.length !== 3) {
123
+ throw new Error(`Invalid channel key (expected 3 segments separated by '#'): ${key}`);
124
+ }
125
+ const [aid, type, name] = parts;
126
+ if (!aid || !type || !name) {
127
+ throw new Error(`Invalid channel key (empty segment): ${key}`);
128
+ }
129
+ return { aid, type, name };
130
+ }
131
+ export function tryParseChannelKey(key) {
132
+ try {
133
+ return parseChannelKey(key);
134
+ }
135
+ catch {
136
+ return null;
137
+ }
138
+ }
139
+ export function isValidChannelName(name) {
140
+ return typeof name === 'string' && name.length > 0 && !name.includes(SEP);
141
+ }
142
+ export function buildReloadHooks(deps) {
143
+ const { channelLoader, channelInstances, registerChannelInstance, messageQueue } = deps;
144
+ const drainDelayMs = deps.drainDelayMs ?? 500;
145
+ const drainTimeoutMs = deps.drainTimeoutMs ?? 30000;
146
+ return {
147
+ async drainChannel(channelName) {
148
+ logger.info(`[Reload] Draining channel: ${channelName}`);
149
+ if (messageQueue) {
150
+ const pollMs = 100;
151
+ const start = Date.now();
152
+ while (messageQueue.isChannelProcessing(channelName)) {
153
+ if (Date.now() - start > drainTimeoutMs) {
154
+ logger.warn(`[Reload] Drain timeout (${drainTimeoutMs}ms) for channel: ${channelName}, proceeding anyway`);
155
+ return;
156
+ }
157
+ await new Promise(r => setTimeout(r, pollMs));
158
+ }
159
+ logger.info(`[Reload] Drain complete: ${channelName}`);
160
+ }
161
+ else if (drainDelayMs > 0) {
162
+ await new Promise(r => setTimeout(r, drainDelayMs));
163
+ }
164
+ },
165
+ async disconnectChannel(channelName) {
166
+ const inst = channelInstances.find(i => i.adapter.channelName === channelName);
167
+ if (!inst) {
168
+ logger.warn(`[Reload] Channel ${channelName} not found, skipping disconnect`);
169
+ return;
170
+ }
171
+ try {
172
+ await inst.disconnect();
173
+ const idx = channelInstances.indexOf(inst);
174
+ if (idx >= 0)
175
+ channelInstances.splice(idx, 1);
176
+ logger.info(`[Reload] Disconnected channel: ${channelName}`);
177
+ }
178
+ catch (e) {
179
+ logger.error(`[Reload] Failed to disconnect ${channelName}: ${e}`);
180
+ throw e;
181
+ }
182
+ },
183
+ async startChannel(agent, channelName) {
184
+ const channels = agent.config.channels;
185
+ let channelType = null;
186
+ for (const [type, raw] of Object.entries(channels)) {
187
+ const instances = Array.isArray(raw) ? raw : [raw];
188
+ for (const inst of instances) {
189
+ const name = inst.name ?? type;
190
+ if (name === channelName) {
191
+ channelType = type;
192
+ break;
193
+ }
194
+ }
195
+ if (channelType)
196
+ break;
197
+ }
198
+ if (!channelType) {
199
+ const msg = `[Reload] Channel ${channelName} not found in agent ${agent.name} config`;
200
+ logger.error(msg);
201
+ throw new Error(msg);
202
+ }
203
+ const partialConfig = {
204
+ agents: agent.config.agents,
205
+ channels: { [channelType]: channels[channelType] },
206
+ projects: agent.config.projects,
207
+ };
208
+ const newInstances = await channelLoader.createAll(partialConfig);
209
+ const newInst = newInstances.find(i => i.adapter.channelName === channelName);
210
+ if (!newInst)
211
+ throw new Error(`[Reload] Failed to create instance ${channelName}`);
212
+ registerChannelInstance(newInst);
213
+ await newInst.connect();
214
+ channelInstances.push(newInst);
215
+ logger.info(`[Reload] Started channel: ${channelName}`);
216
+ },
217
+ };
218
+ }