evolclaw 3.1.1 → 3.1.3
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/CHANGELOG.md +428 -0
- package/README.md +3 -7
- package/SKILLS.md +311 -0
- package/dist/agents/claude-runner.js +1 -1
- package/dist/agents/codex-runner.js +75 -19
- package/dist/agents/gemini-runner.js +0 -2
- package/dist/agents/kit-renderer.js +59 -10
- package/dist/aun/aid/agentmd.js +50 -27
- package/dist/aun/aid/client.js +5 -11
- package/dist/aun/aid/identity.js +32 -13
- package/dist/aun/aid/index.js +1 -1
- package/dist/aun/msg/group.js +1 -0
- package/dist/aun/msg/p2p.js +15 -2
- package/dist/aun/msg/upload.js +57 -18
- package/dist/aun/rpc/connection.js +3 -0
- package/dist/channels/aun.js +122 -48
- package/dist/channels/dingtalk.js +1 -0
- package/dist/channels/feishu.js +5 -4
- package/dist/channels/qqbot.js +1 -0
- package/dist/channels/wechat.js +1 -0
- package/dist/channels/wecom.js +1 -0
- package/dist/cli/agent.js +142 -40
- package/dist/cli/index.js +103 -58
- package/dist/cli/init-channel.js +4 -2
- package/dist/cli/init.js +55 -26
- package/dist/cli/watch-msg.js +3 -1
- package/dist/config-store.js +22 -1
- package/dist/core/channel-loader.js +4 -4
- package/dist/core/command-handler.js +626 -538
- package/dist/core/evolagent-registry.js +45 -9
- package/dist/core/evolagent.js +35 -4
- package/dist/core/message/im-renderer.js +14 -4
- package/dist/core/message/message-bridge.js +149 -25
- package/dist/core/message/message-processor.js +45 -38
- package/dist/core/session/session-fs-store.js +23 -0
- package/dist/core/session/session-manager.js +188 -42
- package/dist/index.js +15 -17
- package/dist/paths.js +35 -0
- package/dist/utils/cross-platform.js +2 -1
- package/kits/docs/INDEX.md +6 -0
- package/kits/eck_manifest.json +3 -3
- package/kits/rules/02-navigation.md +1 -0
- package/kits/rules/06-channel.md +2 -18
- package/kits/templates/system-fragments/baseagent.md +2 -2
- package/kits/templates/system-fragments/channel.md +18 -9
- package/kits/templates/system-fragments/eckruntime.md +14 -0
- package/kits/templates/system-fragments/identity.md +5 -6
- package/kits/templates/system-fragments/relation.md +7 -5
- package/kits/templates/system-fragments/venue.md +2 -3
- package/package.json +5 -2
- package/kits/templates/system-fragments/runtime.md +0 -19
package/dist/cli/init.js
CHANGED
|
@@ -3,7 +3,8 @@ import readline from 'readline';
|
|
|
3
3
|
import { resolvePaths, ensureDataDirs } from '../paths.js';
|
|
4
4
|
import { commandExists } from '../utils/cross-platform.js';
|
|
5
5
|
import { scanInstances } from '../utils/instance-registry.js';
|
|
6
|
-
import { saveDefaultsSafe } from '../config-store.js';
|
|
6
|
+
import { saveDefaultsSafe, loadAllAgents } from '../config-store.js';
|
|
7
|
+
import { isCodexSdkAvailable } from '../agents/codex-runner.js';
|
|
7
8
|
// ==================== Helpers ====================
|
|
8
9
|
function ask(rl, question) {
|
|
9
10
|
return new Promise(resolve => rl.question(question, resolve));
|
|
@@ -14,8 +15,13 @@ const BASEAGENT_ENV_KEY = {
|
|
|
14
15
|
codex: 'OPENAI_API_KEY',
|
|
15
16
|
gemini: 'GEMINI_API_KEY',
|
|
16
17
|
};
|
|
18
|
+
function isBaseagentAvailable(baseagent) {
|
|
19
|
+
if (baseagent === 'codex')
|
|
20
|
+
return isCodexSdkAvailable();
|
|
21
|
+
return commandExists(baseagent);
|
|
22
|
+
}
|
|
17
23
|
function detectAvailable() {
|
|
18
|
-
return BASEAGENT_CANDIDATES.filter(
|
|
24
|
+
return BASEAGENT_CANDIDATES.filter(isBaseagentAvailable);
|
|
19
25
|
}
|
|
20
26
|
function pickDefault(available) {
|
|
21
27
|
return (available.includes('claude') ? 'claude' : available[0]);
|
|
@@ -45,9 +51,10 @@ export async function cmdInit(options) {
|
|
|
45
51
|
// ── 2. 探测 baseagent ──
|
|
46
52
|
const available = detectAvailable();
|
|
47
53
|
if (available.length === 0) {
|
|
48
|
-
console.log('❌
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
console.log('❌ 未检测到可用 baseagent。请安装至少一款:');
|
|
55
|
+
console.log(' - claude CLI');
|
|
56
|
+
console.log(' - gemini CLI');
|
|
57
|
+
console.log(' - optional dependency @openai/codex-sdk');
|
|
51
58
|
console.log('\n安装后重新运行 evolclaw init');
|
|
52
59
|
return;
|
|
53
60
|
}
|
|
@@ -70,7 +77,7 @@ export async function cmdInit(options) {
|
|
|
70
77
|
return;
|
|
71
78
|
}
|
|
72
79
|
if (!available.includes(options.baseagent)) {
|
|
73
|
-
console.log(`❌ ${options.baseagent}
|
|
80
|
+
console.log(`❌ ${options.baseagent} 当前环境不可用(可用: ${available.join('/')})`);
|
|
74
81
|
return;
|
|
75
82
|
}
|
|
76
83
|
chosen = options.baseagent;
|
|
@@ -81,19 +88,21 @@ export async function cmdInit(options) {
|
|
|
81
88
|
writeDefaults(defaultsPath, chosen);
|
|
82
89
|
console.log(`✓ 已${exists ? '覆盖' : '创建'}: ${defaultsPath}`);
|
|
83
90
|
console.log(` active_baseagent: ${chosen}`);
|
|
91
|
+
const { agents } = loadAllAgents();
|
|
92
|
+
if (agents.length === 0) {
|
|
93
|
+
console.log('\n提示:尚无 agent,运行以下命令创建:');
|
|
94
|
+
console.log(' evolclaw agent new <aid>.agentid.pub');
|
|
95
|
+
}
|
|
84
96
|
return;
|
|
85
97
|
}
|
|
86
98
|
// ── 4. 交互式分支 ──
|
|
87
99
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
88
|
-
|
|
89
|
-
if (exists) {
|
|
90
|
-
const ans = (await ask(rl, `配置文件已存在: ${defaultsPath}\n 是否覆盖?[y/N] `)).trim().toLowerCase();
|
|
91
|
-
if (ans !== 'y' && ans !== 'yes') {
|
|
92
|
-
console.log(' 已取消');
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
100
|
+
async function askBaseagent() {
|
|
96
101
|
const defaultBa = pickDefault(available);
|
|
102
|
+
if (available.length === 1) {
|
|
103
|
+
console.log(` baseagent: ${defaultBa}`);
|
|
104
|
+
return defaultBa;
|
|
105
|
+
}
|
|
97
106
|
let chosen = null;
|
|
98
107
|
while (chosen === null) {
|
|
99
108
|
const input = (await ask(rl, `默认 baseagent (${available.join('/')}) [${defaultBa}]: `)).trim() || defaultBa;
|
|
@@ -102,22 +111,42 @@ export async function cmdInit(options) {
|
|
|
102
111
|
continue;
|
|
103
112
|
}
|
|
104
113
|
if (!available.includes(input)) {
|
|
105
|
-
console.log(` ${input}
|
|
114
|
+
console.log(` ${input} 当前环境不可用(可用: ${available.join('/')})`);
|
|
106
115
|
continue;
|
|
107
116
|
}
|
|
108
117
|
chosen = input;
|
|
109
118
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
return chosen;
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
if (exists) {
|
|
123
|
+
const ans = (await ask(rl, `配置文件已存在: ${defaultsPath}\n 是否覆盖?[y/N] `)).trim().toLowerCase();
|
|
124
|
+
if (ans === 'y' || ans === 'yes') {
|
|
125
|
+
const chosen = await askBaseagent();
|
|
126
|
+
writeDefaults(defaultsPath, chosen);
|
|
127
|
+
console.log(`\n✓ 已覆盖: ${defaultsPath}`);
|
|
128
|
+
console.log(` active_baseagent: ${chosen}\n`);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
console.log(' 已跳过(保留现有配置)\n');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
const chosen = await askBaseagent();
|
|
136
|
+
writeDefaults(defaultsPath, chosen);
|
|
137
|
+
console.log(`\n✓ 已创建: ${defaultsPath}`);
|
|
138
|
+
console.log(` active_baseagent: ${chosen}\n`);
|
|
139
|
+
}
|
|
140
|
+
// ── 5. 无 agent 时自动进入 agent new ──
|
|
141
|
+
const { agents } = loadAllAgents();
|
|
142
|
+
if (agents.length === 0) {
|
|
143
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
144
|
+
console.log('下一步:创建 agent\n');
|
|
145
|
+
const { agentCreateInteractive } = await import('./agent.js');
|
|
146
|
+
const result = await agentCreateInteractive({ rl });
|
|
147
|
+
if (!result.ok) {
|
|
148
|
+
console.error(`❌ ${result.error}`);
|
|
149
|
+
}
|
|
121
150
|
}
|
|
122
151
|
}
|
|
123
152
|
finally {
|
package/dist/cli/watch-msg.js
CHANGED
|
@@ -316,7 +316,9 @@ function renderMessagesPanel(state, width, height) {
|
|
|
316
316
|
const metaTags = (m.encrypt != null || m.chatmode) ? `${MAGENTA}[${encLabel}|${modeLabel}]${RST}` : '';
|
|
317
317
|
let typeTag = '';
|
|
318
318
|
if (m.dir === 'out') {
|
|
319
|
-
const
|
|
319
|
+
const rawSource = m.source;
|
|
320
|
+
// 4 种来源: daemon | ctl | msg | cli
|
|
321
|
+
const source = (rawSource === 'ctl' || rawSource === 'msg' || rawSource === 'cli') ? rawSource : 'daemon';
|
|
320
322
|
const method = m.msgType === 'thought' ? 'thought' : 'send';
|
|
321
323
|
typeTag = `${DIM}[${source}|${method}]${RST}`;
|
|
322
324
|
}
|
package/dist/config-store.js
CHANGED
|
@@ -348,9 +348,30 @@ export function loadAgent(aid) {
|
|
|
348
348
|
if (raw.aid !== aid) {
|
|
349
349
|
throw new Error(`[config] ${p}: aid field "${raw.aid}" != directory name "${aid}"`);
|
|
350
350
|
}
|
|
351
|
-
|
|
351
|
+
const cfg = expandEnvRefs(raw);
|
|
352
|
+
if (cfg.projects?.defaultPath) {
|
|
353
|
+
cfg.projects.defaultPath = cfg.projects.defaultPath.replace(/[/\\]+$/, '');
|
|
354
|
+
}
|
|
355
|
+
return cfg;
|
|
352
356
|
}
|
|
353
357
|
export function saveAgent(value) {
|
|
358
|
+
if (!isValidAid(value.aid)) {
|
|
359
|
+
throw new Error(`[config] saveAgent: invalid aid "${value.aid}" (must be a valid multi-level domain like mybot.agentid.pub)`);
|
|
360
|
+
}
|
|
361
|
+
if (value.owners) {
|
|
362
|
+
for (const o of value.owners) {
|
|
363
|
+
if (!isValidAid(o)) {
|
|
364
|
+
throw new Error(`[config] saveAgent: invalid owner AID "${o}" in ${value.aid} (must be a valid multi-level domain like alice.agentid.pub)`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (value.admins) {
|
|
369
|
+
for (const a of value.admins) {
|
|
370
|
+
if (!isValidAid(a)) {
|
|
371
|
+
throw new Error(`[config] saveAgent: invalid admin AID "${a}" in ${value.aid} (must be a valid multi-level domain like alice.agentid.pub)`);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
354
375
|
atomicWriteJson(agentConfigPath(value.aid), value);
|
|
355
376
|
}
|
|
356
377
|
/**
|
|
@@ -128,18 +128,18 @@ export class ChannelLoader {
|
|
|
128
128
|
}
|
|
129
129
|
const SEP = '#';
|
|
130
130
|
export function formatChannelKey(k) {
|
|
131
|
-
return `${k.
|
|
131
|
+
return `${k.type}${SEP}${encodeURIComponent(k.selfPeerId)}${SEP}${k.name}`;
|
|
132
132
|
}
|
|
133
133
|
export function parseChannelKey(key) {
|
|
134
134
|
const parts = key.split(SEP);
|
|
135
135
|
if (parts.length !== 3) {
|
|
136
136
|
throw new Error(`Invalid channel key (expected 3 segments separated by '#'): ${key}`);
|
|
137
137
|
}
|
|
138
|
-
const [
|
|
139
|
-
if (!
|
|
138
|
+
const [type, encodedSelfPeerId, name] = parts;
|
|
139
|
+
if (!type || !encodedSelfPeerId || !name) {
|
|
140
140
|
throw new Error(`Invalid channel key (empty segment): ${key}`);
|
|
141
141
|
}
|
|
142
|
-
return {
|
|
142
|
+
return { type, selfPeerId: decodeURIComponent(encodedSelfPeerId), name };
|
|
143
143
|
}
|
|
144
144
|
export function tryParseChannelKey(key) {
|
|
145
145
|
try {
|