evolclaw 3.1.5 → 3.1.6

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 (46) hide show
  1. package/CHANGELOG.md +53 -3
  2. package/dist/agents/claude-runner.js +69 -24
  3. package/dist/agents/kit-renderer.js +15 -4
  4. package/dist/aun/aid/agentmd.js +10 -3
  5. package/dist/aun/msg/group.js +2 -2
  6. package/dist/channels/aun.js +98 -12
  7. package/dist/channels/dingtalk.js +1 -1
  8. package/dist/channels/feishu.js +31 -9
  9. package/dist/channels/qqbot.js +1 -1
  10. package/dist/channels/wechat.js +1 -1
  11. package/dist/channels/wecom.js +1 -1
  12. package/dist/cli/agent.js +10 -11
  13. package/dist/cli/bench.js +1 -5
  14. package/dist/cli/help.js +8 -0
  15. package/dist/cli/index.js +91 -128
  16. package/dist/cli/init.js +37 -21
  17. package/dist/cli/link-rules.js +1 -7
  18. package/dist/cli/model.js +231 -6
  19. package/dist/config-store.js +1 -22
  20. package/dist/core/command-handler.js +181 -48
  21. package/dist/core/evolagent.js +0 -18
  22. package/dist/core/message/im-renderer.js +9 -20
  23. package/dist/core/message/message-bridge.js +7 -3
  24. package/dist/core/message/message-processor.js +138 -35
  25. package/dist/core/relation/peer-identity.js +23 -11
  26. package/dist/core/trigger/parser.js +4 -4
  27. package/dist/core/trigger/scheduler.js +20 -6
  28. package/dist/index.js +55 -5
  29. package/dist/ipc.js +1 -1
  30. package/dist/utils/error-utils.js +6 -0
  31. package/dist/utils/process-introspect.js +7 -5
  32. package/kits/docs/INDEX.md +4 -8
  33. package/kits/docs/context-assembly.md +1 -0
  34. package/kits/docs/evolclaw/INDEX.md +43 -0
  35. package/kits/docs/evolclaw/group.md +13 -6
  36. package/kits/docs/evolclaw/model.md +51 -0
  37. package/kits/docs/evolclaw/msg.md +5 -0
  38. package/kits/docs/venues/group.md +13 -1
  39. package/kits/eck_manifest.json +9 -0
  40. package/kits/rules/06-channel.md +5 -1
  41. package/kits/templates/system-fragments/baseagent.md +7 -1
  42. package/kits/templates/system-fragments/channel.md +7 -5
  43. package/kits/templates/system-fragments/commands.md +19 -0
  44. package/kits/templates/system-fragments/session.md +9 -0
  45. package/kits/templates/system-fragments/venue.md +15 -0
  46. package/package.json +3 -3
package/dist/cli/init.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import fs from 'fs';
2
+ import path from 'path';
2
3
  import readline from 'readline';
3
4
  import { resolvePaths, ensureDataDirs } from '../paths.js';
4
5
  import { commandExists } from '../utils/cross-platform.js';
@@ -10,11 +11,6 @@ function ask(rl, question) {
10
11
  return new Promise(resolve => rl.question(question, resolve));
11
12
  }
12
13
  const BASEAGENT_CANDIDATES = ['claude', 'codex', 'gemini'];
