evolclaw 3.1.2 → 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 +21 -0
- package/README.md +2 -6
- 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 +49 -27
- package/dist/aun/aid/index.js +1 -1
- package/dist/aun/rpc/connection.js +3 -0
- package/dist/channels/aun.js +67 -14
- package/dist/cli/agent.js +13 -6
- package/dist/cli/index.js +27 -37
- package/dist/cli/init.js +13 -6
- package/dist/core/command-handler.js +615 -534
- package/dist/core/evolagent.js +31 -0
- package/dist/core/message/im-renderer.js +10 -0
- package/dist/core/message/message-bridge.js +123 -24
- package/dist/core/message/message-processor.js +43 -14
- package/dist/core/session/session-manager.js +185 -42
- 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 +1 -1
- package/kits/templates/system-fragments/runtime.md +0 -19
package/dist/channels/aun.js
CHANGED
|
@@ -6,7 +6,7 @@ import os from 'os';
|
|
|
6
6
|
import { logger, localTimestamp } from '../utils/logger.js';
|
|
7
7
|
import { LogWriter } from '../utils/log-writer.js';
|
|
8
8
|
import { normalizeChannelInstances, getChannelShowActivities } from '../utils/channel-helpers.js';
|
|
9
|
-
import { resolvePaths, getPackageRoot, agentMdPath as agentMdPathFn, agentDir as agentDirPath } from '../paths.js';
|
|
9
|
+
import { resolvePaths, getPackageRoot, agentMdPath as agentMdPathFn, agentDir as agentDirPath, resolveRoot } from '../paths.js';
|
|
10
10
|
import { saveToUploads, sanitizeFileName } from '../utils/media-cache.js';
|
|
11
11
|
import { appendAidEvent } from '../utils/instance-registry.js';
|
|
12
12
|
import { appendMessageLog, buildOutboundEntry } from '../core/message/message-log.js';
|
|
@@ -57,6 +57,46 @@ function getEvolclawVersion() {
|
|
|
57
57
|
}
|
|
58
58
|
return _cachedVersion;
|
|
59
59
|
}
|
|
60
|
+
function migrateAunData(targetPath) {
|
|
61
|
+
const legacyPath = path.join(os.homedir(), '.aun');
|
|
62
|
+
if (legacyPath === targetPath)
|
|
63
|
+
return;
|
|
64
|
+
// AIDs 迁移:逐个检查每个 AID,缺少 private 的就从 legacy 复制
|
|
65
|
+
const srcAIDs = path.join(legacyPath, 'AIDs');
|
|
66
|
+
const dstAIDs = path.join(targetPath, 'AIDs');
|
|
67
|
+
if (fs.existsSync(srcAIDs)) {
|
|
68
|
+
fs.mkdirSync(dstAIDs, { recursive: true });
|
|
69
|
+
try {
|
|
70
|
+
for (const entry of fs.readdirSync(srcAIDs, { withFileTypes: true })) {
|
|
71
|
+
if (!entry.isDirectory())
|
|
72
|
+
continue;
|
|
73
|
+
const aidName = entry.name;
|
|
74
|
+
const srcAidDir = path.join(srcAIDs, aidName);
|
|
75
|
+
const dstAidDir = path.join(dstAIDs, aidName);
|
|
76
|
+
const srcPrivate = path.join(srcAidDir, 'private');
|
|
77
|
+
const dstPrivate = path.join(dstAidDir, 'private');
|
|
78
|
+
// 如果目标 AID 目录不存在或缺少 private,从源复制整个 AID 目录
|
|
79
|
+
if (fs.existsSync(srcPrivate) && !fs.existsSync(dstPrivate)) {
|
|
80
|
+
fs.cpSync(srcAidDir, dstAidDir, { recursive: true });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch { }
|
|
85
|
+
}
|
|
86
|
+
// CA 迁移
|
|
87
|
+
const srcCA = path.join(legacyPath, 'CA');
|
|
88
|
+
const dstCA = path.join(targetPath, 'CA');
|
|
89
|
+
if (fs.existsSync(srcCA) && !fs.existsSync(dstCA)) {
|
|
90
|
+
fs.cpSync(srcCA, dstCA, { recursive: true });
|
|
91
|
+
}
|
|
92
|
+
for (const file of ['.seed', '.device_id']) {
|
|
93
|
+
const src = path.join(legacyPath, file);
|
|
94
|
+
const dst = path.join(targetPath, file);
|
|
95
|
+
if (fs.existsSync(src) && !fs.existsSync(dst)) {
|
|
96
|
+
fs.copyFileSync(src, dst);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
60
100
|
export class AUNChannel {
|
|
61
101
|
config;
|
|
62
102
|
client = null;
|
|
@@ -445,6 +485,10 @@ export class AUNChannel {
|
|
|
445
485
|
'text', 'quote', 'image', 'video', 'voice', 'file', 'json',
|
|
446
486
|
'merge', 'link', 'location', 'personal_card',
|
|
447
487
|
]);
|
|
488
|
+
/** Menu protocol 请求类型:自定义消息快速路径,绕过白名单直接分发到 bridge */
|
|
489
|
+
static MENU_REQUEST_TYPES = new Set([
|
|
490
|
+
'menu.list', 'menu.query', 'menu.options', 'menu.update', 'menu.action',
|
|
491
|
+
]);
|
|
448
492
|
// Reconnect state
|
|
449
493
|
// SDK 自己跑无限指数退避(1s → 5min);TS 层只在 SDK 够不到的两类场景下接管:
|
|
450
494
|
// 1. flap:短命 connected 反复出现(SDK 不记忆跨轮 base delay,会从 1s 重新开始)
|
|
@@ -541,9 +585,11 @@ export class AUNChannel {
|
|
|
541
585
|
this.client = null;
|
|
542
586
|
}
|
|
543
587
|
this.connected = false;
|
|
544
|
-
const aunPath = this.config.keystorePath ||
|
|
588
|
+
const aunPath = this.config.keystorePath || resolveRoot();
|
|
545
589
|
const aidName = this.config.aid;
|
|
546
590
|
const encryptionSeed = this.config.encryptionSeed || process.env.AUN_ENCRYPTION_SEED || undefined;
|
|
591
|
+
// Migrate legacy ~/.aun data to EVOLCLAW_HOME on first run
|
|
592
|
+
migrateAunData(aunPath);
|
|
547
593
|
// Gateway URL 解析:优先用配置的 gatewayUrl,否则通过 well-known 自动发现
|
|
548
594
|
let gateway = this.config.gatewayUrl || '';
|
|
549
595
|
if (!gateway) {
|
|
@@ -781,9 +827,9 @@ EvolClaw AI Agent 网关,支持多项目会话管理和多 AI 后端切换。
|
|
|
781
827
|
fs.mkdirSync(path.dirname(agentMdLocalPath), { recursive: true });
|
|
782
828
|
fs.writeFileSync(agentMdLocalPath, newAgentMd, 'utf-8');
|
|
783
829
|
logger.info(`${this.logPrefix()} Updated agent.md for ${aidName}`);
|
|
784
|
-
// Publish to AUN network via
|
|
830
|
+
// Publish to AUN network via publishAgentMd (auto-sign)
|
|
785
831
|
try {
|
|
786
|
-
await this.client.
|
|
832
|
+
await this.client.publishAgentMd();
|
|
787
833
|
logger.info(`${this.logPrefix()} Published agent.md to AUN network`);
|
|
788
834
|
}
|
|
789
835
|
catch (e) {
|
|
@@ -800,8 +846,7 @@ EvolClaw AI Agent 网关,支持多项目会话管理和多 AI 后端切换。
|
|
|
800
846
|
2. **查看帮助**:发送 \`/help\` 查看所有可用命令
|
|
801
847
|
3. **切换项目**:发送 \`/project <项目名>\` 切换到其他项目
|
|
802
848
|
4. **查看状态**:发送 \`/status\` 查看当前会话状态
|
|
803
|
-
5.
|
|
804
|
-
6. **会话管理**:发送 \`/session\` 查看和切换会话
|
|
849
|
+
5. **会话管理**:发送 \`/session\` 查看和切换会话
|
|
805
850
|
|
|
806
851
|
💡 **提示**:
|
|
807
852
|
- 直接发送消息即可与 Claude/Codex 对话
|
|
@@ -963,8 +1008,8 @@ EvolClaw AI Agent 网关,支持多项目会话管理和多 AI 后端切换。
|
|
|
963
1008
|
// action_card_reply 已在 extractTextPayload 中消费,不分发给 agent
|
|
964
1009
|
if (p2pPayloadType === 'action_card_reply')
|
|
965
1010
|
return;
|
|
966
|
-
// menu
|
|
967
|
-
if (p2pPayloadType
|
|
1011
|
+
// menu.* 协议:自定义消息快速路径,需要原始 payload JSON 传递给 bridge
|
|
1012
|
+
if (AUNChannel.MENU_REQUEST_TYPES.has(p2pPayloadType)) {
|
|
968
1013
|
this.acknowledgeImmediately(messageId, seq);
|
|
969
1014
|
this.dispatchMessage({
|
|
970
1015
|
channelId: chatId, userId: fromAid,
|
|
@@ -1069,8 +1114,8 @@ EvolClaw AI Agent 网关,支持多项目会话管理和多 AI 后端切换。
|
|
|
1069
1114
|
{
|
|
1070
1115
|
const payloadObj = (payload && typeof payload === 'object') ? payload : null;
|
|
1071
1116
|
const payloadType = payloadObj?.type ?? '';
|
|
1072
|
-
// menu
|
|
1073
|
-
if (payloadType
|
|
1117
|
+
// menu.* 协议:自定义消息快速路径
|
|
1118
|
+
if (AUNChannel.MENU_REQUEST_TYPES.has(payloadType)) {
|
|
1074
1119
|
this.acknowledgeImmediately(messageId, seq);
|
|
1075
1120
|
this.dispatchMessage({
|
|
1076
1121
|
channelId: groupId, userId: senderAid,
|
|
@@ -2373,7 +2418,9 @@ EvolClaw AI Agent 网关,支持多项目会话管理和多 AI 后端切换。
|
|
|
2373
2418
|
if (!this.client)
|
|
2374
2419
|
return { type: null };
|
|
2375
2420
|
try {
|
|
2376
|
-
const
|
|
2421
|
+
const { agentmdSync } = await import('../aun/aid/agentmd.js');
|
|
2422
|
+
const result = await agentmdSync(aid, { client: this.client });
|
|
2423
|
+
const md = result.content ?? '';
|
|
2377
2424
|
const typeMatch = md.match(/^type:\s*["']?(\w+)["']?/m);
|
|
2378
2425
|
const nameMatch = md.match(/^name:\s*["']?(.+?)["']?\s*$/m);
|
|
2379
2426
|
const type = typeMatch?.[1] === 'human' ? 'human' : 'ai';
|
|
@@ -2385,7 +2432,7 @@ EvolClaw AI Agent 网关,支持多项目会话管理和多 AI 后端切换。
|
|
|
2385
2432
|
}
|
|
2386
2433
|
catch (e) {
|
|
2387
2434
|
logger.debug(`${this.logPrefix()} fetchPeerInfo failed for ${aid}: ${e}`);
|
|
2388
|
-
return { type: null };
|
|
2435
|
+
return { type: null };
|
|
2389
2436
|
}
|
|
2390
2437
|
}
|
|
2391
2438
|
/** 同步取 peerInfo 缓存,未命中返回 undefined,不发起任何网络请求。 */
|
|
@@ -2401,12 +2448,18 @@ EvolClaw AI Agent 网关,支持多项目会话管理和多 AI 后端切换。
|
|
|
2401
2448
|
async uploadAgentMd(content) {
|
|
2402
2449
|
if (!this.client)
|
|
2403
2450
|
throw new Error('not connected');
|
|
2404
|
-
await
|
|
2451
|
+
const { agentMdPath } = await import('../paths.js');
|
|
2452
|
+
const localPath = agentMdPath(this.config.aid);
|
|
2453
|
+
fs.mkdirSync(path.dirname(localPath), { recursive: true });
|
|
2454
|
+
fs.writeFileSync(localPath, content, 'utf-8');
|
|
2455
|
+
await this.client.publishAgentMd();
|
|
2405
2456
|
}
|
|
2406
2457
|
async downloadAgentMd(aid) {
|
|
2407
2458
|
if (!this.client)
|
|
2408
2459
|
throw new Error('not connected');
|
|
2409
|
-
|
|
2460
|
+
const { agentmdSync } = await import('../aun/aid/agentmd.js');
|
|
2461
|
+
const result = await agentmdSync(aid, { client: this.client });
|
|
2462
|
+
return result.content ?? '';
|
|
2410
2463
|
}
|
|
2411
2464
|
}
|
|
2412
2465
|
// Plugin implementation
|
package/dist/cli/agent.js
CHANGED
|
@@ -8,6 +8,7 @@ import { ipcQuery } from '../ipc.js';
|
|
|
8
8
|
import { CONFIG_SCHEMA_VERSION } from '../types.js';
|
|
9
9
|
import { isValidChannelName } from '../core/channel-loader.js';
|
|
10
10
|
import { commandExists } from '../utils/cross-platform.js';
|
|
11
|
+
import { isCodexSdkAvailable } from '../agents/codex-runner.js';
|
|
11
12
|
// ==================== Helpers ====================
|
|
12
13
|
const BASEAGENT_CANDIDATES = ['claude', 'codex', 'gemini'];
|
|
13
14
|
const BASEAGENT_ENV_KEY = {
|
|
@@ -15,8 +16,13 @@ const BASEAGENT_ENV_KEY = {
|
|
|
15
16
|
codex: 'OPENAI_API_KEY',
|
|
16
17
|
gemini: 'GEMINI_API_KEY',
|
|
17
18
|
};
|
|
19
|
+
function isBaseagentAvailable(baseagent) {
|
|
20
|
+
if (baseagent === 'codex')
|
|
21
|
+
return isCodexSdkAvailable();
|
|
22
|
+
return commandExists(baseagent);
|
|
23
|
+
}
|
|
18
24
|
function detectAvailableBaseagents() {
|
|
19
|
-
return BASEAGENT_CANDIDATES.filter(
|
|
25
|
+
return BASEAGENT_CANDIDATES.filter(isBaseagentAvailable);
|
|
20
26
|
}
|
|
21
27
|
function pickDefaultBaseagent(available) {
|
|
22
28
|
if (available.length === 0)
|
|
@@ -316,7 +322,7 @@ export async function agentCreateInteractive(opts = {}) {
|
|
|
316
322
|
// Baseagent
|
|
317
323
|
const available = detectAvailableBaseagents();
|
|
318
324
|
if (available.length === 0) {
|
|
319
|
-
return { ok: false, error: `No baseagent
|
|
325
|
+
return { ok: false, error: `No usable baseagent detected. Install claude/gemini CLI or optional dependency @openai/codex-sdk.` };
|
|
320
326
|
}
|
|
321
327
|
const defaultBa = pickDefaultBaseagent(available);
|
|
322
328
|
let baseagent;
|
|
@@ -333,7 +339,7 @@ export async function agentCreateInteractive(opts = {}) {
|
|
|
333
339
|
continue;
|
|
334
340
|
}
|
|
335
341
|
if (!available.includes(input)) {
|
|
336
|
-
console.log(` ${input} not
|
|
342
|
+
console.log(` ${input} is not available in the current environment. Available: ${available.join('/')}`);
|
|
337
343
|
continue;
|
|
338
344
|
}
|
|
339
345
|
chosen = input;
|
|
@@ -463,7 +469,7 @@ export async function agentCreateNonInteractive(opts) {
|
|
|
463
469
|
// Baseagent
|
|
464
470
|
const available = detectAvailableBaseagents();
|
|
465
471
|
if (available.length === 0) {
|
|
466
|
-
return { ok: false, error: `No baseagent
|
|
472
|
+
return { ok: false, error: `No usable baseagent detected. Install claude/gemini CLI or optional dependency @openai/codex-sdk.` };
|
|
467
473
|
}
|
|
468
474
|
let baseagent;
|
|
469
475
|
if (opts.baseagent) {
|
|
@@ -471,7 +477,7 @@ export async function agentCreateNonInteractive(opts) {
|
|
|
471
477
|
return { ok: false, error: `Invalid baseagent: ${opts.baseagent} (options: ${BASEAGENT_CANDIDATES.join('/')})` };
|
|
472
478
|
}
|
|
473
479
|
if (!available.includes(opts.baseagent)) {
|
|
474
|
-
return { ok: false, error: `${opts.baseagent} not
|
|
480
|
+
return { ok: false, error: `${opts.baseagent} is not available in the current environment (available: ${available.join('/')})` };
|
|
475
481
|
}
|
|
476
482
|
baseagent = opts.baseagent;
|
|
477
483
|
}
|
|
@@ -592,7 +598,8 @@ export async function agentCreateNonInteractive(opts) {
|
|
|
592
598
|
hotLoadError,
|
|
593
599
|
};
|
|
594
600
|
}
|
|
595
|
-
// ==================== agentSyncAids ====================
|
|
601
|
+
// ==================== agentSyncAids (deprecated) ====================
|
|
602
|
+
/** @deprecated sync-aids 已废弃,不再从 CLI 调用 */
|
|
596
603
|
export async function agentSyncAids() {
|
|
597
604
|
const p = resolvePaths();
|
|
598
605
|
const { aidList } = await import('../aun/aid/index.js');
|
package/dist/cli/index.js
CHANGED
|
@@ -2739,6 +2739,7 @@ async function cmdCtl(args) {
|
|
|
2739
2739
|
查询:
|
|
2740
2740
|
status 查看会话状态
|
|
2741
2741
|
check 检查渠道健康状态
|
|
2742
|
+
pwd 显示当前项目路径
|
|
2742
2743
|
help 显示帮助
|
|
2743
2744
|
|
|
2744
2745
|
配置:
|
|
@@ -2747,15 +2748,14 @@ async function cmdCtl(args) {
|
|
|
2747
2748
|
compact 压缩当前会话上下文
|
|
2748
2749
|
perm [mode] 查看/切换权限模式
|
|
2749
2750
|
|
|
2750
|
-
项目:
|
|
2751
|
-
bind <path> 注册项目目录(不切换当前会话)
|
|
2752
|
-
|
|
2753
2751
|
消息:
|
|
2754
2752
|
send <消息内容> 主动发送文本消息(proactive 模式)
|
|
2755
2753
|
file [channel] <path> 发送项目内文件
|
|
2756
2754
|
|
|
2755
|
+
Agent:
|
|
2756
|
+
agent <subcommand> EvolAgent 管理(list/show/new/enable/disable/reload/delete)
|
|
2757
|
+
|
|
2757
2758
|
运维:
|
|
2758
|
-
agentmd [put|set <内容>] 查看/管理 agent.md(仅 AUN 通道)
|
|
2759
2759
|
restart [channel] 重启服务或重连指定渠道
|
|
2760
2760
|
|
|
2761
2761
|
示例:
|
|
@@ -2808,7 +2808,6 @@ Commands:
|
|
|
2808
2808
|
show <aid> 查看 agent 详情(身份 + 配置 + 连接 + 会话 + 路径)
|
|
2809
2809
|
new [aid] 交互式创建 agent
|
|
2810
2810
|
new <aid> --non-interactive ... 非交互式创建
|
|
2811
|
-
sync-aids 从本地 AID 批量创建 agent
|
|
2812
2811
|
enable <aid> 启用 agent
|
|
2813
2812
|
disable <aid> 停用 agent
|
|
2814
2813
|
get <aid> <key> 读取单个配置字段(支持点路径)
|
|
@@ -2831,7 +2830,7 @@ Options:
|
|
|
2831
2830
|
evolclaw agent delete mybot.agentid.pub --purge`);
|
|
2832
2831
|
return;
|
|
2833
2832
|
}
|
|
2834
|
-
const { agentList, agentShow, agentCreateInteractive, agentCreateNonInteractive,
|
|
2833
|
+
const { agentList, agentShow, agentCreateInteractive, agentCreateNonInteractive, agentReload, agentEnable, agentDisable, agentGet, agentSet, agentDelete, agentRename, } = await import('./agent.js');
|
|
2835
2834
|
// --- list ---
|
|
2836
2835
|
if (!sub || sub === 'list') {
|
|
2837
2836
|
const result = await agentList();
|
|
@@ -2966,36 +2965,28 @@ Options:
|
|
|
2966
2965
|
}
|
|
2967
2966
|
return;
|
|
2968
2967
|
}
|
|
2969
|
-
// --- sync-aids ---
|
|
2970
|
-
if (sub === 'sync-aids') {
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
console.log(` ✓ ${aid}`);
|
|
2992
|
-
if (result.hotReloaded)
|
|
2993
|
-
console.log(' ✓ 已热加载到运行中的进程');
|
|
2994
|
-
else
|
|
2995
|
-
console.log(' evolclaw 未运行,新 agent 将在下次启动时加载。');
|
|
2996
|
-
}
|
|
2997
|
-
return;
|
|
2998
|
-
}
|
|
2968
|
+
// --- sync-aids (deprecated, commented out) ---
|
|
2969
|
+
// if (sub === 'sync-aids') {
|
|
2970
|
+
// const result = await agentSyncAids();
|
|
2971
|
+
// if (!result.ok) {
|
|
2972
|
+
// if (formatJson) { console.log(JSON.stringify(result)); }
|
|
2973
|
+
// else { console.error(`❌ ${result.error}`); }
|
|
2974
|
+
// process.exit(1);
|
|
2975
|
+
// }
|
|
2976
|
+
// if (formatJson) {
|
|
2977
|
+
// console.log(JSON.stringify(result, null, 2));
|
|
2978
|
+
// return;
|
|
2979
|
+
// }
|
|
2980
|
+
// if (result.created.length === 0) {
|
|
2981
|
+
// console.log('所有本地 AID 都已有对应 agent,无需同步。');
|
|
2982
|
+
// } else {
|
|
2983
|
+
// console.log(`✓ 同步完成:新建 ${result.created.length} 个 agent(模板: ${result.template})`);
|
|
2984
|
+
// for (const aid of result.created) console.log(` ✓ ${aid}`);
|
|
2985
|
+
// if (result.hotReloaded) console.log(' ✓ 已热加载到运行中的进程');
|
|
2986
|
+
// else console.log(' evolclaw 未运行,新 agent 将在下次启动时加载。');
|
|
2987
|
+
// }
|
|
2988
|
+
// return;
|
|
2989
|
+
// }
|
|
2999
2990
|
// --- reload ---
|
|
3000
2991
|
if (sub === 'reload') {
|
|
3001
2992
|
const target = args[1] && !args[1].startsWith('--') ? args[1] : undefined;
|
|
@@ -4645,7 +4636,6 @@ Commands:
|
|
|
4645
4636
|
--name <display-name>
|
|
4646
4637
|
--description <text>
|
|
4647
4638
|
--force (覆盖已有 config.json)
|
|
4648
|
-
agent sync-aids 从本地 AID 批量同步创建 agent(以最早 agent 为模板)
|
|
4649
4639
|
agent reload 全量 resync(扫磁盘,新增上线、删除下线、修改热更新)
|
|
4650
4640
|
agent reload <n> 热重载指定 agent 配置
|
|
4651
4641
|
aid AID 身份管理
|
package/dist/cli/init.js
CHANGED
|
@@ -4,6 +4,7 @@ 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
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;
|
|
@@ -104,7 +111,7 @@ export async function cmdInit(options) {
|
|
|
104
111
|
continue;
|
|
105
112
|
}
|
|
106
113
|
if (!available.includes(input)) {
|
|
107
|
-
console.log(` ${input}
|
|
114
|
+
console.log(` ${input} 当前环境不可用(可用: ${available.join('/')})`);
|
|
108
115
|
continue;
|
|
109
116
|
}
|
|
110
117
|
chosen = input;
|