evolclaw 3.1.2 → 3.1.4
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 +38 -0
- package/README.md +2 -6
- package/assets/.env.template +4 -0
- package/assets/config.json.template +6 -0
- package/assets/wechat-group-qr.jpeg +0 -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 +85 -22
- package/dist/aun/aid/agentmd.js +67 -74
- package/dist/aun/aid/client.js +22 -7
- package/dist/aun/aid/identity.js +314 -28
- package/dist/aun/aid/index.js +2 -2
- package/dist/aun/rpc/connection.js +8 -10
- package/dist/channels/aun.js +53 -41
- package/dist/cli/agent.js +28 -28
- package/dist/cli/bench.js +8 -14
- package/dist/cli/help.js +23 -0
- package/dist/cli/index.js +398 -73
- package/dist/cli/init-channel.js +2 -3
- package/dist/cli/init.js +13 -6
- package/dist/cli/link-rules.js +2 -1
- package/dist/cli/net-check.js +10 -11
- package/dist/core/command-handler.js +621 -541
- 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 +61 -31
- package/dist/core/relation/peer-identity.js +64 -21
- package/dist/core/session/session-manager.js +191 -44
- package/dist/core/trigger/manager.js +37 -0
- package/dist/index.js +4 -1
- package/dist/paths.js +87 -16
- package/dist/utils/npm-ops.js +18 -11
- package/kits/eck_manifest.json +9 -9
- package/kits/rules/02-navigation.md +1 -0
- package/kits/rules/05-venue.md +2 -2
- package/kits/rules/06-channel.md +2 -18
- package/kits/templates/system-fragments/baseagent.md +8 -2
- package/kits/templates/system-fragments/channel.md +20 -8
- package/kits/templates/system-fragments/identity.md +5 -6
- package/kits/templates/system-fragments/relation.md +10 -5
- package/kits/templates/system-fragments/session.md +20 -0
- package/kits/templates/system-fragments/venue.md +5 -3
- package/package.json +4 -2
- package/dist/net-check.js +0 -640
- package/dist/watch-msg.js +0 -544
- package/kits/templates/system-fragments/runtime.md +0 -19
package/dist/cli/index.js
CHANGED
|
@@ -11,6 +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
15
|
import * as platform from '../utils/cross-platform.js';
|
|
15
16
|
import { EventBus } from '../core/event-bus.js';
|
|
16
17
|
import { tryUpgrade, tryUpgradeAunSdk } from '../utils/npm-ops.js';
|
|
@@ -2739,6 +2740,7 @@ async function cmdCtl(args) {
|
|
|
2739
2740
|
查询:
|
|
2740
2741
|
status 查看会话状态
|
|
2741
2742
|
check 检查渠道健康状态
|
|
2743
|
+
pwd 显示当前项目路径
|
|
2742
2744
|
help 显示帮助
|
|
2743
2745
|
|
|
2744
2746
|
配置:
|
|
@@ -2747,15 +2749,14 @@ async function cmdCtl(args) {
|
|
|
2747
2749
|
compact 压缩当前会话上下文
|
|
2748
2750
|
perm [mode] 查看/切换权限模式
|
|
2749
2751
|
|
|
2750
|
-
项目:
|
|
2751
|
-
bind <path> 注册项目目录(不切换当前会话)
|
|
2752
|
-
|
|
2753
2752
|
消息:
|
|
2754
2753
|
send <消息内容> 主动发送文本消息(proactive 模式)
|
|
2755
2754
|
file [channel] <path> 发送项目内文件
|
|
2756
2755
|
|
|
2756
|
+
Agent:
|
|
2757
|
+
agent <subcommand> EvolAgent 管理(list/show/new/enable/disable/reload/delete)
|
|
2758
|
+
|
|
2757
2759
|
运维:
|
|
2758
|
-
agentmd [put|set <内容>] 查看/管理 agent.md(仅 AUN 通道)
|
|
2759
2760
|
restart [channel] 重启服务或重连指定渠道
|
|
2760
2761
|
|
|
2761
2762
|
示例:
|
|
@@ -2765,7 +2766,7 @@ async function cmdCtl(args) {
|
|
|
2765
2766
|
process.exit(1);
|
|
2766
2767
|
}
|
|
2767
2768
|
// help 不需要连接服务,直接复用无参数时的帮助输出
|
|
2768
|
-
if (args[0]
|
|
2769
|
+
if (isHelpFlag(args[0])) {
|
|
2769
2770
|
return cmdCtl([]);
|
|
2770
2771
|
}
|
|
2771
2772
|
const sessionId = process.env.EVOLCLAW_SESSION_ID;
|
|
@@ -2800,7 +2801,7 @@ async function cmdCtl(args) {
|
|
|
2800
2801
|
async function cmdAgent(args) {
|
|
2801
2802
|
const sub = args[0];
|
|
2802
2803
|
const formatJson = args.includes('--format') && args[args.indexOf('--format') + 1] === 'json';
|
|
2803
|
-
if (!sub || sub
|
|
2804
|
+
if (!sub || isHelpFlag(sub)) {
|
|
2804
2805
|
console.log(`用法: evolclaw agent <command>
|
|
2805
2806
|
|
|
2806
2807
|
Commands:
|
|
@@ -2808,7 +2809,6 @@ Commands:
|
|
|
2808
2809
|
show <aid> 查看 agent 详情(身份 + 配置 + 连接 + 会话 + 路径)
|
|
2809
2810
|
new [aid] 交互式创建 agent
|
|
2810
2811
|
new <aid> --non-interactive ... 非交互式创建
|
|
2811
|
-
sync-aids 从本地 AID 批量创建 agent
|
|
2812
2812
|
enable <aid> 启用 agent
|
|
2813
2813
|
disable <aid> 停用 agent
|
|
2814
2814
|
get <aid> <key> 读取单个配置字段(支持点路径)
|
|
@@ -2819,6 +2819,7 @@ Commands:
|
|
|
2819
2819
|
|
|
2820
2820
|
Options:
|
|
2821
2821
|
--format json 输出 JSON 格式
|
|
2822
|
+
--help, -h 各子命令均支持,查看详细用法
|
|
2822
2823
|
|
|
2823
2824
|
示例:
|
|
2824
2825
|
evolclaw agent list
|
|
@@ -2831,9 +2832,15 @@ Options:
|
|
|
2831
2832
|
evolclaw agent delete mybot.agentid.pub --purge`);
|
|
2832
2833
|
return;
|
|
2833
2834
|
}
|
|
2834
|
-
const { agentList, agentShow, agentCreateInteractive, agentCreateNonInteractive,
|
|
2835
|
+
const { agentList, agentShow, agentCreateInteractive, agentCreateNonInteractive, agentReload, agentEnable, agentDisable, agentGet, agentSet, agentDelete, agentRename, } = await import('./agent.js');
|
|
2835
2836
|
// --- list ---
|
|
2836
|
-
if (
|
|
2837
|
+
if (sub === 'list') {
|
|
2838
|
+
if (wantsHelp(args)) {
|
|
2839
|
+
console.log(`用法: evolclaw agent list [--format json]
|
|
2840
|
+
|
|
2841
|
+
列出所有 agent,显示名称、状态、渠道、项目、基座、最后活跃时间。`);
|
|
2842
|
+
return;
|
|
2843
|
+
}
|
|
2837
2844
|
const result = await agentList();
|
|
2838
2845
|
if (!result.ok) {
|
|
2839
2846
|
if (formatJson) {
|
|
@@ -2894,6 +2901,24 @@ Options:
|
|
|
2894
2901
|
}
|
|
2895
2902
|
// --- new ---
|
|
2896
2903
|
if (sub === 'new') {
|
|
2904
|
+
if (wantsHelp(args)) {
|
|
2905
|
+
console.log(`用法: evolclaw agent new [aid] 交互式创建
|
|
2906
|
+
evolclaw agent new <aid> --non-interactive [选项]
|
|
2907
|
+
|
|
2908
|
+
非交互模式选项:
|
|
2909
|
+
--baseagent <claude|codex|gemini> 默认: PATH 中第一个可用
|
|
2910
|
+
--project <absolute path> 必填
|
|
2911
|
+
--owner <aid>
|
|
2912
|
+
--name <display-name>
|
|
2913
|
+
--description <text>
|
|
2914
|
+
--force 覆盖已有 config.json
|
|
2915
|
+
--format json 输出 JSON
|
|
2916
|
+
|
|
2917
|
+
示例:
|
|
2918
|
+
evolclaw agent new mybot.agentid.pub
|
|
2919
|
+
evolclaw agent new mybot.agentid.pub --non-interactive --project /abs/path --baseagent claude`);
|
|
2920
|
+
return;
|
|
2921
|
+
}
|
|
2897
2922
|
const name = args[1];
|
|
2898
2923
|
const nonInteractive = args.includes('--non-interactive');
|
|
2899
2924
|
if (nonInteractive) {
|
|
@@ -2966,38 +2991,38 @@ Options:
|
|
|
2966
2991
|
}
|
|
2967
2992
|
return;
|
|
2968
2993
|
}
|
|
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
|
-
}
|
|
2994
|
+
// --- sync-aids (deprecated, commented out) ---
|
|
2995
|
+
// if (sub === 'sync-aids') {
|
|
2996
|
+
// const result = await agentSyncAids();
|
|
2997
|
+
// if (!result.ok) {
|
|
2998
|
+
// if (formatJson) { console.log(JSON.stringify(result)); }
|
|
2999
|
+
// else { console.error(`❌ ${result.error}`); }
|
|
3000
|
+
// process.exit(1);
|
|
3001
|
+
// }
|
|
3002
|
+
// if (formatJson) {
|
|
3003
|
+
// console.log(JSON.stringify(result, null, 2));
|
|
3004
|
+
// return;
|
|
3005
|
+
// }
|
|
3006
|
+
// if (result.created.length === 0) {
|
|
3007
|
+
// console.log('所有本地 AID 都已有对应 agent,无需同步。');
|
|
3008
|
+
// } else {
|
|
3009
|
+
// console.log(`✓ 同步完成:新建 ${result.created.length} 个 agent(模板: ${result.template})`);
|
|
3010
|
+
// for (const aid of result.created) console.log(` ✓ ${aid}`);
|
|
3011
|
+
// if (result.hotReloaded) console.log(' ✓ 已热加载到运行中的进程');
|
|
3012
|
+
// else console.log(' evolclaw 未运行,新 agent 将在下次启动时加载。');
|
|
3013
|
+
// }
|
|
3014
|
+
// return;
|
|
3015
|
+
// }
|
|
2999
3016
|
// --- reload ---
|
|
3000
3017
|
if (sub === 'reload') {
|
|
3018
|
+
if (wantsHelp(args)) {
|
|
3019
|
+
console.log(`用法: evolclaw agent reload [aid] [--format json]
|
|
3020
|
+
|
|
3021
|
+
热重载 agent 配置。
|
|
3022
|
+
无参数 全量 resync(扫磁盘,新增上线、删除下线、修改热更新)
|
|
3023
|
+
<aid> 仅热重载指定 agent`);
|
|
3024
|
+
return;
|
|
3025
|
+
}
|
|
3001
3026
|
const target = args[1] && !args[1].startsWith('--') ? args[1] : undefined;
|
|
3002
3027
|
const result = await agentReload(target);
|
|
3003
3028
|
if (!result.ok) {
|
|
@@ -3025,6 +3050,12 @@ Options:
|
|
|
3025
3050
|
}
|
|
3026
3051
|
// --- enable ---
|
|
3027
3052
|
if (sub === 'enable') {
|
|
3053
|
+
if (wantsHelp(args)) {
|
|
3054
|
+
console.log(`用法: evolclaw agent enable <aid> [--format json]
|
|
3055
|
+
|
|
3056
|
+
启用 agent。若服务运行中会热重载,否则下次 evolclaw start 时生效。`);
|
|
3057
|
+
return;
|
|
3058
|
+
}
|
|
3028
3059
|
const aid = args[1];
|
|
3029
3060
|
if (!aid) {
|
|
3030
3061
|
console.error('用法: evolclaw agent enable <aid>');
|
|
@@ -3050,6 +3081,12 @@ Options:
|
|
|
3050
3081
|
}
|
|
3051
3082
|
// --- disable ---
|
|
3052
3083
|
if (sub === 'disable') {
|
|
3084
|
+
if (wantsHelp(args)) {
|
|
3085
|
+
console.log(`用法: evolclaw agent disable <aid> [--format json]
|
|
3086
|
+
|
|
3087
|
+
停用 agent。若服务运行中会热重载离线,否则在配置中标记为禁用。`);
|
|
3088
|
+
return;
|
|
3089
|
+
}
|
|
3053
3090
|
const aid = args[1];
|
|
3054
3091
|
if (!aid) {
|
|
3055
3092
|
console.error('用法: evolclaw agent disable <aid>');
|
|
@@ -3075,6 +3112,16 @@ Options:
|
|
|
3075
3112
|
}
|
|
3076
3113
|
// --- get ---
|
|
3077
3114
|
if (sub === 'get') {
|
|
3115
|
+
if (wantsHelp(args)) {
|
|
3116
|
+
console.log(`用法: evolclaw agent get <aid> <key> [--format json]
|
|
3117
|
+
|
|
3118
|
+
读取单个配置字段。key 支持点路径,如 "channels.aun.enabled"。
|
|
3119
|
+
|
|
3120
|
+
示例:
|
|
3121
|
+
evolclaw agent get mybot.agentid.pub active_baseagent
|
|
3122
|
+
evolclaw agent get mybot.agentid.pub channels.aun.enabled`);
|
|
3123
|
+
return;
|
|
3124
|
+
}
|
|
3078
3125
|
const aid = args[1];
|
|
3079
3126
|
const key = args[2];
|
|
3080
3127
|
if (!aid || !key) {
|
|
@@ -3102,6 +3149,16 @@ Options:
|
|
|
3102
3149
|
}
|
|
3103
3150
|
// --- set ---
|
|
3104
3151
|
if (sub === 'set') {
|
|
3152
|
+
if (wantsHelp(args)) {
|
|
3153
|
+
console.log(`用法: evolclaw agent set <aid> <key> <value> [--format json]
|
|
3154
|
+
|
|
3155
|
+
修改单个配置字段。key 支持点路径。修改后若服务运行中会自动热重载。
|
|
3156
|
+
|
|
3157
|
+
示例:
|
|
3158
|
+
evolclaw agent set mybot.agentid.pub active_baseagent codex
|
|
3159
|
+
evolclaw agent set mybot.agentid.pub channels.aun.enabled true`);
|
|
3160
|
+
return;
|
|
3161
|
+
}
|
|
3105
3162
|
const aid = args[1];
|
|
3106
3163
|
const key = args[2];
|
|
3107
3164
|
const val = args[3];
|
|
@@ -3129,6 +3186,15 @@ Options:
|
|
|
3129
3186
|
}
|
|
3130
3187
|
// --- rename ---
|
|
3131
3188
|
if (sub === 'rename') {
|
|
3189
|
+
if (wantsHelp(args)) {
|
|
3190
|
+
console.log(`用法: evolclaw agent rename <aid> <name> [--format json]
|
|
3191
|
+
|
|
3192
|
+
修改 agent 显示名称。同时更新本地 agent.md 并尝试重新上传。
|
|
3193
|
+
|
|
3194
|
+
示例:
|
|
3195
|
+
evolclaw agent rename mybot.agentid.pub "My Bot"`);
|
|
3196
|
+
return;
|
|
3197
|
+
}
|
|
3132
3198
|
const aid = args[1];
|
|
3133
3199
|
const newName = args[2];
|
|
3134
3200
|
if (!aid || !newName) {
|
|
@@ -3155,6 +3221,14 @@ Options:
|
|
|
3155
3221
|
}
|
|
3156
3222
|
// --- delete ---
|
|
3157
3223
|
if (sub === 'delete') {
|
|
3224
|
+
if (wantsHelp(args)) {
|
|
3225
|
+
console.log(`用法: evolclaw agent delete <aid> [--purge] [--format json]
|
|
3226
|
+
|
|
3227
|
+
删除 agent 的配置。
|
|
3228
|
+
--purge 同时清除该 agent 的会话、消息、日志等运行时数据
|
|
3229
|
+
默认 仅删除 config.json,运行时数据保留`);
|
|
3230
|
+
return;
|
|
3231
|
+
}
|
|
3158
3232
|
const aid = args[1];
|
|
3159
3233
|
if (!aid) {
|
|
3160
3234
|
console.error('用法: evolclaw agent delete <aid> [--purge]');
|
|
@@ -3181,6 +3255,12 @@ Options:
|
|
|
3181
3255
|
}
|
|
3182
3256
|
// --- show ---
|
|
3183
3257
|
if (sub === 'show') {
|
|
3258
|
+
if (wantsHelp(args)) {
|
|
3259
|
+
console.log(`用法: evolclaw agent show <aid> [--format json]
|
|
3260
|
+
|
|
3261
|
+
查看 agent 详情:身份、配置、连接状态、会话路径等。`);
|
|
3262
|
+
return;
|
|
3263
|
+
}
|
|
3184
3264
|
const aid = args[1];
|
|
3185
3265
|
if (!aid) {
|
|
3186
3266
|
console.error('用法: evolclaw agent show <aid>');
|
|
@@ -3294,63 +3374,134 @@ function resolveAunPath(args) {
|
|
|
3294
3374
|
return process.env.AUN_HOME || undefined;
|
|
3295
3375
|
}
|
|
3296
3376
|
async function cmdAid(args) {
|
|
3297
|
-
const sub = args[0]
|
|
3377
|
+
const sub = args[0];
|
|
3298
3378
|
const formatJson = args.includes('--format') && args[args.indexOf('--format') + 1] === 'json';
|
|
3299
3379
|
const aunPath = resolveAunPath(args);
|
|
3300
|
-
if (!sub || sub
|
|
3380
|
+
if (!sub || isHelpFlag(sub)) {
|
|
3301
3381
|
console.log(`用法: evolclaw aid <command>
|
|
3302
3382
|
|
|
3303
3383
|
Commands:
|
|
3304
|
-
list 列出本地所有 AID
|
|
3305
|
-
show <aid> 查看本地 AID
|
|
3384
|
+
list 列出本地所有 AID(实测 sign+verify)
|
|
3385
|
+
show <aid> 查看本地 AID 详情(证书、私钥、签名能力)
|
|
3306
3386
|
new <aid> 创建新 AID 身份
|
|
3307
|
-
delete <aid>
|
|
3387
|
+
delete <aid> 删除指定本地 AID(无网络注销)
|
|
3388
|
+
delete --orphan 批量清理无私钥的外部 AID 缓存
|
|
3389
|
+
delete --no-cert 批量清理无私钥也无公钥证书的孤儿目录
|
|
3390
|
+
delete --unrecoverable 批量清理云端公钥已变更、本地不可恢复的 AID
|
|
3391
|
+
批量删除默认 dry-run,加 --yes 执行
|
|
3308
3392
|
lookup <aid> 远程探测 AID(是否存在 + 网关 + agent.md)
|
|
3309
3393
|
agentmd put <aid> 读本地 agent.md → 签名 → 上传
|
|
3310
3394
|
agentmd get <aid> 下载 agent.md → 验签 → 本地持久化
|
|
3311
3395
|
|
|
3312
3396
|
Options:
|
|
3313
3397
|
--format json 输出 JSON 格式
|
|
3398
|
+
--help, -h 各子命令均支持,查看详细用法
|
|
3314
3399
|
|
|
3315
3400
|
示例:
|
|
3316
3401
|
evolclaw aid list
|
|
3317
3402
|
evolclaw aid show toleiliang2.agentid.pub
|
|
3318
3403
|
evolclaw aid new reviewer.agentid.pub
|
|
3404
|
+
evolclaw aid delete --help
|
|
3319
3405
|
evolclaw aid delete old.agentid.pub
|
|
3406
|
+
evolclaw aid delete --orphan
|
|
3407
|
+
evolclaw aid delete --unrecoverable --yes
|
|
3320
3408
|
evolclaw aid lookup someone.agentid.pub
|
|
3321
3409
|
evolclaw aid agentmd put mybot.agentid.pub
|
|
3322
3410
|
evolclaw aid agentmd get someone.agentid.pub`);
|
|
3323
3411
|
return;
|
|
3324
3412
|
}
|
|
3325
|
-
const { aidList, aidCreate, aidShow, aidDelete, aidLookup, agentmdPut, agentmdGet, buildInitialAgentMd, isValidAid } = await import('../aun/aid/index.js');
|
|
3413
|
+
const { aidList, aidListVerified, aidCreate, aidShow, aidDelete, aidLookup, agentmdPut, agentmdGet, buildInitialAgentMd, isValidAid } = await import('../aun/aid/index.js');
|
|
3326
3414
|
if (sub === 'list') {
|
|
3327
|
-
|
|
3415
|
+
if (wantsHelp(args)) {
|
|
3416
|
+
console.log(`用法: evolclaw aid list [筛选选项] [--no-verify] [--format json]
|
|
3417
|
+
|
|
3418
|
+
列出本地 AID 并跑 sign+verify 自检。
|
|
3419
|
+
|
|
3420
|
+
筛选选项(可组合,不指定 = 列出 mine + broken + peer-cert):
|
|
3421
|
+
--mine 仅本地可用身份(实测可签名+验签通过)
|
|
3422
|
+
--broken 仅有私钥但不可用(公钥不匹配 / 证书过期 / sign 失败)
|
|
3423
|
+
--peer-cert 仅对端 AID(无私钥,有公钥证书)
|
|
3424
|
+
--no-cert 仅无私钥无证书的目录(默认隐藏,需用 aid delete --no-cert 清理)
|
|
3425
|
+
|
|
3426
|
+
选项:
|
|
3427
|
+
--no-verify 跳过 sign+verify 实测,仅静态扫描(更快,mine/broken 仅按静态判定近似)
|
|
3428
|
+
--format json JSON 格式输出
|
|
3429
|
+
|
|
3430
|
+
输出图标:
|
|
3431
|
+
🔑 有私钥
|
|
3432
|
+
✅ 实测可签名/验签
|
|
3433
|
+
❌ 不可签名(公钥不匹配 / sign 失败 / verify 失败等)
|
|
3434
|
+
⌛ 证书过期
|
|
3435
|
+
📜 有公钥证书
|
|
3436
|
+
📄 有 agent.md
|
|
3437
|
+
|
|
3438
|
+
示例:
|
|
3439
|
+
evolclaw aid list 列出 mine + broken + peer-cert
|
|
3440
|
+
evolclaw aid list --mine 仅可用身份
|
|
3441
|
+
evolclaw aid list --mine --broken 所有有私钥的 AID
|
|
3442
|
+
evolclaw aid list --no-cert 仅无私钥无证书的孤儿目录
|
|
3443
|
+
evolclaw aid list --no-verify 跳过实测,快速静态扫描`);
|
|
3444
|
+
return;
|
|
3445
|
+
}
|
|
3446
|
+
const wantMine = args.includes('--mine');
|
|
3447
|
+
const wantBroken = args.includes('--broken');
|
|
3448
|
+
const wantPeerCert = args.includes('--peer-cert');
|
|
3449
|
+
const wantNoCert = args.includes('--no-cert');
|
|
3450
|
+
const noVerify = args.includes('--no-verify');
|
|
3451
|
+
const anyFilter = wantMine || wantBroken || wantPeerCert || wantNoCert;
|
|
3452
|
+
// 默认: mine + broken + peer-cert(隐藏 no-cert,需显式 --no-cert 才列)
|
|
3453
|
+
const showMine = anyFilter ? wantMine : true;
|
|
3454
|
+
const showBroken = anyFilter ? wantBroken : true;
|
|
3455
|
+
const showPeerCert = anyFilter ? wantPeerCert : true;
|
|
3456
|
+
const showNoCert = anyFilter ? wantNoCert : false;
|
|
3457
|
+
const all = noVerify ? aidList(aunPath) : await aidListVerified(aunPath);
|
|
3458
|
+
const aids = all.filter(a => (showMine && a.category === 'mine') ||
|
|
3459
|
+
(showBroken && a.category === 'broken') ||
|
|
3460
|
+
(showPeerCert && a.category === 'peer-cert') ||
|
|
3461
|
+
(showNoCert && a.category === 'no-cert'));
|
|
3328
3462
|
if (formatJson) {
|
|
3329
3463
|
console.log(JSON.stringify(aids, null, 2));
|
|
3330
3464
|
return;
|
|
3331
3465
|
}
|
|
3332
3466
|
if (aids.length === 0) {
|
|
3333
|
-
console.log('
|
|
3467
|
+
console.log('无匹配 AID');
|
|
3334
3468
|
return;
|
|
3335
3469
|
}
|
|
3336
|
-
console.log('
|
|
3470
|
+
console.log(`本地 AID${noVerify ? '(静态扫描,未实测)' : ''}:`);
|
|
3337
3471
|
for (const a of aids) {
|
|
3338
|
-
const
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3472
|
+
const keyIcon = a.hasPrivateKey ? '🔑' : ' ';
|
|
3473
|
+
let signIcon = ' ';
|
|
3474
|
+
// --no-verify 时 signVerified 始终为 null,用 canSign 作为静态近似
|
|
3475
|
+
const effectiveOk = noVerify ? a.canSign : a.signVerified === true;
|
|
3476
|
+
const effectiveFail = noVerify ? (a.hasPrivateKey && !a.canSign) : (a.hasPrivateKey && a.signVerified === false);
|
|
3477
|
+
if (effectiveOk)
|
|
3478
|
+
signIcon = '✅';
|
|
3479
|
+
else if (a.hasPrivateKey && a.certExpired)
|
|
3480
|
+
signIcon = '⌛';
|
|
3481
|
+
else if (effectiveFail)
|
|
3482
|
+
signIcon = '❌';
|
|
3483
|
+
const certIcon = a.hasCert ? '📜' : ' ';
|
|
3484
|
+
const mdIcon = a.hasAgentMd ? '📄' : ' ';
|
|
3485
|
+
const tail = !noVerify && a.signVerified === false && a.signError && !(a.keyMatchesCert === false || a.certExpired || !a.hasPrivateKey || !a.hasCert)
|
|
3486
|
+
? ` (${a.signError})` : '';
|
|
3487
|
+
console.log(` ${keyIcon} ${signIcon} ${certIcon} ${mdIcon} ${a.aid}${tail}`);
|
|
3488
|
+
}
|
|
3489
|
+
console.log('\n🔑=私钥 ✅=可签名/验签 ❌=不可签名 ⌛=证书过期 📜=公钥证书 📄=agent.md');
|
|
3345
3490
|
return;
|
|
3346
3491
|
}
|
|
3347
3492
|
if (sub === 'show') {
|
|
3493
|
+
if (wantsHelp(args)) {
|
|
3494
|
+
console.log(`用法: evolclaw aid show <aid> [--format json]
|
|
3495
|
+
|
|
3496
|
+
查看本地 AID 详情:私钥/证书/agent.md 状态、签名能力实测。`);
|
|
3497
|
+
return;
|
|
3498
|
+
}
|
|
3348
3499
|
const aid = args[1];
|
|
3349
3500
|
if (!aid) {
|
|
3350
3501
|
console.error('用法: evolclaw aid show <aid>');
|
|
3351
3502
|
process.exit(1);
|
|
3352
3503
|
}
|
|
3353
|
-
const info = aidShow(aid, { aunPath });
|
|
3504
|
+
const info = await aidShow(aid, { aunPath });
|
|
3354
3505
|
if (formatJson) {
|
|
3355
3506
|
console.log(JSON.stringify(info, null, 2));
|
|
3356
3507
|
return;
|
|
@@ -3358,12 +3509,37 @@ Options:
|
|
|
3358
3509
|
console.log(`AID: ${info.aid}`);
|
|
3359
3510
|
console.log(` 私钥: ${info.hasPrivateKey ? '有' : '无'}`);
|
|
3360
3511
|
console.log(` agent.md: ${info.hasAgentMd ? '有' : '无'}`);
|
|
3361
|
-
|
|
3512
|
+
if (info.hasAgentMd) {
|
|
3513
|
+
const sigLabel = info.agentMdSignature === 'verified' ? '✓ 已验签'
|
|
3514
|
+
: info.agentMdSignature === 'unsigned' ? '⚠ 未签名'
|
|
3515
|
+
: info.agentMdSignature === 'invalid' ? `✗ 签名无效${info.agentMdSignatureReason ? ': ' + info.agentMdSignatureReason : ''}`
|
|
3516
|
+
: '? 未知';
|
|
3517
|
+
console.log(` 签名状态: ${sigLabel}`);
|
|
3518
|
+
}
|
|
3519
|
+
console.log(` 证书到期: ${info.certExpiresAt ?? '无证书'}${info.certExpired ? ' (已过期!)' : ''}`);
|
|
3362
3520
|
if (info.certSubject)
|
|
3363
3521
|
console.log(` 证书主体: ${info.certSubject}`);
|
|
3522
|
+
if (info.keyMatchesCert === false)
|
|
3523
|
+
console.log(` 密钥/证书: ✗ 公钥不匹配(cert.pem 与 key.json 公钥不一致)`);
|
|
3524
|
+
else if (info.keyMatchesCert === true)
|
|
3525
|
+
console.log(` 密钥/证书: ✓ 公钥一致`);
|
|
3526
|
+
if (info.signVerified === true)
|
|
3527
|
+
console.log(` 可签名/验签: ✓ 实测通过`);
|
|
3528
|
+
else if (info.signVerified === false)
|
|
3529
|
+
console.log(` 可签名/验签: ✗ 失败${info.signError ? `(${info.signError})` : ''}`);
|
|
3530
|
+
else
|
|
3531
|
+
console.log(` 可签名/验签: ? 未知`);
|
|
3364
3532
|
return;
|
|
3365
3533
|
}
|
|
3366
3534
|
if (sub === 'new') {
|
|
3535
|
+
if (wantsHelp(args)) {
|
|
3536
|
+
console.log(`用法: evolclaw aid new <完整AID>
|
|
3537
|
+
|
|
3538
|
+
创建新 AID 身份:生成 ECDSA 密钥对、向 Issuer 申请证书、构建并上传初始 agent.md。
|
|
3539
|
+
|
|
3540
|
+
例: evolclaw aid new reviewer.agentid.pub`);
|
|
3541
|
+
return;
|
|
3542
|
+
}
|
|
3367
3543
|
const aid = args[1];
|
|
3368
3544
|
if (!aid) {
|
|
3369
3545
|
console.error('用法: evolclaw aid new <完整AID>\n例: evolclaw aid new reviewer.agentid.pub');
|
|
@@ -3394,22 +3570,162 @@ Options:
|
|
|
3394
3570
|
return;
|
|
3395
3571
|
}
|
|
3396
3572
|
if (sub === 'delete') {
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3573
|
+
if (wantsHelp(args)) {
|
|
3574
|
+
console.log(`用法: evolclaw aid delete <子命令>
|
|
3575
|
+
|
|
3576
|
+
单个删除:
|
|
3577
|
+
evolclaw aid delete <aid> 删除指定 AID 的本地数据(无网络注销)
|
|
3578
|
+
|
|
3579
|
+
批量删除(默认 dry-run,加 --yes 才真删):
|
|
3580
|
+
evolclaw aid delete --orphan 删除所有"无私钥"的本地缓存(外部 AID)
|
|
3581
|
+
evolclaw aid delete --no-cert 删除所有"无私钥也无公钥证书"的目录
|
|
3582
|
+
条件:!hasPrivateKey && !hasCert
|
|
3583
|
+
这些目录最多只剩 agent.md 或 SQLite 残留,
|
|
3584
|
+
对验签和加密通信都没用,删除安全。
|
|
3585
|
+
evolclaw aid delete --unrecoverable 删除所有不可恢复的 AID
|
|
3586
|
+
条件:本地 sign+verify 实测失败
|
|
3587
|
+
且 PKI 探测确认云端公钥也不等本地 key.json
|
|
3588
|
+
|
|
3589
|
+
选项:
|
|
3590
|
+
--yes 跳过 dry-run,立即执行
|
|
3591
|
+
--skip-pki --unrecoverable 时跳过 PKI 探测,仅依据本地 sign+verify 失败判断(危险,可能误删可恢复 AID)
|
|
3592
|
+
--format json 输出 JSON 格式
|
|
3593
|
+
|
|
3594
|
+
示例:
|
|
3595
|
+
evolclaw aid delete old.agentid.pub
|
|
3596
|
+
evolclaw aid delete --orphan 列出会被清理的孤儿
|
|
3597
|
+
evolclaw aid delete --orphan --yes 实际清理
|
|
3598
|
+
evolclaw aid delete --no-cert 列出无证书孤儿目录
|
|
3599
|
+
evolclaw aid delete --no-cert --yes 实际清理
|
|
3600
|
+
evolclaw aid delete --unrecoverable 联网探测后列出无救 AID
|
|
3601
|
+
evolclaw aid delete --unrecoverable --yes`);
|
|
3602
|
+
return;
|
|
3603
|
+
}
|
|
3604
|
+
const yes = args.includes('--yes');
|
|
3605
|
+
const skipPki = args.includes('--skip-pki');
|
|
3606
|
+
const orphan = args.includes('--orphan');
|
|
3607
|
+
const noCert = args.includes('--no-cert');
|
|
3608
|
+
const unrecoverable = args.includes('--unrecoverable');
|
|
3609
|
+
const modes = [orphan, noCert, unrecoverable].filter(Boolean).length;
|
|
3610
|
+
if (modes > 1) {
|
|
3611
|
+
console.error('❌ --orphan / --no-cert / --unrecoverable 互斥,不能同时使用');
|
|
3400
3612
|
process.exit(1);
|
|
3401
3613
|
}
|
|
3402
|
-
|
|
3403
|
-
if (
|
|
3404
|
-
|
|
3614
|
+
// 单个 aid 删除:保留原有行为
|
|
3615
|
+
if (modes === 0) {
|
|
3616
|
+
const aid = args[1];
|
|
3617
|
+
if (!aid) {
|
|
3618
|
+
console.error('用法: evolclaw aid delete <aid>\n evolclaw aid delete --orphan | --no-cert | --unrecoverable [--yes]\n evolclaw aid delete --help 查看完整用法');
|
|
3619
|
+
process.exit(1);
|
|
3620
|
+
}
|
|
3621
|
+
const deleted = aidDelete(aid, { aunPath });
|
|
3622
|
+
if (deleted) {
|
|
3623
|
+
console.log(`✓ ${aid} 已删除`);
|
|
3624
|
+
}
|
|
3625
|
+
else {
|
|
3626
|
+
console.error(`❌ 本地不存在: ${aid}`);
|
|
3627
|
+
process.exit(1);
|
|
3628
|
+
}
|
|
3629
|
+
return;
|
|
3630
|
+
}
|
|
3631
|
+
// 批量模式:先选出候选
|
|
3632
|
+
const { probePkiRecoverability } = await import('../aun/aid/index.js');
|
|
3633
|
+
const candidates = [];
|
|
3634
|
+
if (orphan) {
|
|
3635
|
+
const aids = aidList(aunPath);
|
|
3636
|
+
for (const a of aids) {
|
|
3637
|
+
if (!a.hasPrivateKey)
|
|
3638
|
+
candidates.push({ aid: a.aid, reason: 'no private key (external AID cache)' });
|
|
3639
|
+
}
|
|
3640
|
+
}
|
|
3641
|
+
else if (noCert) {
|
|
3642
|
+
const aids = aidList(aunPath);
|
|
3643
|
+
for (const a of aids) {
|
|
3644
|
+
if (!a.hasPrivateKey && !a.hasCert) {
|
|
3645
|
+
const traits = [a.hasAgentMd ? 'agent.md' : null].filter(Boolean).join(', ');
|
|
3646
|
+
candidates.push({ aid: a.aid, reason: `no private key, no cert${traits ? ` (only: ${traits})` : ''}` });
|
|
3647
|
+
}
|
|
3648
|
+
}
|
|
3405
3649
|
}
|
|
3406
3650
|
else {
|
|
3407
|
-
|
|
3408
|
-
|
|
3651
|
+
// unrecoverable: 必须先做 sign+verify 实测
|
|
3652
|
+
if (!formatJson)
|
|
3653
|
+
console.log('扫描中: 本地签名/验签实测...');
|
|
3654
|
+
const aids = await aidListVerified(aunPath);
|
|
3655
|
+
const localBroken = aids.filter(a => a.hasPrivateKey && a.signVerified === false);
|
|
3656
|
+
if (skipPki) {
|
|
3657
|
+
for (const a of localBroken) {
|
|
3658
|
+
candidates.push({ aid: a.aid, reason: `sign+verify failed (${a.signError ?? 'unknown'}) [--skip-pki: 未联网验证]` });
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3661
|
+
else {
|
|
3662
|
+
if (!formatJson)
|
|
3663
|
+
console.log(`扫描中: 对 ${localBroken.length} 个本地损坏 AID 做 PKI 探测...`);
|
|
3664
|
+
for (const a of localBroken) {
|
|
3665
|
+
const r = await probePkiRecoverability(a.aid, { aunPath });
|
|
3666
|
+
if (r.kind === 'unrecoverable') {
|
|
3667
|
+
candidates.push({ aid: a.aid, reason: `local broken; PKI: ${r.reason}`, pki: 'unrecoverable' });
|
|
3668
|
+
}
|
|
3669
|
+
else if (r.kind === 'no-server-record') {
|
|
3670
|
+
candidates.push({ aid: a.aid, reason: `local broken; PKI: ${r.reason}`, pki: 'no-server-record' });
|
|
3671
|
+
}
|
|
3672
|
+
else {
|
|
3673
|
+
// recoverable / no-key / unknown 一律保守不删
|
|
3674
|
+
if (!formatJson)
|
|
3675
|
+
console.log(` · 跳过 ${a.aid}: PKI=${r.kind}${('reason' in r) ? ' — ' + r.reason : ''}`);
|
|
3676
|
+
}
|
|
3677
|
+
}
|
|
3678
|
+
}
|
|
3679
|
+
}
|
|
3680
|
+
if (formatJson) {
|
|
3681
|
+
console.log(JSON.stringify({
|
|
3682
|
+
mode: orphan ? 'orphan' : noCert ? 'no-cert' : 'unrecoverable',
|
|
3683
|
+
dryRun: !yes,
|
|
3684
|
+
skipPki: unrecoverable ? skipPki : undefined,
|
|
3685
|
+
candidates,
|
|
3686
|
+
}, null, 2));
|
|
3687
|
+
if (yes) {
|
|
3688
|
+
for (const c of candidates)
|
|
3689
|
+
aidDelete(c.aid, { aunPath });
|
|
3690
|
+
}
|
|
3691
|
+
return;
|
|
3692
|
+
}
|
|
3693
|
+
if (candidates.length === 0) {
|
|
3694
|
+
console.log(orphan ? '✓ 无孤儿 AID' : noCert ? '✓ 无无证书孤儿目录' : '✓ 无不可恢复 AID');
|
|
3695
|
+
return;
|
|
3696
|
+
}
|
|
3697
|
+
console.log(`\n${yes ? '将删除' : '候选删除(dry-run)'}:${candidates.length} 个 AID`);
|
|
3698
|
+
for (const c of candidates) {
|
|
3699
|
+
console.log(` - ${c.aid}`);
|
|
3700
|
+
console.log(` ${c.reason}`);
|
|
3701
|
+
}
|
|
3702
|
+
if (!yes) {
|
|
3703
|
+
console.log('\n(dry-run,未真删除。加 --yes 执行真删。)');
|
|
3704
|
+
return;
|
|
3705
|
+
}
|
|
3706
|
+
let ok = 0;
|
|
3707
|
+
let fail = 0;
|
|
3708
|
+
for (const c of candidates) {
|
|
3709
|
+
const deleted = aidDelete(c.aid, { aunPath });
|
|
3710
|
+
if (deleted) {
|
|
3711
|
+
console.log(` ✓ 删除 ${c.aid}`);
|
|
3712
|
+
ok++;
|
|
3713
|
+
}
|
|
3714
|
+
else {
|
|
3715
|
+
console.log(` ✗ 失败 ${c.aid}(已不存在?)`);
|
|
3716
|
+
fail++;
|
|
3717
|
+
}
|
|
3409
3718
|
}
|
|
3719
|
+
console.log(`\n完成:成功 ${ok},失败 ${fail}`);
|
|
3410
3720
|
return;
|
|
3411
3721
|
}
|
|
3412
3722
|
if (sub === 'lookup') {
|
|
3723
|
+
if (wantsHelp(args)) {
|
|
3724
|
+
console.log(`用法: evolclaw aid lookup <aid> [--format json]
|
|
3725
|
+
|
|
3726
|
+
远程探测 AID:是否注册、所在网关、是否有 agent.md(不验签,仅获取)。`);
|
|
3727
|
+
return;
|
|
3728
|
+
}
|
|
3413
3729
|
const aid = args[1];
|
|
3414
3730
|
if (!aid) {
|
|
3415
3731
|
console.error('用法: evolclaw aid lookup <aid>');
|
|
@@ -3447,6 +3763,13 @@ Options:
|
|
|
3447
3763
|
if (sub === 'agentmd') {
|
|
3448
3764
|
const verb = args[1];
|
|
3449
3765
|
const aid = args[2];
|
|
3766
|
+
if (!verb || isHelpFlag(verb) || wantsHelp(args)) {
|
|
3767
|
+
console.log(`用法: evolclaw aid agentmd <put|get> <aid> [--format json]
|
|
3768
|
+
|
|
3769
|
+
put <aid> 读本地 agent.md → 用本地私钥签名 → 上传到 PKI
|
|
3770
|
+
get <aid> 从 PKI 下载 agent.md → 验签 → 持久化到本地`);
|
|
3771
|
+
return;
|
|
3772
|
+
}
|
|
3450
3773
|
if (verb === 'put') {
|
|
3451
3774
|
if (!aid) {
|
|
3452
3775
|
console.error('用法: evolclaw aid agentmd put <aid>');
|
|
@@ -3518,7 +3841,7 @@ Options:
|
|
|
3518
3841
|
}
|
|
3519
3842
|
// ==================== RPC ====================
|
|
3520
3843
|
async function cmdRpc(args) {
|
|
3521
|
-
if (args
|
|
3844
|
+
if (args.length === 0 || isHelpFlag(args[0])) {
|
|
3522
3845
|
console.log(`用法: evolclaw rpc --as <aid> --params <params>
|
|
3523
3846
|
|
|
3524
3847
|
通用 AUN RPC 调用。
|
|
@@ -3597,7 +3920,7 @@ async function cmdStorage(args) {
|
|
|
3597
3920
|
const sub = args[0];
|
|
3598
3921
|
const aunPath = resolveAunPath(args);
|
|
3599
3922
|
const formatJson = args.includes('--format') && args[args.indexOf('--format') + 1] === 'json';
|
|
3600
|
-
if (!sub || sub
|
|
3923
|
+
if (!sub || isHelpFlag(sub)) {
|
|
3601
3924
|
console.log(`用法: evolclaw storage <command> <aid> [options]
|
|
3602
3925
|
|
|
3603
3926
|
Commands:
|
|
@@ -3747,7 +4070,7 @@ async function cmdMsg(args) {
|
|
|
3747
4070
|
const appIdx = args.indexOf('--app');
|
|
3748
4071
|
const appSlot = appIdx >= 0 ? args[appIdx + 1] : undefined;
|
|
3749
4072
|
const asDaemon = args.includes('--as-daemon');
|
|
3750
|
-
if (!sub || sub
|
|
4073
|
+
if (!sub || isHelpFlag(sub)) {
|
|
3751
4074
|
console.log(`用法: evolclaw msg <command> <from-aid> [args...] [options]
|
|
3752
4075
|
|
|
3753
4076
|
Commands:
|
|
@@ -4033,7 +4356,7 @@ async function cmdGroup(args) {
|
|
|
4033
4356
|
const appIdx = args.indexOf('--app');
|
|
4034
4357
|
const appSlot = appIdx >= 0 ? args[appIdx + 1] : undefined;
|
|
4035
4358
|
const asDaemon = args.includes('--as-daemon');
|
|
4036
|
-
if (!sub || sub
|
|
4359
|
+
if (!sub || isHelpFlag(sub)) {
|
|
4037
4360
|
console.log(`用法: evolclaw group <command> <from-aid> [args...] [options]
|
|
4038
4361
|
|
|
4039
4362
|
消息:
|
|
@@ -4433,7 +4756,7 @@ export async function main(args) {
|
|
|
4433
4756
|
}
|
|
4434
4757
|
switch (cmd) {
|
|
4435
4758
|
case 'init':
|
|
4436
|
-
if (args[1]
|
|
4759
|
+
if (isHelpFlag(args[1])) {
|
|
4437
4760
|
console.log(`用法: evolclaw init [渠道] [选项]
|
|
4438
4761
|
|
|
4439
4762
|
仅初始化 defaults.json:
|
|
@@ -4509,7 +4832,7 @@ export async function main(args) {
|
|
|
4509
4832
|
await cmdWatchAid();
|
|
4510
4833
|
}
|
|
4511
4834
|
else if (args[1] === 'msg') {
|
|
4512
|
-
if (args[2]
|
|
4835
|
+
if (isHelpFlag(args[2])) {
|
|
4513
4836
|
console.log(`用法: evolclaw watch msg
|
|
4514
4837
|
|
|
4515
4838
|
三面板交互式消息监控 TUI。
|
|
@@ -4645,17 +4968,19 @@ Commands:
|
|
|
4645
4968
|
--name <display-name>
|
|
4646
4969
|
--description <text>
|
|
4647
4970
|
--force (覆盖已有 config.json)
|
|
4648
|
-
agent sync-aids 从本地 AID 批量同步创建 agent(以最早 agent 为模板)
|
|
4649
4971
|
agent reload 全量 resync(扫磁盘,新增上线、删除下线、修改热更新)
|
|
4650
4972
|
agent reload <n> 热重载指定 agent 配置
|
|
4651
4973
|
aid AID 身份管理
|
|
4652
4974
|
aid list 列出本地所有 AID
|
|
4653
4975
|
aid show <aid> 查看本地 AID 详情(证书有效期、私钥状态)
|
|
4654
4976
|
aid new <aid> 创建新 AID 身份
|
|
4655
|
-
aid delete <aid> 删除本地 AID
|
|
4656
4977
|
aid lookup <aid> 远程探测 AID(是否存在 + 网关 + agent.md)
|
|
4657
4978
|
aid agentmd put <aid> 签名并上传 agent.md
|
|
4658
4979
|
aid agentmd get <aid> 下载并验签 agent.md
|
|
4980
|
+
aid delete <aid> 删除指定 AID
|
|
4981
|
+
aid delete --orphan 清理无私钥的外部 AID 缓存
|
|
4982
|
+
aid delete --unrecoverable 清理云端公钥已变更、不可恢复的 AID
|
|
4983
|
+
默认 dry-run,加 --yes 执行
|
|
4659
4984
|
net 网络链路诊断
|
|
4660
4985
|
net check [<aid>] 10 步链路检测(DNS→Discovery→TCP→TLS→WSS→Auth→Ping→Echo)
|
|
4661
4986
|
net help 查看详细帮助
|