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.
- package/README.md +21 -12
- package/dist/agents/claude-runner.js +102 -38
- package/dist/agents/codex-runner.js +11 -14
- package/dist/agents/gemini-runner.js +10 -12
- package/dist/agents/resolve.js +134 -0
- package/dist/agents/templates.js +3 -3
- package/dist/aun/aid/agentmd.js +186 -0
- package/dist/aun/aid/client.js +134 -0
- package/dist/aun/aid/identity.js +131 -0
- package/dist/aun/aid/index.js +3 -0
- package/dist/aun/aid/types.js +1 -0
- package/dist/aun/aid/validation.js +21 -0
- package/dist/aun/msg/group.js +291 -0
- package/dist/aun/msg/index.js +4 -0
- package/dist/aun/msg/p2p.js +144 -0
- package/dist/aun/msg/payload-type.js +27 -0
- package/dist/aun/msg/upload.js +98 -0
- package/dist/aun/outbox.js +138 -0
- package/dist/aun/rpc/caller.js +42 -0
- package/dist/aun/rpc/connection.js +34 -0
- package/dist/aun/rpc/index.js +2 -0
- package/dist/aun/storage/download.js +29 -0
- package/dist/aun/storage/index.js +3 -0
- package/dist/aun/storage/manage.js +10 -0
- package/dist/aun/storage/upload.js +35 -0
- package/dist/channels/aun.js +1051 -288
- package/dist/channels/dingtalk.js +58 -5
- package/dist/channels/feishu.js +266 -30
- package/dist/channels/qqbot.js +67 -12
- package/dist/channels/wechat.js +61 -4
- package/dist/channels/wecom.js +58 -5
- package/dist/cli/agent.js +800 -0
- package/dist/cli/index.js +4253 -0
- package/dist/{utils → cli}/init-channel.js +211 -621
- package/dist/cli/init.js +178 -0
- package/dist/config-store.js +613 -0
- package/dist/core/{agent-loader.js → baseagent-loader.js} +6 -12
- package/dist/core/channel-loader.js +162 -11
- package/dist/core/command-handler.js +858 -847
- package/dist/core/evolagent-registry.js +191 -371
- package/dist/core/evolagent.js +203 -234
- package/dist/core/interaction-router.js +52 -5
- package/dist/core/message/im-renderer.js +480 -0
- package/dist/core/message/items-formatter.js +61 -0
- package/dist/core/message/message-bridge.js +104 -56
- package/dist/core/message/message-log.js +91 -0
- package/dist/core/message/message-processor.js +309 -142
- package/dist/core/message/message-queue.js +3 -3
- package/dist/core/permission.js +21 -8
- package/dist/core/session/adapters/codex-session-file-adapter.js +24 -2
- package/dist/core/session/session-fs-store.js +230 -0
- package/dist/core/session/session-manager.js +704 -775
- package/dist/core/session/session-mapper.js +87 -0
- package/dist/core/trigger/manager.js +122 -0
- package/dist/core/trigger/parser.js +128 -0
- package/dist/core/trigger/scheduler.js +224 -0
- package/dist/{templates → data}/prompts.md +34 -1
- package/dist/index.js +431 -275
- package/dist/ipc.js +49 -0
- package/dist/paths.js +82 -9
- package/dist/types.js +8 -2
- package/dist/utils/atomic-write.js +79 -0
- package/dist/utils/channel-helpers.js +46 -0
- package/dist/utils/cross-platform.js +0 -18
- package/dist/utils/instance-registry.js +433 -0
- package/dist/utils/log-writer.js +216 -0
- package/dist/utils/logger.js +24 -77
- package/dist/utils/media-cache.js +23 -0
- package/dist/utils/{upgrade.js → npm-ops.js} +52 -21
- package/dist/utils/process-introspect.js +144 -0
- package/dist/utils/stats.js +192 -0
- package/dist/watch-msg.js +529 -0
- package/evolclaw-install-aun.md +114 -46
- package/kits/aun/meta.md +25 -0
- package/kits/aun/role.md +25 -0
- package/kits/channels/aun.md +25 -0
- package/kits/evolclaw/commands.md +31 -0
- package/kits/evolclaw/identity-tools.md +26 -0
- package/kits/evolclaw/self-summary.md +29 -0
- package/kits/evolclaw/tools.md +25 -0
- package/kits/templates/group.md +20 -0
- package/kits/templates/private.md +9 -0
- package/kits/templates/system-fragments/personal-context.md +3 -0
- package/kits/templates/system-fragments/self-intro.md +5 -0
- package/kits/templates/system-fragments/speaker-intro.md +5 -0
- package/kits/templates/system-fragments/venue-intro.md +5 -0
- package/package.json +7 -5
- package/data/evolclaw.sample.json +0 -60
- package/dist/channels/aun-ops.js +0 -275
- package/dist/cli.js +0 -2178
- package/dist/config.js +0 -591
- package/dist/core/agent-registry.js +0 -450
- package/dist/core/evolagent-schema.js +0 -72
- package/dist/core/message/stream-flusher.js +0 -238
- package/dist/core/message/thought-emitter.js +0 -162
- package/dist/core/reload-hooks.js +0 -87
- package/dist/prompts/templates.js +0 -122
- package/dist/templates/skills.md +0 -66
- package/dist/utils/channel-fingerprint.js +0 -59
- package/dist/utils/error-dict.js +0 -63
- package/dist/utils/format.js +0 -32
- package/dist/utils/init.js +0 -645
- package/dist/utils/migrate-project.js +0 -122
- package/dist/utils/reload-hooks.js +0 -87
- package/dist/utils/stats-collector.js +0 -99
package/dist/cli/init.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import readline from 'readline';
|
|
4
|
+
import { resolvePaths, ensureDataDirs } from '../paths.js';
|
|
5
|
+
import { commandExists } from '../utils/cross-platform.js';
|
|
6
|
+
import { scanInstances } from '../utils/instance-registry.js';
|
|
7
|
+
// ==================== Helpers ====================
|
|
8
|
+
function ask(rl, question) {
|
|
9
|
+
return new Promise(resolve => rl.question(question, resolve));
|
|
10
|
+
}
|
|
11
|
+
const BASEAGENT_CANDIDATES = ['claude', 'codex', 'gemini'];
|
|
12
|
+
const BASEAGENT_ENV_KEY = {
|
|
13
|
+
claude: 'ANTHROPIC_API_KEY',
|
|
14
|
+
codex: 'OPENAI_API_KEY',
|
|
15
|
+
gemini: 'GEMINI_API_KEY',
|
|
16
|
+
};
|
|
17
|
+
function detectAvailable() {
|
|
18
|
+
return BASEAGENT_CANDIDATES.filter(b => commandExists(b));
|
|
19
|
+
}
|
|
20
|
+
function pickDefault(available) {
|
|
21
|
+
return (available.includes('claude') ? 'claude' : available[0]);
|
|
22
|
+
}
|
|
23
|
+
function buildDefaults(chosen) {
|
|
24
|
+
const env = BASEAGENT_ENV_KEY[chosen];
|
|
25
|
+
return {
|
|
26
|
+
$schema_version: 1,
|
|
27
|
+
active_baseagent: chosen,
|
|
28
|
+
baseagents: { [chosen]: env ? { apiKey: `$ENV:${env}` } : {} },
|
|
29
|
+
};
|
|
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');
|
|
34
|
+
}
|
|
35
|
+
// ==================== Main ====================
|
|
36
|
+
export async function cmdInit(options) {
|
|
37
|
+
const p = resolvePaths();
|
|
38
|
+
ensureDataDirs();
|
|
39
|
+
// ── 1. 单进程互斥 ──
|
|
40
|
+
const aliveMains = scanInstances().mains.filter(m => m.alive);
|
|
41
|
+
if (aliveMains.length > 0) {
|
|
42
|
+
const pids = aliveMains.map(m => m.record.pid).join(', ');
|
|
43
|
+
console.log(`❌ EvolClaw 正在运行 (PID: ${pids}),请先执行 evolclaw stop`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
// ── 2. 探测 baseagent ──
|
|
47
|
+
const available = detectAvailable();
|
|
48
|
+
if (available.length === 0) {
|
|
49
|
+
console.log('❌ 未检测到任何 baseagent CLI,请先安装至少一款:');
|
|
50
|
+
for (const b of BASEAGENT_CANDIDATES)
|
|
51
|
+
console.log(` - ${b}`);
|
|
52
|
+
console.log('\n安装后重新运行 evolclaw init');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
console.log('检测到可用的 baseagent:');
|
|
56
|
+
for (const b of available)
|
|
57
|
+
console.log(` ● ${b}`);
|
|
58
|
+
console.log('');
|
|
59
|
+
const defaultsPath = p.defaultsConfig;
|
|
60
|
+
const exists = fs.existsSync(defaultsPath);
|
|
61
|
+
// ── 3. 非交互式分支 ──
|
|
62
|
+
if (options?.nonInteractive) {
|
|
63
|
+
if (exists && !options.force) {
|
|
64
|
+
console.log(`❌ 配置已存在: ${defaultsPath}(加 --force 可覆盖)`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
let chosen;
|
|
68
|
+
if (options.baseagent) {
|
|
69
|
+
if (!BASEAGENT_CANDIDATES.includes(options.baseagent)) {
|
|
70
|
+
console.log(`❌ 无效 baseagent: ${options.baseagent}(可选: ${BASEAGENT_CANDIDATES.join('/')})`);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (!available.includes(options.baseagent)) {
|
|
74
|
+
console.log(`❌ ${options.baseagent} 未在 PATH 中检测到(可用: ${available.join('/')})`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
chosen = options.baseagent;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
chosen = pickDefault(available);
|
|
81
|
+
}
|
|
82
|
+
writeDefaults(defaultsPath, chosen);
|
|
83
|
+
console.log(`✓ 已${exists ? '覆盖' : '创建'}: ${defaultsPath}`);
|
|
84
|
+
console.log(` active_baseagent: ${chosen}`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// ── 4. 交互式分支 ──
|
|
88
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
89
|
+
try {
|
|
90
|
+
if (exists) {
|
|
91
|
+
const ans = (await ask(rl, `配置文件已存在: ${defaultsPath}\n 是否覆盖?[y/N] `)).trim().toLowerCase();
|
|
92
|
+
if (ans !== 'y' && ans !== 'yes') {
|
|
93
|
+
console.log(' 已取消');
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const defaultBa = pickDefault(available);
|
|
98
|
+
let chosen = null;
|
|
99
|
+
while (chosen === null) {
|
|
100
|
+
const input = (await ask(rl, `默认 baseagent (${available.join('/')}) [${defaultBa}]: `)).trim() || defaultBa;
|
|
101
|
+
if (!BASEAGENT_CANDIDATES.includes(input)) {
|
|
102
|
+
console.log(` 无效选择,可选: ${BASEAGENT_CANDIDATES.join('/')}`);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (!available.includes(input)) {
|
|
106
|
+
console.log(` ${input} 未在 PATH 中检测到(可用: ${available.join('/')})`);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
chosen = input;
|
|
110
|
+
}
|
|
111
|
+
writeDefaults(defaultsPath, chosen);
|
|
112
|
+
console.log(`\n✓ 已${exists ? '覆盖' : '创建'}: ${defaultsPath}`);
|
|
113
|
+
console.log(` active_baseagent: ${chosen}\n`);
|
|
114
|
+
rl.close();
|
|
115
|
+
// ── 5. 嵌套 agent new ──
|
|
116
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
117
|
+
console.log('下一步:创建 agent\n');
|
|
118
|
+
const { agentCreateInteractive } = await import('./agent.js');
|
|
119
|
+
const result = await agentCreateInteractive();
|
|
120
|
+
if (!result.ok) {
|
|
121
|
+
console.error(`❌ ${result.error}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
try {
|
|
126
|
+
rl.close();
|
|
127
|
+
}
|
|
128
|
+
catch { /* ignore */ }
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Present instance selection menu when existing instances are found.
|
|
133
|
+
* Returns the user's choice, or null if cancelled.
|
|
134
|
+
*/
|
|
135
|
+
export async function selectInstance(rl, channelType, instances) {
|
|
136
|
+
const typeLabel = channelType === 'feishu' ? '飞书' : channelType === 'wechat' ? '微信' : channelType === 'dingtalk' ? '钉钉' : channelType === 'qqbot' ? 'QQ机器人' : channelType === 'wecom' ? '企业微信' : channelType.toUpperCase();
|
|
137
|
+
console.log(`\n发现已有 ${typeLabel} 配置:`);
|
|
138
|
+
const letters = 'abcdefghijklmnopqrstuvwxyz';
|
|
139
|
+
for (let i = 0; i < instances.length; i++) {
|
|
140
|
+
const inst = instances[i];
|
|
141
|
+
const id = inst.aid || inst.appId || inst.botId || inst.clientId || inst.token?.slice(0, 16) || '';
|
|
142
|
+
const suffix = id ? ` (${id})` : '';
|
|
143
|
+
console.log(` ${letters[i]}. ${inst.name}${suffix}`);
|
|
144
|
+
}
|
|
145
|
+
const addLetter = letters[instances.length];
|
|
146
|
+
console.log(` ${addLetter}. 添加新配置`);
|
|
147
|
+
console.log('');
|
|
148
|
+
const validOptions = letters.slice(0, instances.length + 1).split('');
|
|
149
|
+
let choice = '';
|
|
150
|
+
while (!validOptions.includes(choice)) {
|
|
151
|
+
choice = (await new Promise(r => rl.question('请选择: ', r))).trim().toLowerCase();
|
|
152
|
+
if (!validOptions.includes(choice)) {
|
|
153
|
+
console.log(`无效选择,请输入 ${validOptions.join('/')}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const choiceIndex = letters.indexOf(choice);
|
|
157
|
+
if (choiceIndex === instances.length) {
|
|
158
|
+
let name = '';
|
|
159
|
+
while (!name) {
|
|
160
|
+
name = (await new Promise(r => rl.question('请输入新配置名称: ', r))).trim();
|
|
161
|
+
if (!name)
|
|
162
|
+
console.log(' 名称不能为空');
|
|
163
|
+
if (instances.some(i => i.name === name)) {
|
|
164
|
+
console.log(` 名称 "${name}" 已存在,请换一个`);
|
|
165
|
+
name = '';
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return { action: 'add', name };
|
|
169
|
+
}
|
|
170
|
+
const target = instances[choiceIndex];
|
|
171
|
+
console.log(`\n已选择:${target.name}`);
|
|
172
|
+
const confirm = (await new Promise(r => rl.question(`⚠️ 即将覆盖该配置,确认?(y/N) `, r))).trim().toLowerCase();
|
|
173
|
+
if (confirm !== 'y' && confirm !== 'yes') {
|
|
174
|
+
console.log('已取消');
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
return { action: 'overwrite', index: choiceIndex, name: target.name };
|
|
178
|
+
}
|