evolclaw 3.1.3 → 3.1.5

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 (100) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/assets/.env.template +4 -0
  3. package/assets/config.json.template +6 -0
  4. package/assets/wechat-group-qr.jpeg +0 -0
  5. package/dist/agents/claude-runner.js +348 -156
  6. package/dist/agents/kit-renderer.js +211 -42
  7. package/dist/aun/aid/agentmd.js +75 -139
  8. package/dist/aun/aid/client.js +1 -14
  9. package/dist/aun/aid/identity.js +381 -54
  10. package/dist/aun/aid/index.js +3 -2
  11. package/dist/aun/aid/store.js +74 -0
  12. package/dist/aun/msg/p2p.js +26 -2
  13. package/dist/aun/rpc/connection.js +23 -35
  14. package/dist/channels/aun.js +92 -144
  15. package/dist/channels/dingtalk.js +1 -0
  16. package/dist/channels/feishu.js +270 -190
  17. package/dist/channels/qqbot.js +1 -0
  18. package/dist/channels/wechat.js +1 -0
  19. package/dist/channels/wecom.js +1 -0
  20. package/dist/cli/agent.js +26 -27
  21. package/dist/cli/bench.js +45 -34
  22. package/dist/cli/help.js +23 -0
  23. package/dist/cli/index.js +538 -77
  24. package/dist/cli/init-channel.js +7 -4
  25. package/dist/cli/link-rules.js +2 -1
  26. package/dist/cli/model.js +324 -0
  27. package/dist/cli/net-check.js +138 -56
  28. package/dist/cli/watch-msg.js +7 -7
  29. package/dist/cli/watch-web/debug-log.js +18 -0
  30. package/dist/cli/watch-web/server.js +306 -0
  31. package/dist/cli/watch-web/sources/aid.js +63 -0
  32. package/dist/cli/watch-web/sources/msg.js +70 -0
  33. package/dist/cli/watch-web/sources/session.js +638 -0
  34. package/dist/cli/watch-web/sources/types.js +10 -0
  35. package/dist/cli/watch-web/static/app.js +546 -0
  36. package/dist/cli/watch-web/static/index.html +54 -0
  37. package/dist/cli/watch-web/static/style.css +247 -0
  38. package/dist/core/channel-loader.js +7 -4
  39. package/dist/core/command-handler.js +87 -93
  40. package/dist/core/evolagent-registry.js +1 -1
  41. package/dist/core/evolagent.js +4 -4
  42. package/dist/core/interaction-router.js +59 -0
  43. package/dist/core/message/message-bridge.js +6 -6
  44. package/dist/core/message/message-log.js +2 -2
  45. package/dist/core/message/message-processor.js +104 -118
  46. package/dist/core/message/stream-idle-monitor.js +21 -0
  47. package/dist/core/model/model-catalog.js +215 -0
  48. package/dist/core/model/model-scope.js +250 -0
  49. package/dist/core/relation/peer-identity.js +78 -44
  50. package/dist/core/relation/peer-key.js +16 -0
  51. package/dist/core/session/session-fs-store.js +34 -55
  52. package/dist/core/session/session-key.js +24 -0
  53. package/dist/core/session/session-manager.js +312 -251
  54. package/dist/core/session/session-mapper.js +9 -4
  55. package/dist/core/trigger/manager.js +37 -0
  56. package/dist/core/trigger/scheduler.js +2 -1
  57. package/dist/index.js +10 -3
  58. package/dist/ipc.js +22 -0
  59. package/dist/paths.js +87 -16
  60. package/dist/utils/npm-ops.js +18 -11
  61. package/kits/docs/GUIDE.md +2 -2
  62. package/kits/docs/INDEX.md +11 -7
  63. package/kits/docs/channels/aun.md +56 -17
  64. package/kits/docs/channels/feishu.md +41 -12
  65. package/kits/docs/context-assembly.md +181 -0
  66. package/kits/docs/evolclaw/agent.md +49 -0
  67. package/kits/docs/evolclaw/aid.md +49 -0
  68. package/kits/docs/evolclaw/ctl.md +46 -0
  69. package/kits/docs/evolclaw/group.md +82 -0
  70. package/kits/docs/evolclaw/msg.md +86 -0
  71. package/kits/docs/evolclaw/rpc.md +35 -0
  72. package/kits/docs/evolclaw/storage.md +49 -0
  73. package/kits/docs/venues/aun-group.md +10 -0
  74. package/kits/docs/venues/aun-private.md +10 -0
  75. package/kits/docs/venues/client-desktop.md +10 -0
  76. package/kits/docs/venues/client-mobile.md +10 -0
  77. package/kits/docs/venues/feishu-group.md +13 -0
  78. package/kits/docs/venues/feishu-private.md +9 -0
  79. package/kits/docs/venues/group.md +11 -0
  80. package/kits/docs/venues/private.md +10 -0
  81. package/kits/eck_manifest.json +75 -39
  82. package/kits/rules/01-overview.md +20 -10
  83. package/kits/rules/05-venue.md +2 -2
  84. package/kits/rules/06-channel.md +30 -27
  85. package/kits/templates/system-fragments/baseagent.md +7 -1
  86. package/kits/templates/system-fragments/channel.md +4 -1
  87. package/kits/templates/system-fragments/identity.md +4 -4
  88. package/kits/templates/system-fragments/relation.md +8 -5
  89. package/kits/templates/system-fragments/session.md +27 -0
  90. package/kits/templates/system-fragments/venue.md +13 -1
  91. package/package.json +13 -6
  92. package/dist/aun/aid/lifecycle-log.js +0 -33
  93. package/dist/net-check.js +0 -640
  94. package/dist/utils/aid-lifecycle-log.js +0 -33
  95. package/dist/watch-msg.js +0 -544
  96. package/kits/docs/evolclaw/AGENT_CMD.md +0 -31
  97. package/kits/docs/evolclaw/MSG_GROUP.md +0 -30
  98. package/kits/docs/evolclaw/MSG_PRIVATE.md +0 -72
  99. package/kits/docs/evolclaw/tools.md +0 -25
  100. package/kits/templates/system-fragments/eckruntime.md +0 -14
