evolcore 0.0.2 → 0.0.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 +44 -793
- package/dist/agents/claude-runner.js +197 -17
- package/dist/agents/codex-runner.js +46 -3
- package/dist/aun/outbox.js +8 -0
- package/dist/channels/aun.js +21 -4
- package/dist/channels/contact-bind-code.js +134 -0
- package/dist/channels/dingtalk.js +979 -149
- package/dist/channels/feishu.js +130 -54
- package/dist/channels/wecom-card.js +101 -0
- package/dist/channels/wecom-onboarding.js +82 -0
- package/dist/channels/wecom-state.js +191 -0
- package/dist/channels/wecom.js +755 -163
- package/dist/cli/agent-command.js +2 -1
- package/dist/cli/aun-commands.js +88 -33
- package/dist/cli/bench.js +2 -2
- package/dist/cli/contact.js +71 -0
- package/dist/cli/ctl-command.js +2 -2
- package/dist/cli/daemon-commands.js +77 -214
- package/dist/cli/handoff-command.js +2 -2
- package/dist/cli/help.js +9 -5
- package/dist/cli/index.js +132 -116
- package/dist/cli/init-channel.js +92 -97
- package/dist/cli/init.js +63 -26
- package/dist/cli/model.js +2 -1
- package/dist/cli/net-check.js +2 -2
- package/dist/cli/queue-command.js +30 -6
- package/dist/cli/raw-key-input.js +25 -0
- package/dist/cli/response.js +5 -6
- package/dist/cli/restart-monitor.js +25 -1
- package/dist/cli/stats.js +6 -4
- package/dist/cli/trigger-command.js +55 -15
- package/dist/cli/version.js +6 -1
- package/dist/config/builtin-role-templates.js +22 -10
- package/dist/config/builtin-roles.js +7 -1
- package/dist/config/config-manager.js +221 -17
- package/dist/config/contact-alias.js +68 -0
- package/dist/config/contact-book-store.js +454 -0
- package/dist/config/contact-book-v2-startup.js +35 -0
- package/dist/config/contact-book.js +156 -303
- package/dist/config/contact-operation-service.js +110 -0
- package/dist/config/peer-role-resolver.js +133 -54
- package/dist/config/role-ranks.js +18 -0
- package/dist/config/role-service.js +16 -19
- package/dist/config/role-store.js +16 -5
- package/dist/config/roles.js +10 -1
- package/dist/config-store.js +0 -2
- package/dist/core/auth/authorization-audit.js +10 -1
- package/dist/core/auth/operation-authorizer.js +2 -0
- package/dist/core/auth/operation-catalog.js +56 -0
- package/dist/core/command/command-handler.js +105 -10
- package/dist/core/command/connect-menu.js +374 -0
- package/dist/core/command/menu-handler.js +114 -16
- package/dist/core/command/role-menu.js +128 -29
- package/dist/core/command/slash-handler.js +28 -18
- package/dist/core/daemon-file-cache.js +12 -6
- package/dist/core/event-catalog.js +70 -0
- package/dist/core/evolagent-registry.js +0 -1
- package/dist/core/evolagent.js +20 -9
- package/dist/core/message/im-renderer.js +2 -0
- package/dist/core/message/message-bridge.js +79 -8
- package/dist/core/message/message-queue.js +10 -0
- package/dist/core/message/message-utils.js +8 -2
- package/dist/core/message/response-engine.js +269 -25
- package/dist/core/message/send-receipt.js +24 -0
- package/dist/core/message/stream-debouncer.js +11 -2
- package/dist/core/permission/tool-policy.js +47 -15
- package/dist/core/protected-paths.js +2 -0
- package/dist/core/session/session-fs-store.js +44 -3
- package/dist/core/session/session-manager.js +61 -5
- package/dist/index.js +62 -6
- package/dist/ipc.js +34 -5
- package/dist/stats/billing.js +20 -8
- package/dist/trigger/manager.js +3 -0
- package/dist/trigger/parser.js +77 -2
- package/dist/trigger/patch.js +8 -1
- package/dist/trigger/scheduler.js +3 -1
- package/dist/trigger/validation.js +13 -0
- package/dist/utils/aid-bind.js +43 -29
- package/dist/utils/instance-registry.js +14 -7
- package/dist/utils/log-writer.js +46 -0
- package/dist/utils/media-cache.js +4 -1
- package/dist/utils/model-prices.jsonl +6 -3
- package/dist/utils/restart-safety.js +31 -0
- package/dist/utils/system-memory.js +62 -0
- package/kits/docs/INDEX.md +2 -1
- package/kits/docs/evolcore/INDEX.md +5 -3
- package/kits/docs/evolcore/agent.md +9 -1
- package/kits/docs/evolcore/aid.md +5 -2
- package/kits/docs/evolcore/contact.md +57 -0
- package/kits/docs/evolcore/fs.md +9 -0
- package/kits/docs/evolcore/group.md +12 -3
- package/kits/docs/evolcore/model.md +4 -1
- package/kits/docs/evolcore/msg.md +9 -3
- package/kits/docs/evolcore/response.md +16 -21
- package/kits/docs/evolcore/rpc.md +2 -0
- package/kits/docs/evolcore/stats.md +15 -2
- package/kits/docs/evolcore/storage.md +1 -0
- package/kits/docs/evolcore/trigger.md +17 -2
- package/kits/eck_manifest.json +12 -0
- package/kits/migrations/migrate-contact-book-v2.mjs +747 -0
- package/kits/schemas/_meta.json +7 -4
- package/kits/schemas/agent-config.schema.6.json +322 -0
- package/kits/schemas/contact-book.schema.2.json +43 -0
- package/kits/schemas/relation-config.schema.5.json +47 -0
- package/kits/schemas/role-config.schema.1.json +1 -0
- package/kits/schemas/role-registry.schema.1.json +2 -2
- package/kits/templates/roles/admin.json +1 -0
- package/kits/templates/roles/member.json +1 -0
- package/kits/templates/roles/owner.json +1 -0
- package/kits/templates/roles/visitor.json +1 -0
- package/kits/templates/system-fragments/commands.md +3 -1
- package/package.json +4 -4
- package/assets/brand/evolcore/README.md +0 -19
- package/assets/brand/evolcore/evolcore-app-icon.png +0 -0
- package/assets/brand/evolcore/evolcore-app-icon.svg +0 -13
- package/assets/brand/evolcore/evolcore-brand-board.png +0 -0
- package/assets/brand/evolcore/evolcore-brand-board.svg +0 -126
- package/assets/brand/evolcore/evolcore-logo-kit.zip +0 -0
- package/assets/brand/evolcore/evolcore-logo-reverse.png +0 -0
- package/assets/brand/evolcore/evolcore-logo-reverse.svg +0 -14
- package/assets/brand/evolcore/evolcore-logo.png +0 -0
- package/assets/brand/evolcore/evolcore-logo.svg +0 -14
- package/assets/brand/evolcore/evolcore-mark.png +0 -0
- package/assets/brand/evolcore/evolcore-mark.svg +0 -10
package/dist/cli/index.js
CHANGED
|
@@ -3,18 +3,82 @@
|
|
|
3
3
|
process.env.AUN_LOG_INI_DISABLE = '1';
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import path from 'path';
|
|
6
|
-
import {
|
|
6
|
+
import { getPackageRoot } from '../paths.js';
|
|
7
7
|
import { cmdInit } from './init.js';
|
|
8
8
|
import { cmdInitWechat, cmdInitFeishu, cmdInitDingtalk, cmdInitQQBot, cmdInitWecom, cmdInitAun } from './init-channel.js';
|
|
9
|
-
import { isHelpFlag, getArgValue } from './help.js';
|
|
9
|
+
import { isHelpFlag, wantsHelp, getArgValue } from './help.js';
|
|
10
10
|
import * as platform from '../utils/cross-platform.js';
|
|
11
11
|
import { cmdRestartMonitor } from './restart-monitor.js';
|
|
12
12
|
import { cmdAid, cmdRpc, cmdStorage, cmdMsg, cmdGroup } from './aun-commands.js';
|
|
13
13
|
import { cmdAgent } from './agent-command.js';
|
|
14
14
|
import { cmdCtl } from './ctl-command.js';
|
|
15
15
|
import { cmdQueue } from './queue-command.js';
|
|
16
|
-
import { cmdStart, cmdStop, cmdRestart, cmdStatus, cmdLogs, cmdWatchCommand,
|
|
16
|
+
import { cmdStart, cmdStop, cmdRestart, cmdStatus, cmdLogs, cmdWatchCommand, cmdMv, cmdDiagnose } from './daemon-commands.js';
|
|
17
17
|
import { logCliCommand } from './command-log.js';
|
|
18
|
+
const MAIN_HELP = `用法: ec <command> [选项]
|
|
19
|
+
|
|
20
|
+
服务:
|
|
21
|
+
init 初始化默认配置、owner、控制 AID 与 EC Web
|
|
22
|
+
start 启动服务
|
|
23
|
+
stop 停止服务
|
|
24
|
+
restart 重启服务并检查更新
|
|
25
|
+
status 查看运行状态
|
|
26
|
+
logs 持续查看 daemon 日志
|
|
27
|
+
watch 打开日志、AID、消息或 EC Web 监控
|
|
28
|
+
|
|
29
|
+
Agent 与会话:
|
|
30
|
+
agent 管理 EvolAgent
|
|
31
|
+
ctl 当前托管会话的控制命令
|
|
32
|
+
queue 查询或操作 agent 消息队列
|
|
33
|
+
trigger 管理定时与事件触发器
|
|
34
|
+
handoff 查询和完成跨会话回流
|
|
35
|
+
model 查看或设置模型与推理强度
|
|
36
|
+
response 查看或设置响应模式
|
|
37
|
+
|
|
38
|
+
AUN:
|
|
39
|
+
aid 管理 AID 身份与 agent.md
|
|
40
|
+
msg 私聊消息收发、撤回、在线状态与历史
|
|
41
|
+
group 群消息与群管理
|
|
42
|
+
fs AUN 文件系统
|
|
43
|
+
storage 底层对象存储命令
|
|
44
|
+
rpc 调用底层 AUN RPC
|
|
45
|
+
contact 联系人黑名单管理
|
|
46
|
+
net AUN 网络链路诊断
|
|
47
|
+
|
|
48
|
+
配置与诊断:
|
|
49
|
+
config 读取、修改和检查分层配置
|
|
50
|
+
stats Token 用量与费用统计
|
|
51
|
+
diagnose 检查启动环境
|
|
52
|
+
version 显示组件版本
|
|
53
|
+
mv 迁移项目目录和会话路径
|
|
54
|
+
|
|
55
|
+
维护命令:
|
|
56
|
+
mode 切换开发源码与 npm 包运行模式
|
|
57
|
+
restart-monitor 运行 daemon 重启监控器
|
|
58
|
+
bench AUN 消息性能基准测试
|
|
59
|
+
link-rules 连接 ECK rules 到项目目录
|
|
60
|
+
|
|
61
|
+
运行 ec <command> --help 查看该命令的完整参数。
|
|
62
|
+
|
|
63
|
+
环境变量:
|
|
64
|
+
EVOLCORE_HOME 数据目录(默认: ~/.evolcore)
|
|
65
|
+
LOG_LEVEL 日志级别(默认: INFO)
|
|
66
|
+
MESSAGE_LOG 消息日志(默认: true)
|
|
67
|
+
EVENT_LOG 事件日志(默认: true)`;
|
|
68
|
+
function printLifecycleHelp(command) {
|
|
69
|
+
const help = {
|
|
70
|
+
start: `用法: ec start [--foreground] [--diagnose|-d]\n\n --foreground 前台运行,适合 systemd 或容器直接管理\n --diagnose, -d 以诊断模式启动 daemon`,
|
|
71
|
+
stop: '用法: ec stop\n\n停止当前 EVOLCORE_HOME 下运行的 EvolCore 服务。',
|
|
72
|
+
restart: `用法: ec restart [--clear] [--diagnose|-d]\n\n --clear 同时清理跨 HOME 残留的 EvolCore 主进程\n --diagnose, -d 以诊断模式启动新 daemon`,
|
|
73
|
+
status: '用法: ec status\n\n查看 daemon、agent、渠道与会话运行状态。',
|
|
74
|
+
logs: `用法: ec logs [选项]\n\n --level <error|warn|info|debug> 最低日志级别\n --module <name> 只显示指定模块\n --raw 原始输出\n --no-color 禁用颜色`,
|
|
75
|
+
watch: `用法: ec watch [logs|log|aid|msg|web|session]\n\n ec watch 打开监控选择菜单\n ec watch logs 选择日志类型后监控\n ec watch log <类型...> 直接监控指定日志类型\n ec watch aid 监控 AID 连接\n ec watch msg 打开消息 TUI\n ec watch web 安装/升级并启动 EC Web\n ec watch session ec watch web 的兼容别名`,
|
|
76
|
+
'restart-monitor': '用法: ec restart-monitor\n\n运行内 daemon 重启与升级监控器。',
|
|
77
|
+
diagnose: '用法: ec diagnose\n\n检查配置、数据库、进程和编译产物。',
|
|
78
|
+
mv: '用法: ec mv <old-directory> <new-directory>\n\n迁移项目目录以及 Claude、Codex 和 EvolCore 会话路径。',
|
|
79
|
+
};
|
|
80
|
+
console.log(help[command]);
|
|
81
|
+
}
|
|
18
82
|
// Suppress Node.js ExperimentalWarning (e.g. SQLite) from cluttering CLI output
|
|
19
83
|
process.removeAllListeners('warning');
|
|
20
84
|
process.on('warning', (w) => { if (w.name === 'ExperimentalWarning')
|
|
@@ -27,9 +91,13 @@ export async function main(args) {
|
|
|
27
91
|
console.log(pkg.version);
|
|
28
92
|
return;
|
|
29
93
|
}
|
|
94
|
+
if (isHelpFlag(cmd)) {
|
|
95
|
+
console.log(MAIN_HELP);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
30
98
|
switch (cmd) {
|
|
31
99
|
case 'init':
|
|
32
|
-
if (
|
|
100
|
+
if (wantsHelp(args.slice(1))) {
|
|
33
101
|
console.log(`用法: ec init [渠道] [选项]
|
|
34
102
|
|
|
35
103
|
仅初始化 defaults.json:
|
|
@@ -43,7 +111,7 @@ export async function main(args) {
|
|
|
43
111
|
--owner <aid> 必填。唯一 daemon owner AID
|
|
44
112
|
--baseagent <claude|codex|gemini> 可选。默认从 PATH 检测
|
|
45
113
|
--projectpath <abs-path> 可选。默认项目目录(必须绝对路径,自动创建)
|
|
46
|
-
--ecweb
|
|
114
|
+
--ecweb 可选。安装 EC Web 并启用自启动
|
|
47
115
|
--format json 可选但推荐。stdout 输出 init.result JSON
|
|
48
116
|
--force 已有不同 owner 时强制覆盖
|
|
49
117
|
|
|
@@ -53,7 +121,7 @@ export async function main(args) {
|
|
|
53
121
|
ec init wechat 微信扫码登录
|
|
54
122
|
ec init dingtalk 钉钉扫码登录
|
|
55
123
|
ec init qqbot QQ 机器人扫码绑定
|
|
56
|
-
ec init wecom 企业微信 AI Bot
|
|
124
|
+
ec init wecom 企业微信 AI Bot 扫码创建/手工配置`);
|
|
57
125
|
}
|
|
58
126
|
else if (args[1] === 'aun') {
|
|
59
127
|
const { suppressSdkLogs } = await import('../aun/aid/index.js');
|
|
@@ -105,36 +173,84 @@ export async function main(args) {
|
|
|
105
173
|
}
|
|
106
174
|
break;
|
|
107
175
|
case 'start':
|
|
176
|
+
if (wantsHelp(args.slice(1))) {
|
|
177
|
+
printLifecycleHelp('start');
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
108
180
|
await cmdStart({
|
|
109
181
|
diagnose: args.includes('--diagnose') || args.includes('-d'),
|
|
110
182
|
foreground: args.includes('--foreground'),
|
|
111
183
|
});
|
|
112
184
|
break;
|
|
113
185
|
case 'stop':
|
|
186
|
+
if (wantsHelp(args.slice(1))) {
|
|
187
|
+
printLifecycleHelp('stop');
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
114
190
|
await cmdStop();
|
|
115
191
|
break;
|
|
116
192
|
case 'restart':
|
|
193
|
+
if (wantsHelp(args.slice(1))) {
|
|
194
|
+
printLifecycleHelp('restart');
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
117
197
|
await cmdRestart({ clear: args.includes('--clear'), diagnose: args.includes('--diagnose') || args.includes('-d') });
|
|
118
198
|
break;
|
|
119
199
|
case 'status':
|
|
200
|
+
if (wantsHelp(args.slice(1))) {
|
|
201
|
+
printLifecycleHelp('status');
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
120
204
|
await cmdStatus();
|
|
121
205
|
break;
|
|
122
206
|
case 'logs':
|
|
207
|
+
if (wantsHelp(args.slice(1))) {
|
|
208
|
+
printLifecycleHelp('logs');
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
123
211
|
cmdLogs(args.slice(1));
|
|
124
212
|
break;
|
|
125
213
|
case 'watch':
|
|
214
|
+
if (wantsHelp(args.slice(1))) {
|
|
215
|
+
printLifecycleHelp('watch');
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
126
218
|
await cmdWatchCommand(args.slice(1));
|
|
127
219
|
break;
|
|
128
220
|
case 'restart-monitor':
|
|
221
|
+
if (wantsHelp(args.slice(1))) {
|
|
222
|
+
printLifecycleHelp('restart-monitor');
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
129
225
|
await cmdRestartMonitor();
|
|
130
226
|
break;
|
|
131
|
-
case '
|
|
132
|
-
|
|
227
|
+
case 'mode':
|
|
228
|
+
try {
|
|
229
|
+
// 开发源码仓可提供 mode.js;正式 npm 包可以不携带该内部命令。
|
|
230
|
+
const { cmdMode } = await import('./mode.js');
|
|
231
|
+
await cmdMode(args.slice(1));
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
if (error?.code === 'ERR_MODULE_NOT_FOUND' && /(?:^|[\\/])mode\.js(?:$|')/.test(String(error?.message ?? ''))) {
|
|
235
|
+
console.error('❌ 无效指令: mode');
|
|
236
|
+
process.exitCode = 1;
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
throw error;
|
|
240
|
+
}
|
|
133
241
|
break;
|
|
134
242
|
case 'mv':
|
|
243
|
+
if (wantsHelp(args.slice(1))) {
|
|
244
|
+
printLifecycleHelp('mv');
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
135
247
|
await cmdMv(args[1], args[2]);
|
|
136
248
|
break;
|
|
137
249
|
case 'diagnose':
|
|
250
|
+
if (wantsHelp(args.slice(1))) {
|
|
251
|
+
printLifecycleHelp('diagnose');
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
138
254
|
await cmdDiagnose();
|
|
139
255
|
break;
|
|
140
256
|
case 'net': {
|
|
@@ -217,6 +333,11 @@ export async function main(args) {
|
|
|
217
333
|
await cmdConfig(args.slice(1));
|
|
218
334
|
break;
|
|
219
335
|
}
|
|
336
|
+
case 'contact': {
|
|
337
|
+
const { cmdContact } = await import('./contact.js');
|
|
338
|
+
await cmdContact(args.slice(1));
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
220
341
|
case 'stats': {
|
|
221
342
|
const { handleStats } = await import('./stats.js');
|
|
222
343
|
await handleStats(args.slice(1));
|
|
@@ -242,114 +363,9 @@ export async function main(args) {
|
|
|
242
363
|
break;
|
|
243
364
|
}
|
|
244
365
|
default:
|
|
245
|
-
console.
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
init 初始化 evolcore home (${resolvePaths().defaultsConfig})
|
|
249
|
-
init feishu 飞书扫码登录并写入配置
|
|
250
|
-
init wechat 微信扫码登录并写入配置
|
|
251
|
-
init dingtalk 钉钉扫码登录并写入配置
|
|
252
|
-
init qqbot QQ 机器人扫码绑定并写入配置
|
|
253
|
-
init wecom 企业微信 AI Bot 配置(手动输入 Bot ID + Secret)
|
|
254
|
-
start 启动服务 (默认)
|
|
255
|
-
--foreground 前台运行,适合 systemd/Docker 直接管理进程
|
|
256
|
-
stop 停止服务
|
|
257
|
-
restart 重启服务
|
|
258
|
-
--clear 顺带 SIGKILL 跨 HOME 残留的 evolcore 主进程
|
|
259
|
-
status 查看状态
|
|
260
|
-
logs 查看日志 (tail -f, 着色渲染)
|
|
261
|
-
--level error|warn 只显示指定级别及以上
|
|
262
|
-
--module <name> 只显示指定模块(如 feishu、AgentRunner)
|
|
263
|
-
--raw 原始输出,不着色
|
|
264
|
-
watch 监控面板选择菜单(↑↓ 选择 log/aid/msg)
|
|
265
|
-
watch logs 勾选日志类型后实时监控(记忆上次选择,存入 daemon.json)
|
|
266
|
-
watch log <类型...> 直接监控指定类型(如 evolcore aun),不读写偏好
|
|
267
|
-
watch aid AID 连接状态实时监控(显示各 AID 在线/离线/重连状态)
|
|
268
|
-
watch msg 消息监控(三面板交互式 TUI:AID 列表 / 对端统计 / 消息流)
|
|
269
|
-
ctl 当前会话工具(发送消息/文件、名称、队列、路径、状态)
|
|
270
|
-
ec ctl help 查看完整命令列表
|
|
271
|
-
trigger daemon 级触发器管理(list/show/history/create/update/run)
|
|
272
|
-
handoff 跨会话任务回流
|
|
273
|
-
handoff return [id] [content] 确认当前 handoff;required 策略需提供内容
|
|
274
|
-
handoff list/trace 查询实例和审计事件
|
|
275
|
-
queue 消息队列查询与操作
|
|
276
|
-
queue --agent <aid> 查看 agent 的所有队列
|
|
277
|
-
queue --agent <aid> --clear 清空待处理消息
|
|
278
|
-
queue --agent <aid> --interrupt --sessionkey <key> 打断处理中任务
|
|
279
|
-
agent 管理 EvolAgent
|
|
280
|
-
agent 列出所有 agent
|
|
281
|
-
agent <name> 查看指定 agent 详情
|
|
282
|
-
agent new <name> 创建新 agent(交互式)
|
|
283
|
-
agent new <name> --non-interactive ... 非交互创建(自动化)
|
|
284
|
-
必填: --project <absolute path>
|
|
285
|
-
可选: --baseagent <claude|codex|gemini> (默认: PATH 中第一个可用)
|
|
286
|
-
--owner <aid>
|
|
287
|
-
--name <display-name>
|
|
288
|
-
--description <text>
|
|
289
|
-
--force (覆盖已有 config.json)
|
|
290
|
-
agent reload 全量 resync(扫磁盘,新增上线、删除下线、修改热更新)
|
|
291
|
-
agent reload <n> 热重载指定 agent 配置
|
|
292
|
-
model 模型管理(agent/关系可写,支持角色策略预览)
|
|
293
|
-
model list 列出可用模型并显示当前生效模型
|
|
294
|
-
model current 显示实际生效的模型、强度和来源
|
|
295
|
-
model info <id> 查看模型详情
|
|
296
|
-
model use <id> 设置模型(写操作需要 --self)
|
|
297
|
-
model effort <lv> 设置推理强度
|
|
298
|
-
model reset 清除当前作用域的模型和强度设置
|
|
299
|
-
model check 诊断网关与模型可用性
|
|
300
|
-
response 响应模式管理(查看/切换/配置,作用域:全局/agent/关系)
|
|
301
|
-
response list 列出所有响应模式
|
|
302
|
-
response current 显示当前作用域生效的默认模式
|
|
303
|
-
response info <id> 查看单个模式详情(场景/配置参数)
|
|
304
|
-
response set <id> 设置默认模式(--scene private/group)
|
|
305
|
-
response config 查看/修改模式配置参数
|
|
306
|
-
response reset 清除指定作用域设置
|
|
307
|
-
response help 查看完整用法
|
|
308
|
-
aid AID 身份管理
|
|
309
|
-
aid list 列出本地所有 AID
|
|
310
|
-
aid show <aid> 查看本地 AID 详情(证书有效期、私钥状态)
|
|
311
|
-
aid new <aid> 创建新 AID 身份
|
|
312
|
-
aid lookup <aid> 远程探测 AID(是否存在 + 网关 + agent.md)
|
|
313
|
-
aid agentmd put <aid> 签名并上传 agent.md
|
|
314
|
-
aid agentmd get <aid> 下载并验签 agent.md
|
|
315
|
-
aid delete <aid> 删除指定 AID
|
|
316
|
-
aid delete --orphan 清理无私钥的外部 AID 缓存
|
|
317
|
-
aid delete --unrecoverable 清理云端公钥已变更、不可恢复的 AID
|
|
318
|
-
默认 dry-run,加 --yes 执行
|
|
319
|
-
fs AUN 文件系统统一入口
|
|
320
|
-
fs ls|stat|cat|find <AID>:/path
|
|
321
|
-
fs cp <src> <dst> 上传/下载/远程复制
|
|
322
|
-
fs mv <src> <dst> 移动/改名(同后端)
|
|
323
|
-
fs rm [-r] <AID>:/path
|
|
324
|
-
fs mkdir [-p] <AID>:/path
|
|
325
|
-
fs ln -s <target> <AID>:/path
|
|
326
|
-
fs chmod +r|o-r <AID>:/path
|
|
327
|
-
fs setfacl|getfacl <AID>:/path
|
|
328
|
-
fs token issue|revoke|ls <AID>:/path
|
|
329
|
-
fs df <AID>:
|
|
330
|
-
fs mount <target> --volume <id>|--source <src>
|
|
331
|
-
net 网络链路诊断
|
|
332
|
-
net check [<aid>] 10 步链路检测(DNS→Discovery→TCP→TLS→WSS→Auth→Ping→Echo)
|
|
333
|
-
net help 查看详细帮助
|
|
334
|
-
rpc AUN RPC 调用
|
|
335
|
-
rpc --as <aid> --params <json|jsonl|file>
|
|
336
|
-
storage 文件存储
|
|
337
|
-
storage upload <aid> <file> <path> [--public]
|
|
338
|
-
storage download <aid> <url> [local-path]
|
|
339
|
-
storage ls <aid> [prefix]
|
|
340
|
-
storage rm <aid> <path>
|
|
341
|
-
storage quota <aid>
|
|
342
|
-
diagnose 诊断启动环境(配置、数据库、进程)
|
|
343
|
-
mv <old> <new> 迁移项目目录(保留 Claude/Codex/EvolCore 会话)
|
|
344
|
-
bench AUN 消息性能基准测试
|
|
345
|
-
bench --aids 5 --rounds 10 --concurrency 5
|
|
346
|
-
|
|
347
|
-
Environment:
|
|
348
|
-
EVOLCORE_HOME 数据目录 (默认: ~/.evolcore)
|
|
349
|
-
LOG_LEVEL 日志级别 (默认: INFO)
|
|
350
|
-
MESSAGE_LOG 消息日志 (默认: true)
|
|
351
|
-
EVENT_LOG 事件日志 (默认: true)`);
|
|
352
|
-
process.exit(1);
|
|
366
|
+
console.error(`未知命令: ${cmd}`);
|
|
367
|
+
console.log(MAIN_HELP);
|
|
368
|
+
process.exitCode = 1;
|
|
353
369
|
}
|
|
354
370
|
}
|
|
355
371
|
// 直接运行时自动执行(node dist/cli/index.js ...)
|
package/dist/cli/init-channel.js
CHANGED
|
@@ -17,6 +17,8 @@ import { cmdStart } from './daemon-commands.js';
|
|
|
17
17
|
import * as platform from '../utils/cross-platform.js';
|
|
18
18
|
import { cleanupInstances } from '../utils/instance-registry.js';
|
|
19
19
|
import { bindContactAlias } from '../config/contact-book.js';
|
|
20
|
+
import { listStaticAgentAdmins } from '../config/peer-role-resolver.js';
|
|
21
|
+
import { setupRawKeyListener } from './raw-key-input.js';
|
|
20
22
|
function ask(rl, question) {
|
|
21
23
|
return new Promise(resolve => rl.question(question, resolve));
|
|
22
24
|
}
|
|
@@ -198,26 +200,12 @@ async function pollBindStatusWithKeyboard(taskId, expiresAt) {
|
|
|
198
200
|
let quit = false;
|
|
199
201
|
let skip = false;
|
|
200
202
|
const p = resolvePaths();
|
|
201
|
-
const
|
|
202
|
-
if (
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const handler = (key) => {
|
|
208
|
-
if (key === 'q' || key === '\u0003')
|
|
209
|
-
quit = true;
|
|
210
|
-
if (key === 's' || key === 'S')
|
|
211
|
-
skip = true;
|
|
212
|
-
};
|
|
213
|
-
process.stdin.on('data', handler);
|
|
214
|
-
return () => {
|
|
215
|
-
process.stdin.removeListener('data', handler);
|
|
216
|
-
process.stdin.setRawMode(false);
|
|
217
|
-
// Don't pause stdin - let the next readline/prompt handle it naturally
|
|
218
|
-
};
|
|
219
|
-
};
|
|
220
|
-
const cleanup = setupKeyListener();
|
|
203
|
+
const cleanup = setupRawKeyListener((key) => {
|
|
204
|
+
if (key === 'q' || key === '\u0003')
|
|
205
|
+
quit = true;
|
|
206
|
+
if (key === 's' || key === 'S')
|
|
207
|
+
skip = true;
|
|
208
|
+
});
|
|
221
209
|
try {
|
|
222
210
|
while (Date.now() < expiresAt) {
|
|
223
211
|
if (quit)
|
|
@@ -305,26 +293,12 @@ async function runQrRegistrationFlow() {
|
|
|
305
293
|
console.log('请用飞书/Lark 扫描上方二维码...\n');
|
|
306
294
|
console.log('按 q 退出 | 按 s 跳过扫码手动输入 appId/appSecret\n');
|
|
307
295
|
let userAction = null;
|
|
308
|
-
const
|
|
309
|
-
if (
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const handler = (key) => {
|
|
315
|
-
if (key === 'q' || key === '\u0003')
|
|
316
|
-
userAction = QUIT;
|
|
317
|
-
if (key === 's')
|
|
318
|
-
userAction = SKIP;
|
|
319
|
-
};
|
|
320
|
-
process.stdin.on('data', handler);
|
|
321
|
-
return () => {
|
|
322
|
-
process.stdin.removeListener('data', handler);
|
|
323
|
-
process.stdin.setRawMode(false);
|
|
324
|
-
// Don't pause stdin - let the next readline/prompt handle it naturally
|
|
325
|
-
};
|
|
326
|
-
};
|
|
327
|
-
const cleanup = setupKeyListener();
|
|
296
|
+
const cleanup = setupRawKeyListener((key) => {
|
|
297
|
+
if (key === 'q' || key === '\u0003')
|
|
298
|
+
userAction = QUIT;
|
|
299
|
+
if (key === 's')
|
|
300
|
+
userAction = SKIP;
|
|
301
|
+
});
|
|
328
302
|
const startedAt = Date.now();
|
|
329
303
|
let pollIntervalSeconds = Number(beginResult.interval ?? 5);
|
|
330
304
|
const expireInSeconds = Number(beginResult.expires_in ?? beginResult.expire_in ?? 600);
|
|
@@ -473,7 +447,7 @@ export async function cmdInitFeishu() {
|
|
|
473
447
|
bindQrActorToContact(aid, contactBinding, 'feishu', result.openId, commitResult.channelKey);
|
|
474
448
|
// Show unified init success message
|
|
475
449
|
const { generateInitSuccessMessage } = await import('../utils/welcome.js');
|
|
476
|
-
console.log(generateInitSuccessMessage('feishu',
|
|
450
|
+
console.log(generateInitSuccessMessage('feishu', contactBinding !== null));
|
|
477
451
|
}
|
|
478
452
|
// ==================== WeChat ====================
|
|
479
453
|
const DEFAULT_BASE_URL = 'https://ilinkai.weixin.qq.com';
|
|
@@ -610,7 +584,7 @@ export async function cmdInitWechat() {
|
|
|
610
584
|
bindQrActorToContact(aid, contactBinding, 'wechat', result.userId, commitResult.channelKey);
|
|
611
585
|
// Show unified init success message
|
|
612
586
|
const { generateInitSuccessMessage } = await import('../utils/welcome.js');
|
|
613
|
-
console.log(generateInitSuccessMessage('wechat',
|
|
587
|
+
console.log(generateInitSuccessMessage('wechat', contactBinding !== null));
|
|
614
588
|
}
|
|
615
589
|
// ==================== AUN ====================
|
|
616
590
|
export async function cmdInitAun() {
|
|
@@ -752,26 +726,12 @@ async function runDingtalkQrFlow() {
|
|
|
752
726
|
console.log('提示: 扫码页面标注 "OpenClaw" 是钉钉生态接入桥,可放心使用。\n');
|
|
753
727
|
console.log('按 q 退出 | 按 s 跳过扫码手动输入\n');
|
|
754
728
|
let userAction = null;
|
|
755
|
-
const
|
|
756
|
-
if (
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
const handler = (key) => {
|
|
762
|
-
if (key === 'q' || key === '\u0003')
|
|
763
|
-
userAction = QUIT;
|
|
764
|
-
if (key === 's')
|
|
765
|
-
userAction = SKIP;
|
|
766
|
-
};
|
|
767
|
-
process.stdin.on('data', handler);
|
|
768
|
-
return () => {
|
|
769
|
-
process.stdin.removeListener('data', handler);
|
|
770
|
-
process.stdin.setRawMode(false);
|
|
771
|
-
// Don't pause stdin - let the next readline/prompt handle it naturally
|
|
772
|
-
};
|
|
773
|
-
};
|
|
774
|
-
const cleanup = setupKeyListener();
|
|
729
|
+
const cleanup = setupRawKeyListener((key) => {
|
|
730
|
+
if (key === 'q' || key === '\u0003')
|
|
731
|
+
userAction = QUIT;
|
|
732
|
+
if (key === 's')
|
|
733
|
+
userAction = SKIP;
|
|
734
|
+
});
|
|
775
735
|
const pollInterval = Math.max(Number(beginData.interval ?? 3), 2);
|
|
776
736
|
const expiresIn = Number(beginData.expires_in ?? 7200);
|
|
777
737
|
const startedAt = Date.now();
|
|
@@ -904,7 +864,7 @@ export async function cmdInitDingtalk() {
|
|
|
904
864
|
console.log(' ⚠ 服务未运行或热重载失败,无法注册钉钉绑定码;请启动服务后重新执行 ec init dingtalk 并再次扫码绑定。');
|
|
905
865
|
}
|
|
906
866
|
const { generateInitSuccessMessage } = await import('../utils/welcome.js');
|
|
907
|
-
console.log(generateInitSuccessMessage('dingtalk',
|
|
867
|
+
console.log(generateInitSuccessMessage('dingtalk', contactBinding !== null));
|
|
908
868
|
}
|
|
909
869
|
// ==================== QQBot ====================
|
|
910
870
|
const QQBOT_PORTAL_HOST = 'q.qq.com';
|
|
@@ -968,26 +928,12 @@ async function runQQBotBindFlow() {
|
|
|
968
928
|
console.log('请用 QQ 扫描上方二维码绑定机器人...\n');
|
|
969
929
|
console.log('按 q 退出 | 按 s 跳过扫码手动输入\n');
|
|
970
930
|
let userAction = null;
|
|
971
|
-
const
|
|
972
|
-
if (
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
const handler = (key) => {
|
|
978
|
-
if (key === 'q' || key === '\u0003')
|
|
979
|
-
userAction = QUIT;
|
|
980
|
-
if (key === 's')
|
|
981
|
-
userAction = SKIP;
|
|
982
|
-
};
|
|
983
|
-
process.stdin.on('data', handler);
|
|
984
|
-
return () => {
|
|
985
|
-
process.stdin.removeListener('data', handler);
|
|
986
|
-
process.stdin.setRawMode(false);
|
|
987
|
-
// Don't pause stdin - let the next readline/prompt handle it naturally
|
|
988
|
-
};
|
|
989
|
-
};
|
|
990
|
-
const cleanup = setupKeyListener();
|
|
931
|
+
const cleanup = setupRawKeyListener((key) => {
|
|
932
|
+
if (key === 'q' || key === '\u0003')
|
|
933
|
+
userAction = QUIT;
|
|
934
|
+
if (key === 's')
|
|
935
|
+
userAction = SKIP;
|
|
936
|
+
});
|
|
991
937
|
const startedAt = Date.now();
|
|
992
938
|
try {
|
|
993
939
|
// Step 3: Poll for bind result
|
|
@@ -1122,7 +1068,7 @@ export async function cmdInitQQBot() {
|
|
|
1122
1068
|
console.log(` App ID: ${result.appId}`);
|
|
1123
1069
|
bindQrActorToContact(aid, contactBinding, 'qqbot', result.userOpenId, commitResult.channelKey);
|
|
1124
1070
|
const { generateInitSuccessMessage } = await import('../utils/welcome.js');
|
|
1125
|
-
console.log(generateInitSuccessMessage('qqbot',
|
|
1071
|
+
console.log(generateInitSuccessMessage('qqbot', contactBinding !== null));
|
|
1126
1072
|
}
|
|
1127
1073
|
// ==================== WeCom (企业微信) ====================
|
|
1128
1074
|
export async function cmdInitWecom() {
|
|
@@ -1130,6 +1076,7 @@ export async function cmdInitWecom() {
|
|
|
1130
1076
|
let aid = null;
|
|
1131
1077
|
let agentConfig = null;
|
|
1132
1078
|
let choice = null;
|
|
1079
|
+
let contactBinding = null;
|
|
1133
1080
|
let botId = '';
|
|
1134
1081
|
let secret = '';
|
|
1135
1082
|
try {
|
|
@@ -1145,8 +1092,43 @@ export async function cmdInitWecom() {
|
|
|
1145
1092
|
choice = await pickInstanceWithinAgent(rl, 'wecom', existing);
|
|
1146
1093
|
if (choice === null)
|
|
1147
1094
|
return;
|
|
1095
|
+
contactBinding = await pickOwnerAdminForChannelBinding(rl, agentConfig, 'wecom');
|
|
1096
|
+
if (!contactBinding)
|
|
1097
|
+
return;
|
|
1148
1098
|
console.log('\n企业微信 AI Bot 配置');
|
|
1149
|
-
|
|
1099
|
+
const method = (await ask(rl, ' 接入方式:1. 扫码创建(推荐) 2. 手工输入 [1]: ')).trim() || '1';
|
|
1100
|
+
if (method === '1') {
|
|
1101
|
+
try {
|
|
1102
|
+
const { createWecomQrSession, pollWecomQrCredentials } = await import('../channels/wecom-onboarding.js');
|
|
1103
|
+
const session = await createWecomQrSession();
|
|
1104
|
+
const qrterm = await import('qrcode-terminal');
|
|
1105
|
+
console.log('\n请使用企业微信扫描以下二维码:\n');
|
|
1106
|
+
await new Promise(resolve => {
|
|
1107
|
+
qrterm.default.generate(session.authUrl, { small: true }, (qr) => {
|
|
1108
|
+
console.log(qr);
|
|
1109
|
+
resolve();
|
|
1110
|
+
});
|
|
1111
|
+
});
|
|
1112
|
+
console.log(`也可在浏览器打开:${session.browserUrl}`);
|
|
1113
|
+
console.log('等待扫码确认,二维码 5 分钟内有效...\n');
|
|
1114
|
+
const credentials = await pollWecomQrCredentials(session.scode, {
|
|
1115
|
+
onStatus: status => {
|
|
1116
|
+
if (status !== 'waiting')
|
|
1117
|
+
console.log(` 扫码状态: ${status}`);
|
|
1118
|
+
},
|
|
1119
|
+
});
|
|
1120
|
+
botId = credentials.botId;
|
|
1121
|
+
secret = credentials.secret;
|
|
1122
|
+
console.log(' ✓ 已取得 Bot ID 和 Secret');
|
|
1123
|
+
}
|
|
1124
|
+
catch (error) {
|
|
1125
|
+
console.log(` ⚠ 扫码接入失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
1126
|
+
console.log(' 将切换到手工输入模式。\n');
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
if (!botId || !secret) {
|
|
1130
|
+
console.log('请在企业微信管理后台 → AI Bot 页面获取 Bot ID 和 Secret\n');
|
|
1131
|
+
}
|
|
1150
1132
|
while (!botId) {
|
|
1151
1133
|
botId = (await ask(rl, ' Bot ID: ')).trim();
|
|
1152
1134
|
if (!botId)
|
|
@@ -1168,10 +1150,18 @@ export async function cmdInitWecom() {
|
|
|
1168
1150
|
botId,
|
|
1169
1151
|
secret,
|
|
1170
1152
|
};
|
|
1171
|
-
await commitChannel(aid, channel, choice.action);
|
|
1153
|
+
const commitResult = await commitChannel(aid, channel, choice.action);
|
|
1154
|
+
if (!commitResult)
|
|
1155
|
+
return;
|
|
1172
1156
|
console.log(` Bot ID: ${botId}`);
|
|
1157
|
+
if (commitResult.reloaded) {
|
|
1158
|
+
await registerWecomContactBind(aid, commitResult.channelKey, contactBinding);
|
|
1159
|
+
}
|
|
1160
|
+
else {
|
|
1161
|
+
console.log(' ⚠ 服务未运行或热重载失败,无法注册企微绑定码;请启动服务后重新执行 ec init wecom。');
|
|
1162
|
+
}
|
|
1173
1163
|
const { generateInitSuccessMessage } = await import('../utils/welcome.js');
|
|
1174
|
-
console.log(generateInitSuccessMessage('wecom',
|
|
1164
|
+
console.log(generateInitSuccessMessage('wecom', contactBinding !== null));
|
|
1175
1165
|
}
|
|
1176
1166
|
// ==================== Shared helpers for per-agent init <channel> ====================
|
|
1177
1167
|
/**
|
|
@@ -1221,8 +1211,8 @@ async function pickInstanceWithinAgent(rl, channelType, existing) {
|
|
|
1221
1211
|
async function pickOwnerAdminForChannelBinding(rl, agentConfig, channelType) {
|
|
1222
1212
|
const candidates = ownerAdminContactCandidates(agentConfig);
|
|
1223
1213
|
if (candidates.length === 0) {
|
|
1224
|
-
console.log(`\n❌ agent ${agentConfig.aid} 尚未配置
|
|
1225
|
-
console.log(' 请先通过 AUN 绑定 agent owner
|
|
1214
|
+
console.log(`\n❌ agent ${agentConfig.aid} 尚未配置 owner/admin,无法为 ${channelType} 扫码账号建立身份映射。`);
|
|
1215
|
+
console.log(' 请先通过 AUN 绑定 agent owner,或由 owner 在 AUN 私聊 relation 中分配 admin 后重试。');
|
|
1226
1216
|
return null;
|
|
1227
1217
|
}
|
|
1228
1218
|
console.log(`\n请选择 ${channelType} 扫码账号要绑定到的 owner/admin AID:`);
|
|
@@ -1255,7 +1245,7 @@ function ownerAdminContactCandidates(agentConfig) {
|
|
|
1255
1245
|
};
|
|
1256
1246
|
for (const owner of agentConfig.owners ?? [])
|
|
1257
1247
|
add(owner, 'owner');
|
|
1258
|
-
for (const admin of agentConfig.
|
|
1248
|
+
for (const admin of listStaticAgentAdmins(agentConfig.aid))
|
|
1259
1249
|
add(admin, 'admin');
|
|
1260
1250
|
return [...labels.entries()].map(([primaryId, roles]) => ({
|
|
1261
1251
|
primaryId,
|
|
@@ -1273,7 +1263,7 @@ function bindQrActorToContact(aid, binding, channelType, actorId, channelKey) {
|
|
|
1273
1263
|
try {
|
|
1274
1264
|
const changed = bindContactAlias(aid, binding.primaryId, channelType, normalizedActor, channelKey);
|
|
1275
1265
|
const action = changed ? '已写入' : '已存在';
|
|
1276
|
-
console.log(` ✓ 身份映射${action}: ${
|
|
1266
|
+
console.log(` ✓ 身份映射${action}: ${channelKey}:${encodeURIComponent(normalizedActor)} -> ${binding.primaryId}`);
|
|
1277
1267
|
}
|
|
1278
1268
|
catch (error) {
|
|
1279
1269
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1281,23 +1271,28 @@ function bindQrActorToContact(aid, binding, channelType, actorId, channelKey) {
|
|
|
1281
1271
|
}
|
|
1282
1272
|
}
|
|
1283
1273
|
async function registerDingtalkContactBind(aid, channelName, binding) {
|
|
1274
|
+
await registerChannelContactBind('dingtalk', '钉钉', aid, channelName, binding);
|
|
1275
|
+
}
|
|
1276
|
+
async function registerWecomContactBind(aid, channelName, binding) {
|
|
1277
|
+
await registerChannelContactBind('wecom', '企微', aid, channelName, binding);
|
|
1278
|
+
}
|
|
1279
|
+
async function registerChannelContactBind(channelType, displayName, aid, channelName, binding) {
|
|
1284
1280
|
if (!binding)
|
|
1285
1281
|
return;
|
|
1286
1282
|
const result = await ipcQuery(resolvePaths().socket, {
|
|
1287
|
-
type:
|
|
1283
|
+
type: `${channelType}.contact-bind.register`,
|
|
1288
1284
|
selfAid: aid,
|
|
1289
1285
|
channelName,
|
|
1290
1286
|
primaryId: binding.primaryId,
|
|
1291
1287
|
}, 3000);
|
|
1292
1288
|
if (!result?.ok) {
|
|
1293
|
-
console.log(` ⚠
|
|
1294
|
-
console.log(
|
|
1289
|
+
console.log(` ⚠ ${displayName}绑定码注册失败: ${result?.error || 'daemon 不可用'}`);
|
|
1290
|
+
console.log(` 请重新执行 ec init ${channelType} 并再次绑定。`);
|
|
1295
1291
|
return;
|
|
1296
1292
|
}
|
|
1297
1293
|
const expiresAt = new Date(Number(result.expiresAt)).toLocaleString();
|
|
1298
|
-
console.log(` ✓
|
|
1299
|
-
console.log(` 请在 10
|
|
1300
|
-
console.log(' 非纯数字或位数不对只会提醒格式,不计入错误次数;6 位数字输错最多 5 次。');
|
|
1294
|
+
console.log(` ✓ ${displayName}身份绑定码: ${result.code}`);
|
|
1295
|
+
console.log(` 请在 10 分钟内私聊${displayName}机器人,直接发送这 6 位数字绑定码。有效期至: ${expiresAt}`);
|
|
1301
1296
|
}
|
|
1302
1297
|
function firstNonEmpty(...values) {
|
|
1303
1298
|
for (const value of values) {
|