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/cli/init.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
2
|
import readline from 'readline';
|
|
4
3
|
import { resolvePaths, ensureDataDirs } from '../paths.js';
|
|
5
4
|
import { commandExists } from '../utils/cross-platform.js';
|
|
6
5
|
import { scanInstances } from '../utils/instance-registry.js';
|
|
6
|
+
import { saveDefaultsSafe } from '../config-store.js';
|
|
7
7
|
// ==================== Helpers ====================
|
|
8
8
|
function ask(rl, question) {
|
|
9
9
|
return new Promise(resolve => rl.question(question, resolve));
|
|
@@ -28,9 +28,8 @@ function buildDefaults(chosen) {
|
|
|
28
28
|
baseagents: { [chosen]: env ? { apiKey: `$ENV:${env}` } : {} },
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
|
-
function writeDefaults(
|
|
32
|
-
|
|
33
|
-
fs.writeFileSync(defaultsPath, JSON.stringify(buildDefaults(chosen), null, 2) + '\n');
|
|
31
|
+
function writeDefaults(_defaultsPath, chosen) {
|
|
32
|
+
saveDefaultsSafe(buildDefaults(chosen));
|
|
34
33
|
}
|
|
35
34
|
// ==================== Main ====================
|
|
36
35
|
export async function cmdInit(options) {
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { kitsRulesDir, resolvePaths } from '../paths.js';
|
|
4
|
+
import { atomicWriteJson, atomicReadJson } from '../utils/atomic-write.js';
|
|
5
|
+
const isWindows = process.platform === 'win32';
|
|
6
|
+
const KNOWN_BASEAGENTS = ['cc', 'codex', 'gemini'];
|
|
7
|
+
function statePath() {
|
|
8
|
+
return path.join(resolvePaths().eckDir, 'link-state.json');
|
|
9
|
+
}
|
|
10
|
+
function loadState() {
|
|
11
|
+
return atomicReadJson(statePath()) ?? {};
|
|
12
|
+
}
|
|
13
|
+
function saveState(state) {
|
|
14
|
+
atomicWriteJson(statePath(), state);
|
|
15
|
+
}
|
|
16
|
+
function getEntry(state, ba) {
|
|
17
|
+
return state[ba] ?? { current: null, history: [] };
|
|
18
|
+
}
|
|
19
|
+
function pushHistory(entry, dir) {
|
|
20
|
+
entry.history = [dir, ...entry.history.filter(h => h !== dir)].slice(0, 5);
|
|
21
|
+
}
|
|
22
|
+
// ── symlink 目标路径(baseagent 决定放哪)──
|
|
23
|
+
function resolveTarget(ba, dir) {
|
|
24
|
+
switch (ba) {
|
|
25
|
+
case 'cc':
|
|
26
|
+
return path.join(dir, '.claude', 'rules', 'eck');
|
|
27
|
+
case 'codex':
|
|
28
|
+
return path.join(dir, '.codex', 'rules', 'eck');
|
|
29
|
+
case 'gemini':
|
|
30
|
+
return path.join(dir, '.gemini', 'rules', 'eck');
|
|
31
|
+
default:
|
|
32
|
+
return path.join(dir, '.claude', 'rules', 'eck');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// ── 创建 symlink/junction ──
|
|
36
|
+
function createLink(source, target) {
|
|
37
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
38
|
+
if (isWindows) {
|
|
39
|
+
fs.symlinkSync(source, target, 'junction');
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
fs.symlinkSync(source, target, 'dir');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// ── 删除 symlink/junction + 逐级清理空目录 ──
|
|
46
|
+
function removeLink(target) {
|
|
47
|
+
if (!fs.existsSync(target))
|
|
48
|
+
return false;
|
|
49
|
+
const stat = fs.lstatSync(target);
|
|
50
|
+
if (stat.isSymbolicLink()) {
|
|
51
|
+
fs.rmSync(target, { recursive: true });
|
|
52
|
+
}
|
|
53
|
+
else if (isWindows && stat.isDirectory()) {
|
|
54
|
+
const real = fs.realpathSync(target);
|
|
55
|
+
const resolved = path.resolve(target);
|
|
56
|
+
if (real.toLowerCase() === resolved.toLowerCase()) {
|
|
57
|
+
return false; // regular directory, not a junction
|
|
58
|
+
}
|
|
59
|
+
fs.rmSync(target, { recursive: true });
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
cleanEmptyParents(path.dirname(target));
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
function cleanEmptyParents(dir) {
|
|
68
|
+
try {
|
|
69
|
+
const entries = fs.readdirSync(dir);
|
|
70
|
+
if (entries.length > 0)
|
|
71
|
+
return;
|
|
72
|
+
fs.rmdirSync(dir);
|
|
73
|
+
cleanEmptyParents(path.dirname(dir));
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// stop on error (permission, root, etc.)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// ── 子命令 ──
|
|
80
|
+
function showHelp() {
|
|
81
|
+
console.log(`Usage: evolclaw link-rules <subcommand> [baseagent] [--dir <path>]
|
|
82
|
+
|
|
83
|
+
Subcommands:
|
|
84
|
+
connect Connect ECK rules to a project directory (default: cwd)
|
|
85
|
+
disconnect Remove ECK rules connection for a baseagent
|
|
86
|
+
status Show connection state for all baseagents
|
|
87
|
+
|
|
88
|
+
Arguments:
|
|
89
|
+
baseagent Target base agent: ${KNOWN_BASEAGENTS.join(', ')} (default: cc)
|
|
90
|
+
--dir <path> Target directory (default: current working directory)
|
|
91
|
+
|
|
92
|
+
Supported baseagents:
|
|
93
|
+
cc Claude Code (.claude/rules/eck/)
|
|
94
|
+
codex Codex (.codex/rules/eck/)
|
|
95
|
+
gemini Gemini CLI (.gemini/rules/eck/)
|
|
96
|
+
|
|
97
|
+
Examples:
|
|
98
|
+
evolclaw link-rules connect # connect cc in cwd
|
|
99
|
+
evolclaw link-rules connect codex # connect codex in cwd
|
|
100
|
+
evolclaw link-rules connect cc --dir /x # connect cc in specific dir
|
|
101
|
+
evolclaw link-rules disconnect cc # disconnect cc
|
|
102
|
+
evolclaw link-rules status # show all connections`);
|
|
103
|
+
}
|
|
104
|
+
function showStatus() {
|
|
105
|
+
const state = loadState();
|
|
106
|
+
const source = kitsRulesDir();
|
|
107
|
+
console.log(`ECK rules source: ${source}\n`);
|
|
108
|
+
for (const ba of KNOWN_BASEAGENTS) {
|
|
109
|
+
const entry = getEntry(state, ba);
|
|
110
|
+
const status = entry.current ? '● connected' : '○ disconnected';
|
|
111
|
+
console.log(`[${ba}] ${status}`);
|
|
112
|
+
if (entry.current) {
|
|
113
|
+
const target = resolveTarget(ba, entry.current);
|
|
114
|
+
console.log(` path: ${entry.current}`);
|
|
115
|
+
console.log(` link: ${target}`);
|
|
116
|
+
console.log(` rules: ${source}`);
|
|
117
|
+
}
|
|
118
|
+
if (entry.history.length > 0) {
|
|
119
|
+
console.log(` history:`);
|
|
120
|
+
for (const h of entry.history) {
|
|
121
|
+
console.log(` - ${h}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
console.log('');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function connect(ba, dir) {
|
|
128
|
+
const source = kitsRulesDir();
|
|
129
|
+
if (!fs.existsSync(source)) {
|
|
130
|
+
console.error(`❌ kits/rules/ not found at: ${source}`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
const absDir = path.resolve(dir);
|
|
134
|
+
if (!fs.existsSync(absDir)) {
|
|
135
|
+
console.error(`❌ Directory does not exist: ${absDir}`);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
const state = loadState();
|
|
139
|
+
const entry = getEntry(state, ba);
|
|
140
|
+
// disconnect old link if exists (different dir)
|
|
141
|
+
if (entry.current && entry.current !== absDir) {
|
|
142
|
+
const oldTarget = resolveTarget(ba, entry.current);
|
|
143
|
+
removeLink(oldTarget);
|
|
144
|
+
console.log(` disconnected old: ${entry.current}`);
|
|
145
|
+
}
|
|
146
|
+
// create new link
|
|
147
|
+
const target = resolveTarget(ba, absDir);
|
|
148
|
+
if (fs.existsSync(target)) {
|
|
149
|
+
// already linked here — check if it points to our source
|
|
150
|
+
try {
|
|
151
|
+
const real = fs.realpathSync(target);
|
|
152
|
+
const sourceReal = fs.realpathSync(source);
|
|
153
|
+
if (pathEquals(real, sourceReal)) {
|
|
154
|
+
console.log(`✓ Already connected: [${ba}] → ${absDir}`);
|
|
155
|
+
entry.current = absDir;
|
|
156
|
+
pushHistory(entry, absDir);
|
|
157
|
+
state[ba] = entry;
|
|
158
|
+
saveState(state);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch { /* fall through */ }
|
|
163
|
+
console.error(`❌ Target already exists and points elsewhere: ${target}`);
|
|
164
|
+
console.error(` Run 'evolclaw link-rules disconnect ${ba}' first, or remove manually.`);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
createLink(source, target);
|
|
168
|
+
entry.current = absDir;
|
|
169
|
+
pushHistory(entry, absDir);
|
|
170
|
+
state[ba] = entry;
|
|
171
|
+
saveState(state);
|
|
172
|
+
console.log(`✓ Connected: [${ba}] ${absDir}`);
|
|
173
|
+
console.log(` ${target} → ${source}`);
|
|
174
|
+
}
|
|
175
|
+
function disconnect(ba) {
|
|
176
|
+
const state = loadState();
|
|
177
|
+
const entry = getEntry(state, ba);
|
|
178
|
+
if (!entry.current) {
|
|
179
|
+
console.log(`[${ba}] not connected.`);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const target = resolveTarget(ba, entry.current);
|
|
183
|
+
const removed = removeLink(target);
|
|
184
|
+
if (removed) {
|
|
185
|
+
console.log(`✓ Disconnected: [${ba}] ${entry.current}`);
|
|
186
|
+
}
|
|
187
|
+
else if (!fs.existsSync(target)) {
|
|
188
|
+
console.log(`✓ Disconnected: [${ba}] (link was already gone)`);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
console.error(`❌ Could not remove: ${target} (not a symlink/junction)`);
|
|
192
|
+
}
|
|
193
|
+
entry.current = null;
|
|
194
|
+
state[ba] = entry;
|
|
195
|
+
saveState(state);
|
|
196
|
+
}
|
|
197
|
+
// ── 入口 ──
|
|
198
|
+
export function cmdLinkRules(args) {
|
|
199
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
200
|
+
showHelp();
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const sub = args[0];
|
|
204
|
+
if (sub === 'status') {
|
|
205
|
+
showStatus();
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
if (sub === 'disconnect') {
|
|
209
|
+
const ba = resolveBaseAgent(args[1]);
|
|
210
|
+
disconnect(ba);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (sub === 'connect') {
|
|
214
|
+
const ba = resolveBaseAgent(args[1] && !args[1].startsWith('-') ? args[1] : undefined);
|
|
215
|
+
const dir = getArgValue(args, '--dir') || process.cwd();
|
|
216
|
+
connect(ba, dir);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
// no subcommand or unknown → show help
|
|
220
|
+
showHelp();
|
|
221
|
+
}
|
|
222
|
+
function resolveBaseAgent(input) {
|
|
223
|
+
if (!input || input === 'claude-code')
|
|
224
|
+
return 'cc';
|
|
225
|
+
if (KNOWN_BASEAGENTS.includes(input))
|
|
226
|
+
return input;
|
|
227
|
+
// allow full names
|
|
228
|
+
if (input === 'claude' || input === 'claude-code')
|
|
229
|
+
return 'cc';
|
|
230
|
+
console.error(`❌ Unknown baseagent: ${input}`);
|
|
231
|
+
console.error(` Supported: ${KNOWN_BASEAGENTS.join(', ')}`);
|
|
232
|
+
process.exit(1);
|
|
233
|
+
}
|
|
234
|
+
function getArgValue(args, flag) {
|
|
235
|
+
const idx = args.indexOf(flag);
|
|
236
|
+
if (idx === -1 || idx + 1 >= args.length)
|
|
237
|
+
return undefined;
|
|
238
|
+
return args[idx + 1];
|
|
239
|
+
}
|
|
240
|
+
function pathEquals(a, b) {
|
|
241
|
+
if (isWindows) {
|
|
242
|
+
return path.resolve(a).toLowerCase() === path.resolve(b).toLowerCase();
|
|
243
|
+
}
|
|
244
|
+
return path.resolve(a) === path.resolve(b);
|
|
245
|
+
}
|