package/dist/watch-msg.js DELETED
@@ -1,544 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { resolvePaths, getPackageRoot } from './paths.js';
4
- import { decodeDirSegment, readAllJsonlLines } from './core/session/session-fs-store.js';
5
- // ==================== ANSI ====================
6
- const isTTY = !!process.stdout.isTTY;
7
- const RST = isTTY ? '\x1b[0m' : '';
8
- const DIM = isTTY ? '\x1b[2m' : '';
9
- const BOLD = isTTY ? '\x1b[1m' : '';
10
- const CYAN = isTTY ? '\x1b[36m' : '';
11
- const GREEN = isTTY ? '\x1b[32m' : '';
12
- const BLUE = isTTY ? '\x1b[34m' : '';
13
- const ORANGE = isTTY ? '\x1b[38;5;208m' : '';
14
- const BG_SEL = isTTY ? '\x1b[48;5;236m' : ''; // dark gray background for selected row
15
- // ==================== Helpers ====================
16
- function visualWidth(s) {
17
- const stripped = s.replace(/\x1b\[[0-9;]*m/g, '');
18
- let w = 0;
19
- for (const ch of stripped) {
20
- const code = ch.charCodeAt(0);
21
- w += (code >= 0x4e00 && code <= 0x9fff) || (code >= 0x3000 && code <= 0x30ff) ||
22
- (code >= 0xff00 && code <= 0xffef) ? 2 : 1;
23
- }
24
- return w;
25
- }
26
- function padRight(s, width) {
27
- const pad = Math.max(0, width - visualWidth(s));
28
- return s + ' '.repeat(pad);
29
- }
30
- function truncate(s, maxWidth) {
31
- let w = 0;
32
- let i = 0;
33
- for (const ch of s) {
34
- const code = ch.charCodeAt(0);
35
- const cw = (code >= 0x4e00 && code <= 0x9fff) || (code >= 0x3000 && code <= 0x30ff) ||
36
- (code >= 0xff00 && code <= 0xffef) ? 2 : 1;
37
- if (w + cw > maxWidth - 1)
38
- return s.slice(0, i) + '…';
39
- w += cw;
40
- i += ch.length;
41
- }
42
- return s;
43
- }
44
- function formatTimeAgo(ms) {
45
- const sec = Math.floor(ms / 1000);
46
- if (sec < 60)
47
- return `${sec}s`;
48
- const min = Math.floor(sec / 60);
49
- if (min < 60)
50
- return `${min}m`;
51
- const hour = Math.floor(min / 60);
52
- if (hour < 24)
53
- return `${hour}h`;
54
- return `${Math.floor(hour / 24)}d`;
55
- }
56
- function formatTime(ts) {
57
- const d = new Date(ts);
58
- return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
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
- }
68
- function shortAid(aid) {
69
- return aid.split('.')[0];
70
- }
71
- // ==================== Data Layer ====================
72
- function getSessionsAunDir() {
73
- const p = resolvePaths();
74
- return path.join(p.sessionsDir, 'aun');
75
- }
76
- function listLocalAids(aunDir) {
77
- try {
78
- return fs.readdirSync(aunDir, { withFileTypes: true })
79
- .filter(e => e.isDirectory())
80
- .map(e => decodeDirSegment(e.name));
81
- }
82
- catch {
83
- return [];
84
- }
85
- }
86
- function listPeers(aunDir, localAid) {
87
- const aidDir = path.join(aunDir, encodeSegment(localAid));
88
- try {
89
- return fs.readdirSync(aidDir, { withFileTypes: true })
90
- .filter(e => e.isDirectory() && !e.name.startsWith('_'))
91
- .map(e => decodeDirSegment(e.name));
92
- }
93
- catch {
94
- return [];
95
- }
96
- }
97
- function readMessages(aunDir, localAid, peerId) {
98
- const msgPath = path.join(aunDir, encodeSegment(localAid), encodeSegment(peerId), 'messages.jsonl');
99
- return readAllJsonlLines(msgPath);
100
- }
101
- function readPeerName(aunDir, localAid, peerId) {
102
- const activePath = path.join(aunDir, encodeSegment(localAid), encodeSegment(peerId), 'active.json');
103
- try {
104
- const data = JSON.parse(fs.readFileSync(activePath, 'utf-8'));
105
- return data?.metadata?.peerName || null;
106
- }
107
- catch {
108
- return null;
109
- }
110
- }
111
- function encodeSegment(s) {
112
- return s.replace(/[/%\\:*?"<>|]/g, ch => '%' + ch.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0'));
113
- }
114
- function loadAidInfo(aunDir, aid) {
115
- const peers = listPeers(aunDir, aid);
116
- let totalIn = 0, totalOut = 0;
117
- for (const peer of peers) {
118
- const msgs = readMessages(aunDir, aid, peer);
119
- for (const m of msgs) {
120
- if (m.dir === 'in')
121
- totalIn++;
122
- else
123
- totalOut++;
124
- }
125
- }
126
- return { aid, totalIn, totalOut, peerCount: peers.length };
127
- }
128
- function loadPeerInfos(aunDir, localAid) {
129
- const peers = listPeers(aunDir, localAid);
130
- const infos = [];
131
- for (const peerId of peers) {
132
- const msgs = readMessages(aunDir, localAid, peerId);
133
- let inbound = 0, outbound = 0, lastAt = 0;
134
- for (const m of msgs) {
135
- if (m.dir === 'in')
136
- inbound++;
137
- else
138
- outbound++;
139
- if (m.ts > lastAt)
140
- lastAt = m.ts;
141
- }
142
- const peerName = readPeerName(aunDir, localAid, peerId);
143
- infos.push({ peerId, peerName, inbound, outbound, lastAt });
144
- }
145
- infos.sort((a, b) => b.lastAt - a.lastAt);
146
- return infos;
147
- }
148
- function loadAllMessages(aunDir, localAid) {
149
- const peers = listPeers(aunDir, localAid);
150
- const all = [];
151
- for (const peer of peers) {
152
- all.push(...readMessages(aunDir, localAid, peer));
153
- }
154
- all.sort((a, b) => a.ts - b.ts);
155
- if (all.length > 1000)
156
- return all.slice(-1000);
157
- return all;
158
- }
159
- // ==================== Rendering ====================
160
- function renderScrollbar(totalLines, visibleLines, offset, height) {
161
- if (totalLines <= visibleLines)
162
- return Array(height).fill(' ');
163
- const thumbSize = Math.max(1, Math.floor(height * visibleLines / totalLines));
164
- const maxOffset = totalLines - visibleLines;
165
- const thumbPos = Math.floor((maxOffset - offset) / maxOffset * (height - thumbSize));
166
- const bar = [];
167
- for (let i = 0; i < height; i++) {
168
- bar.push(i >= thumbPos && i < thumbPos + thumbSize ? `${DIM}█${RST}` : `${DIM}░${RST}`);
169
- }
170
- return bar;
171
- }
172
- function renderScopePanel(state, width, height) {
173
- const lines = [];
174
- const title = `${DIM}─ Scope ─${RST}`;
175
- lines.push(padRight(title, width));
176
- const isActive = state.activePanel === 'scope';
177
- for (let i = 0; i < state.localAids.length && lines.length < height; i++) {
178
- const a = state.localAids[i];
179
- const sel = isActive && i === state.scopeIndex;
180
- const chosen = state.selectedLocalAid === a.aid;
181
- const bg = sel ? BG_SEL : '';
182
- const marker = sel ? `${bg}${CYAN}${BOLD}▸ ` : (chosen ? `${CYAN} ` : ' ');
183
- const name = truncate(shortAid(a.aid), width - 4);
184
- lines.push(padRight(`${marker}${name}${RST}`, width));
185
- const statsBg = sel ? BG_SEL : '';
186
- const stats = `${statsBg} ${DIM}↓${a.totalIn} ↑${a.totalOut} peers:${a.peerCount}${RST}`;
187
- lines.push(padRight(stats, width));
188
- if (lines.length < height)
189
- lines.push(padRight('', width));
190
- }
191
- while (lines.length < height)
192
- lines.push(padRight('', width));
193
- return lines.slice(0, height);
194
- }
195
- function renderStatsPanel(state, width, height) {
196
- const lines = [];
197
- const title = `${DIM}─ Stats ─${RST}`;
198
- lines.push(padRight(title, width));
199
- if (!state.selectedLocalAid) {
200
- lines.push(padRight(`${DIM} select an AID${RST}`, width));
201
- while (lines.length < height)
202
- lines.push(padRight('', width));
203
- return lines.slice(0, height);
204
- }
205
- const isActive = state.activePanel === 'stats';
206
- const now = Date.now();
207
- // "All" item at index 0
208
- const allSel = isActive && state.statsIndex === 0;
209
- const allBg = allSel ? BG_SEL : '';
210
- const allMarker = allSel ? `${allBg}${CYAN}${BOLD}▸ ` : ' ';
211
- lines.push(padRight(`${allMarker}All (${state.peers.length} peers)${RST}`, width));
212
- if (lines.length < height)
213
- lines.push(padRight('', width));
214
- for (let i = 0; i < state.peers.length && lines.length < height; i++) {
215
- const p = state.peers[i];
216
- const sel = isActive && state.statsIndex === i + 1;
217
- const bg = sel ? BG_SEL : '';
218
- const marker = sel ? `${bg}${CYAN}${BOLD}▸ ` : ' ';
219
- const displayName = p.peerName || shortAid(p.peerId);
220
- const name = truncate(displayName, width - 4);
221
- lines.push(padRight(`${marker}${name}${RST}`, width));
222
- const detailBg = sel ? BG_SEL : '';
223
- const ago = p.lastAt ? formatTimeAgo(now - p.lastAt) : '-';
224
- const detail = `${detailBg} ${DIM}↓${p.inbound} ↑${p.outbound} ${ago}${RST}`;
225
- lines.push(padRight(detail, width));
226
- if (lines.length < height)
227
- lines.push(padRight('', width));
228
- }
229
- while (lines.length < height)
230
- lines.push(padRight('', width));
231
- return lines.slice(0, height);
232
- }
233
- // ==================== Messages Panel ====================
234
- function renderMessagesPanel(state, width, height) {
235
- const lines = [];
236
- const title = `${DIM}─ Messages ─${RST}`;
237
- lines.push(padRight(title, width));
238
- const contentHeight = height - 1;
239
- const msgs = state.messages;
240
- const totalMsgs = msgs.length;
241
- const visibleCount = contentHeight;
242
- const startIdx = Math.max(0, totalMsgs - visibleCount - state.messageScrollOffset);
243
- const endIdx = Math.min(totalMsgs, startIdx + visibleCount);
244
- const scrollbar = renderScrollbar(totalMsgs, visibleCount, state.messageScrollOffset, contentHeight);
245
- const msgWidth = width - 3;
246
- for (let i = startIdx; i < endIdx; i++) {
247
- const m = msgs[i];
248
- const time = formatDateTime(m.ts);
249
- const dir = m.dir === 'in' ? `${GREEN}↓${RST}` : `${BLUE}↑${RST}`;
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}`;
253
- const headerLine = padRight(header, msgWidth);
254
- const sbIdx = lines.length - 1;
255
- lines.push(`${headerLine} ${scrollbar[sbIdx] || ' '}`);
256
- if (lines.length - 1 < contentHeight) {
257
- const content = truncate(m.content.replace(/\n/g, ' '), msgWidth - 2);
258
- const contentLine = padRight(` ${content}`, msgWidth);
259
- const sbIdx2 = lines.length - 1;
260
- lines.push(`${contentLine} ${scrollbar[sbIdx2] || ' '}`);
261
- }
262
- }
263
- while (lines.length < height) {
264
- const sbIdx = lines.length - 1;
265
- lines.push(padRight('', msgWidth) + ` ${scrollbar[sbIdx] || ' '}`);
266
- }
267
- return lines.slice(0, height);
268
- }
269
- // ==================== Main Render ====================
270
- function renderFrame(state) {
271
- const cols = process.stdout.columns || 120;
272
- const rows = (process.stdout.rows || 40) - 3;
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);
276
- const bodyHeight = rows - 2;
277
- const leftLines = renderScopePanel(state, leftW, bodyHeight);
278
- const midLines = renderStatsPanel(state, midW, bodyHeight);
279
- const msgLines = renderMessagesPanel(state, rightW, bodyHeight);
280
- const sep = `${DIM}│${RST}`;
281
- let buf = '\x1b[H';
282
- const topBorder = `${DIM}┌${'─'.repeat(leftW)}┬${'─'.repeat(midW)}┬${'─'.repeat(rightW + 1)}┐${RST}`;
283
- buf += `\x1b[2K${topBorder}\n`;
284
- for (let i = 0; i < bodyHeight; i++) {
285
- const l = leftLines[i] || padRight('', leftW);
286
- const m = midLines[i] || padRight('', midW);
287
- const r = msgLines[i] || padRight('', rightW);
288
- buf += `\x1b[2K${sep}${l}${sep}${m}${sep}${r}${sep}\n`;
289
- }
290
- const bottomBorder = `${DIM}├${'─'.repeat(leftW)}┴${'─'.repeat(midW)}┴${'─'.repeat(rightW + 1)}┤${RST}`;
291
- buf += `\x1b[2K${bottomBorder}\n`;
292
- const pkgRoot = getPackageRoot();
293
- const helpLine = `${DIM}│ Tab: panel ↑↓: nav Enter: select Backspace: back ESC: exit ${pkgRoot}${RST}`;
294
- buf += `\x1b[2K${helpLine}\n`;
295
- const closeBorder = `${DIM}└${'─'.repeat(cols - 2)}┘${RST}`;
296
- buf += `\x1b[2K${closeBorder}\n`;
297
- return buf;
298
- }
299
- // ==================== Main ====================
300
- export async function cmdWatchMsg() {
301
- const aunDir = getSessionsAunDir();
302
- if (!fs.existsSync(aunDir)) {
303
- console.log('No session data found.');
304
- return;
305
- }
306
- let watcher = null;
307
- const state = {
308
- activePanel: 'scope',
309
- localAids: [],
310
- scopeIndex: 0,
311
- selectedLocalAid: null,
312
- peers: [],
313
- statsIndex: 0,
314
- selectedPeer: null,
315
- messages: [],
316
- messageScrollOffset: 0,
317
- dirty: true,
318
- };
319
- function loadScope() {
320
- const aids = listLocalAids(aunDir);
321
- state.localAids = aids.map(aid => loadAidInfo(aunDir, aid));
322
- state.localAids.sort((a, b) => (b.totalIn + b.totalOut) - (a.totalIn + a.totalOut));
323
- }
324
- function selectAid(aid) {
325
- state.selectedLocalAid = aid;
326
- state.peers = loadPeerInfos(aunDir, aid);
327
- state.statsIndex = 0;
328
- state.selectedPeer = null;
329
- state.messages = loadAllMessages(aunDir, aid);
330
- state.messageScrollOffset = 0;
331
- startWatching(aid);
332
- }
333
- function selectPeer(peerId) {
334
- state.selectedPeer = peerId;
335
- if (!state.selectedLocalAid)
336
- return;
337
- if (peerId) {
338
- state.messages = readMessages(aunDir, state.selectedLocalAid, peerId);
339
- if (state.messages.length > 1000)
340
- state.messages = state.messages.slice(-1000);
341
- }
342
- else {
343
- state.messages = loadAllMessages(aunDir, state.selectedLocalAid);
344
- }
345
- state.messageScrollOffset = 0;
346
- }
347
- function startWatching(aid) {
348
- if (watcher) {
349
- watcher.close();
350
- watcher = null;
351
- }
352
- const aidDir = path.join(aunDir, encodeSegment(aid));
353
- try {
354
- watcher = fs.watch(aidDir, { recursive: true }, (_, filename) => {
355
- if (filename && filename.endsWith('messages.jsonl')) {
356
- refreshData();
357
- render();
358
- }
359
- });
360
- }
361
- catch { /* directory may not exist */ }
362
- }
363
- function refreshData() {
364
- if (!state.selectedLocalAid)
365
- return;
366
- state.peers = loadPeerInfos(aunDir, state.selectedLocalAid);
367
- if (state.selectedPeer) {
368
- state.messages = readMessages(aunDir, state.selectedLocalAid, state.selectedPeer);
369
- if (state.messages.length > 1000)
370
- state.messages = state.messages.slice(-1000);
371
- }
372
- else {
373
- state.messages = loadAllMessages(aunDir, state.selectedLocalAid);
374
- }
375
- // Also refresh scope stats for the selected AID
376
- const idx = state.localAids.findIndex(a => a.aid === state.selectedLocalAid);
377
- if (idx >= 0) {
378
- state.localAids[idx] = loadAidInfo(aunDir, state.selectedLocalAid);
379
- }
380
- }
381
- function render() {
382
- process.stdout.write(renderFrame(state));
383
- }
384
- function cleanup() {
385
- if (watcher) {
386
- watcher.close();
387
- watcher = null;
388
- }
389
- if (process.stdin.isTTY)
390
- try {
391
- process.stdin.setRawMode(false);
392
- }
393
- catch { }
394
- process.stdin.pause();
395
- process.stdout.write('\x1b[?25h\x1b[2J\x1b[H');
396
- }
397
- function handleKey(data) {
398
- // ESC
399
- if (data[0] === 0x1b && data.length === 1) {
400
- cleanup();
401
- process.exit(0);
402
- }
403
- // Ctrl+C
404
- if (data[0] === 0x03) {
405
- cleanup();
406
- process.exit(0);
407
- }
408
- // Arrow keys
409
- if (data[0] === 0x1b && data[1] === 0x5b) {
410
- const code = data[2];
411
- if (code === 0x41)
412
- handleUp();
413
- else if (code === 0x42)
414
- handleDown();
415
- else if (code === 0x43)
416
- handleRight();
417
- else if (code === 0x44)
418
- handleLeft();
419
- else if (code === 0x35)
420
- handlePageUp(); // Page Up: \x1b[5~
421
- else if (code === 0x36)
422
- handlePageDown(); // Page Down: \x1b[6~
423
- render();
424
- return;
425
- }
426
- // Tab
427
- if (data[0] === 0x09) {
428
- handleRight();
429
- render();
430
- return;
431
- }
432
- // Shift+Tab (some terminals: \x1b[Z)
433
- if (data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x5a) {
434
- handleLeft();
435
- render();
436
- return;
437
- }
438
- // Enter
439
- if (data[0] === 0x0d) {
440
- handleEnter();
441
- render();
442
- return;
443
- }
444
- // Backspace
445
- if (data[0] === 0x7f || data[0] === 0x08) {
446
- handleBackspace();
447
- render();
448
- return;
449
- }
450
- }
451
- function handleUp() {
452
- if (state.activePanel === 'scope') {
453
- state.scopeIndex = Math.max(0, state.scopeIndex - 1);
454
- }
455
- else if (state.activePanel === 'stats') {
456
- state.statsIndex = Math.max(0, state.statsIndex - 1);
457
- }
458
- else if (state.activePanel === 'messages') {
459
- state.messageScrollOffset = Math.min(Math.max(0, state.messages.length - 5), state.messageScrollOffset + 3);
460
- }
461
- }
462
- function handleDown() {
463
- if (state.activePanel === 'scope') {
464
- state.scopeIndex = Math.min(state.localAids.length - 1, state.scopeIndex + 1);
465
- }
466
- else if (state.activePanel === 'stats') {
467
- state.statsIndex = Math.min(state.peers.length, state.statsIndex + 1);
468
- }
469
- else if (state.activePanel === 'messages') {
470
- state.messageScrollOffset = Math.max(0, state.messageScrollOffset - 3);
471
- }
472
- }
473
- function handleLeft() {
474
- if (state.activePanel === 'messages')
475
- state.activePanel = 'stats';
476
- else if (state.activePanel === 'stats')
477
- state.activePanel = 'scope';
478
- }
479
- function handleRight() {
480
- if (state.activePanel === 'scope')
481
- state.activePanel = 'stats';
482
- else if (state.activePanel === 'stats')
483
- state.activePanel = 'messages';
484
- }
485
- function handlePageUp() {
486
- if (state.activePanel === 'messages') {
487
- const pageSize = (process.stdout.rows || 40) - 6;
488
- state.messageScrollOffset = Math.min(Math.max(0, state.messages.length - 5), state.messageScrollOffset + pageSize);
489
- }
490
- }
491
- function handlePageDown() {
492
- if (state.activePanel === 'messages') {
493
- const pageSize = (process.stdout.rows || 40) - 6;
494
- state.messageScrollOffset = Math.max(0, state.messageScrollOffset - pageSize);
495
- }
496
- }
497
- function handleEnter() {
498
- if (state.activePanel === 'scope' && state.localAids.length > 0) {
499
- const aid = state.localAids[state.scopeIndex];
500
- selectAid(aid.aid);
501
- state.activePanel = 'stats';
502
- }
503
- else if (state.activePanel === 'stats') {
504
- if (state.statsIndex === 0) {
505
- selectPeer(null);
506
- }
507
- else {
508
- const peer = state.peers[state.statsIndex - 1];
509
- if (peer)
510
- selectPeer(peer.peerId);
511
- }
512
- state.activePanel = 'messages';
513
- }
514
- }
515
- function handleBackspace() {
516
- if (state.activePanel === 'messages') {
517
- state.activePanel = 'stats';
518
- state.messageScrollOffset = 0;
519
- }
520
- else if (state.activePanel === 'stats') {
521
- state.activePanel = 'scope';
522
- state.selectedLocalAid = null;
523
- state.peers = [];
524
- state.messages = [];
525
- if (watcher) {
526
- watcher.close();
527
- watcher = null;
528
- }
529
- }
530
- }
531
- // ── Init ──
532
- process.on('SIGINT', () => { cleanup(); process.exit(0); });
533
- process.on('SIGTERM', () => { cleanup(); process.exit(0); });
534
- loadScope();
535
- process.stdout.write('\x1b[?25l\x1b[2J\x1b[H');
536
- render();
537
- if (process.stdin.isTTY) {
538
- process.stdin.setRawMode(true);
539
- process.stdin.resume();
540
- process.stdin.on('data', handleKey);
541
- }
542
- // Keep process alive
543
- await new Promise(() => { });
544
- }
@@ -1,31 +0,0 @@
1
- # EvolClaw 可用命令
2
-
3
- 通过 `evolclaw ctl <command> [args]` 管理运行时配置。仅在 evolclaw 托管环境中可用。
4
-
5
- ## 查询类(所有用户)
6
- - `evolclaw ctl help` — 显示帮助
7
- - `evolclaw ctl status` — 显示会话状态
8
- - `evolclaw ctl check` — 检查渠道健康状态
9
-
10
- ## 配置类(管理员)
11
- - `evolclaw ctl model` — 查看当前模型和可选列表
12
- - `evolclaw ctl model <model-id>` — 切换模型(如 `opus`, `sonnet`, `haiku`)
13
- - `evolclaw ctl effort` — 查看当前推理强度
14
- - `evolclaw ctl effort <low|medium|high|max>` — 切换推理强度
15
- - `evolclaw ctl compact` — 压缩当前会话上下文
16
-
17
- ## 权限类
18
- - `evolclaw ctl perm` — 查看当前权限模式(管理员)
19
- - `evolclaw ctl perm <mode>` — 切换权限模式(仅 owner)
20
-
21
- ## 运维类(仅 owner)
22
- - `evolclaw ctl activity <all|dm|owner|none>` — 查看/控制中间输出显示模式
23
- - `evolclaw ctl send [channel] <message>` — 发送消息
24
- - `evolclaw ctl file <path>` — 发送文件
25
- - `evolclaw ctl restart` — 重启服务
26
- - `evolclaw ctl restart <channel>` — 重连指定渠道
27
- - `evolclaw ctl agentmd` — 查看当前 agent.md
28
- - `evolclaw ctl agentmd put` — 发布本地 agent.md
29
- - `evolclaw ctl agentmd set <内容>` — 直接设置 agent.md 内容
30
- - `evolclaw ctl aid` — 列出所有 AUN 实例及连接状态
31
- - `evolclaw ctl aid new <aid>` — 创建新 AID 并热加载
@@ -1,30 +0,0 @@
1
- # 群聊消息命令
2
-
3
- <!-- TODO: 填充群聊消息命令详细参考 -->
4
-
5
- ## 发送群消息
6
-
7
- ```bash
8
- evolclaw group send <from-aid> <group-id> "<message>"
9
- ```
10
-
11
- ## 拉取群消息
12
-
13
- ```bash
14
- evolclaw group pull <self-aid> <group-id> --app <app-name>
15
- ```
16
-
17
- ## 群管理
18
-
19
- ```bash
20
- evolclaw group create <owner-aid> --name "<group-name>"
21
- evolclaw group list <self-aid>
22
- evolclaw group info <self-aid> <group-id>
23
- evolclaw group invite <self-aid> <group-id> <target-aid>
24
- evolclaw group kick <self-aid> <group-id> <target-aid>
25
- evolclaw group members <self-aid> <group-id>
26
- ```
27
-
28
- ## 自主回复策略
29
-
30
- 群聊中被 @ 才默认响应,可通过 venue policy 配置其他触发条件。
@@ -1,72 +0,0 @@
1
- # 私聊消息命令
2
-
3
- ## 发送消息
4
-
5
- ### 以指定 AID 发送(首选)
6
-
7
- ```bash
8
- # 明文
9
- ec msg send <from-aid> <to-aid> "<message>"
10
-
11
- # 密文(E2EE)
12
- ec msg send <from-aid> <to-aid> "<message>" --encrypt
13
- ```
14
-
15
- ### 发送文件
16
-
17
- ```bash
18
- ec msg send <from-aid> <to-aid> --file <path>
19
- ec msg send <from-aid> <to-aid> --file <path> --as image
20
- ec msg send <from-aid> <to-aid> --file <path> --encrypt
21
- ```
22
-
23
- `--as` 可选值:`image` | `video` | `voice` | `file`(默认按扩展名推断)
24
-
25
- ## 拉取消息
26
-
27
- ```bash
28
- ec msg pull <self-aid> --app <app-name>
29
- ec msg pull <self-aid> --app <app-name> --after-seq <N> --limit <N>
30
- ```
31
-
32
- ## 确认消息已读
33
-
34
- ```bash
35
- ec msg ack <self-aid> <seq> --app <app-name>
36
- ```
37
-
38
- `--app` 必须传,否则会污染 daemon 游标。
39
-
40
- ## 撤回消息
41
-
42
- ```bash
43
- ec msg recall <self-aid> <message-id>
44
- ```
45
-
46
- ## 查询在线状态
47
-
48
- ```bash
49
- ec msg online <self-aid> <target-aid>
50
- ```
51
-
52
- ## 自主回复策略
53
-
54
- 收到消息 ≠ 必须回复。是否回复、怎么回复、何时回复由 agent 自主决定。
55
-
56
- 加密策略:
57
- - 对端发来密文消息时,回复也应使用 `--encrypt`(保持对话加密一致性)
58
- - 对端发来明文消息时,默认明文回复
59
-
60
- ## 在当前会话中快速回复(备选)
61
-
62
- 仅当无法使用 `ec msg send` 时(如不知道自己的 AID),可用 `ec ctl send`:
63
-
64
- ```bash
65
- # 明文
66
- ec ctl send "<text>"
67
-
68
- # 密文
69
- ec ctl send --encrypt "<text>"
70
- ```
71
-
72
- `ec ctl send` 自动继承当前会话的 AID 和对端,无需指定。
@@ -1,25 +0,0 @@
1
- # EvolClaw 可用工具
2
-
3
- evolclaw 托管环境下,baseagent 可通过 Bash 工具调用以下命令:
4
-
5
- ## 消息发送
6
- - `evolclaw ctl send "<消息>"` — 发送文本消息给当前对话方
7
- - `evolclaw ctl file <路径>` — 发送项目内文件
8
-
9
- ## 运行时查询
10
- - `evolclaw ctl status` — 当前会话状态
11
- - `evolclaw ctl model` — 当前模型信息
12
- - `evolclaw ctl effort` — 当前推理强度
13
- - `evolclaw ctl check` — 渠道健康检查
14
- - `evolclaw ctl aid` — AUN 连接状态
15
-
16
- ## 运行时配置
17
- - `evolclaw ctl model <id>` — 切换模型
18
- - `evolclaw ctl effort <level>` — 切换推理强度
19
- - `evolclaw ctl compact` — 压缩上下文
20
- - `evolclaw ctl perm <mode>` — 切换权限模式
21
-
22
- ## agent.md 管理
23
- - `evolclaw ctl agentmd` — 查看当前 agent.md
24
- - `evolclaw ctl agentmd put` — 发布到 AUN 网络
25
- - `evolclaw ctl agentmd set <内容>` — 直接设置内容