evolclaw 3.0.0 → 3.1.1
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/bin/ec.js +29 -0
- package/dist/agents/baseagent-normalize.js +19 -0
- package/dist/agents/claude-runner.js +47 -12
- package/dist/agents/codex-runner.js +2 -0
- package/dist/agents/gemini-runner.js +9 -9
- package/dist/agents/kit-renderer.js +281 -0
- package/dist/aun/aid/identity.js +28 -0
- package/dist/aun/aid/index.js +1 -1
- package/dist/aun/aid/lifecycle-log.js +33 -0
- package/dist/aun/msg/group.js +3 -1
- package/dist/aun/msg/p2p.js +42 -1
- package/dist/channels/aun.js +427 -146
- package/dist/channels/dingtalk.js +3 -1
- package/dist/channels/feishu.js +128 -7
- package/dist/channels/qqbot.js +3 -1
- package/dist/channels/wechat.js +4 -1
- package/dist/channels/wecom.js +3 -1
- package/dist/cli/bench.js +1219 -0
- package/dist/cli/index.js +418 -40
- package/dist/cli/init.js +3 -4
- package/dist/cli/link-rules.js +245 -0
- package/dist/cli/net-check.js +640 -0
- package/dist/cli/watch-msg.js +666 -0
- package/dist/config-store.js +82 -5
- package/dist/core/channel-loader.js +23 -10
- package/dist/core/command-handler.js +127 -99
- package/dist/core/evolagent.js +5 -10
- package/dist/core/message/im-renderer.js +93 -48
- package/dist/core/message/items-formatter.js +11 -4
- package/dist/core/message/message-bridge.js +11 -2
- package/dist/core/message/message-log.js +8 -1
- package/dist/core/message/message-processor.js +194 -127
- package/dist/core/message/message-queue.js +10 -3
- package/dist/core/permission.js +95 -3
- package/dist/core/relation/peer-identity.js +161 -0
- package/dist/core/session/session-manager.js +103 -65
- package/dist/core/trigger/manager.js +16 -0
- package/dist/core/trigger/parser.js +110 -0
- package/dist/core/trigger/scheduler.js +7 -1
- package/dist/data/error-dict.json +118 -0
- package/dist/eck/baseagent-caps.js +18 -0
- package/dist/eck/detect.js +47 -0
- package/dist/eck/init.js +77 -0
- package/dist/eck/rules-loader.js +28 -0
- package/dist/index.js +186 -19
- package/dist/net-check.js +640 -0
- package/dist/paths.js +31 -40
- package/dist/utils/aid-lifecycle-log.js +33 -0
- package/dist/utils/atomic-write.js +10 -0
- package/dist/utils/cross-platform.js +17 -8
- package/dist/utils/error-utils.js +27 -15
- package/dist/utils/instance-registry.js +6 -5
- package/dist/utils/log-writer.js +2 -1
- package/dist/utils/logger.js +10 -0
- package/dist/utils/npm-ops.js +35 -3
- package/dist/utils/process-introspect.js +16 -38
- package/dist/utils/stats.js +216 -2
- package/dist/watch-msg.js +26 -11
- package/evolclaw-install-aun.md +14 -2
- package/kits/docs/GUIDE.md +20 -0
- package/kits/docs/INDEX.md +52 -0
- package/kits/docs/aun/CHEATSHEET.md +17 -0
- package/kits/docs/aun/SYNC_PROTOCOL.md +15 -0
- package/kits/docs/channels/feishu.md +27 -0
- package/kits/docs/eck_templates/GUIDE.template.md +22 -0
- package/kits/docs/eck_templates/INDEX.template.md +28 -0
- package/kits/docs/eck_templates/path-registry.template.md +33 -0
- package/kits/docs/eck_templates/runtime.template.md +19 -0
- package/kits/docs/evolclaw/MSG_GROUP.md +30 -0
- package/kits/docs/evolclaw/MSG_PRIVATE.md +72 -0
- package/kits/docs/identity/AID_PROFILE_SPEC.md +27 -0
- package/kits/docs/identity/PATH_OPS.md +16 -0
- package/kits/docs/identity/ROLE_DETAIL.md +20 -0
- package/kits/docs/path-registry.md +43 -0
- package/kits/eck_manifest.json +95 -0
- package/kits/rules/01-overview.md +120 -0
- package/kits/rules/02-navigation.md +75 -0
- package/kits/rules/03-identity.md +34 -0
- package/kits/rules/04-relation.md +49 -0
- package/kits/rules/05-venue.md +45 -0
- package/kits/rules/06-channel.md +73 -0
- package/kits/templates/system-fragments/baseagent.md +2 -0
- package/kits/templates/system-fragments/channel.md +10 -0
- package/kits/templates/system-fragments/identity.md +12 -0
- package/kits/templates/system-fragments/relation.md +9 -0
- package/kits/templates/system-fragments/runtime.md +19 -0
- package/kits/templates/system-fragments/venue.md +5 -0
- package/package.json +7 -5
- package/dist/agents/templates.js +0 -122
- package/dist/data/prompts.md +0 -137
- package/kits/aun/meta.md +0 -25
- package/kits/aun/role.md +0 -25
- package/kits/templates/group.md +0 -20
- package/kits/templates/private.md +0 -9
- package/kits/templates/system-fragments/personal-context.md +0 -3
- package/kits/templates/system-fragments/self-intro.md +0 -5
- package/kits/templates/system-fragments/speaker-intro.md +0 -5
- package/kits/templates/system-fragments/venue-intro.md +0 -5
- /package/kits/{channels → docs/channels}/aun.md +0 -0
- /package/kits/{evolclaw/commands.md → docs/evolclaw/AGENT_CMD.md} +0 -0
- /package/kits/{evolclaw → docs/evolclaw}/self-summary.md +0 -0
- /package/kits/{evolclaw → docs/evolclaw}/tools.md +0 -0
- /package/kits/{evolclaw → docs/identity}/identity-tools.md +0 -0
package/dist/utils/stats.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
1
3
|
export class StatsCollector {
|
|
2
4
|
events = [];
|
|
3
5
|
startTime;
|
|
@@ -100,6 +102,71 @@ export class StatsCollector {
|
|
|
100
102
|
export class AidStatsCollector {
|
|
101
103
|
entries = new Map();
|
|
102
104
|
queueStatsProvider;
|
|
105
|
+
/** sessionId → 当前正在跑该 session 的 agent,task:started 写入,task:completed/error 清除 */
|
|
106
|
+
sessionToAgent = new Map();
|
|
107
|
+
constructor(eventBus) {
|
|
108
|
+
if (!eventBus)
|
|
109
|
+
return;
|
|
110
|
+
eventBus.subscribe('task:started', (event) => {
|
|
111
|
+
const e = event;
|
|
112
|
+
if (e.agentName)
|
|
113
|
+
this.onTaskStart(e.agentName, e.encrypt, e.chatmode);
|
|
114
|
+
if (e.agentName && e.sessionId)
|
|
115
|
+
this.sessionToAgent.set(e.sessionId, e.agentName);
|
|
116
|
+
});
|
|
117
|
+
eventBus.subscribe('task:completed', (event) => {
|
|
118
|
+
const e = event;
|
|
119
|
+
if (e.agentName)
|
|
120
|
+
this.onTaskEnd(e.agentName, 'completed', undefined, e.finalText, e.numTurns);
|
|
121
|
+
if (e.sessionId)
|
|
122
|
+
this.sessionToAgent.delete(e.sessionId);
|
|
123
|
+
});
|
|
124
|
+
eventBus.subscribe('task:error', (event) => {
|
|
125
|
+
const e = event;
|
|
126
|
+
if (e.agentName)
|
|
127
|
+
this.onTaskEnd(e.agentName, 'error', e.errorType);
|
|
128
|
+
if (e.sessionId)
|
|
129
|
+
this.sessionToAgent.delete(e.sessionId);
|
|
130
|
+
});
|
|
131
|
+
// thought.put 次数 + 最后一次 thought 文本
|
|
132
|
+
// 注意:thought.put 是 fire-and-forget async,可能在 task:completed 之后才到达,
|
|
133
|
+
// 所以同时累加到 currentTask(task 进行中)或 lastTaskEnd(task 已结束但 thought 属于它)
|
|
134
|
+
eventBus.subscribe('message:thought-put', (event) => {
|
|
135
|
+
const e = event;
|
|
136
|
+
if (!e.agentName)
|
|
137
|
+
return;
|
|
138
|
+
const entry = this.entries.get(e.agentName);
|
|
139
|
+
if (!entry)
|
|
140
|
+
return;
|
|
141
|
+
if (entry.currentTaskStartAt != null) {
|
|
142
|
+
// task 进行中
|
|
143
|
+
entry.currentTaskThoughtPutCount++;
|
|
144
|
+
if (e.text)
|
|
145
|
+
entry.currentTaskLastThoughtText = e.text;
|
|
146
|
+
}
|
|
147
|
+
else if (entry.lastTaskEnd) {
|
|
148
|
+
// task 已结束,回填到最近一次 task
|
|
149
|
+
entry.lastTaskEnd.thoughtPutCount++;
|
|
150
|
+
entry.lastTaskEnd.thoughtDuringTask = true;
|
|
151
|
+
if (e.text) {
|
|
152
|
+
const t = e.text.length > 100 ? e.text.slice(0, 100) + '…' : e.text;
|
|
153
|
+
entry.lastTaskEnd.lastThoughtText = t;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
// 工具调用次数(tool:use 事件)
|
|
158
|
+
eventBus.subscribe('tool:use', (event) => {
|
|
159
|
+
const e = event;
|
|
160
|
+
if (!e.sessionId)
|
|
161
|
+
return;
|
|
162
|
+
const agent = this.sessionToAgent.get(e.sessionId);
|
|
163
|
+
if (!agent)
|
|
164
|
+
return;
|
|
165
|
+
const entry = this.entries.get(agent);
|
|
166
|
+
if (entry && entry.currentTaskStartAt != null)
|
|
167
|
+
entry.currentTaskToolUseCount++;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
103
170
|
setQueueStatsProvider(provider) {
|
|
104
171
|
this.queueStatsProvider = provider;
|
|
105
172
|
}
|
|
@@ -119,19 +186,145 @@ export class AidStatsCollector {
|
|
|
119
186
|
lastSentAt: null,
|
|
120
187
|
lastReceivedText: null,
|
|
121
188
|
lastReceivedFrom: null,
|
|
189
|
+
lastReceivedEncrypt: null,
|
|
190
|
+
lastReceivedChatmode: null,
|
|
122
191
|
lastSentText: null,
|
|
123
192
|
lastSentTo: null,
|
|
193
|
+
lastSentEncrypt: null,
|
|
194
|
+
lastSentChatmode: null,
|
|
124
195
|
uniquePeers: new Set(),
|
|
196
|
+
currentTaskStartAt: null,
|
|
197
|
+
currentTaskReplyCount: 0,
|
|
198
|
+
currentTaskThoughtPutCount: 0,
|
|
199
|
+
currentTaskToolUseCount: 0,
|
|
200
|
+
currentTaskNumTurns: 0,
|
|
201
|
+
currentTaskLastThoughtText: null,
|
|
202
|
+
currentTaskSessionId: null,
|
|
203
|
+
currentTaskChatmode: null,
|
|
204
|
+
currentTaskEncrypt: null,
|
|
205
|
+
lastTaskEnd: undefined,
|
|
125
206
|
};
|
|
126
207
|
this.entries.set(aid, entry);
|
|
127
208
|
}
|
|
128
209
|
return entry;
|
|
129
210
|
}
|
|
211
|
+
sessionsDir;
|
|
212
|
+
setSessionsDir(dir) {
|
|
213
|
+
this.sessionsDir = dir;
|
|
214
|
+
}
|
|
215
|
+
onTaskStart(aid, encrypt, chatmode) {
|
|
216
|
+
const entry = this.getOrCreate(aid);
|
|
217
|
+
entry.currentTaskStartAt = Date.now();
|
|
218
|
+
entry.currentTaskReplyCount = 0;
|
|
219
|
+
entry.currentTaskThoughtPutCount = 0;
|
|
220
|
+
entry.currentTaskToolUseCount = 0;
|
|
221
|
+
entry.currentTaskNumTurns = 0;
|
|
222
|
+
entry.currentTaskLastThoughtText = null;
|
|
223
|
+
entry.currentTaskChatmode = chatmode ?? null;
|
|
224
|
+
entry.currentTaskEncrypt = encrypt ?? null;
|
|
225
|
+
}
|
|
226
|
+
onTaskEnd(aid, status, errorType, finalText, numTurns) {
|
|
227
|
+
const entry = this.getOrCreate(aid);
|
|
228
|
+
const startedAt = entry.currentTaskStartAt;
|
|
229
|
+
const taskEndTs = Date.now();
|
|
230
|
+
// 先用内存计数写入初始值(立即可用)
|
|
231
|
+
const buildTaskEnd = (msgCount, thoughtCount, lastThought) => ({
|
|
232
|
+
ts: taskEndTs,
|
|
233
|
+
status,
|
|
234
|
+
errorType,
|
|
235
|
+
sentDuringTask: msgCount > 0,
|
|
236
|
+
thoughtDuringTask: thoughtCount > 0,
|
|
237
|
+
lastThoughtText: lastThought,
|
|
238
|
+
replyCount: msgCount,
|
|
239
|
+
thoughtPutCount: thoughtCount,
|
|
240
|
+
toolUseCount: entry.currentTaskToolUseCount,
|
|
241
|
+
numTurns: numTurns ?? entry.currentTaskNumTurns,
|
|
242
|
+
finalText: finalText ? (finalText.length > 100 ? finalText.slice(0, 100) + '…' : finalText) : undefined,
|
|
243
|
+
chatmode: entry.currentTaskChatmode ?? undefined,
|
|
244
|
+
encrypt: entry.currentTaskEncrypt ?? undefined,
|
|
245
|
+
});
|
|
246
|
+
entry.lastTaskEnd = buildTaskEnd(entry.currentTaskReplyCount, entry.currentTaskThoughtPutCount, entry.currentTaskLastThoughtText ?? undefined);
|
|
247
|
+
// 500ms 后从 jsonl 重新统计(覆盖 thought.put 异步延迟问题)
|
|
248
|
+
if (this.sessionsDir && startedAt != null) {
|
|
249
|
+
const sessionsDir = this.sessionsDir;
|
|
250
|
+
const toolUseCount = entry.currentTaskToolUseCount;
|
|
251
|
+
const resolvedNumTurns = numTurns ?? entry.currentTaskNumTurns;
|
|
252
|
+
const chatmode = entry.currentTaskChatmode;
|
|
253
|
+
const encrypt = entry.currentTaskEncrypt;
|
|
254
|
+
setTimeout(() => {
|
|
255
|
+
try {
|
|
256
|
+
const { chatDirPath } = require('../core/session/session-fs-store.js');
|
|
257
|
+
// 找该 aid 下所有 peer 的 messages.jsonl,统计 ts >= startedAt 的出站条目
|
|
258
|
+
const aidDir = path.join(sessionsDir, 'aun', aid.replace(/[/%\\:*?"<>|]/g, ch => '%' + ch.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0')));
|
|
259
|
+
if (!fs.existsSync(aidDir))
|
|
260
|
+
return;
|
|
261
|
+
let msgCount = 0, thoughtCount = 0;
|
|
262
|
+
let lastThoughtText;
|
|
263
|
+
let lastMsgText;
|
|
264
|
+
for (const peerDir of fs.readdirSync(aidDir, { withFileTypes: true })) {
|
|
265
|
+
if (!peerDir.isDirectory() || peerDir.name.startsWith('_'))
|
|
266
|
+
continue;
|
|
267
|
+
const msgFile = path.join(aidDir, peerDir.name, 'messages.jsonl');
|
|
268
|
+
if (!fs.existsSync(msgFile))
|
|
269
|
+
continue;
|
|
270
|
+
const lines = fs.readFileSync(msgFile, 'utf-8').split('\n').filter(Boolean);
|
|
271
|
+
for (const line of lines) {
|
|
272
|
+
try {
|
|
273
|
+
const rec = JSON.parse(line);
|
|
274
|
+
if (rec.dir !== 'out' || rec.ts < startedAt || rec.ts > taskEndTs + 2000)
|
|
275
|
+
continue;
|
|
276
|
+
if (rec.msgType === 'thought') {
|
|
277
|
+
thoughtCount++;
|
|
278
|
+
if (rec.content)
|
|
279
|
+
lastThoughtText = rec.content.length > 100 ? rec.content.slice(0, 100) + '…' : rec.content;
|
|
280
|
+
}
|
|
281
|
+
else if (rec.msgType === 'text') {
|
|
282
|
+
msgCount++;
|
|
283
|
+
if (rec.content)
|
|
284
|
+
lastMsgText = rec.content.length > 100 ? rec.content.slice(0, 100) + '…' : rec.content;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
catch { }
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const currentEntry = this.entries.get(aid);
|
|
291
|
+
if (currentEntry?.lastTaskEnd?.ts === taskEndTs) {
|
|
292
|
+
currentEntry.lastTaskEnd = {
|
|
293
|
+
ts: taskEndTs,
|
|
294
|
+
status,
|
|
295
|
+
errorType,
|
|
296
|
+
sentDuringTask: msgCount > 0,
|
|
297
|
+
thoughtDuringTask: thoughtCount > 0,
|
|
298
|
+
lastThoughtText: lastThoughtText,
|
|
299
|
+
replyCount: msgCount,
|
|
300
|
+
thoughtPutCount: thoughtCount,
|
|
301
|
+
toolUseCount,
|
|
302
|
+
numTurns: resolvedNumTurns,
|
|
303
|
+
finalText: finalText ? (finalText.length > 100 ? finalText.slice(0, 100) + '…' : finalText) : undefined,
|
|
304
|
+
chatmode: chatmode ?? undefined,
|
|
305
|
+
encrypt: encrypt ?? undefined,
|
|
306
|
+
};
|
|
307
|
+
// 更新 lastSentText 为最后一条 msg(如果有)
|
|
308
|
+
if (lastMsgText && msgCount > 0) {
|
|
309
|
+
currentEntry.lastSentText = lastMsgText;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
catch { }
|
|
314
|
+
}, 500);
|
|
315
|
+
}
|
|
316
|
+
entry.currentTaskStartAt = null;
|
|
317
|
+
entry.currentTaskReplyCount = 0;
|
|
318
|
+
entry.currentTaskThoughtPutCount = 0;
|
|
319
|
+
entry.currentTaskToolUseCount = 0;
|
|
320
|
+
entry.currentTaskNumTurns = 0;
|
|
321
|
+
entry.currentTaskLastThoughtText = null;
|
|
322
|
+
}
|
|
130
323
|
setSelfName(aid, name) {
|
|
131
324
|
const entry = this.getOrCreate(aid);
|
|
132
325
|
entry.selfName = name;
|
|
133
326
|
}
|
|
134
|
-
recordInbound(aid, fromPeer, byteLength, text, isSystem = false) {
|
|
327
|
+
recordInbound(aid, fromPeer, byteLength, text, isSystem = false, encrypt, chatmode) {
|
|
135
328
|
const entry = this.getOrCreate(aid);
|
|
136
329
|
if (isSystem) {
|
|
137
330
|
entry.systemReceived++;
|
|
@@ -142,11 +335,15 @@ export class AidStatsCollector {
|
|
|
142
335
|
entry.lastReceivedFrom = fromPeer;
|
|
143
336
|
if (text)
|
|
144
337
|
entry.lastReceivedText = text.length > 100 ? text.slice(0, 100) + '…' : text;
|
|
338
|
+
if (encrypt != null)
|
|
339
|
+
entry.lastReceivedEncrypt = encrypt;
|
|
340
|
+
if (chatmode)
|
|
341
|
+
entry.lastReceivedChatmode = chatmode;
|
|
145
342
|
}
|
|
146
343
|
entry.bytesReceived += byteLength;
|
|
147
344
|
entry.uniquePeers.add(fromPeer);
|
|
148
345
|
}
|
|
149
|
-
recordOutbound(aid, toPeer, byteLength, text, isSystem = false) {
|
|
346
|
+
recordOutbound(aid, toPeer, byteLength, text, isSystem = false, encrypt, chatmode) {
|
|
150
347
|
const entry = this.getOrCreate(aid);
|
|
151
348
|
if (isSystem) {
|
|
152
349
|
entry.systemSent++;
|
|
@@ -157,6 +354,18 @@ export class AidStatsCollector {
|
|
|
157
354
|
entry.lastSentTo = toPeer;
|
|
158
355
|
if (text)
|
|
159
356
|
entry.lastSentText = text.length > 100 ? text.slice(0, 100) + '…' : text;
|
|
357
|
+
if (encrypt != null)
|
|
358
|
+
entry.lastSentEncrypt = encrypt;
|
|
359
|
+
if (chatmode)
|
|
360
|
+
entry.lastSentChatmode = chatmode;
|
|
361
|
+
// 累计当前 task 的回复数
|
|
362
|
+
if (entry.currentTaskStartAt != null) {
|
|
363
|
+
entry.currentTaskReplyCount++;
|
|
364
|
+
if (chatmode)
|
|
365
|
+
entry.currentTaskChatmode = chatmode;
|
|
366
|
+
if (encrypt != null)
|
|
367
|
+
entry.currentTaskEncrypt = encrypt;
|
|
368
|
+
}
|
|
160
369
|
}
|
|
161
370
|
entry.bytesSent += byteLength;
|
|
162
371
|
entry.uniquePeers.add(toPeer);
|
|
@@ -180,11 +389,16 @@ export class AidStatsCollector {
|
|
|
180
389
|
lastSentAt: entry.lastSentAt,
|
|
181
390
|
lastReceivedText: entry.lastReceivedText,
|
|
182
391
|
lastReceivedFrom: entry.lastReceivedFrom,
|
|
392
|
+
lastReceivedEncrypt: entry.lastReceivedEncrypt,
|
|
393
|
+
lastReceivedChatmode: entry.lastReceivedChatmode,
|
|
183
394
|
lastSentText: entry.lastSentText,
|
|
184
395
|
lastSentTo: entry.lastSentTo,
|
|
396
|
+
lastSentEncrypt: entry.lastSentEncrypt,
|
|
397
|
+
lastSentChatmode: entry.lastSentChatmode,
|
|
185
398
|
uniquePeerCount: entry.uniquePeers.size,
|
|
186
399
|
processing: queueStats.processing,
|
|
187
400
|
queued: queueStats.queued,
|
|
401
|
+
lastTaskEnd: entry.lastTaskEnd,
|
|
188
402
|
});
|
|
189
403
|
}
|
|
190
404
|
return out;
|
package/dist/watch-msg.js
CHANGED
|
@@ -11,6 +11,7 @@ const CYAN = isTTY ? '\x1b[36m' : '';
|
|
|
11
11
|
const GREEN = isTTY ? '\x1b[32m' : '';
|
|
12
12
|
const BLUE = isTTY ? '\x1b[34m' : '';
|
|
13
13
|
const ORANGE = isTTY ? '\x1b[38;5;208m' : '';
|
|
14
|
+
const BG_SEL = isTTY ? '\x1b[48;5;236m' : ''; // dark gray background for selected row
|
|
14
15
|
// ==================== Helpers ====================
|
|
15
16
|
function visualWidth(s) {
|
|
16
17
|
const stripped = s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
@@ -56,6 +57,14 @@ function formatTime(ts) {
|
|
|
56
57
|
const d = new Date(ts);
|
|
57
58
|
return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
|
|
58
59
|
}
|
|
60
|
+
function formatDateTime(ts) {
|
|
61
|
+
const d = new Date(ts);
|
|
62
|
+
const mo = String(d.getMonth() + 1).padStart(2, '0');
|
|
63
|
+
const dd = String(d.getDate()).padStart(2, '0');
|
|
64
|
+
const hh = String(d.getHours()).padStart(2, '0');
|
|
65
|
+
const mm = String(d.getMinutes()).padStart(2, '0');
|
|
66
|
+
return `${mo}-${dd} ${hh}:${mm}`;
|
|
67
|
+
}
|
|
59
68
|
function shortAid(aid) {
|
|
60
69
|
return aid.split('.')[0];
|
|
61
70
|
}
|
|
@@ -169,10 +178,12 @@ function renderScopePanel(state, width, height) {
|
|
|
169
178
|
const a = state.localAids[i];
|
|
170
179
|
const sel = isActive && i === state.scopeIndex;
|
|
171
180
|
const chosen = state.selectedLocalAid === a.aid;
|
|
172
|
-
const
|
|
181
|
+
const bg = sel ? BG_SEL : '';
|
|
182
|
+
const marker = sel ? `${bg}${CYAN}${BOLD}▸ ` : (chosen ? `${CYAN} ` : ' ');
|
|
173
183
|
const name = truncate(shortAid(a.aid), width - 4);
|
|
174
184
|
lines.push(padRight(`${marker}${name}${RST}`, width));
|
|
175
|
-
const
|
|
185
|
+
const statsBg = sel ? BG_SEL : '';
|
|
186
|
+
const stats = `${statsBg} ${DIM}↓${a.totalIn} ↑${a.totalOut} peers:${a.peerCount}${RST}`;
|
|
176
187
|
lines.push(padRight(stats, width));
|
|
177
188
|
if (lines.length < height)
|
|
178
189
|
lines.push(padRight('', width));
|
|
@@ -195,19 +206,22 @@ function renderStatsPanel(state, width, height) {
|
|
|
195
206
|
const now = Date.now();
|
|
196
207
|
// "All" item at index 0
|
|
197
208
|
const allSel = isActive && state.statsIndex === 0;
|
|
198
|
-
const
|
|
209
|
+
const allBg = allSel ? BG_SEL : '';
|
|
210
|
+
const allMarker = allSel ? `${allBg}${CYAN}${BOLD}▸ ` : ' ';
|
|
199
211
|
lines.push(padRight(`${allMarker}All (${state.peers.length} peers)${RST}`, width));
|
|
200
212
|
if (lines.length < height)
|
|
201
213
|
lines.push(padRight('', width));
|
|
202
214
|
for (let i = 0; i < state.peers.length && lines.length < height; i++) {
|
|
203
215
|
const p = state.peers[i];
|
|
204
216
|
const sel = isActive && state.statsIndex === i + 1;
|
|
205
|
-
const
|
|
217
|
+
const bg = sel ? BG_SEL : '';
|
|
218
|
+
const marker = sel ? `${bg}${CYAN}${BOLD}▸ ` : ' ';
|
|
206
219
|
const displayName = p.peerName || shortAid(p.peerId);
|
|
207
220
|
const name = truncate(displayName, width - 4);
|
|
208
221
|
lines.push(padRight(`${marker}${name}${RST}`, width));
|
|
222
|
+
const detailBg = sel ? BG_SEL : '';
|
|
209
223
|
const ago = p.lastAt ? formatTimeAgo(now - p.lastAt) : '-';
|
|
210
|
-
const detail =
|
|
224
|
+
const detail = `${detailBg} ${DIM}↓${p.inbound} ↑${p.outbound} ${ago}${RST}`;
|
|
211
225
|
lines.push(padRight(detail, width));
|
|
212
226
|
if (lines.length < height)
|
|
213
227
|
lines.push(padRight('', width));
|
|
@@ -231,10 +245,11 @@ function renderMessagesPanel(state, width, height) {
|
|
|
231
245
|
const msgWidth = width - 3;
|
|
232
246
|
for (let i = startIdx; i < endIdx; i++) {
|
|
233
247
|
const m = msgs[i];
|
|
234
|
-
const time =
|
|
248
|
+
const time = formatDateTime(m.ts);
|
|
235
249
|
const dir = m.dir === 'in' ? `${GREEN}↓${RST}` : `${BLUE}↑${RST}`;
|
|
236
|
-
const
|
|
237
|
-
const
|
|
250
|
+
const from = shortAid(m.from);
|
|
251
|
+
const to = shortAid(m.to);
|
|
252
|
+
const header = `${DIM}${time}${RST} ${dir} ${ORANGE}${from}${RST}${DIM}→${RST}${GREEN}${to}${RST}`;
|
|
238
253
|
const headerLine = padRight(header, msgWidth);
|
|
239
254
|
const sbIdx = lines.length - 1;
|
|
240
255
|
lines.push(`${headerLine} ${scrollbar[sbIdx] || ' '}`);
|
|
@@ -255,9 +270,9 @@ function renderMessagesPanel(state, width, height) {
|
|
|
255
270
|
function renderFrame(state) {
|
|
256
271
|
const cols = process.stdout.columns || 120;
|
|
257
272
|
const rows = (process.stdout.rows || 40) - 3;
|
|
258
|
-
const leftW = Math.max(
|
|
259
|
-
const midW = Math.max(
|
|
260
|
-
const rightW = Math.max(
|
|
273
|
+
const leftW = Math.max(20, Math.floor(cols * 0.20));
|
|
274
|
+
const midW = Math.max(24, Math.floor(cols * 0.22));
|
|
275
|
+
const rightW = Math.max(40, cols - leftW - midW - 4);
|
|
261
276
|
const bodyHeight = rows - 2;
|
|
262
277
|
const leftLines = renderScopePanel(state, leftW, bodyHeight);
|
|
263
278
|
const midLines = renderStatsPanel(state, midW, bodyHeight);
|
package/evolclaw-install-aun.md
CHANGED
|
@@ -19,6 +19,8 @@ EvolClaw 是一个开源的 AI Agent 网关,将 Claude/Codex 等 AI 后端连
|
|
|
19
19
|
|
|
20
20
|
## 安装步骤
|
|
21
21
|
|
|
22
|
+
> **⚠️ 给执行安装的 AI Agent**:本文档中所有破坏性命令(`evolclaw stop` / `evolclaw restart` / `rm -rf` / `evolclaw aid delete` 等)**必须先 `AskUserQuestion` 等用户明确回复后才能执行**,不要因为已经发出确认提示就默认 yes 自动跑。用户在打字的几秒内决定 "等等先别停",比事后回滚要省事得多。
|
|
23
|
+
|
|
22
24
|
### 步骤 1:检查环境
|
|
23
25
|
|
|
24
26
|
```bash
|
|
@@ -169,23 +171,33 @@ AUN 通道由 `agent.aid` 隐式驱动,不需要单独配 channel——`evolcl
|
|
|
169
171
|
cat $EVOLCLAW_HOME/agents/<aid>/config.json
|
|
170
172
|
```
|
|
171
173
|
|
|
172
|
-
|
|
174
|
+
检查关键字段:
|
|
173
175
|
|
|
174
176
|
- `aid` — 你的 AID
|
|
175
177
|
- `owners` — Owner AID 数组(可为空,留给自动绑定)
|
|
176
178
|
- `active_baseagent` — `claude` / `codex` / `gemini`
|
|
177
179
|
- `projects.defaultPath` — 项目路径(目录需存在)
|
|
178
|
-
- `channels` —
|
|
180
|
+
- `channels` — 数组,初始为空(AUN 隐式上线,无需在此配置)
|
|
179
181
|
- `initialized` — 应为 `false`(首次连接成功后由系统更新为 `true`)
|
|
180
182
|
|
|
183
|
+
> 注:config.json 还包含 `$schema_version`、`enabled`、`baseagents`、`chatmode`、`dispatch` 等字段,由 `agent new` 自动填入,无需手动检查。
|
|
184
|
+
|
|
181
185
|
如发现缺失或异常,向用户说明并提供修复方案。
|
|
182
186
|
|
|
183
187
|
### 步骤 9:启动服务
|
|
184
188
|
|
|
189
|
+
首次安装(服务未运行):
|
|
190
|
+
|
|
185
191
|
```bash
|
|
186
192
|
evolclaw start
|
|
187
193
|
```
|
|
188
194
|
|
|
195
|
+
若服务已在运行(升级/重装场景,步骤 3 已停止旧进程):
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
evolclaw restart
|
|
199
|
+
```
|
|
200
|
+
|
|
189
201
|
### 步骤 10:验证运行状态
|
|
190
202
|
|
|
191
203
|
```bash
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# 文档查阅指南
|
|
2
|
+
|
|
3
|
+
## 查阅流程
|
|
4
|
+
|
|
5
|
+
1. 先看 `$KITS_RULES`(自动加载的 8 个规则文件)了解机制骨架
|
|
6
|
+
2. 需要详细信息时,按 `INDEX.md` 找到对应文档路径
|
|
7
|
+
3. Read 对应文档
|
|
8
|
+
|
|
9
|
+
## 路径解析
|
|
10
|
+
|
|
11
|
+
文档中用 `$名称` 引用路径。解析步骤:
|
|
12
|
+
1. 查 `$KITS_RULES/01-entry.md` 的路径体系速查表
|
|
13
|
+
2. 如需完整定义,Read `$KITS_DOCS/path-registry.md`
|
|
14
|
+
3. 如需运行时实际值,Read `$ECK/path-registry.md`
|
|
15
|
+
|
|
16
|
+
## 不要做的事
|
|
17
|
+
|
|
18
|
+
- 不要一次性加载所有文档——按需逐个 Read
|
|
19
|
+
- 不要猜测路径——查注册表
|
|
20
|
+
- 不要在当前会话输出对外消息——用 CLI
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# EvolClaw 文档索引
|
|
2
|
+
|
|
3
|
+
本文件是 `$KITS_DOCS` 下所有文档的索引。
|
|
4
|
+
|
|
5
|
+
## 路径与机制
|
|
6
|
+
|
|
7
|
+
| 文档 | 路径 | 说明 |
|
|
8
|
+
|------|------|------|
|
|
9
|
+
| 查阅指南 | `GUIDE.md` | 文档查阅流程 |
|
|
10
|
+
| 路径定义 | `path-registry.md` | 所有预定义路径及派生规则 |
|
|
11
|
+
|
|
12
|
+
## AUN 协议
|
|
13
|
+
|
|
14
|
+
| 文档 | 路径 | 说明 |
|
|
15
|
+
|------|------|------|
|
|
16
|
+
| 速查表 | `aun/CHEATSHEET.md` | AUN 协议命名空间与常用操作速查 |
|
|
17
|
+
| 同步协议 | `aun/SYNC_PROTOCOL.md` | 上游协议同步 SOP |
|
|
18
|
+
|
|
19
|
+
## EvolClaw 命令
|
|
20
|
+
|
|
21
|
+
| 文档 | 路径 | 说明 |
|
|
22
|
+
|------|------|------|
|
|
23
|
+
| Agent 命令 | `evolclaw/AGENT_CMD.md` | agent 全生命周期管理命令 |
|
|
24
|
+
| 运行时工具 | `evolclaw/tools.md` | ctl 命令集 |
|
|
25
|
+
| 自我总结 | `evolclaw/self-summary.md` | 自我总结流程指南 |
|
|
26
|
+
| 私聊消息 | `evolclaw/MSG_PRIVATE.md` | 私聊消息命令 |
|
|
27
|
+
| 群聊消息 | `evolclaw/MSG_GROUP.md` | 群聊消息命令 |
|
|
28
|
+
|
|
29
|
+
## 身份
|
|
30
|
+
|
|
31
|
+
| 文档 | 路径 | 说明 |
|
|
32
|
+
|------|------|------|
|
|
33
|
+
| 身份工具 | `identity/identity-tools.md` | 身份识别与环境层工具 |
|
|
34
|
+
| 角色详情 | `identity/ROLE_DETAIL.md` | 角色与场景详细规则 |
|
|
35
|
+
| AID 档案规范 | `identity/AID_PROFILE_SPEC.md` | AID 档案格式规范 |
|
|
36
|
+
| 路径运维 | `identity/PATH_OPS.md` | 路径运维操作 |
|
|
37
|
+
|
|
38
|
+
## 渠道
|
|
39
|
+
|
|
40
|
+
| 文档 | 路径 | 说明 |
|
|
41
|
+
|------|------|------|
|
|
42
|
+
| AUN 渠道 | `channels/aun.md` | AUN 通信约定 |
|
|
43
|
+
| 飞书渠道 | `channels/feishu.md` | 飞书渠道接入 |
|
|
44
|
+
|
|
45
|
+
## ECK 模板
|
|
46
|
+
|
|
47
|
+
| 文档 | 路径 | 说明 |
|
|
48
|
+
|------|------|------|
|
|
49
|
+
| 运行时配置模板 | `eck_templates/runtime.template.md` | agent 运行时配置模板 |
|
|
50
|
+
| 路径注册表模板 | `eck_templates/path-registry.template.md` | 路径实例模板 |
|
|
51
|
+
| 索引模板 | `eck_templates/INDEX.template.md` | agent 级索引模板 |
|
|
52
|
+
| 指南模板 | `eck_templates/GUIDE.template.md` | agent 级查阅指南模板 |
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# AUN 协议速查表
|
|
2
|
+
|
|
3
|
+
<!-- TODO: 填充 AUN 协议命名空间与常用操作速查内容 -->
|
|
4
|
+
|
|
5
|
+
## 命名空间
|
|
6
|
+
|
|
7
|
+
| 命名空间 | 作用 |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `auth.*` | AID 创建、认证、JWT |
|
|
10
|
+
| `message.*` | 点对点消息收发 |
|
|
11
|
+
| `group.*` | 群组生命周期、群消息 |
|
|
12
|
+
| `storage.*` | 文件上传下载 |
|
|
13
|
+
| `stream.*` | 实时流(语音/视频/token) |
|
|
14
|
+
| `meta.*` | ping、状态、信任根查询 |
|
|
15
|
+
| `nameservice.*` | AID 名字注册查询 |
|
|
16
|
+
| `custody.*` | AID 托管 |
|
|
17
|
+
| `peer.*` / `relay.*` | 直连/中继认证 |
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# 飞书渠道
|
|
2
|
+
|
|
3
|
+
<!-- TODO: 填充飞书渠道接入文档 -->
|
|
4
|
+
|
|
5
|
+
## 概述
|
|
6
|
+
|
|
7
|
+
飞书渠道通过 evolclaw 的 feishu channel 实现,支持:
|
|
8
|
+
- 单聊消息收发
|
|
9
|
+
- 群聊消息收发
|
|
10
|
+
- 合并转发消息解析
|
|
11
|
+
- 文件/图片/视频消息
|
|
12
|
+
|
|
13
|
+
## 配置
|
|
14
|
+
|
|
15
|
+
在 evolclaw 配置中启用飞书渠道:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"channels": {
|
|
20
|
+
"feishu": {
|
|
21
|
+
"enabled": true,
|
|
22
|
+
"appId": "<app-id>",
|
|
23
|
+
"appSecret": "<app-secret>"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Agent 查阅指南
|
|
2
|
+
|
|
3
|
+
本文件是 {{SELF_AID}} 的个人查阅指南。
|
|
4
|
+
|
|
5
|
+
## 查阅优先级
|
|
6
|
+
|
|
7
|
+
1. `$KITS_RULES`(自动加载)— ECK 机制骨架
|
|
8
|
+
2. `$AGENT_INDEX/INDEX.md`(本目录)— 个人索引
|
|
9
|
+
3. `$KITS_DOCS/INDEX.md` — evolclaw 级文档索引
|
|
10
|
+
4. 按索引中的路径 Read 具体文档
|
|
11
|
+
|
|
12
|
+
## 路径解析
|
|
13
|
+
|
|
14
|
+
遇到 `$名称` 时:
|
|
15
|
+
1. 查 `$ECK/path-registry.md` 获取实际路径
|
|
16
|
+
2. 如果实例文件中没有,查 `$KITS_DOCS/path-registry.md` 了解派生规则
|
|
17
|
+
|
|
18
|
+
## 索引维护
|
|
19
|
+
|
|
20
|
+
当以下范围内有文档变动时,更新本索引:
|
|
21
|
+
- `{{CURRENT_PROJECT}}`
|
|
22
|
+
- `{{AGENT_DIR}}`
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Agent 索引
|
|
2
|
+
|
|
3
|
+
本文件是 {{SELF_AID}} 的 agent 级文档索引。
|
|
4
|
+
|
|
5
|
+
## 项目文档
|
|
6
|
+
|
|
7
|
+
| 文档 | 路径 | 说明 | 最后更新 |
|
|
8
|
+
|------|------|------|----------|
|
|
9
|
+
| — | — | (初始化后由 agent 维护) | — |
|
|
10
|
+
|
|
11
|
+
## 个人档案
|
|
12
|
+
|
|
13
|
+
| 文档 | 路径 | 说明 | 最后更新 |
|
|
14
|
+
|------|------|------|----------|
|
|
15
|
+
| 人格档案 | `$SELF_DIR/persona.md` | 行为规范与人格定义 | {{CREATED_AT}} |
|
|
16
|
+
| 工作记忆 | `$SELF_DIR/memory/working.md` | 短期关注点 | {{CREATED_AT}} |
|
|
17
|
+
|
|
18
|
+
## 关系档案
|
|
19
|
+
|
|
20
|
+
| 对端 AID | 路径 | 最后交互 |
|
|
21
|
+
|----------|------|----------|
|
|
22
|
+
| — | — | — |
|
|
23
|
+
|
|
24
|
+
## 场所档案
|
|
25
|
+
|
|
26
|
+
| 场所 | 路径 | 说明 |
|
|
27
|
+
|------|------|------|
|
|
28
|
+
| — | — | — |
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# 路径注册表实例
|
|
2
|
+
|
|
3
|
+
本文件记录运行时解析出的实际路径值。由 evolclaw 初始化时生成。
|
|
4
|
+
|
|
5
|
+
## 基础路径
|
|
6
|
+
|
|
7
|
+
| 名称 | 实际路径 |
|
|
8
|
+
|------|----------|
|
|
9
|
+
| `$EVOLCLAW_HOME` | {{EVOLCLAW_HOME}} |
|
|
10
|
+
| `$PACKAGE_ROOT` | {{PACKAGE_ROOT}} |
|
|
11
|
+
| `$CURRENT_PROJECT` | {{CURRENT_PROJECT}} |
|
|
12
|
+
|
|
13
|
+
## 派生路径
|
|
14
|
+
|
|
15
|
+
| 名称 | 实际路径 |
|
|
16
|
+
|------|----------|
|
|
17
|
+
| `$KITS` | {{KITS}} |
|
|
18
|
+
| `$KITS_RULES` | {{KITS_RULES}} |
|
|
19
|
+
| `$KITS_DOCS` | {{KITS_DOCS}} |
|
|
20
|
+
| `$KITS_TEMPLATES` | {{KITS_TEMPLATES}} |
|
|
21
|
+
| `$ECK` | {{ECK}} |
|
|
22
|
+
| `$AGENT_DIR` | {{AGENT_DIR}} |
|
|
23
|
+
| `$SELF_DIR` | {{SELF_DIR}} |
|
|
24
|
+
| `$RELATIONS_DIR` | {{RELATIONS_DIR}} |
|
|
25
|
+
| `$VENUES_DIR` | {{VENUES_DIR}} |
|
|
26
|
+
| `$AGENT_INDEX` | {{AGENT_INDEX}} |
|
|
27
|
+
|
|
28
|
+
## 外部依赖
|
|
29
|
+
|
|
30
|
+
| 名称 | 实际路径 | 状态 |
|
|
31
|
+
|------|----------|------|
|
|
32
|
+
| `$KITE` | {{KITE}} | {{KITE_STATUS}} |
|
|
33
|
+
| `$AUN_SDK_CORE` | {{AUN_SDK_CORE}} | {{AUN_SDK_STATUS}} |
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# 运行时配置
|
|
2
|
+
|
|
3
|
+
## 基本信息
|
|
4
|
+
|
|
5
|
+
- AID: {{SELF_AID}}
|
|
6
|
+
- 名称: {{AGENT_NAME}}
|
|
7
|
+
- 创建时间: {{CREATED_AT}}
|
|
8
|
+
|
|
9
|
+
## 运行时参数
|
|
10
|
+
|
|
11
|
+
- 模型: {{MODEL_ID}}
|
|
12
|
+
- 推理强度: {{EFFORT_LEVEL}}
|
|
13
|
+
- 权限模式: {{PERMISSION_MODE}}
|
|
14
|
+
|
|
15
|
+
## 行为配置
|
|
16
|
+
|
|
17
|
+
- 自我总结: {{SELF_SUMMARY_ENABLED}}
|
|
18
|
+
- 空闲总结间隔: {{IDLE_SUMMARY_MINUTES}} 分钟
|
|
19
|
+
- 每日总结 token 预算: {{DAILY_SUMMARY_BUDGET}}
|