evolclaw 3.1.4 → 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.
- package/CHANGELOG.md +60 -0
- package/dist/agents/claude-runner.js +398 -161
- package/dist/agents/kit-renderer.js +191 -25
- package/dist/aun/aid/agentmd.js +75 -103
- package/dist/aun/aid/client.js +1 -29
- package/dist/aun/aid/identity.js +105 -64
- package/dist/aun/aid/index.js +2 -1
- package/dist/aun/aid/store.js +74 -0
- package/dist/aun/msg/group.js +2 -2
- package/dist/aun/msg/p2p.js +26 -2
- package/dist/aun/rpc/connection.js +23 -30
- package/dist/channels/aun.js +174 -99
- package/dist/channels/dingtalk.js +2 -1
- package/dist/channels/feishu.js +301 -199
- package/dist/channels/qqbot.js +2 -1
- package/dist/channels/wechat.js +2 -1
- package/dist/channels/wecom.js +2 -1
- package/dist/cli/agent.js +21 -16
- package/dist/cli/bench.js +41 -28
- package/dist/cli/help.js +8 -0
- package/dist/cli/index.js +176 -87
- package/dist/cli/init-channel.js +5 -1
- package/dist/cli/init.js +37 -21
- package/dist/cli/link-rules.js +1 -7
- package/dist/cli/model.js +549 -0
- package/dist/cli/net-check.js +133 -50
- package/dist/cli/watch-msg.js +7 -7
- package/dist/cli/watch-web/debug-log.js +18 -0
- package/dist/cli/watch-web/server.js +306 -0
- package/dist/cli/watch-web/sources/aid.js +63 -0
- package/dist/cli/watch-web/sources/msg.js +70 -0
- package/dist/cli/watch-web/sources/session.js +638 -0
- package/dist/cli/watch-web/sources/types.js +10 -0
- package/dist/cli/watch-web/static/app.js +546 -0
- package/dist/cli/watch-web/static/index.html +54 -0
- package/dist/cli/watch-web/static/style.css +247 -0
- package/dist/config-store.js +1 -22
- package/dist/core/channel-loader.js +7 -4
- package/dist/core/command-handler.js +261 -133
- package/dist/core/evolagent-registry.js +1 -1
- package/dist/core/evolagent.js +4 -22
- package/dist/core/interaction-router.js +59 -0
- package/dist/core/message/im-renderer.js +9 -20
- package/dist/core/message/message-bridge.js +13 -9
- package/dist/core/message/message-log.js +2 -2
- package/dist/core/message/message-processor.js +211 -123
- package/dist/core/message/stream-idle-monitor.js +21 -0
- package/dist/core/model/model-catalog.js +215 -0
- package/dist/core/model/model-scope.js +250 -0
- package/dist/core/relation/peer-identity.js +58 -55
- package/dist/core/relation/peer-key.js +16 -0
- package/dist/core/session/session-fs-store.js +34 -55
- package/dist/core/session/session-key.js +24 -0
- package/dist/core/session/session-manager.js +308 -251
- package/dist/core/session/session-mapper.js +9 -4
- package/dist/core/trigger/manager.js +3 -3
- package/dist/core/trigger/parser.js +4 -4
- package/dist/core/trigger/scheduler.js +22 -7
- package/dist/index.js +61 -7
- package/dist/ipc.js +23 -1
- package/dist/utils/error-utils.js +6 -0
- package/dist/utils/process-introspect.js +7 -5
- package/kits/docs/GUIDE.md +2 -2
- package/kits/docs/INDEX.md +8 -8
- package/kits/docs/channels/aun.md +56 -17
- package/kits/docs/channels/feishu.md +41 -12
- package/kits/docs/context-assembly.md +182 -0
- package/kits/docs/evolclaw/INDEX.md +43 -0
- package/kits/docs/evolclaw/agent.md +49 -0
- package/kits/docs/evolclaw/aid.md +49 -0
- package/kits/docs/evolclaw/ctl.md +46 -0
- package/kits/docs/evolclaw/group.md +89 -0
- package/kits/docs/evolclaw/model.md +51 -0
- package/kits/docs/evolclaw/msg.md +91 -0
- package/kits/docs/evolclaw/rpc.md +35 -0
- package/kits/docs/evolclaw/storage.md +49 -0
- package/kits/docs/venues/aun-group.md +10 -0
- package/kits/docs/venues/aun-private.md +10 -0
- package/kits/docs/venues/client-desktop.md +10 -0
- package/kits/docs/venues/client-mobile.md +10 -0
- package/kits/docs/venues/feishu-group.md +13 -0
- package/kits/docs/venues/feishu-private.md +9 -0
- package/kits/docs/venues/group.md +23 -0
- package/kits/docs/venues/private.md +10 -0
- package/kits/eck_manifest.json +81 -36
- package/kits/rules/01-overview.md +20 -10
- package/kits/rules/06-channel.md +34 -27
- package/kits/templates/system-fragments/baseagent.md +7 -1
- package/kits/templates/system-fragments/channel.md +7 -5
- package/kits/templates/system-fragments/commands.md +19 -0
- package/kits/templates/system-fragments/session.md +19 -3
- package/kits/templates/system-fragments/venue.md +24 -0
- package/package.json +10 -5
- package/dist/aun/aid/lifecycle-log.js +0 -33
- package/dist/utils/aid-lifecycle-log.js +0 -33
- package/kits/docs/evolclaw/AGENT_CMD.md +0 -31
- package/kits/docs/evolclaw/MSG_GROUP.md +0 -30
- package/kits/docs/evolclaw/MSG_PRIVATE.md +0 -72
- package/kits/docs/evolclaw/tools.md +0 -25
package/dist/cli/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { migrateProject } from '../config-store.js';
|
|
|
11
11
|
import { cmdInit } from './init.js';
|
|
12
12
|
import { ipcQuery } from '../ipc.js';
|
|
13
13
|
import { cmdInitWechat, cmdInitFeishu, cmdInitDingtalk, cmdInitQQBot, cmdInitWecom } from './init-channel.js';
|
|
14
|
-
import { isHelpFlag, wantsHelp } from './help.js';
|
|
14
|
+
import { isHelpFlag, wantsHelp, getArgValue } from './help.js';
|
|
15
15
|
import * as platform from '../utils/cross-platform.js';
|
|
16
16
|
import { EventBus } from '../core/event-bus.js';
|
|
17
17
|
import { tryUpgrade, tryUpgradeAunSdk } from '../utils/npm-ops.js';
|
|
@@ -292,6 +292,13 @@ async function cmdStart() {
|
|
|
292
292
|
// 旧配置自动迁移(evolclaw.json → 新结构)
|
|
293
293
|
const { autoMigrateIfNeeded } = await import('../config-store.js');
|
|
294
294
|
autoMigrateIfNeeded();
|
|
295
|
+
// 未初始化时自动引导
|
|
296
|
+
const defaults = loadDefaults();
|
|
297
|
+
if (!defaults || !defaults.baseagents || Object.keys(defaults.baseagents).length === 0) {
|
|
298
|
+
console.log('⚡ 未检测到初始化配置,自动启动初始化向导...\n');
|
|
299
|
+
await cmdInit();
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
295
302
|
// 检查至少有一个 self-agent
|
|
296
303
|
const { agents, skipped } = loadAllAgents();
|
|
297
304
|
if (agents.length === 0) {
|
|
@@ -313,7 +320,7 @@ async function cmdStart() {
|
|
|
313
320
|
const aliveMains = status.mains.filter(m => m.alive);
|
|
314
321
|
if (aliveMains.length > 0) {
|
|
315
322
|
const first = aliveMains[0];
|
|
316
|
-
console.log(
|
|
323
|
+
console.log(` EvolClaw is already running (PID: ${aliveMains.map(m => m.record.pid).join(', ')})`);
|
|
317
324
|
console.log(` 启动于: ${new Date(first.record.startedAtIso).toLocaleString()}`);
|
|
318
325
|
console.log(` 启动方式: ${first.record.launchedBy}`);
|
|
319
326
|
// 报告 AID 状态
|
|
@@ -371,14 +378,7 @@ async function cmdStart() {
|
|
|
371
378
|
const checkReady = () => {
|
|
372
379
|
// ready signal 出现(优先检查,避免 Windows 上误判进程状态)
|
|
373
380
|
if (fs.existsSync(p.readySignal)) {
|
|
374
|
-
|
|
375
|
-
let aunVer = 'unknown';
|
|
376
|
-
try {
|
|
377
|
-
const aunPkg = JSON.parse(fs.readFileSync(path.join(getPackageRoot(), 'node_modules', '@agentunion', 'fastaun', 'package.json'), 'utf-8'));
|
|
378
|
-
aunVer = aunPkg.version;
|
|
379
|
-
}
|
|
380
|
-
catch { /* ignore */ }
|
|
381
|
-
console.log(`✓ EvolClaw v${pkg.version} started successfully (PID: ${childPid}) fastaun v${aunVer}`);
|
|
381
|
+
console.log(`✓ EvolClaw started successfully (PID: ${childPid})`);
|
|
382
382
|
console.log(` EVOLCLAW_HOME: ${resolveRoot()}`);
|
|
383
383
|
console.log(` Logs: ${p.logs}/`);
|
|
384
384
|
// 从主日志提取渠道连接摘要
|
|
@@ -495,7 +495,6 @@ async function cmdStop() {
|
|
|
495
495
|
}
|
|
496
496
|
async function cmdRestart(opts = {}) {
|
|
497
497
|
const cmdStartedAt = Date.now();
|
|
498
|
-
printStartupInfo();
|
|
499
498
|
console.log('🔄 Restarting EvolClaw...');
|
|
500
499
|
// 版本检查与自动升级
|
|
501
500
|
console.log('📦 Checking for updates...');
|
|
@@ -884,8 +883,8 @@ async function cmdStatus() {
|
|
|
884
883
|
const configChannelNames = new Set();
|
|
885
884
|
for (const cfg of agents) {
|
|
886
885
|
for (const inst of cfg.channels) {
|
|
887
|
-
// effective key: <type>#<
|
|
888
|
-
configChannelNames.add(`${inst.type}#${
|
|
886
|
+
// effective key: <type>#<selfAID>#<name>
|
|
887
|
+
configChannelNames.add(`${inst.type}#${cfg.aid}#${inst.name}`);
|
|
889
888
|
}
|
|
890
889
|
}
|
|
891
890
|
for (const s of allSessions) {
|
|
@@ -1014,7 +1013,7 @@ async function cmdStatus() {
|
|
|
1014
1013
|
}
|
|
1015
1014
|
}
|
|
1016
1015
|
/**
|
|
1017
|
-
* 把 channel fingerprint 列表(`<type>#<
|
|
1016
|
+
* 把 channel fingerprint 列表(`<type>#<selfAID>#<name>`)折叠成展示用摘要。
|
|
1018
1017
|
*
|
|
1019
1018
|
* 聚合规则:
|
|
1020
1019
|
* - 按 type 分组
|
|
@@ -1414,6 +1413,7 @@ async function cmdWatchMenu() {
|
|
|
1414
1413
|
{ key: 'log', label: 'log', desc: 'real-time log tail' },
|
|
1415
1414
|
{ key: 'aid', label: 'aid', desc: 'AID connection stats' },
|
|
1416
1415
|
{ key: 'msg', label: 'msg', desc: 'message inspector' },
|
|
1416
|
+
{ key: 'web', label: 'web', desc: 'browser dashboard (aid/msg/session)' },
|
|
1417
1417
|
];
|
|
1418
1418
|
let index = 0;
|
|
1419
1419
|
const useColor = !!process.stdout.isTTY;
|
|
@@ -1477,6 +1477,9 @@ async function cmdWatchMenu() {
|
|
|
1477
1477
|
const { cmdWatchMsg } = await import('./watch-msg.js');
|
|
1478
1478
|
await cmdWatchMsg();
|
|
1479
1479
|
}
|
|
1480
|
+
else if (chosen === 'web') {
|
|
1481
|
+
await cmdWatchWeb();
|
|
1482
|
+
}
|
|
1480
1483
|
resolve();
|
|
1481
1484
|
}
|
|
1482
1485
|
};
|
|
@@ -2098,6 +2101,24 @@ async function cmdWatchAid() {
|
|
|
2098
2101
|
}
|
|
2099
2102
|
platform.onShutdown(cleanup);
|
|
2100
2103
|
}
|
|
2104
|
+
async function cmdWatchWeb() {
|
|
2105
|
+
// ecweb 是独立插件包(可执行命令),按需安装。
|
|
2106
|
+
// 复用 npm-ops.npmInstallGlobal(含 EACCES→sudo 回退、Windows npm.cmd、超时)。
|
|
2107
|
+
const { execFileSync } = await import('child_process');
|
|
2108
|
+
const home = resolvePaths().root;
|
|
2109
|
+
if (!platform.commandExists('ecweb')) {
|
|
2110
|
+
process.stdout.write('📦 ecweb 未安装,正在从 npm 安装...\n');
|
|
2111
|
+
const { npmInstallGlobal } = await import('../utils/npm-ops.js');
|
|
2112
|
+
try {
|
|
2113
|
+
await npmInstallGlobal('ecweb');
|
|
2114
|
+
}
|
|
2115
|
+
catch (e) {
|
|
2116
|
+
process.stderr.write(`❌ 安装 ecweb 失败: ${e?.stderr || e?.message || e}\n 可手动安装: npm install -g ecweb\n`);
|
|
2117
|
+
process.exit(1);
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
execFileSync('ecweb', ['--home', home], { stdio: 'inherit' });
|
|
2121
|
+
}
|
|
2101
2122
|
async function cmdRestartMonitor() {
|
|
2102
2123
|
const p = resolvePaths();
|
|
2103
2124
|
const restartLog = path.join(p.logs, 'restart.log');
|
|
@@ -2472,14 +2493,13 @@ function archiveSelfHealLog(p, log) {
|
|
|
2472
2493
|
* Searches across all channel types (feishu, wechat, aun) for a matching instance.
|
|
2473
2494
|
*/
|
|
2474
2495
|
function resolveInstanceConfig(instanceName) {
|
|
2475
|
-
// 新结构:channel key 是 <type>#<
|
|
2496
|
+
// 新结构:channel key 是 <type>#<selfAID>#<name>,解析后从对应 agent 的 channels[] 找
|
|
2476
2497
|
const parts = instanceName.split('#');
|
|
2477
2498
|
if (parts.length === 3) {
|
|
2478
|
-
const [type,
|
|
2479
|
-
const selfPeerId = decodeURIComponent(encodedSelfPeerId);
|
|
2499
|
+
const [type, selfAID, name] = parts;
|
|
2480
2500
|
const { agents } = loadAllAgents();
|
|
2481
|
-
// AUN channel 的
|
|
2482
|
-
const agent = agents.find(a => a.aid ===
|
|
2501
|
+
// AUN channel 的 selfAID 就是 agent.aid
|
|
2502
|
+
const agent = agents.find(a => a.aid === selfAID);
|
|
2483
2503
|
if (!agent)
|
|
2484
2504
|
return null;
|
|
2485
2505
|
const inst = agent.channels.find((c) => c.type === type && c.name === name);
|
|
@@ -2625,8 +2645,6 @@ async function cmdMv(oldDir, newDir) {
|
|
|
2625
2645
|
console.log('✓ 项目目录已移动');
|
|
2626
2646
|
if (r.evolclawDbUpdated > 0)
|
|
2627
2647
|
console.log(`✓ EvolClaw 会话存储已更新 (${r.evolclawDbUpdated} 条记录)`);
|
|
2628
|
-
if (r.evolclawConfigUpdated)
|
|
2629
|
-
console.log('✓ agent config projects.list 已更新');
|
|
2630
2648
|
console.log('\n迁移完成!');
|
|
2631
2649
|
}
|
|
2632
2650
|
catch (e) {
|
|
@@ -2800,7 +2818,7 @@ Agent:
|
|
|
2800
2818
|
// ==================== Agent ====================
|
|
2801
2819
|
async function cmdAgent(args) {
|
|
2802
2820
|
const sub = args[0];
|
|
2803
|
-
const formatJson = args
|
|
2821
|
+
const formatJson = getArgValue(args, '--format') === 'json';
|
|
2804
2822
|
if (!sub || isHelpFlag(sub)) {
|
|
2805
2823
|
console.log(`用法: evolclaw agent <command>
|
|
2806
2824
|
|
|
@@ -3375,7 +3393,7 @@ function resolveAunPath(args) {
|
|
|
3375
3393
|
}
|
|
3376
3394
|
async function cmdAid(args) {
|
|
3377
3395
|
const sub = args[0];
|
|
3378
|
-
const formatJson = args
|
|
3396
|
+
const formatJson = getArgValue(args, '--format') === 'json';
|
|
3379
3397
|
const aunPath = resolveAunPath(args);
|
|
3380
3398
|
if (!sub || isHelpFlag(sub)) {
|
|
3381
3399
|
console.log(`用法: evolclaw aid <command>
|
|
@@ -3467,7 +3485,7 @@ Options:
|
|
|
3467
3485
|
console.log('无匹配 AID');
|
|
3468
3486
|
return;
|
|
3469
3487
|
}
|
|
3470
|
-
console.log(`本地 AID${noVerify ? '(静态扫描,未实测)' : ''}
|
|
3488
|
+
console.log(`本地 AID${noVerify ? '(静态扫描,未实测)' : ''}(${aunPath ?? resolveRoot()}):`);
|
|
3471
3489
|
for (const a of aids) {
|
|
3472
3490
|
const keyIcon = a.hasPrivateKey ? '🔑' : ' ';
|
|
3473
3491
|
let signIcon = ' ';
|
|
@@ -3533,40 +3551,63 @@ Options:
|
|
|
3533
3551
|
}
|
|
3534
3552
|
if (sub === 'new') {
|
|
3535
3553
|
if (wantsHelp(args)) {
|
|
3536
|
-
console.log(`用法: evolclaw aid new <完整AID>
|
|
3554
|
+
console.log(`用法: evolclaw aid new <完整AID> [--force]
|
|
3537
3555
|
|
|
3538
3556
|
创建新 AID 身份:生成 ECDSA 密钥对、向 Issuer 申请证书、构建并上传初始 agent.md。
|
|
3539
3557
|
|
|
3540
|
-
|
|
3558
|
+
选项:
|
|
3559
|
+
--force 强制重新注册,覆盖已存在的身份(即使签名验证失败)
|
|
3560
|
+
|
|
3561
|
+
例: evolclaw aid new reviewer.agentid.pub
|
|
3562
|
+
evolclaw aid new reviewer.agentid.pub --force`);
|
|
3541
3563
|
return;
|
|
3542
3564
|
}
|
|
3543
3565
|
const aid = args[1];
|
|
3566
|
+
const force = args.includes('--force');
|
|
3544
3567
|
if (!aid) {
|
|
3545
|
-
console.error('用法: evolclaw aid new <完整AID
|
|
3568
|
+
console.error('用法: evolclaw aid new <完整AID> [--force]\n例: evolclaw aid new reviewer.agentid.pub');
|
|
3546
3569
|
process.exit(1);
|
|
3547
3570
|
}
|
|
3548
3571
|
if (!isValidAid(aid)) {
|
|
3549
3572
|
console.error(`❌ 无效 AID 格式: ${aid}`);
|
|
3550
3573
|
process.exit(1);
|
|
3551
3574
|
}
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3575
|
+
try {
|
|
3576
|
+
const result = await aidCreate(aid, { aunPath, force });
|
|
3577
|
+
if (!result.alreadyExisted) {
|
|
3578
|
+
const content = buildInitialAgentMd({ aid });
|
|
3579
|
+
try {
|
|
3580
|
+
await agentmdPut(content, { aid, aunPath });
|
|
3581
|
+
console.log('✓ agent.md 已发布');
|
|
3582
|
+
}
|
|
3583
|
+
catch (e) {
|
|
3584
|
+
console.warn(`⚠ agent.md 发布失败(首次连接将自动重试): ${String(e.message || e).slice(0, 100)}`);
|
|
3585
|
+
}
|
|
3586
|
+
}
|
|
3555
3587
|
try {
|
|
3556
|
-
await
|
|
3557
|
-
console.log('✓ agent.md 已发布');
|
|
3588
|
+
await result.client.close();
|
|
3558
3589
|
}
|
|
3559
|
-
catch
|
|
3560
|
-
|
|
3590
|
+
catch { }
|
|
3591
|
+
try {
|
|
3592
|
+
result.store?.close();
|
|
3561
3593
|
}
|
|
3594
|
+
catch { }
|
|
3595
|
+
const verb = result.alreadyExisted ? '已存在且有效' : (force ? '已重新创建' : '已创建');
|
|
3596
|
+
console.log(`✓ ${aid} ${verb}`);
|
|
3597
|
+
console.log(' 如需上线 AUN 通道,运行 evolclaw agent new ' + aid);
|
|
3562
3598
|
}
|
|
3563
|
-
|
|
3564
|
-
|
|
3599
|
+
catch (e) {
|
|
3600
|
+
if (e.code === 'AID_INVALID') {
|
|
3601
|
+
console.error(`❌ ${e.message}`);
|
|
3602
|
+
process.exit(1);
|
|
3603
|
+
}
|
|
3604
|
+
if (e.code === -32052 || e.constructor?.name === 'IdentityConflictError') {
|
|
3605
|
+
console.error(`❌ AID ${aid} 已在服务端注册,但本地密钥无法匹配。\n` +
|
|
3606
|
+
`该 AID 可能由其他设备创建,无法在本地恢复。请选择其他名称。`);
|
|
3607
|
+
process.exit(1);
|
|
3608
|
+
}
|
|
3609
|
+
throw e;
|
|
3565
3610
|
}
|
|
3566
|
-
catch { }
|
|
3567
|
-
const verb = result.alreadyExisted ? '已存在' : '已创建';
|
|
3568
|
-
console.log(`✓ ${aid} ${verb}`);
|
|
3569
|
-
console.log(' 如需上线 AUN 通道,运行 evolclaw agent new ' + aid);
|
|
3570
3611
|
return;
|
|
3571
3612
|
}
|
|
3572
3613
|
if (sub === 'delete') {
|
|
@@ -3853,6 +3894,10 @@ async function cmdRpc(args) {
|
|
|
3853
3894
|
|
|
3854
3895
|
每行 JSON 格式: {"method":"<namespace.method>","params":{...}}
|
|
3855
3896
|
|
|
3897
|
+
Options:
|
|
3898
|
+
--app <name> 指定应用 slot(独立消费通道)。仅对 message.pull / group.pull
|
|
3899
|
+
等消费类方法有意义——隔离 seq 游标与消息过滤;默认与 daemon 共享通道。
|
|
3900
|
+
|
|
3856
3901
|
示例:
|
|
3857
3902
|
evolclaw rpc --as alice.agentid.pub --params '{"method":"message.send","params":{"to":"bob.agentid.pub","payload":{"type":"text","text":"hello"}}}'
|
|
3858
3903
|
evolclaw rpc --as alice.agentid.pub --params calls.jsonl`);
|
|
@@ -3861,6 +3906,7 @@ async function cmdRpc(args) {
|
|
|
3861
3906
|
const asIdx = args.indexOf('--as');
|
|
3862
3907
|
const paramsIdx = args.indexOf('--params');
|
|
3863
3908
|
const aunPath = resolveAunPath(args);
|
|
3909
|
+
const appSlot = getArgValue(args, '--app');
|
|
3864
3910
|
if (asIdx === -1 || asIdx + 1 >= args.length) {
|
|
3865
3911
|
console.error('❌ 缺少 --as <aid>');
|
|
3866
3912
|
process.exit(1);
|
|
@@ -3905,11 +3951,11 @@ async function cmdRpc(args) {
|
|
|
3905
3951
|
}
|
|
3906
3952
|
const { rpcCall, rpcBatch } = await import('../aun/rpc/index.js');
|
|
3907
3953
|
if (calls.length === 1) {
|
|
3908
|
-
const result = await rpcCall(aid, calls[0].method, calls[0].params, { aunPath });
|
|
3954
|
+
const result = await rpcCall(aid, calls[0].method, calls[0].params, { aunPath, slotId: appSlot });
|
|
3909
3955
|
console.log(JSON.stringify(result));
|
|
3910
3956
|
}
|
|
3911
3957
|
else {
|
|
3912
|
-
const results = await rpcBatch(aid, calls, { aunPath });
|
|
3958
|
+
const results = await rpcBatch(aid, calls, { aunPath, slotId: appSlot });
|
|
3913
3959
|
for (const r of results) {
|
|
3914
3960
|
console.log(JSON.stringify(r));
|
|
3915
3961
|
}
|
|
@@ -3919,7 +3965,7 @@ async function cmdRpc(args) {
|
|
|
3919
3965
|
async function cmdStorage(args) {
|
|
3920
3966
|
const sub = args[0];
|
|
3921
3967
|
const aunPath = resolveAunPath(args);
|
|
3922
|
-
const formatJson = args
|
|
3968
|
+
const formatJson = getArgValue(args, '--format') === 'json';
|
|
3923
3969
|
if (!sub || isHelpFlag(sub)) {
|
|
3924
3970
|
console.log(`用法: evolclaw storage <command> <aid> [options]
|
|
3925
3971
|
|
|
@@ -4066,10 +4112,9 @@ Commands:
|
|
|
4066
4112
|
async function cmdMsg(args) {
|
|
4067
4113
|
const sub = args[0];
|
|
4068
4114
|
const aunPath = resolveAunPath(args);
|
|
4069
|
-
const formatJson = args
|
|
4115
|
+
const formatJson = getArgValue(args, '--format') === 'json';
|
|
4070
4116
|
const appIdx = args.indexOf('--app');
|
|
4071
4117
|
const appSlot = appIdx >= 0 ? args[appIdx + 1] : undefined;
|
|
4072
|
-
const asDaemon = args.includes('--as-daemon');
|
|
4073
4118
|
if (!sub || isHelpFlag(sub)) {
|
|
4074
4119
|
console.log(`用法: evolclaw msg <command> <from-aid> [args...] [options]
|
|
4075
4120
|
|
|
@@ -4079,19 +4124,20 @@ Commands:
|
|
|
4079
4124
|
send <from> <to> --link <url> [--title T] 发送链接卡片
|
|
4080
4125
|
send <from> <to> --payload <json> 发送自定义 payload
|
|
4081
4126
|
pull <from> [--after-seq N] [--limit N] 拉取收件箱
|
|
4082
|
-
ack <from> <seq> --app <name>
|
|
4127
|
+
ack <from> <seq> [--app <name>] 确认已读
|
|
4083
4128
|
recall <from> <message-id> [<message-id>...] 撤回消息
|
|
4084
4129
|
online <from> <target-aid> [<target-aid>...] 查询在线状态
|
|
4085
4130
|
|
|
4086
4131
|
Options:
|
|
4087
|
-
--app <name> 指定应用 slot
|
|
4088
|
-
--as-daemon ack 时显式以 daemon 身份(高危,会污染 daemon 游标)
|
|
4132
|
+
--app <name> 指定应用 slot(独立消费通道,不影响 daemon)
|
|
4089
4133
|
--format json 输出 JSON 格式
|
|
4090
4134
|
--encrypt 启用端到端加密
|
|
4091
4135
|
--thread <id> 指定话题 ID(用于多话题路由)
|
|
4092
4136
|
--content-type <mime> 显式覆盖 MIME(仅 --file 模式)
|
|
4093
4137
|
--text <说明> 附件说明文字(仅 --file 模式)
|
|
4094
4138
|
--transcript <text> 语音转写(仅 --as voice)
|
|
4139
|
+
-- end-of-options:其后所有参数按正文处理
|
|
4140
|
+
(用于发送恰好等于某 flag 的文本,如 send a b -- --encrypt)
|
|
4095
4141
|
|
|
4096
4142
|
示例:
|
|
4097
4143
|
evolclaw msg send alice.agentid.pub bob.agentid.pub "hello"
|
|
@@ -4211,7 +4257,7 @@ Options:
|
|
|
4211
4257
|
}
|
|
4212
4258
|
if (sub === 'pull') {
|
|
4213
4259
|
if (!appSlot) {
|
|
4214
|
-
console.
|
|
4260
|
+
console.warn('⚠ 警告: 未传 --app,当前与 daemon 共享 evolclaw 消费通道。pull 会看到/影响 daemon 的消息消费;如需独立消费请用 --app <name>');
|
|
4215
4261
|
}
|
|
4216
4262
|
const afterSeqStr = getArgValue(args, '--after-seq');
|
|
4217
4263
|
const limitStr = getArgValue(args, '--limit');
|
|
@@ -4253,7 +4299,7 @@ Options:
|
|
|
4253
4299
|
if (sub === 'ack') {
|
|
4254
4300
|
const seqStr = args[2];
|
|
4255
4301
|
if (!seqStr) {
|
|
4256
|
-
console.error('用法: evolclaw msg ack <from> <seq> --app <name>');
|
|
4302
|
+
console.error('用法: evolclaw msg ack <from> <seq> [--app <name>]');
|
|
4257
4303
|
process.exit(1);
|
|
4258
4304
|
}
|
|
4259
4305
|
const seq = Number(seqStr);
|
|
@@ -4261,10 +4307,8 @@ Options:
|
|
|
4261
4307
|
console.error(`❌ seq 必须是数字: ${seqStr}`);
|
|
4262
4308
|
process.exit(1);
|
|
4263
4309
|
}
|
|
4264
|
-
if (!appSlot
|
|
4265
|
-
console.
|
|
4266
|
-
console.error(' 理由: 不传 --app 会推进 daemon 共享的 ack 游标,导致 daemon 丢消息');
|
|
4267
|
-
process.exit(1);
|
|
4310
|
+
if (!appSlot) {
|
|
4311
|
+
console.warn('⚠ 警告: 未传 --app,ack 将推进与 daemon 共享的 evolclaw 消费游标,可能影响 daemon 收消息;如需独立请用 --app <name>');
|
|
4268
4312
|
}
|
|
4269
4313
|
const result = await msgAck({ from, seq, ...commonOpts });
|
|
4270
4314
|
if (!result.ok) {
|
|
@@ -4352,10 +4396,9 @@ Options:
|
|
|
4352
4396
|
async function cmdGroup(args) {
|
|
4353
4397
|
const sub = args[0];
|
|
4354
4398
|
const aunPath = resolveAunPath(args);
|
|
4355
|
-
const formatJson = args
|
|
4399
|
+
const formatJson = getArgValue(args, '--format') === 'json';
|
|
4356
4400
|
const appIdx = args.indexOf('--app');
|
|
4357
4401
|
const appSlot = appIdx >= 0 ? args[appIdx + 1] : undefined;
|
|
4358
|
-
const asDaemon = args.includes('--as-daemon');
|
|
4359
4402
|
if (!sub || isHelpFlag(sub)) {
|
|
4360
4403
|
console.log(`用法: evolclaw group <command> <from-aid> [args...] [options]
|
|
4361
4404
|
|
|
@@ -4364,7 +4407,7 @@ async function cmdGroup(args) {
|
|
|
4364
4407
|
send <from> <group-id> --file <path> [--as <type>] 发送群文件
|
|
4365
4408
|
send <from> <group-id> --payload <json> 发送自定义 payload
|
|
4366
4409
|
pull <from> <group-id> [--after-seq N] [--limit N] 拉取群消息
|
|
4367
|
-
ack <from> <group-id> <seq> --app <name>
|
|
4410
|
+
ack <from> <group-id> <seq> [--app <name>] 确认已读
|
|
4368
4411
|
|
|
4369
4412
|
群管理:
|
|
4370
4413
|
create <from> <name> [--visibility public|private] [--description D] [--join-mode M] 创建群
|
|
@@ -4382,11 +4425,13 @@ async function cmdGroup(args) {
|
|
|
4382
4425
|
online <from> <group-id> 查看在线成员
|
|
4383
4426
|
|
|
4384
4427
|
Options:
|
|
4385
|
-
--app <name> 指定应用 slot
|
|
4386
|
-
--as-daemon ack 时显式以 daemon 身份(高危)
|
|
4428
|
+
--app <name> 指定应用 slot(独立消费通道,不影响 daemon)
|
|
4387
4429
|
--format json 输出 JSON 格式
|
|
4388
|
-
--
|
|
4430
|
+
--encrypt 启用端到端加密(仅 send)
|
|
4431
|
+
--mention <aid> 发送时 @ 某个成员(可多次,或用逗号分隔多个 aid)
|
|
4389
4432
|
--mention-all 发送时 @ 所有人
|
|
4433
|
+
-- end-of-options:其后所有参数按正文处理
|
|
4434
|
+
(用于发送恰好等于某 flag 的文本,如 send a g -- --encrypt)
|
|
4390
4435
|
|
|
4391
4436
|
示例:
|
|
4392
4437
|
evolclaw group create alice.agentid.pub "Dev Team" --visibility private
|
|
@@ -4418,12 +4463,23 @@ Options:
|
|
|
4418
4463
|
}
|
|
4419
4464
|
return gid;
|
|
4420
4465
|
};
|
|
4421
|
-
// 收集 --mention
|
|
4466
|
+
// 收集 --mention(可多次;每次的值支持逗号分隔多个 aid)
|
|
4422
4467
|
const collectMentions = () => {
|
|
4423
4468
|
const mentions = [];
|
|
4424
|
-
for (let i = 0; i < args.length
|
|
4425
|
-
if (args[i]
|
|
4426
|
-
|
|
4469
|
+
for (let i = 0; i < args.length; i++) {
|
|
4470
|
+
if (args[i] !== '--mention')
|
|
4471
|
+
continue;
|
|
4472
|
+
const val = args[i + 1];
|
|
4473
|
+
if (val === undefined || val.startsWith('--')) {
|
|
4474
|
+
console.error(`❌ --mention 后面缺少 <aid>`);
|
|
4475
|
+
process.exit(1);
|
|
4476
|
+
}
|
|
4477
|
+
for (const aid of val.split(',').map(s => s.trim()).filter(Boolean)) {
|
|
4478
|
+
if (!isValidAid(aid)) {
|
|
4479
|
+
console.error(`❌ --mention 的 aid 无效: ${aid}`);
|
|
4480
|
+
process.exit(1);
|
|
4481
|
+
}
|
|
4482
|
+
mentions.push({ aid });
|
|
4427
4483
|
}
|
|
4428
4484
|
}
|
|
4429
4485
|
if (args.includes('--mention-all')) {
|
|
@@ -4496,7 +4552,7 @@ Options:
|
|
|
4496
4552
|
if (sub === 'pull') {
|
|
4497
4553
|
const groupId = requireGroupId();
|
|
4498
4554
|
if (!appSlot) {
|
|
4499
|
-
console.
|
|
4555
|
+
console.warn('⚠ 警告: 未传 --app,当前与 daemon 共享 evolclaw 消费通道。pull 会看到/影响 daemon 的消息消费;如需独立消费请用 --app <name>');
|
|
4500
4556
|
}
|
|
4501
4557
|
const afterSeqStr = getArgValue(args, '--after-seq');
|
|
4502
4558
|
const limitStr = getArgValue(args, '--limit');
|
|
@@ -4517,7 +4573,7 @@ Options:
|
|
|
4517
4573
|
const groupId = requireGroupId();
|
|
4518
4574
|
const seqStr = args[3];
|
|
4519
4575
|
if (!seqStr) {
|
|
4520
|
-
console.error('用法: evolclaw group ack <from> <group-id> <seq> --app <name>');
|
|
4576
|
+
console.error('用法: evolclaw group ack <from> <group-id> <seq> [--app <name>]');
|
|
4521
4577
|
process.exit(1);
|
|
4522
4578
|
}
|
|
4523
4579
|
const seq = Number(seqStr);
|
|
@@ -4525,9 +4581,8 @@ Options:
|
|
|
4525
4581
|
console.error(`❌ seq 必须是数字: ${seqStr}`);
|
|
4526
4582
|
process.exit(1);
|
|
4527
4583
|
}
|
|
4528
|
-
if (!appSlot
|
|
4529
|
-
console.
|
|
4530
|
-
process.exit(1);
|
|
4584
|
+
if (!appSlot) {
|
|
4585
|
+
console.warn('⚠ 警告: 未传 --app,ack 将推进与 daemon 共享的 evolclaw 消费游标,可能影响 daemon 收消息;如需独立请用 --app <name>');
|
|
4531
4586
|
}
|
|
4532
4587
|
const result = await groupAck({ from, groupId, seq, ...commonOpts });
|
|
4533
4588
|
outputResult(result, () => {
|
|
@@ -4718,32 +4773,50 @@ Options:
|
|
|
4718
4773
|
process.exit(1);
|
|
4719
4774
|
}
|
|
4720
4775
|
// ==================== Main ====================
|
|
4721
|
-
function getArgValue(args, flag) {
|
|
4722
|
-
const idx = args.indexOf(flag);
|
|
4723
|
-
return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : undefined;
|
|
4724
|
-
}
|
|
4725
4776
|
/**
|
|
4726
|
-
* 收集位置参数(从 startIdx
|
|
4727
|
-
*
|
|
4777
|
+
* 收集位置参数(从 startIdx 开始)。
|
|
4778
|
+
*
|
|
4779
|
+
* flag 判定采用**精确匹配已知 flag 集合**,而非 `startsWith('--')`——
|
|
4780
|
+
* 这样"正文恰好以 -- 开头"(如消息文本 `--file 坏了`)不会被误当 flag 吞掉。
|
|
4781
|
+
* 仅当 token 精确等于某个已知 flag 时才按 flag 处理:
|
|
4782
|
+
* - VALUE_FLAGS:消耗自身 + 下一个 arg(flag 的值)
|
|
4783
|
+
* - BOOLEAN_FLAGS:仅消耗自身
|
|
4784
|
+
* 其余以 -- 开头但不在集合中的 token,一律视为正文。
|
|
4785
|
+
*
|
|
4786
|
+
* 另支持 POSIX `--` end-of-options 分隔符:遇到单独的 `--` 后,
|
|
4787
|
+
* 其后所有 token 无条件按正文处理(用于发送精确等于某 flag 的文本,如 `-- --encrypt`)。
|
|
4728
4788
|
*/
|
|
4789
|
+
const VALUE_FLAGS = new Set([
|
|
4790
|
+
'--format', '--app', '--after-seq', '--limit', '--file', '--link',
|
|
4791
|
+
'--payload', '--title', '--description', '--text', '--transcript',
|
|
4792
|
+
'--as', '--content-type', '--mention', '--visibility', '--join-mode',
|
|
4793
|
+
'--group-id', '--name', '--message', '--answer', '--page', '--size',
|
|
4794
|
+
'--aun-path', '--thread',
|
|
4795
|
+
]);
|
|
4796
|
+
const BOOLEAN_FLAGS = new Set([
|
|
4797
|
+
'--encrypt', '--mention-all',
|
|
4798
|
+
]);
|
|
4729
4799
|
function collectPositional(args, startIdx) {
|
|
4730
|
-
const VALUE_FLAGS = new Set([
|
|
4731
|
-
'--format', '--app', '--after-seq', '--limit', '--file', '--link',
|
|
4732
|
-
'--payload', '--title', '--description', '--text', '--transcript',
|
|
4733
|
-
'--as', '--content-type', '--mention', '--visibility', '--join-mode',
|
|
4734
|
-
'--group-id', '--name', '--message', '--answer', '--page', '--size',
|
|
4735
|
-
'--aun-path',
|
|
4736
|
-
]);
|
|
4737
4800
|
const out = [];
|
|
4801
|
+
let endOfFlags = false;
|
|
4738
4802
|
for (let i = startIdx; i < args.length; i++) {
|
|
4739
4803
|
const a = args[i];
|
|
4740
|
-
if (
|
|
4741
|
-
|
|
4742
|
-
i++; // 跳过 flag 的值
|
|
4743
|
-
// else: 开关 flag,自身已被跳过
|
|
4804
|
+
if (endOfFlags) {
|
|
4805
|
+
out.push(a);
|
|
4744
4806
|
continue;
|
|
4745
4807
|
}
|
|
4746
|
-
|
|
4808
|
+
if (a === '--') {
|
|
4809
|
+
endOfFlags = true;
|
|
4810
|
+
continue;
|
|
4811
|
+
}
|
|
4812
|
+
if (VALUE_FLAGS.has(a)) {
|
|
4813
|
+
i++;
|
|
4814
|
+
continue;
|
|
4815
|
+
} // 精确匹配取值 flag:跳过其值
|
|
4816
|
+
if (BOOLEAN_FLAGS.has(a)) {
|
|
4817
|
+
continue;
|
|
4818
|
+
} // 精确匹配开关 flag:仅跳过自身
|
|
4819
|
+
out.push(a); // 其余(含以 -- 开头的未知 token)= 正文
|
|
4747
4820
|
}
|
|
4748
4821
|
return out;
|
|
4749
4822
|
}
|
|
@@ -4857,6 +4930,9 @@ export async function main(args) {
|
|
|
4857
4930
|
else if (args[1] === 'log') {
|
|
4858
4931
|
cmdWatch();
|
|
4859
4932
|
}
|
|
4933
|
+
else if (args[1] === 'web' || args[1] === 'session') {
|
|
4934
|
+
await cmdWatchWeb();
|
|
4935
|
+
}
|
|
4860
4936
|
else if (!args[1]) {
|
|
4861
4937
|
await cmdWatchMenu();
|
|
4862
4938
|
}
|
|
@@ -4920,6 +4996,11 @@ export async function main(args) {
|
|
|
4920
4996
|
await cmdGroup(args.slice(1));
|
|
4921
4997
|
break;
|
|
4922
4998
|
}
|
|
4999
|
+
case 'model': {
|
|
5000
|
+
const { cmdModel } = await import('./model.js');
|
|
5001
|
+
await cmdModel(args.slice(1));
|
|
5002
|
+
break;
|
|
5003
|
+
}
|
|
4923
5004
|
case 'bench': {
|
|
4924
5005
|
const { suppressSdkLogs } = await import('../aun/aid/index.js');
|
|
4925
5006
|
suppressSdkLogs();
|
|
@@ -4970,6 +5051,14 @@ Commands:
|
|
|
4970
5051
|
--force (覆盖已有 config.json)
|
|
4971
5052
|
agent reload 全量 resync(扫磁盘,新增上线、删除下线、修改热更新)
|
|
4972
5053
|
agent reload <n> 热重载指定 agent 配置
|
|
5054
|
+
model 模型管理(查看/切换,作用域:全局/agent/关系/会话)
|
|
5055
|
+
model list 列出可用模型,标注各作用域命中
|
|
5056
|
+
model current 显示实际生效的模型 + 来源
|
|
5057
|
+
model info <id> 查看单个模型详情(价格/上下文/模态等)
|
|
5058
|
+
model use <id> 切换模型(--self/--peer/--session 决定作用域)
|
|
5059
|
+
model effort <lv> 设置推理强度
|
|
5060
|
+
model reset 清除指定作用域设置,回落上一级
|
|
5061
|
+
model help 查看完整用法
|
|
4973
5062
|
aid AID 身份管理
|
|
4974
5063
|
aid list 列出本地所有 AID
|
|
4975
5064
|
aid show <aid> 查看本地 AID 详情(证书有效期、私钥状态)
|
package/dist/cli/init-channel.js
CHANGED
|
@@ -463,7 +463,7 @@ export async function setupAunAid(rl, _config) {
|
|
|
463
463
|
const agentType = typeInput === 'human' ? 'human' : 'ai';
|
|
464
464
|
const content = buildInitialAgentMd({ aid, type: agentType });
|
|
465
465
|
try {
|
|
466
|
-
await agentmdPut(content, { aid
|
|
466
|
+
await agentmdPut(content, { aid });
|
|
467
467
|
console.log(' ✓ agent.md 已发布并写入本地');
|
|
468
468
|
}
|
|
469
469
|
catch (e) {
|
|
@@ -484,6 +484,10 @@ export async function setupAunAid(rl, _config) {
|
|
|
484
484
|
await result.client.close();
|
|
485
485
|
}
|
|
486
486
|
catch { /* ignore */ }
|
|
487
|
+
try {
|
|
488
|
+
result.store?.close();
|
|
489
|
+
}
|
|
490
|
+
catch { /* ignore */ }
|
|
487
491
|
}
|
|
488
492
|
catch (e) {
|
|
489
493
|
const msg = e.message || String(e);
|