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.
Files changed (104) 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 +47 -12
  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 +42 -1
  13. package/dist/channels/aun.js +427 -146
  14. package/dist/channels/dingtalk.js +3 -1
  15. package/dist/channels/feishu.js +128 -7
  16. package/dist/channels/qqbot.js +3 -1
  17. package/dist/channels/wechat.js +4 -1
  18. package/dist/channels/wecom.js +3 -1
  19. package/dist/cli/bench.js +1219 -0
  20. package/dist/cli/index.js +418 -40
  21. package/dist/cli/init.js +3 -4
  22. package/dist/cli/link-rules.js +245 -0
  23. package/dist/cli/net-check.js +640 -0
  24. package/dist/cli/watch-msg.js +666 -0
  25. package/dist/config-store.js +82 -5
  26. package/dist/core/channel-loader.js +23 -10
  27. package/dist/core/command-handler.js +127 -99
  28. package/dist/core/evolagent.js +5 -10
  29. package/dist/core/message/im-renderer.js +93 -48
  30. package/dist/core/message/items-formatter.js +11 -4
  31. package/dist/core/message/message-bridge.js +11 -2
  32. package/dist/core/message/message-log.js +8 -1
  33. package/dist/core/message/message-processor.js +194 -127
  34. package/dist/core/message/message-queue.js +10 -3
  35. package/dist/core/permission.js +95 -3
  36. package/dist/core/relation/peer-identity.js +161 -0
  37. package/dist/core/session/session-manager.js +103 -65
  38. package/dist/core/trigger/manager.js +16 -0
  39. package/dist/core/trigger/parser.js +110 -0
  40. package/dist/core/trigger/scheduler.js +7 -1
  41. package/dist/data/error-dict.json +118 -0
  42. package/dist/eck/baseagent-caps.js +18 -0
  43. package/dist/eck/detect.js +47 -0
  44. package/dist/eck/init.js +77 -0
  45. package/dist/eck/rules-loader.js +28 -0
  46. package/dist/index.js +186 -19
  47. package/dist/net-check.js +640 -0
  48. package/dist/paths.js +31 -40
  49. package/dist/utils/aid-lifecycle-log.js +33 -0
  50. package/dist/utils/atomic-write.js +10 -0
  51. package/dist/utils/cross-platform.js +17 -8
  52. package/dist/utils/error-utils.js +27 -15
  53. package/dist/utils/instance-registry.js +6 -5
  54. package/dist/utils/log-writer.js +2 -1
  55. package/dist/utils/logger.js +10 -0
  56. package/dist/utils/npm-ops.js +35 -3
  57. package/dist/utils/process-introspect.js +16 -38
  58. package/dist/utils/stats.js +216 -2
  59. package/dist/watch-msg.js +26 -11
  60. package/evolclaw-install-aun.md +14 -2
  61. package/kits/docs/GUIDE.md +20 -0
  62. package/kits/docs/INDEX.md +52 -0
  63. package/kits/docs/aun/CHEATSHEET.md +17 -0
  64. package/kits/docs/aun/SYNC_PROTOCOL.md +15 -0
  65. package/kits/docs/channels/feishu.md +27 -0
  66. package/kits/docs/eck_templates/GUIDE.template.md +22 -0
  67. package/kits/docs/eck_templates/INDEX.template.md +28 -0
  68. package/kits/docs/eck_templates/path-registry.template.md +33 -0
  69. package/kits/docs/eck_templates/runtime.template.md +19 -0
  70. package/kits/docs/evolclaw/MSG_GROUP.md +30 -0
  71. package/kits/docs/evolclaw/MSG_PRIVATE.md +72 -0
  72. package/kits/docs/identity/AID_PROFILE_SPEC.md +27 -0
  73. package/kits/docs/identity/PATH_OPS.md +16 -0
  74. package/kits/docs/identity/ROLE_DETAIL.md +20 -0
  75. package/kits/docs/path-registry.md +43 -0
  76. package/kits/eck_manifest.json +95 -0
  77. package/kits/rules/01-overview.md +120 -0
  78. package/kits/rules/02-navigation.md +75 -0
  79. package/kits/rules/03-identity.md +34 -0
  80. package/kits/rules/04-relation.md +49 -0
  81. package/kits/rules/05-venue.md +45 -0
  82. package/kits/rules/06-channel.md +73 -0
  83. package/kits/templates/system-fragments/baseagent.md +2 -0
  84. package/kits/templates/system-fragments/channel.md +10 -0
  85. package/kits/templates/system-fragments/identity.md +12 -0
  86. package/kits/templates/system-fragments/relation.md +9 -0
  87. package/kits/templates/system-fragments/runtime.md +19 -0
  88. package/kits/templates/system-fragments/venue.md +5 -0
  89. package/package.json +7 -5
  90. package/dist/agents/templates.js +0 -122
  91. package/dist/data/prompts.md +0 -137
  92. package/kits/aun/meta.md +0 -25
  93. package/kits/aun/role.md +0 -25
  94. package/kits/templates/group.md +0 -20
  95. package/kits/templates/private.md +0 -9
  96. package/kits/templates/system-fragments/personal-context.md +0 -3
  97. package/kits/templates/system-fragments/self-intro.md +0 -5
  98. package/kits/templates/system-fragments/speaker-intro.md +0 -5
  99. package/kits/templates/system-fragments/venue-intro.md +0 -5
  100. /package/kits/{channels → docs/channels}/aun.md +0 -0
  101. /package/kits/{evolclaw/commands.md → docs/evolclaw/AGENT_CMD.md} +0 -0
  102. /package/kits/{evolclaw → docs/evolclaw}/self-summary.md +0 -0
  103. /package/kits/{evolclaw → docs/evolclaw}/tools.md +0 -0
  104. /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(defaultsPath, chosen) {
32
- fs.mkdirSync(path.dirname(defaultsPath), { recursive: true });
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
+ }