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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import os from 'os';
|
|
4
|
-
import { spawn,
|
|
4
|
+
import { spawn, execFile } from 'child_process';
|
|
5
5
|
import { promisify } from 'util';
|
|
6
6
|
import readline from 'readline';
|
|
7
7
|
import { resolveRoot, resolvePaths, ensureDataDirs, getPackageRoot, agentMdPath } from '../paths.js';
|
|
@@ -27,6 +27,7 @@ import { printCodeStats } from './code-stats.js';
|
|
|
27
27
|
import { getProcessStartTime } from '../utils/process-introspect.js';
|
|
28
28
|
import { AGENT_DELEGATION_TOKEN_ENV } from '../core/auth/agent-delegation.js';
|
|
29
29
|
import { WEB_CLI_BIN, WEB_PACKAGE_LATEST, WEB_PACKAGE_NAME } from '../product.js';
|
|
30
|
+
import { rotateStdoutLog } from '../utils/log-writer.js';
|
|
30
31
|
const execFileAsync = promisify(execFile);
|
|
31
32
|
async function probeDaemon(socketPath, timeoutMs = 1000) {
|
|
32
33
|
const response = await ipcQuery(socketPath, { type: 'ping' }, timeoutMs);
|
|
@@ -81,42 +82,6 @@ export function cleanEnv() {
|
|
|
81
82
|
delete process.env[key];
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
|
-
/**
|
|
85
|
-
* 启动时归档过大的 stdout.log。其它 .log 文件由各自的 LogWriter 管理切片/清理,
|
|
86
|
-
* 不再扫描整个目录——LogWriter 模式下重复的 size 检查会和 hourly rotation 冲突。
|
|
87
|
-
*/
|
|
88
|
-
function rotateStdoutIfNeeded(logDir) {
|
|
89
|
-
if (!fs.existsSync(logDir))
|
|
90
|
-
return;
|
|
91
|
-
const MAX_SIZE = 10 * 1024 * 1024; // 10MB
|
|
92
|
-
const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1000;
|
|
93
|
-
const stdoutLog = path.join(logDir, 'stdout.log');
|
|
94
|
-
// 归档当前 stdout.log(若超过 10MB)
|
|
95
|
-
try {
|
|
96
|
-
const stat = fs.statSync(stdoutLog);
|
|
97
|
-
if (stat.size > MAX_SIZE) {
|
|
98
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '').slice(0, 15);
|
|
99
|
-
const newPath = `${stdoutLog}.${timestamp}`;
|
|
100
|
-
fs.renameSync(stdoutLog, newPath);
|
|
101
|
-
console.log(` Rotated: stdout.log -> ${path.basename(newPath)}`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
catch { /* file not exist */ }
|
|
105
|
-
// 清理 7 天前的 stdout.log.* 归档
|
|
106
|
-
try {
|
|
107
|
-
for (const file of fs.readdirSync(logDir)) {
|
|
108
|
-
if (!file.startsWith('stdout.log.'))
|
|
109
|
-
continue;
|
|
110
|
-
const full = path.join(logDir, file);
|
|
111
|
-
try {
|
|
112
|
-
if (fs.statSync(full).mtimeMs < cutoff)
|
|
113
|
-
fs.unlinkSync(full);
|
|
114
|
-
}
|
|
115
|
-
catch { }
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
catch { }
|
|
119
|
-
}
|
|
120
85
|
function buildDaemonEnv(p, opts) {
|
|
121
86
|
return {
|
|
122
87
|
...process.env,
|
|
@@ -318,7 +283,10 @@ export async function cmdStart(opts = {}) {
|
|
|
318
283
|
// 跨 HOME 孤儿(未登记进程)只警告,不动
|
|
319
284
|
reportOrphans(findOrphanProcesses());
|
|
320
285
|
console.log('🚀 Starting EvolCore...');
|
|
321
|
-
|
|
286
|
+
const stdoutRotation = rotateStdoutLog(p.logs);
|
|
287
|
+
if (stdoutRotation.rotatedPath) {
|
|
288
|
+
console.log(` Rotated: stdout.log -> ${path.basename(stdoutRotation.rotatedPath)}`);
|
|
289
|
+
}
|
|
322
290
|
cleanEnv();
|
|
323
291
|
// 在启动前确保 serviceProxy 配置完整(如果 ecweb 启用但 serviceProxy 未配置)
|
|
324
292
|
ensureServiceProxyConfigBeforeStart(p);
|
|
@@ -604,9 +572,16 @@ export async function cmdRestart(opts = {}) {
|
|
|
604
572
|
// 跨 HOME 的孤儿只在 --clear 时 kill,否则仅警告。
|
|
605
573
|
{
|
|
606
574
|
const orphans = findOrphanProcesses();
|
|
575
|
+
const confirmedTestDaemons = orphans.filter(o => o.confirmedTestDaemon);
|
|
576
|
+
const nonTestOrphans = orphans.filter(o => !o.confirmedTestDaemon);
|
|
577
|
+
if (confirmedTestDaemons.length > 0) {
|
|
578
|
+
const killed = killOrphans(confirmedTestDaemons);
|
|
579
|
+
console.log(`☠ 已清理 ${killed.length} 个泄漏的测试 daemon: ${killed.join(', ')}`);
|
|
580
|
+
await sleep(500);
|
|
581
|
+
}
|
|
607
582
|
const currentHome = resolveRoot();
|
|
608
|
-
const sameHome =
|
|
609
|
-
const otherHome =
|
|
583
|
+
const sameHome = nonTestOrphans.filter(o => o.evolcoreHome === currentHome);
|
|
584
|
+
const otherHome = nonTestOrphans.filter(o => o.evolcoreHome !== currentHome);
|
|
610
585
|
if (sameHome.length > 0) {
|
|
611
586
|
const killed = killOrphans(sameHome);
|
|
612
587
|
console.log(`☠ 已 SIGKILL ${killed.length} 个同 HOME 孤儿进程: ${killed.join(', ')}`);
|
|
@@ -617,6 +592,9 @@ export async function cmdRestart(opts = {}) {
|
|
|
617
592
|
console.log(`☠ 已 SIGKILL ${killed.length} 个跨 HOME 孤儿进程: ${killed.join(', ')}`);
|
|
618
593
|
await sleep(500);
|
|
619
594
|
}
|
|
595
|
+
else if (otherHome.length > 0) {
|
|
596
|
+
reportOrphans(otherHome);
|
|
597
|
+
}
|
|
620
598
|
}
|
|
621
599
|
// 清理 codex app-server 孤儿进程(无 HOME 区分,全局清理)
|
|
622
600
|
{
|
|
@@ -642,141 +620,6 @@ export async function cmdRestart(opts = {}) {
|
|
|
642
620
|
printCodeStats(getPackageRoot(), resolvePaths().logs);
|
|
643
621
|
}
|
|
644
622
|
}
|
|
645
|
-
export async function cmdDev(args) {
|
|
646
|
-
const pkgRoot = getPackageRoot();
|
|
647
|
-
const isNpmInstall = pkgRoot.includes('node_modules');
|
|
648
|
-
const p = resolvePaths();
|
|
649
|
-
const devMarker = path.join(p.dataDir, 'dev-repo.path');
|
|
650
|
-
const sub = args[0];
|
|
651
|
-
if (!sub) {
|
|
652
|
-
if (!isNpmInstall) {
|
|
653
|
-
console.log(`当前: [dev] ${pkgRoot}`);
|
|
654
|
-
console.log('');
|
|
655
|
-
console.log('断开开发仓链接:');
|
|
656
|
-
console.log(' ec dev off');
|
|
657
|
-
}
|
|
658
|
-
else {
|
|
659
|
-
console.log(`当前: [pkg] ${pkgRoot}`);
|
|
660
|
-
console.log('');
|
|
661
|
-
let devPath = null;
|
|
662
|
-
try {
|
|
663
|
-
devPath = fs.readFileSync(devMarker, 'utf-8').trim();
|
|
664
|
-
}
|
|
665
|
-
catch { }
|
|
666
|
-
if (devPath && fs.existsSync(devPath)) {
|
|
667
|
-
console.log('链接到开发仓:');
|
|
668
|
-
console.log(` ec dev on`);
|
|
669
|
-
console.log(` (已记录路径: ${devPath})`);
|
|
670
|
-
}
|
|
671
|
-
else {
|
|
672
|
-
console.log('链接到开发仓:');
|
|
673
|
-
console.log(' ec dev <开发仓路径>');
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
return;
|
|
677
|
-
}
|
|
678
|
-
if (sub === 'off') {
|
|
679
|
-
if (isNpmInstall) {
|
|
680
|
-
console.log('当前已是 [pkg] 模式,无需断开');
|
|
681
|
-
return;
|
|
682
|
-
}
|
|
683
|
-
console.log('🔗 断开开发仓链接...');
|
|
684
|
-
let npmPrefix;
|
|
685
|
-
if (process.platform === 'win32' && process.env.APPDATA) {
|
|
686
|
-
npmPrefix = path.join(process.env.APPDATA, 'npm');
|
|
687
|
-
}
|
|
688
|
-
else {
|
|
689
|
-
npmPrefix = execFileSync('npm', ['prefix', '-g'], { encoding: 'utf-8', shell: true }).trim();
|
|
690
|
-
}
|
|
691
|
-
const linkPath = path.join(npmPrefix, 'node_modules', 'evolcore');
|
|
692
|
-
const binPath = path.join(npmPrefix, 'evolcore');
|
|
693
|
-
try {
|
|
694
|
-
fs.rmSync(linkPath, { recursive: true });
|
|
695
|
-
}
|
|
696
|
-
catch { }
|
|
697
|
-
try {
|
|
698
|
-
fs.unlinkSync(binPath);
|
|
699
|
-
}
|
|
700
|
-
catch { }
|
|
701
|
-
try {
|
|
702
|
-
fs.unlinkSync(binPath + '.cmd');
|
|
703
|
-
}
|
|
704
|
-
catch { }
|
|
705
|
-
try {
|
|
706
|
-
fs.unlinkSync(binPath + '.ps1');
|
|
707
|
-
}
|
|
708
|
-
catch { }
|
|
709
|
-
console.log('✓ 已断开');
|
|
710
|
-
console.log(` 已删除: ${linkPath}`);
|
|
711
|
-
console.log(` 如需恢复: ec dev on(需从已安装的 evolcore 执行)`);
|
|
712
|
-
return;
|
|
713
|
-
}
|
|
714
|
-
if (sub === 'on') {
|
|
715
|
-
if (!isNpmInstall) {
|
|
716
|
-
console.log(`当前已是 [dev] 模式: ${pkgRoot}`);
|
|
717
|
-
return;
|
|
718
|
-
}
|
|
719
|
-
let devPath = null;
|
|
720
|
-
try {
|
|
721
|
-
devPath = fs.readFileSync(devMarker, 'utf-8').trim();
|
|
722
|
-
}
|
|
723
|
-
catch { }
|
|
724
|
-
if (!devPath || !fs.existsSync(devPath)) {
|
|
725
|
-
console.log('未记录开发仓路径');
|
|
726
|
-
console.log('');
|
|
727
|
-
console.log('用法: ec dev <开发仓路径>');
|
|
728
|
-
process.exit(1);
|
|
729
|
-
}
|
|
730
|
-
console.log(`🔗 链接开发仓: ${devPath}`);
|
|
731
|
-
try {
|
|
732
|
-
execFileSync('npm', ['link'], { stdio: 'inherit', cwd: devPath, shell: true });
|
|
733
|
-
console.log(`✓ 已链接 [dev] ${devPath}`);
|
|
734
|
-
}
|
|
735
|
-
catch (e) {
|
|
736
|
-
console.error('❌ npm link 失败:', e.message);
|
|
737
|
-
process.exit(1);
|
|
738
|
-
}
|
|
739
|
-
return;
|
|
740
|
-
}
|
|
741
|
-
// ec dev <path> — 记录路径 + 建立链接
|
|
742
|
-
const devPath = path.resolve(sub);
|
|
743
|
-
const pkgJson = path.join(devPath, 'package.json');
|
|
744
|
-
if (!fs.existsSync(pkgJson)) {
|
|
745
|
-
console.error(`❌ 路径不存在或无 package.json: ${devPath}`);
|
|
746
|
-
process.exit(1);
|
|
747
|
-
}
|
|
748
|
-
let pkg;
|
|
749
|
-
try {
|
|
750
|
-
pkg = JSON.parse(fs.readFileSync(pkgJson, 'utf-8'));
|
|
751
|
-
}
|
|
752
|
-
catch {
|
|
753
|
-
console.error(`❌ 无法解析 package.json: ${pkgJson}`);
|
|
754
|
-
process.exit(1);
|
|
755
|
-
}
|
|
756
|
-
if (pkg.name !== 'evolcore') {
|
|
757
|
-
console.error(`❌ package.json name 不是 evolcore(是 "${pkg.name}")`);
|
|
758
|
-
process.exit(1);
|
|
759
|
-
}
|
|
760
|
-
// 已经链接到同一路径,只记录不重复 link
|
|
761
|
-
if (!isNpmInstall && path.resolve(pkgRoot) === devPath) {
|
|
762
|
-
fs.mkdirSync(p.dataDir, { recursive: true });
|
|
763
|
-
fs.writeFileSync(devMarker, devPath, 'utf-8');
|
|
764
|
-
console.log(`✓ 当前已链接到该路径,路径已记录`);
|
|
765
|
-
return;
|
|
766
|
-
}
|
|
767
|
-
console.log(`🔗 链接开发仓: ${devPath}`);
|
|
768
|
-
try {
|
|
769
|
-
execFileSync('npm', ['link'], { stdio: 'inherit', cwd: devPath, shell: true });
|
|
770
|
-
}
|
|
771
|
-
catch (e) {
|
|
772
|
-
console.error('❌ npm link 失败:', e.message);
|
|
773
|
-
process.exit(1);
|
|
774
|
-
}
|
|
775
|
-
fs.mkdirSync(p.dataDir, { recursive: true });
|
|
776
|
-
fs.writeFileSync(devMarker, devPath, 'utf-8');
|
|
777
|
-
console.log(`✓ 已链接 [dev] ${devPath}`);
|
|
778
|
-
console.log(` 路径已记录,下次可用 ec dev on 快速切换`);
|
|
779
|
-
}
|
|
780
623
|
function formatTimeAgo(ms) {
|
|
781
624
|
const sec = Math.floor(ms / 1000);
|
|
782
625
|
if (sec < 60)
|
|
@@ -885,6 +728,16 @@ function renderAunAidsTable(aids) {
|
|
|
885
728
|
note);
|
|
886
729
|
}
|
|
887
730
|
}
|
|
731
|
+
function readStatusDefaultsConfig(file) {
|
|
732
|
+
try {
|
|
733
|
+
return JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
734
|
+
}
|
|
735
|
+
catch (error) {
|
|
736
|
+
const detail = error?.code ? String(error.code) : error instanceof Error ? error.message : String(error);
|
|
737
|
+
console.log(`⚠ Channel configuration unavailable (${detail})`);
|
|
738
|
+
return null;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
888
741
|
function showConfigChannels(config) {
|
|
889
742
|
const groups = [];
|
|
890
743
|
const channelChecks = [
|
|
@@ -1061,48 +914,52 @@ export async function cmdStatus() {
|
|
|
1061
914
|
}
|
|
1062
915
|
catch { }
|
|
1063
916
|
}
|
|
1064
|
-
// Channel status
|
|
1065
|
-
|
|
917
|
+
// Channel status. A running daemon is authoritative and avoids reading
|
|
918
|
+
// protected config files from the CLI's potentially sandboxed process.
|
|
919
|
+
if (pid) {
|
|
1066
920
|
console.log('');
|
|
1067
|
-
const
|
|
1068
|
-
if (
|
|
1069
|
-
//
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
if (aidsResp?.ok && aidsResp.aids?.length > 0) {
|
|
1076
|
-
console.log('🔑 AUN AIDs:');
|
|
1077
|
-
renderAunAidsTable(aidsResp.aids);
|
|
1078
|
-
}
|
|
1079
|
-
}
|
|
1080
|
-
catch { /* ignore */ }
|
|
1081
|
-
// 控制 AID(daemon 进程身份)状态
|
|
1082
|
-
if (status.controlAid) {
|
|
1083
|
-
const state = status.controlAid.connected ? 'connected' : 'disconnected';
|
|
1084
|
-
console.log(`control: ${status.controlAid.aid} [${state}]`);
|
|
1085
|
-
}
|
|
1086
|
-
else {
|
|
1087
|
-
console.log('control: not configured');
|
|
1088
|
-
}
|
|
1089
|
-
if (status.stats) {
|
|
1090
|
-
console.log('');
|
|
1091
|
-
console.log('📊 Last hour:');
|
|
1092
|
-
console.log(` Messages: ${status.stats.received} received, ${status.stats.completed} completed`);
|
|
1093
|
-
if (status.stats.errors > 0)
|
|
1094
|
-
console.log(` Errors: ${status.stats.errors}`);
|
|
1095
|
-
if (status.stats.completed > 0)
|
|
1096
|
-
console.log(` Avg response: ${(status.stats.avgResponseMs / 1000).toFixed(1)}s`);
|
|
921
|
+
const status = await ipcQuery(p.socket, { type: 'status' });
|
|
922
|
+
if (status) {
|
|
923
|
+
// 🔑 AUN AIDs 表格(详细 AUN 实例状态)
|
|
924
|
+
try {
|
|
925
|
+
const aidsResp = await ipcQuery(p.socket, { type: 'aun-aids' });
|
|
926
|
+
if (aidsResp?.ok && aidsResp.aids?.length > 0) {
|
|
927
|
+
console.log('🔑 AUN AIDs:');
|
|
928
|
+
renderAunAidsTable(aidsResp.aids);
|
|
1097
929
|
}
|
|
1098
930
|
}
|
|
931
|
+
catch { /* ignore */ }
|
|
932
|
+
// 控制 AID(daemon 进程身份)状态
|
|
933
|
+
if (status.controlAid) {
|
|
934
|
+
const state = status.controlAid.connected ? 'connected' : 'disconnected';
|
|
935
|
+
console.log(`control: ${status.controlAid.aid} [${state}]`);
|
|
936
|
+
}
|
|
1099
937
|
else {
|
|
1100
|
-
|
|
938
|
+
console.log('control: not configured');
|
|
939
|
+
}
|
|
940
|
+
if (status.stats) {
|
|
941
|
+
console.log('');
|
|
942
|
+
console.log('📊 Last hour:');
|
|
943
|
+
console.log(` Messages: ${status.stats.received} received, ${status.stats.completed} completed`);
|
|
944
|
+
if (status.stats.errors > 0)
|
|
945
|
+
console.log(` Errors: ${status.stats.errors}`);
|
|
946
|
+
if (status.stats.completed > 0)
|
|
947
|
+
console.log(` Avg response: ${(status.stats.avgResponseMs / 1000).toFixed(1)}s`);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
else {
|
|
951
|
+
// IPC unreachable but PID exists — fall back to local config if readable.
|
|
952
|
+
const config = readStatusDefaultsConfig(p.defaultsConfig);
|
|
953
|
+
if (config) {
|
|
1101
954
|
console.log('🔌 Channels (IPC unreachable):');
|
|
1102
955
|
showConfigChannels(config);
|
|
1103
956
|
}
|
|
1104
957
|
}
|
|
1105
|
-
|
|
958
|
+
}
|
|
959
|
+
else if (fs.existsSync(p.defaultsConfig)) {
|
|
960
|
+
console.log('');
|
|
961
|
+
const config = readStatusDefaultsConfig(p.defaultsConfig);
|
|
962
|
+
if (config) {
|
|
1106
963
|
console.log('🔌 Channel Configuration:');
|
|
1107
964
|
showConfigChannels(config);
|
|
1108
965
|
}
|
|
@@ -2406,11 +2263,17 @@ async function probeEcwebReady(port) {
|
|
|
2406
2263
|
* 2. HTTP 是否就绪——探测根路径 /(serveStatic → index.html, 无副作用)。
|
|
2407
2264
|
*/
|
|
2408
2265
|
async function printEcwebStatus(p) {
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2266
|
+
try {
|
|
2267
|
+
const cfg = loadDaemonConfig();
|
|
2268
|
+
if (cfg.ecweb?.enabled === false) {
|
|
2269
|
+
console.log('');
|
|
2270
|
+
console.log('🔭 ECWeb: 已禁用 (daemon.json → ecweb.enabled: false)');
|
|
2271
|
+
return;
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
catch {
|
|
2275
|
+
// Agent tool sandboxes may mask daemon.json. Instance and HTTP probes below
|
|
2276
|
+
// still provide an authoritative runtime status without local config access.
|
|
2414
2277
|
}
|
|
2415
2278
|
const entries = readEcwebInstanceEntries(p);
|
|
2416
2279
|
let readyEntry;
|
|
@@ -3,7 +3,7 @@ import { resolvePaths } from '../paths.js';
|
|
|
3
3
|
import { ipcQuery } from '../ipc.js';
|
|
4
4
|
import { HANDOFF_QUERY_DEFAULT_LIMIT, HANDOFF_QUERY_MAX_LIMIT, HANDOFF_STATES } from '../core/handoff/types.js';
|
|
5
5
|
import { HANDOFF_ID_RE } from '../core/handoff/store.js';
|
|
6
|
-
import { isHelpFlag } from './help.js';
|
|
6
|
+
import { isHelpFlag, wantsHelp } from './help.js';
|
|
7
7
|
import { AGENT_DELEGATION_TOKEN_ENV } from '../core/auth/agent-delegation.js';
|
|
8
8
|
function parseLimit(value) {
|
|
9
9
|
const limit = Number(value);
|
|
@@ -152,7 +152,7 @@ function formatTimestamp(value) {
|
|
|
152
152
|
}
|
|
153
153
|
export async function cmdHandoff(args) {
|
|
154
154
|
const sub = args[0];
|
|
155
|
-
if (!sub || isHelpFlag(sub)) {
|
|
155
|
+
if (!sub || isHelpFlag(sub) || wantsHelp(args)) {
|
|
156
156
|
console.log(`用法: ec handoff <command> [args]
|
|
157
157
|
|
|
158
158
|
Commands:
|
package/dist/cli/help.js
CHANGED
|
@@ -3,22 +3,26 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 把 7 种历史写法统一为两个语义清晰的函数:
|
|
5
5
|
* - isHelpFlag(token):单 token 是否是 help 标记('help' / '--help' / '-h')
|
|
6
|
-
* - wantsHelp(args)
|
|
6
|
+
* - wantsHelp(args):首 token 为 help,或 `--` 分隔符前出现 --help/-h
|
|
7
7
|
*
|
|
8
8
|
* 两套 API 服务于不同语义:
|
|
9
9
|
* - 顶层路由(如 cmdAid 看到第一个 token 是子命令名时)必须用 isHelpFlag(sub),
|
|
10
10
|
* 否则 `ec aid delete --help` 会被顶层吞掉,永远到不了 delete 自己的 help。
|
|
11
|
-
* - 单层命令(如 cmdLinkRules、cmdAid 的具体 sub 处理块内)用 wantsHelp(args)
|
|
12
|
-
*
|
|
11
|
+
* - 单层命令(如 cmdLinkRules、cmdAid 的具体 sub 处理块内)用 wantsHelp(args),
|
|
12
|
+
* 支持 option 风格帮助,同时不把 `--` 后的正文误判为帮助。
|
|
13
13
|
*/
|
|
14
14
|
const HELP_TOKENS = new Set(['help', '--help', '-h']);
|
|
15
15
|
export function isHelpFlag(token) {
|
|
16
16
|
return token !== undefined && HELP_TOKENS.has(token);
|
|
17
17
|
}
|
|
18
18
|
export function wantsHelp(args) {
|
|
19
|
-
for (
|
|
20
|
-
|
|
19
|
+
for (let i = 0; i < args.length; i++) {
|
|
20
|
+
const arg = args[i];
|
|
21
|
+
if (arg === '--')
|
|
22
|
+
break;
|
|
23
|
+
if (arg === '--help' || arg === '-h' || (i === 0 && arg === 'help'))
|
|
21
24
|
return true;
|
|
25
|
+
}
|
|
22
26
|
return false;
|
|
23
27
|
}
|
|
24
28
|
/**
|