13
- const BASEAGENT_ENV_KEY = {
14
- claude: 'ANTHROPIC_API_KEY',
15
- codex: 'OPENAI_API_KEY',
16
- gemini: 'GEMINI_API_KEY',
17
- };
18
14
  function isBaseagentAvailable(baseagent) {
19
15
  if (baseagent === 'codex')
20
16
  return isCodexSdkAvailable();
@@ -26,16 +22,19 @@ function detectAvailable() {
26
22
  function pickDefault(available) {
27
23
  return (available.includes('claude') ? 'claude' : available[0]);
28
24
  }
29
- function buildDefaults(chosen) {
30
- const env = BASEAGENT_ENV_KEY[chosen];
25
+ function buildDefaults(chosen, available, projectsDefaultPath) {
26
+ const baseagents = {};
27
+ for (const b of available)
28
+ baseagents[b] = {};
31
29
  return {
32
30
  $schema_version: 1,
33
31
  active_baseagent: chosen,
34
- baseagents: { [chosen]: env ? { apiKey: `$ENV:${env}` } : {} },
32
+ baseagents,
33
+ ...(projectsDefaultPath ? { projects: { defaultPath: projectsDefaultPath } } : {}),
35
34
  };
36
35
  }
37
- function writeDefaults(_defaultsPath, chosen) {
38
- saveDefaultsSafe(buildDefaults(chosen));
36
+ function writeDefaults(chosen, available, projectsDefaultPath) {
37
+ saveDefaultsSafe(buildDefaults(chosen, available, projectsDefaultPath));
39
38
  }
40
39
  // ==================== Main ====================
41
40
  export async function cmdInit(options) {
@@ -85,7 +84,7 @@ export async function cmdInit(options) {
85
84
  else {
86
85
  chosen = pickDefault(available);
87
86
  }
88
- writeDefaults(defaultsPath, chosen);
87
+ writeDefaults(chosen, available);
89
88
  console.log(`✓ 已${exists ? '覆盖' : '创建'}: ${defaultsPath}`);
90
89
  console.log(` active_baseagent: ${chosen}`);
91
90
  const { agents } = loadAllAgents();
@@ -118,12 +117,33 @@ export async function cmdInit(options) {
118
117
  }
119
118
  return chosen;
120
119
  }
120
+ async function askProjectsDefaultPath() {
121
+ const defaultDir = path.join(p.root, 'projects', 'default');
122
+ const input = (await ask(rl, `项目默认目录 [${defaultDir}]: `)).trim();
123
+ const resolved = input || defaultDir;
124
+ if (!path.isAbsolute(resolved)) {
125
+ console.log(' ⚠ 需要绝对路径,已跳过');
126
+ return undefined;
127
+ }
128
+ if (!fs.existsSync(resolved)) {
129
+ const create = (await ask(rl, ` 目录不存在,是否创建?[Y/n]: `)).trim().toLowerCase();
130
+ if (create === '' || create === 'y' || create === 'yes') {
131
+ fs.mkdirSync(resolved, { recursive: true });
132
+ console.log(` ✓ 已创建 ${resolved}`);
133
+ }
134
+ else {
135
+ return undefined;
136
+ }
137
+ }
138
+ return resolved;
139
+ }
121
140
  try {
122
141
  if (exists) {
123
142
  const ans = (await ask(rl, `配置文件已存在: ${defaultsPath}\n 是否覆盖?[y/N] `)).trim().toLowerCase();
124
143
  if (ans === 'y' || ans === 'yes') {
125
144
  const chosen = await askBaseagent();
126
- writeDefaults(defaultsPath, chosen);
145
+ const projectsDefaultPath = await askProjectsDefaultPath();
146
+ writeDefaults(chosen, available, projectsDefaultPath);
127
147
  console.log(`\n✓ 已覆盖: ${defaultsPath}`);
128
148
  console.log(` active_baseagent: ${chosen}\n`);
129
149
  }
@@ -133,20 +153,16 @@ export async function cmdInit(options) {
133
153
  }
134
154
  else {
135
155
  const chosen = await askBaseagent();
136
- writeDefaults(defaultsPath, chosen);
156
+ const projectsDefaultPath = await askProjectsDefaultPath();
157
+ writeDefaults(chosen, available, projectsDefaultPath);
137
158
  console.log(`\n✓ 已创建: ${defaultsPath}`);
138
159
  console.log(` active_baseagent: ${chosen}\n`);
139
160
  }
140
- // ── 5. agent 时自动进入 agent new ──
161
+ // ── 5. 提示创建 agent ──
141
162
  const { agents } = loadAllAgents();
142
163
  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
- }
164
+ console.log('提示:尚无 agent,运行以下命令创建:');
165
+ console.log(' evolclaw agent new <aid>.agentid.pub');
150
166
  }
151
167
  }
152
168
  finally {
@@ -2,7 +2,7 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { kitsRulesDir, resolvePaths } from '../paths.js';
4
4
  import { atomicWriteJson, atomicReadJson } from '../utils/atomic-write.js';
5
- import { wantsHelp } from './help.js';
5
+ import { wantsHelp, getArgValue } from './help.js';
6
6
  const isWindows = process.platform === 'win32';
7
7
  const KNOWN_BASEAGENTS = ['cc', 'codex', 'gemini'];
8
8
  function statePath() {
@@ -232,12 +232,6 @@ function resolveBaseAgent(input) {
232
232
  console.error(` Supported: ${KNOWN_BASEAGENTS.join(', ')}`);
233
233
  process.exit(1);
234
234
  }
235
- function getArgValue(args, flag) {
236
- const idx = args.indexOf(flag);
237
- if (idx === -1 || idx + 1 >= args.length)
238
- return undefined;
239
- return args[idx + 1];
240
- }
241
235
  function pathEquals(a, b) {
242
236
  if (isWindows) {
243
237
  return path.resolve(a).toLowerCase() === path.resolve(b).toLowerCase();
package/dist/cli/model.js CHANGED
@@ -10,17 +10,15 @@
10
10
  * 与对话内 slash(/model /setmodel /effort /baseagent)互不影响。
11
11
  * 设计见 docs/model-command-design.md。
12
12
  */
13
- import { isHelpFlag, wantsHelp } from './help.js';
13
+ import { isHelpFlag, wantsHelp, getArgValue } from './help.js';
14
14
  import { ModelScopeError, normalizePeer, determineScope, activeBaseagent, readScope, writeScope, clearScope, resolveEffectiveModel, } from '../core/model/model-scope.js';
15
+ import { loadDefaults, loadAgent } from '../config-store.js';
16
+ import { resolveAnthropicConfig } from '../agents/resolve.js';
15
17
  import { getCatalog, getModelInfo } from '../core/model/model-catalog.js';
16
18
  const ALL_EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max', 'auto'];
17
19
  const SCOPE_LABEL = {
18
20
  global: '全局', agent: 'agent级', relation: '关系级',
19
21
  };
20
- function getArgValue(args, flag) {
21
- const idx = args.indexOf(flag);
22
- return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : undefined;
23
- }
24
22
  /** 输出 JSON 并退出(success=false 时 exit 1)。 */
25
23
  function emit(formatJson, payload, textFn) {
26
24
  if (formatJson) {
@@ -77,6 +75,7 @@ Commands:
77
75
  use <model-id> 设置模型(作用域由 --self/--peer 决定)
78
76
  reset 清除指定作用域的设置,回落上一级
79
77
  effort <level> 设置推理强度(low|medium|high|xhigh|max|auto)
78
+ check 诊断网关连通性与模型可用性(分阶段输出进度)
80
79
 
81
80
  作用域(由参数决定,越具体越优先:关系 > agent > 全局):
82
81
  (无参数) 全局默认 → defaults.json
@@ -99,7 +98,8 @@ Options:
99
98
  evolclaw model use opus
100
99
  evolclaw model use deepseek-v4-pro --self bot.agentid.pub --peer alice.agentid.pub
101
100
  evolclaw model effort high --self bot.agentid.pub
102
- evolclaw model reset --self bot.agentid.pub --peer alice.agentid.pub`;
101
+ evolclaw model reset --self bot.agentid.pub --peer alice.agentid.pub
102
+ evolclaw model check --self bot.agentid.pub`;
103
103
  async function dispatch(sub, args, formatJson) {
104
104
  switch (sub) {
105
105
  case 'list': return await cmdList(args, formatJson);
@@ -108,6 +108,7 @@ async function dispatch(sub, args, formatJson) {
108
108
  case 'use': return await cmdUse(args, formatJson);
109
109
  case 'reset': return await cmdReset(args, formatJson);
110
110
  case 'effort': return await cmdEffort(args, formatJson);
111
+ case 'check': return await cmdCheck(args, formatJson);
111
112
  default:
112
113
  fail(formatJson, 'UNKNOWN_SUBCOMMAND', `未知子命令: ${sub}(model --help 查看用法)`);
113
114
  }
@@ -313,6 +314,230 @@ async function cmdReset(args, formatJson) {
313
314
  return `✓ 已清除 ${SCOPE_LABEL[scope]} 设置,回落上一级(该范围所有会话下条消息生效)`;
314
315
  });
315
316
  }
317
+ /** 带超时的 fetch,返回 Response 或 null(超时/失败)。 */
318
+ async function fetchWithTimeout(url, opts, timeoutMs) {
319
+ const controller = new AbortController();
320
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
321
+ try {
322
+ const resp = await fetch(url, { ...opts, signal: controller.signal });
323
+ clearTimeout(timer);
324
+ return resp;
325
+ }
326
+ catch {
327
+ clearTimeout(timer);
328
+ return null;
329
+ }
330
+ }
331
+ /** 解析网关 baseUrl 和 apiKey(复用 resolveCreds 逻辑,但从 CLI 层调用)。 */
332
+ function resolveGatewayCreds(self) {
333
+ try {
334
+ const defaults = loadDefaults();
335
+ const agentCfg = self ? loadAgent(self) : null;
336
+ const block = agentCfg?.baseagents || defaults?.baseagents || {};
337
+ const claudeCfg = block.claude || {};
338
+ const r = resolveAnthropicConfig({ agents: { claude: claudeCfg } }, claudeCfg);
339
+ return { baseUrl: r.baseUrl, apiKey: r.apiKey };
340
+ }
341
+ catch {
342
+ return {};
343
+ }
344
+ }
345
+ /** 对单个模型发一次最小探测请求,返回延迟 ms 或错误信息。
346
+ * 按网关风格顺序探测:Anthropic Messages API → OpenAI chat completions → 仅列表校验
347
+ */
348
+ async function probeModel(baseUrl, apiKey, modelId, timeoutMs) {
349
+ const base = baseUrl.replace(/\/+$/, '');
350
+ const authHeaders = apiKey
351
+ ? { 'x-api-key': apiKey, Authorization: `Bearer ${apiKey}` }
352
+ : {};
353
+ // 风格 1:Anthropic Messages API
354
+ {
355
+ const t0 = Date.now();
356
+ const resp = await fetchWithTimeout(`${base}/v1/messages`, {
357
+ method: 'POST',
358
+ headers: { 'Content-Type': 'application/json', 'anthropic-version': '2023-06-01', ...authHeaders },
359
+ body: JSON.stringify({ model: modelId, max_tokens: 5, messages: [{ role: 'user', content: 'ok' }] }),
360
+ }, timeoutMs);
361
+ const ms = Date.now() - t0;
362
+ if (resp && resp.ok)
363
+ return { ok: true, ms, style: 'anthropic' };
364
+ if (resp && resp.status >= 400 && resp.status < 500) {
365
+ // 4xx 说明网关支持此风格,但模型不可用
366
+ let errMsg = `HTTP ${resp.status}`;
367
+ try {
368
+ const j = await resp.json();
369
+ errMsg = j?.error?.message || j?.detail || j?.message || errMsg;
370
+ }
371
+ catch { /* ignore */ }
372
+ return { ok: false, ms, error: String(errMsg).slice(0, 80), style: 'anthropic' };
373
+ }
374
+ // 非 4xx(超时/连接失败/5xx)→ 继续尝试下一种风格
375
+ }
376
+ // 风格 2:OpenAI chat completions
377
+ {
378
+ const t0 = Date.now();
379
+ const resp = await fetchWithTimeout(`${base}/v1/chat/completions`, {
380
+ method: 'POST',
381
+ headers: { 'Content-Type': 'application/json', ...authHeaders },
382
+ body: JSON.stringify({ model: modelId, max_tokens: 5, messages: [{ role: 'user', content: 'ok' }] }),
383
+ }, timeoutMs);
384
+ const ms = Date.now() - t0;
385
+ if (resp && resp.ok) {
386
+ // 校验响应体有 choices 字段,否则可能是网关假装成功
387
+ try {
388
+ const j = await resp.json();
389
+ if (j?.choices || j?.id)
390
+ return { ok: true, ms, style: 'openai' };
391
+ }
392
+ catch { /* ignore */ }
393
+ }
394
+ if (resp && resp.status >= 400 && resp.status < 500) {
395
+ let errMsg = `HTTP ${resp.status}`;
396
+ try {
397
+ const j = await resp.json();
398
+ errMsg = j?.error?.message || j?.detail || j?.message || errMsg;
399
+ }
400
+ catch { /* ignore */ }
401
+ return { ok: false, ms, error: String(errMsg).slice(0, 80), style: 'openai' };
402
+ }
403
+ }
404
+ // 两种风格都探测不到:无法判断可用性
405
+ return { ok: false, ms: 0, error: '网关不支持标准探测(无法确认可用性)', style: 'unknown' };
406
+ }
407
+ async function cmdCheck(args, formatJson) {
408
+ if (wantsHelp(args)) {
409
+ console.log(HELP);
410
+ return;
411
+ }
412
+ const sel = parseSelector(args, formatJson);
413
+ const ba = activeBaseagent(sel.self);
414
+ const steps = [];
415
+ const log = (step) => {
416
+ steps.push(step);
417
+ if (!formatJson) {
418
+ const icon = step.ok ? '✓' : '✗';
419
+ const ms = step.ms !== undefined ? ` (${step.ms}ms)` : '';
420
+ console.log(`[${icon}] ${step.label.padEnd(14)} ${step.detail}${ms}`);
421
+ }
422
+ };
423
+ const { baseUrl, apiKey } = resolveGatewayCreds(sel.self);
424
+ // ── 阶段 1:DNS + 连通性 ──────────────────────────────────────────
425
+ if (!formatJson)
426
+ console.log('\n网关诊断\n' + '─'.repeat(50));
427
+ if (!baseUrl) {
428
+ log({ label: '网关地址', ok: false, detail: '未配置自定义网关(baseUrl),使用官方 Anthropic 端点' });
429
+ }
430
+ else {
431
+ // DNS + TCP:用一次 HEAD 请求探测
432
+ const t0 = Date.now();
433
+ const pingResp = await fetchWithTimeout(baseUrl.replace(/\/+$/, '') + '/v1/models', {
434
+ method: 'GET',
435
+ headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : {},
436
+ }, 4000);
437
+ const pingMs = Date.now() - t0;
438
+ if (!pingResp) {
439
+ log({ label: '网关连通', ok: false, detail: `${baseUrl} 无法连接(DNS/TCP 失败)`, ms: pingMs });
440
+ }
441
+ else {
442
+ log({ label: '网关连通', ok: true, detail: baseUrl, ms: pingMs });
443
+ }
444
+ }
445
+ // ── 阶段 2:认证 + 模型列表 ─────────────────────────────────────
446
+ if (!formatJson)
447
+ console.log('');
448
+ const cat = await getCatalog(sel.self, ba);
449
+ const modelIds = cat.models.filter(m => m.owned_by !== 'alias').map(m => m.id);
450
+ if (cat.source === 'mock') {
451
+ log({ label: '模型列表', ok: false, detail: `无法获取远端列表,使用内置 mock(${modelIds.length} 个)` });
452
+ }
453
+ else {
454
+ log({ label: '模型列表', ok: true, detail: `来源: ${cat.source},共 ${modelIds.length} 个模型` });
455
+ }
456
+ // ── 阶段 3:当前配置模型 ──────────────────────────────────────────
457
+ if (!formatJson)
458
+ console.log('');
459
+ const resolved = resolveEffectiveModel(sel, ba);
460
+ const configuredModel = resolved.model;
461
+ if (!configuredModel) {
462
+ log({ label: '配置模型', ok: true, detail: '未配置(将使用 base agent 默认模型)' });
463
+ }
464
+ else {
465
+ log({ label: '配置模型', ok: true, detail: `${configuredModel}(来源: ${resolved.source ?? '未知'})` });
466
+ }
467
+ // ── 阶段 4:模型可用性探测 ────────────────────────────────────────
468
+ // 仅在有自定义网关时才做 API 探测(官方端点跳过,避免消耗 token)
469
+ const probeResults = [];
470
+ if (baseUrl) {
471
+ if (!formatJson)
472
+ console.log('\n模型可用性探测\n' + '─'.repeat(50));
473
+ // 别名解析:从目录里找别名对应的完整 ID
474
+ const aliasMap = new Map(); // alias → full id
475
+ for (const entry of cat.models) {
476
+ if (entry.owned_by === 'alias') {
477
+ // 找目录中与别名前缀匹配的完整 ID
478
+ const match = cat.models.find(m => m.owned_by !== 'alias' && m.id.includes(entry.id));
479
+ if (match)
480
+ aliasMap.set(entry.id, match.id);
481
+ }
482
+ }
483
+ const resolveId = (id) => aliasMap.get(id) ?? id;
484
+ // 优先探测当前配置的模型(解析别名),其余为非别名 ID
485
+ const configResolved = configuredModel ? resolveId(configuredModel) : undefined;
486
+ const allProbeIds = [
487
+ ...(configResolved ? [{ display: configuredModel, probe: configResolved }] : []),
488
+ ...modelIds
489
+ .filter(id => id !== configResolved)
490
+ .map(id => ({ display: id, probe: id })),
491
+ ];
492
+ // 轮次 1:配置模型 + 1 个额外(并发 2,快速验证主要路径)
493
+ const round1 = allProbeIds.slice(0, 2);
494
+ const r1 = await Promise.all(round1.map(({ display, probe }) => probeModel(baseUrl, apiKey, probe, 5000).then(r => ({ id: display, displayId: display, ...r }))));
495
+ probeResults.push(...r1);
496
+ if (!formatJson)
497
+ r1.forEach(r => log({ label: r.id.slice(0, 20), ok: r.ok, detail: r.ok ? '可用' : (r.error ?? '不可用'), ms: r.ms }));
498
+ // 轮次 2:剩余,2 个一组(避免触发限速)
499
+ const rest = allProbeIds.slice(2);
500
+ for (let i = 0; i < rest.length; i += 2) {
501
+ const batch = rest.slice(i, i + 2);
502
+ const br = await Promise.all(batch.map(({ display, probe }) => probeModel(baseUrl, apiKey, probe, 5000).then(r => ({ id: display, displayId: display, ...r }))));
503
+ probeResults.push(...br);
504
+ if (!formatJson)
505
+ br.forEach(r => log({ label: r.id.slice(0, 20), ok: r.ok, detail: r.ok ? '可用' : (r.error ?? '不可用'), ms: r.ms }));
506
+ }
507
+ }
508
+ else {
509
+ if (!formatJson)
510
+ console.log('\n(跳过模型探测:未配置自定义网关)');
511
+ }
512
+ // ── 汇总 ─────────────────────────────────────────────────────────
513
+ const availableModels = probeResults.filter(r => r.ok).map(r => r.id);
514
+ const configModelOk = configuredModel ? probeResults.find(r => r.id === configuredModel)?.ok : undefined;
515
+ if (!formatJson) {
516
+ console.log('\n' + '─'.repeat(50));
517
+ if (configuredModel && configModelOk === false) {
518
+ console.log(`⚠️ 当前配置的模型 ${configuredModel} 不可用`);
519
+ if (availableModels.length > 0) {
520
+ console.log(` 可用模型:${availableModels.slice(0, 3).join('、')}${availableModels.length > 3 ? ` 等 ${availableModels.length} 个` : ''}`);
521
+ }
522
+ }
523
+ else if (configuredModel && configModelOk === true) {
524
+ console.log(`✓ 当前配置的模型 ${configuredModel} 可用`);
525
+ }
526
+ else if (!baseUrl) {
527
+ console.log(`✓ 使用官方 Anthropic 端点,无需探测`);
528
+ }
529
+ }
530
+ else {
531
+ emit(formatJson, {
532
+ ok: true,
533
+ steps,
534
+ configuredModel: configuredModel ?? null,
535
+ configModelAvailable: configModelOk ?? null,
536
+ availableModels,
537
+ catalogSource: cat.source,
538
+ }, () => '');
539
+ }
540
+ }
316
541
  export async function cmdModel(args) {
317
542
  const sub = args[0];
318
543
  const formatJson = getArgValue(args, '--format') === 'json';
@@ -163,7 +163,7 @@ export function autoMigrateIfNeeded() {
163
163
  active_baseagent: oldConfig.agents?.defaultAgent || 'claude',
164
164
  baseagents: {},
165
165
  models: oldConfig.models,
166
- projects: oldConfig.projects ? { defaultPath: oldConfig.projects.defaultPath, list: oldConfig.projects.list, autoCreate: oldConfig.projects.autoCreate } : undefined,
166
+ projects: oldConfig.projects ? { defaultPath: oldConfig.projects.defaultPath } : undefined,
167
167
  chatmode: oldConfig.chatmode,
168
168
  show_activities: oldConfig.showActivities,
169
169
  flush_delay: oldConfig.flushDelay,
@@ -594,7 +594,6 @@ export async function migrateProject(oldPath, newPath) {
594
594
  claudeHistoryUpdated: false,
595
595
  codexUpdated: 0,
596
596
  evolclawDbUpdated: 0,
597
- evolclawConfigUpdated: false,
598
597
  directoryMoved: false,
599
598
  };
600
599
  const oldAbs = path.resolve(oldPath);
@@ -687,25 +686,5 @@ export async function migrateProject(oldPath, newPath) {
687
686
  }
688
687
  catch { /* fs not accessible */ }
689
688
  }
690
- // 7. 更新各 self-agent config.json 的 projects.list
691
- try {
692
- const { agents } = loadAllAgents();
693
- for (const cfg of agents) {
694
- if (!cfg.projects?.list)
695
- continue;
696
- let changed = false;
697
- for (const [k, v] of Object.entries(cfg.projects.list)) {
698
- if (v === oldAbs) {
699
- cfg.projects.list[k] = newAbs;
700
- changed = true;
701
- }
702
- }
703
- if (changed) {
704
- saveAgent(cfg);
705
- result.evolclawConfigUpdated = true;
706
- }
707
- }
708
- }
709
- catch { /* agents not accessible */ }
710
689
  return result;
711
690
  }