evolcore 0.0.38 → 0.0.40
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 +64 -0
- package/README.md +31 -20
- package/bin/ec-safe-output.js +14 -2
- package/dist/agents/baseagent-availability.js +1 -0
- package/dist/agents/claude-runner.js +32 -46
- package/dist/agents/codex-runner.js +54 -30
- package/dist/agents/ecagent-runner.js +18 -7
- package/dist/agents/gemini-runner.js +1 -2
- package/dist/agents/runner-types.js +28 -6
- package/dist/aun/aid/agentmd.js +21 -0
- package/dist/aun/aid/client.js +1 -1
- package/dist/aun/aid/control-aid.js +23 -98
- package/dist/aun/aid/ownership-operation.js +35 -12
- package/dist/aun/group/invite-service.js +6 -0
- package/dist/aun/msg/p2p.js +8 -12
- package/dist/channels/aun.js +66 -48
- package/dist/channels/dingtalk.js +8 -2
- package/dist/channels/feishu.js +6 -1
- package/dist/channels/wecom.js +7 -3
- package/dist/cli/agent-create.js +30 -6
- package/dist/cli/agent.js +30 -37
- package/dist/cli/aid-bind-command.js +16 -2
- package/dist/cli/aun-commands.js +31 -23
- package/dist/cli/config.js +15 -18
- package/dist/cli/contact.js +9 -12
- package/dist/cli/ctl-command.js +3 -3
- package/dist/cli/daemon-commands.js +242 -17
- package/dist/cli/diag.js +7 -3
- package/dist/cli/fs-command.js +5 -4
- package/dist/cli/handoff-command.js +11 -11
- package/dist/cli/help.js +18 -0
- package/dist/cli/index.js +25 -13
- package/dist/cli/init-channel.js +2 -1
- package/dist/cli/memory-command.js +47 -27
- package/dist/cli/model.js +5 -4
- package/dist/cli/queue-command.js +3 -3
- package/dist/cli/response.js +5 -4
- package/dist/cli/restart-monitor.js +35 -13
- package/dist/cli/skill-command.js +13 -13
- package/dist/cli/task-command.js +3 -3
- package/dist/cli/task-context.js +1 -0
- package/dist/cli/thread-command.js +5 -3
- package/dist/cli/trigger-command.js +3 -3
- package/dist/cli/version.js +6 -2
- package/dist/config/config-field-policy.js +1 -0
- package/dist/contracts/ecweb-service-protocol.js +44 -0
- package/dist/core/agent-runtime.js +6 -0
- package/dist/core/auth/agent-delegation.js +7 -4
- package/dist/core/auth/auth-gateway.js +3 -1
- package/dist/core/auth/authorization-audit.js +5 -1
- package/dist/core/auth/debug-context.js +5 -1
- package/dist/core/auth/operation-catalog.js +17 -1
- package/dist/core/bootstrap-service.js +20 -12
- package/dist/core/command/cli-intent-parser.js +5 -2
- package/dist/core/command/command-handler.js +20 -5
- package/dist/core/command/menu-catalog.js +48 -12
- package/dist/core/command/menu-handler.js +74 -6
- package/dist/core/command/menu-protocol.js +20 -1
- package/dist/core/command/slash-gate.js +17 -3
- package/dist/core/command/slash-handler.js +90 -7
- package/dist/core/event-catalog.js +2 -0
- package/dist/core/interaction-router.js +2 -1
- package/dist/core/ipc-registration.js +26 -7
- package/dist/core/memory/batch-meta.js +2 -0
- package/dist/core/memory/consolidation-context.js +42 -51
- package/dist/core/memory/consolidation-ops-records.js +39 -7
- package/dist/core/memory/consolidation-trigger.js +71 -64
- package/dist/core/memory/consolidation.js +226 -20
- package/dist/core/memory/memory-writer.js +160 -34
- package/dist/core/memory/relation-idle-monitor.js +287 -0
- package/dist/core/memory/relation-sweep.js +206 -0
- package/dist/core/message/aun-ipc-sender.js +5 -0
- package/dist/core/message/message-bridge.js +64 -55
- package/dist/core/message/message-log.js +17 -0
- package/dist/core/message/message-queue.js +6 -0
- package/dist/core/message/outbound.js +70 -0
- package/dist/core/message/peer-mode.js +7 -2
- package/dist/core/message/response-engine.js +341 -73
- package/dist/core/ownership/owner-resolver.js +465 -140
- package/dist/core/permission/ec-command-parser.js +19 -3
- package/dist/core/permission/protected-paths.js +51 -0
- package/dist/core/permission/tool-policy.js +7 -7
- package/dist/core/role/runtime-policy.js +64 -0
- package/dist/core/session/session-manager.js +25 -5
- package/dist/core/system-session/memory.js +3 -18
- package/dist/ecweb/basic-settings-service.js +709 -0
- package/dist/ecweb/providers-service.js +172 -0
- package/dist/index.js +92 -4
- package/dist/ipc.js +78 -11
- package/dist/stats/db.js +33 -0
- package/dist/stats/index.js +2 -2
- package/dist/stats/query.js +246 -0
- package/dist/stats/writer.js +41 -1
- package/dist/trigger/application-service.js +12 -0
- package/dist/trigger/authorization.js +2 -2
- package/dist/trigger/history.js +36 -0
- package/dist/trigger/scheduler.js +3 -0
- package/dist/utils/ecweb-supervisor.js +31 -10
- package/dist/utils/error-utils.js +8 -4
- package/dist/utils/evolcore-version.js +3 -2
- package/dist/utils/host-info.js +52 -0
- package/dist/utils/welcome.js +18 -24
- package/ecagent/dist/harness/agent-harness.js +4 -1
- package/kits/docs/evolcore/INDEX.md +1 -1
- package/kits/docs/evolcore/agent.md +1 -1
- package/kits/docs/evolcore/aid.md +58 -8
- package/kits/docs/evolcore/config.md +9 -7
- package/kits/docs/evolcore/memory-architecture.md +3 -4
- package/kits/docs/evolcore/memory-consolidation.md +28 -7
- package/kits/docs/evolcore/memory-tags.md +1 -1
- package/kits/docs/evolcore/memory.md +1 -1
- package/kits/docs/evolcore/menu-client.md +1 -1
- package/kits/docs/evolcore/menu-protocol.md +6 -0
- package/kits/docs/evolcore/msg.md +1 -1
- package/kits/eck_manifest.json +3 -3
- package/kits/rules/04-relation.md +3 -2
- package/kits/schemas/agent-config.schema.13.json +5 -1
- package/kits/templates/memory-consolidation/generalize.md +32 -4
- package/kits/templates/memory-consolidation/notes.md +2 -2
- package/kits/templates/memory-consolidation/promote.md +10 -2
- package/kits/templates/system-fragments/baseagent.md +5 -0
- package/kits/templates/system-fragments/memory.md +12 -3
- package/kits/templates/system-fragments/session.md +1 -1
- package/kits/{rules/07-memory-and-thread.md → templates/system-fragments/thread.md} +17 -80
- package/package.json +3 -3
package/dist/cli/aun-commands.js
CHANGED
|
@@ -4,7 +4,7 @@ import crypto from 'crypto';
|
|
|
4
4
|
import { agentMdPath, resolvePaths, resolveRoot } from '../paths.js';
|
|
5
5
|
import { isExplicitGroupId, normalizeGroupAid, sameGroupAid } from '../aun/group/index.js';
|
|
6
6
|
import { getArgValue, isHelpFlag, wantsHelp } from './help.js';
|
|
7
|
-
import {
|
|
7
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
8
8
|
import { isValidAid as validSendAid } from '../aun/aid/validation.js';
|
|
9
9
|
import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
10
10
|
import { isManagementRole } from '../config/builtin-roles.js';
|
|
@@ -137,14 +137,15 @@ async function runManagedAid(args, formatJson) {
|
|
|
137
137
|
if (requiresSelfAid && runtime?.selfAid && parsed.command.aid !== runtime.selfAid.replace(/^@/, '')) {
|
|
138
138
|
failManagedAid(formatJson, 'SCOPE_MISMATCH', `托管任务只能操作当前 self AID:${runtime.selfAid}`);
|
|
139
139
|
}
|
|
140
|
-
const response = await
|
|
140
|
+
const { response, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
141
141
|
type: 'aid.op',
|
|
142
142
|
argv: ['aid', ...args],
|
|
143
143
|
sessionId,
|
|
144
144
|
delegationToken,
|
|
145
145
|
}, 30_000);
|
|
146
|
-
if (!response)
|
|
147
|
-
failManagedAid(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
|
|
146
|
+
if (!response) {
|
|
147
|
+
failManagedAid(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
|
|
148
|
+
}
|
|
148
149
|
if (!response.ok || !response.result) {
|
|
149
150
|
const error = response.error || 'AID operation failed';
|
|
150
151
|
const aid = args[0] === 'agentmd' ? args[2] : args[1];
|
|
@@ -220,14 +221,15 @@ async function runManagedGroup(args, formatJson) {
|
|
|
220
221
|
failManagedGroup(formatJson, parsed.code, parsed.reason);
|
|
221
222
|
const runtime = await readBestTaskRuntimeContext();
|
|
222
223
|
validateManagedGroupScope(parsed.command.from, parsed.command.groupId, runtime, formatJson);
|
|
223
|
-
const response = await
|
|
224
|
+
const { response, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
224
225
|
type: 'group.op',
|
|
225
226
|
argv: ['group', ...args],
|
|
226
227
|
sessionId,
|
|
227
228
|
delegationToken,
|
|
228
229
|
}, 60_000);
|
|
229
|
-
if (!response)
|
|
230
|
-
failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
|
|
230
|
+
if (!response) {
|
|
231
|
+
failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
|
|
232
|
+
}
|
|
231
233
|
if (!response.ok || !response.result) {
|
|
232
234
|
failManagedGroup(formatJson, response.code || 'GROUP_OPERATION_FAILED', response.error || 'Group operation failed');
|
|
233
235
|
}
|
|
@@ -277,14 +279,15 @@ async function runManagedMsg(args, formatJson) {
|
|
|
277
279
|
failManagedGroup(formatJson, 'SCOPE_MISMATCH', `只能读取当前 AUN 私聊对端:${runtime.channelId}`);
|
|
278
280
|
}
|
|
279
281
|
}
|
|
280
|
-
const response = await
|
|
282
|
+
const { response, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
281
283
|
type: 'msg.op',
|
|
282
284
|
argv: ['msg', ...args],
|
|
283
285
|
sessionId,
|
|
284
286
|
delegationToken,
|
|
285
287
|
}, 30_000);
|
|
286
|
-
if (!response)
|
|
287
|
-
failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
|
|
288
|
+
if (!response) {
|
|
289
|
+
failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
|
|
290
|
+
}
|
|
288
291
|
if (!response.ok || !response.result) {
|
|
289
292
|
failManagedGroup(formatJson, response.code || 'MSG_OPERATION_FAILED', response.error || 'Msg operation failed');
|
|
290
293
|
}
|
|
@@ -469,6 +472,8 @@ Commands:
|
|
|
469
472
|
avatar <aid> --file <path> | --url <https-url> 上传头像并更新 agent.md
|
|
470
473
|
bind <ownerAid> [--subject <subjectAid>] 发起 Ownership 2.1 绑定
|
|
471
474
|
bind status [--subject <subjectAid>] 核验协议 Owner、任务和同步状态
|
|
475
|
+
bind accept <operationId> [--subject <subjectAid>] 接受绑定邀约
|
|
476
|
+
bind reject <operationId> [--reason <text>] [--subject <subjectAid>] 拒绝绑定邀约
|
|
472
477
|
|
|
473
478
|
Options:
|
|
474
479
|
--format json 输出 JSON 格式
|
|
@@ -1159,7 +1164,7 @@ Options:
|
|
|
1159
1164
|
console.error('用法: ec storage upload <aid> <local-file> <remote-path> [--public]');
|
|
1160
1165
|
process.exit(1);
|
|
1161
1166
|
}
|
|
1162
|
-
const result = await
|
|
1167
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
1163
1168
|
type: 'storage.upload',
|
|
1164
1169
|
argv: ['storage', ...args],
|
|
1165
1170
|
aid,
|
|
@@ -1169,8 +1174,9 @@ Options:
|
|
|
1169
1174
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
1170
1175
|
delegationToken,
|
|
1171
1176
|
}, null);
|
|
1172
|
-
if (!result)
|
|
1173
|
-
failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
|
|
1177
|
+
if (!result) {
|
|
1178
|
+
failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
|
|
1179
|
+
}
|
|
1174
1180
|
if (!result.ok)
|
|
1175
1181
|
failManagedGroup(formatJson, result.code || 'STORAGE_UPLOAD_FAILED', result.error || 'Storage upload failed');
|
|
1176
1182
|
if (formatJson)
|
|
@@ -1185,11 +1191,12 @@ Options:
|
|
|
1185
1191
|
}
|
|
1186
1192
|
return;
|
|
1187
1193
|
}
|
|
1188
|
-
const authorization = await
|
|
1194
|
+
const { response: authorization, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
1189
1195
|
type: 'storage.auth', argv: ['storage', ...args], operation, aid, sessionId: process.env.EVOLCORE_SESSION_ID, delegationToken,
|
|
1190
1196
|
}, 10_000);
|
|
1191
|
-
if (!authorization)
|
|
1192
|
-
failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
|
|
1197
|
+
if (!authorization) {
|
|
1198
|
+
failManagedGroup(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
|
|
1199
|
+
}
|
|
1193
1200
|
if (!authorization.ok)
|
|
1194
1201
|
failManagedGroup(formatJson, authorization.code || 'STORAGE_AUTH_FAILED', authorization.error || 'Storage operation denied');
|
|
1195
1202
|
if (sub === 'ls') {
|
|
@@ -1531,7 +1538,7 @@ async function applyCrossThreadSendEffects(input) {
|
|
|
1531
1538
|
originThreadName,
|
|
1532
1539
|
targetThreadName,
|
|
1533
1540
|
});
|
|
1534
|
-
const triggerRes = await
|
|
1541
|
+
const { response: triggerRes, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
1535
1542
|
type: 'trigger.create',
|
|
1536
1543
|
definition: triggerDef,
|
|
1537
1544
|
files: [],
|
|
@@ -1543,7 +1550,7 @@ async function applyCrossThreadSendEffects(input) {
|
|
|
1543
1550
|
delegationToken: readDelegationCredential(),
|
|
1544
1551
|
}, 30_000);
|
|
1545
1552
|
if (!triggerRes?.ok) {
|
|
1546
|
-
process.stderr.write(`⚠ Trigger 创建失败: ${triggerRes?.error ?? 'unknown'}(inbox 仍会写入)\n`);
|
|
1553
|
+
process.stderr.write(`⚠ Trigger 创建失败: ${triggerRes?.error ?? daemonUnavailableMessage(transportError, 'unknown')}(inbox 仍会写入)\n`);
|
|
1547
1554
|
}
|
|
1548
1555
|
else {
|
|
1549
1556
|
// 以 daemon 落盘的结果为准(definition 已带 id,正常应与预设值相同;
|
|
@@ -1691,13 +1698,13 @@ Options:
|
|
|
1691
1698
|
console.error(`request status is limited to the delegated self AID: ${runtime.selfAid}`);
|
|
1692
1699
|
process.exit(1);
|
|
1693
1700
|
}
|
|
1694
|
-
const result = await
|
|
1701
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
1695
1702
|
type: 'aun-msg-request-get', aid, requestId,
|
|
1696
1703
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
1697
1704
|
delegationToken: readDelegationCredential(),
|
|
1698
1705
|
}, 10_000);
|
|
1699
1706
|
if (!result) {
|
|
1700
|
-
console.error('unable to connect to the EvolCore daemon');
|
|
1707
|
+
console.error(daemonUnavailableMessage(transportError, 'unable to connect to the EvolCore daemon'));
|
|
1701
1708
|
process.exit(1);
|
|
1702
1709
|
}
|
|
1703
1710
|
if (formatJson)
|
|
@@ -3388,12 +3395,13 @@ async function runManagedSend(argv, formatJson) {
|
|
|
3388
3395
|
if (!delegationToken)
|
|
3389
3396
|
failManagedGroup(formatJson, 'DELEGATION_REQUIRED', 'Managed send requires delegation');
|
|
3390
3397
|
const runtime = await readBestTaskRuntimeContext();
|
|
3391
|
-
const result = await
|
|
3398
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
3392
3399
|
type: 'aun-msg-send', argv, delegationToken,
|
|
3393
3400
|
originSessionId: process.env.EVOLCORE_SESSION_ID, originMessageId: runtime?.messageId,
|
|
3394
3401
|
}, null);
|
|
3395
|
-
if (!result)
|
|
3396
|
-
failManagedGroup(formatJson, 'AUN_DAEMON_UNAVAILABLE', 'Unable to connect to the EvolCore daemon');
|
|
3402
|
+
if (!result) {
|
|
3403
|
+
failManagedGroup(formatJson, 'AUN_DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the EvolCore daemon'));
|
|
3404
|
+
}
|
|
3397
3405
|
if (!result.ok)
|
|
3398
3406
|
failManagedGroup(formatJson, result.code ?? 'AUN_SEND_FAILED', `${result.error ?? 'Send failed'}${result.request_id ? ` request_id=${result.request_id}` : ''}`, {
|
|
3399
3407
|
...(typeof result.detail_code === 'string' ? { detail_code: result.detail_code } : {}),
|
package/dist/cli/config.js
CHANGED
|
@@ -2,7 +2,7 @@ import { isHelpFlag, wantsHelp, getArgValue } from './help.js';
|
|
|
2
2
|
import { initConfigManager } from '../config/config-manager.js';
|
|
3
3
|
import { resolveConfigCommand } from '../config/resolved-config-op.js';
|
|
4
4
|
import { AUTHENTICATED_CONFIG_ROLE_ENV, executeResolvedConfigCommandAsync, } from '../config/config-operation-service.js';
|
|
5
|
-
import {
|
|
5
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
6
6
|
import { resolvePaths } from '../paths.js';
|
|
7
7
|
import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
8
8
|
import { splitConfigBatchGetArgv } from './cli-argv.js';
|
|
@@ -135,23 +135,19 @@ function managedSession(formatJson) {
|
|
|
135
135
|
return { sessionId, delegationToken };
|
|
136
136
|
}
|
|
137
137
|
async function managedConfigQuery(args, sessionId, delegationToken) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}, 10_000);
|
|
145
|
-
}
|
|
146
|
-
catch {
|
|
147
|
-
return null;
|
|
148
|
-
}
|
|
138
|
+
return queryDaemon(resolvePaths().socket, {
|
|
139
|
+
type: 'config.op',
|
|
140
|
+
argv: ['config', ...args],
|
|
141
|
+
sessionId,
|
|
142
|
+
delegationToken,
|
|
143
|
+
}, 10_000);
|
|
149
144
|
}
|
|
150
145
|
async function runManagedConfig(args, formatJson) {
|
|
151
146
|
const { sessionId, delegationToken } = managedSession(formatJson);
|
|
152
|
-
const response = await managedConfigQuery(args, sessionId, delegationToken);
|
|
153
|
-
if (!response)
|
|
154
|
-
fail(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
|
|
147
|
+
const { response, transportError } = await managedConfigQuery(args, sessionId, delegationToken);
|
|
148
|
+
if (!response) {
|
|
149
|
+
fail(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
|
|
150
|
+
}
|
|
155
151
|
if (!response.ok || !response.result) {
|
|
156
152
|
fail(formatJson, response.code || 'CONFIG_AUTH_FAILED', response.error || 'config operation failed', response.data);
|
|
157
153
|
}
|
|
@@ -197,9 +193,10 @@ async function runDirectBatchGet(fields, rest, formatJson) {
|
|
|
197
193
|
}
|
|
198
194
|
async function runManagedBatchGet(fields, rest, formatJson) {
|
|
199
195
|
const { sessionId, delegationToken } = managedSession(formatJson);
|
|
200
|
-
const response = await managedConfigQuery(['get', ...fields, ...rest], sessionId, delegationToken);
|
|
201
|
-
if (!response)
|
|
202
|
-
fail(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
|
|
196
|
+
const { response, transportError } = await managedConfigQuery(['get', ...fields, ...rest], sessionId, delegationToken);
|
|
197
|
+
if (!response) {
|
|
198
|
+
fail(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
|
|
199
|
+
}
|
|
203
200
|
if (!response.ok || !response.result) {
|
|
204
201
|
fail(formatJson, response.code || 'CONFIG_AUTH_FAILED', response.error || 'config operation failed', response.data);
|
|
205
202
|
}
|
package/dist/cli/contact.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolvePaths } from '../paths.js';
|
|
2
2
|
import { loadAllAgents } from '../config-store.js';
|
|
3
3
|
import { executeResolvedContactCommand, resolveContactCommand, } from '../config/contact-operation-service.js';
|
|
4
|
-
import {
|
|
4
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
5
5
|
import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
6
6
|
import { getArgValue, isHelpFlag, wantsHelp } from './help.js';
|
|
7
7
|
export async function cmdContact(args) {
|
|
@@ -48,18 +48,15 @@ async function runManaged(args, json) {
|
|
|
48
48
|
const delegationToken = readDelegationCredential();
|
|
49
49
|
if (!delegationToken)
|
|
50
50
|
fail(`${AGENT_DELEGATION_TOKEN_ENV} is not set for the active task`, 'DELEGATION_REQUIRED');
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
const { response, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
52
|
+
type: 'contact.op',
|
|
53
|
+
argv: ['contact', ...args],
|
|
54
|
+
sessionId,
|
|
55
|
+
delegationToken,
|
|
56
|
+
}, 10_000);
|
|
57
|
+
if (!response) {
|
|
58
|
+
fail(daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'), 'DAEMON_UNAVAILABLE');
|
|
59
59
|
}
|
|
60
|
-
catch { }
|
|
61
|
-
if (!response)
|
|
62
|
-
fail('Unable to connect to the evolcore daemon', 'DAEMON_UNAVAILABLE');
|
|
63
60
|
if (!response.ok || !response.result) {
|
|
64
61
|
fail(response.error || 'contact operation failed', response.code || 'CONTACT_AUTH_FAILED', response.data);
|
|
65
62
|
}
|
package/dist/cli/ctl-command.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolvePaths } from '../paths.js';
|
|
2
|
-
import {
|
|
2
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
3
3
|
import { isHelpFlag, wantsHelp } from './help.js';
|
|
4
4
|
import { readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
5
5
|
// ==================== Ctl ====================
|
|
@@ -44,14 +44,14 @@ export async function cmdCtl(args) {
|
|
|
44
44
|
process.exit(1);
|
|
45
45
|
}
|
|
46
46
|
const socketPath = resolvePaths().socket;
|
|
47
|
-
const result = await
|
|
47
|
+
const { response: result, transportError } = await queryDaemon(socketPath, {
|
|
48
48
|
type: 'ctl',
|
|
49
49
|
argv: ['ctl', ...args],
|
|
50
50
|
sessionId,
|
|
51
51
|
delegationToken: readDelegationCredential(),
|
|
52
52
|
}, 10_000);
|
|
53
53
|
if (!result) {
|
|
54
|
-
console.error('
|
|
54
|
+
console.error(`错误: ${daemonUnavailableMessage(transportError, '无法连接 evolcore 服务')}`);
|
|
55
55
|
process.exit(1);
|
|
56
56
|
}
|
|
57
57
|
const ctlResult = result;
|
|
@@ -31,6 +31,8 @@ import { rotateStdoutLog } from '../utils/log-writer.js';
|
|
|
31
31
|
import { inspectDataMigrationRequirement } from '../core/data-migration.js';
|
|
32
32
|
import { isInitCancelledError, printInitCancelHint } from './init-cancel.js';
|
|
33
33
|
import { computeBuildId } from '../utils/evolcore-version.js';
|
|
34
|
+
import { readHostInfo } from '../utils/host-info.js';
|
|
35
|
+
import { queryStatusActivity, queryStatusActivityByAgent } from '../stats/query.js';
|
|
34
36
|
import { listCodexAppServerProcesses, unregisterCodexAppServerProcess } from '../agents/codex/app-server-registry.js';
|
|
35
37
|
import { DEFAULT_ECWEB_PORT, ecwebService, setEcwebEnabled } from '../config/daemon-services.js';
|
|
36
38
|
import { checkCodexProjectPath, inspectCodexManagedHook, ensureCodexManagedHook, runCodexHookLaunchDiagnostic, } from '../agents/codex/diagnostics.js';
|
|
@@ -301,7 +303,20 @@ async function requireFreshSourceBuild() {
|
|
|
301
303
|
async function launchPackageLifecycle(source, log, options = {}) {
|
|
302
304
|
const correlated = options.requestId ?? process.env[RESTART_REQUEST_ID_ENV];
|
|
303
305
|
const upgradeJobId = correlated ? readRestartRequest(path.join(daemonControlDir(), 'restart-pending.json'), correlated)?.upgradeJobId : undefined;
|
|
304
|
-
|
|
306
|
+
let configuredAutoUpgrade = true;
|
|
307
|
+
if (!upgradeJobId && options.applyPackageUpgrades === undefined) {
|
|
308
|
+
try {
|
|
309
|
+
configuredAutoUpgrade = loadDaemonConfig().upgrade?.autoOnStart !== false;
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
configuredAutoUpgrade = false;
|
|
313
|
+
log('Could not read autoOnStart; skipping automatic package upgrade');
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const applyPackageUpgrades = upgradeJobId
|
|
317
|
+
? true
|
|
318
|
+
: options.applyPackageUpgrades ?? configuredAutoUpgrade;
|
|
319
|
+
if (!options.prepared && !upgradeJobId && applyPackageUpgrades)
|
|
305
320
|
await ensureFreshPackageVersionInfo(undefined, { source, log });
|
|
306
321
|
const root = resolvePaths().root;
|
|
307
322
|
const launch = platform.resolveMonitorLaunch(getPackageRoot(), path.join(root, 'data', 'monitor-stage'));
|
|
@@ -313,7 +328,12 @@ async function launchPackageLifecycle(source, log, options = {}) {
|
|
|
313
328
|
return { ok: false, reason: 'RESTART_ENTRY_MISSING' };
|
|
314
329
|
}
|
|
315
330
|
const requestId = options.requestId ?? process.env[RESTART_REQUEST_ID_ENV];
|
|
316
|
-
const args = [
|
|
331
|
+
const args = [
|
|
332
|
+
...launch.args,
|
|
333
|
+
'restart-monitor',
|
|
334
|
+
...(options.clear ? ['--clear'] : []),
|
|
335
|
+
applyPackageUpgrades ? '--apply-package-upgrades' : '--skip-package-upgrades',
|
|
336
|
+
];
|
|
317
337
|
const env = {
|
|
318
338
|
...options.env,
|
|
319
339
|
[RUNTIME_HOME_ENV]: root,
|
|
@@ -758,7 +778,7 @@ export async function cmdStart(opts = {}) {
|
|
|
758
778
|
// 这条路由 restart-monitor 拉起 daemon,同样靠覆盖文件把 --as-mode 带过去
|
|
759
779
|
const overrideFile = writeAsModeOverride(opts.asMode);
|
|
760
780
|
const launched = await launchPackageLifecycle('start', console.log, {
|
|
761
|
-
prepared: true, foreground: opts.foreground, env: buildDaemonEnv(p, opts),
|
|
781
|
+
prepared: true, foreground: opts.foreground, env: buildDaemonEnv(p, opts), applyPackageUpgrades: true,
|
|
762
782
|
});
|
|
763
783
|
if (!launched.ok) {
|
|
764
784
|
if (!launched.pending)
|
|
@@ -1291,7 +1311,180 @@ function showConfigChannels(config) {
|
|
|
1291
1311
|
console.log(' (no channels configured)');
|
|
1292
1312
|
}
|
|
1293
1313
|
}
|
|
1294
|
-
|
|
1314
|
+
function showLiveChannels(status) {
|
|
1315
|
+
const channels = status?.channels;
|
|
1316
|
+
if (!channels || typeof channels !== 'object' || Array.isArray(channels))
|
|
1317
|
+
return false;
|
|
1318
|
+
const entries = Object.entries(channels);
|
|
1319
|
+
console.log('🔌 Channels (live status):');
|
|
1320
|
+
if (entries.length === 0) {
|
|
1321
|
+
console.log(' (no channel instances loaded)');
|
|
1322
|
+
return true;
|
|
1323
|
+
}
|
|
1324
|
+
for (const [name, channel] of entries) {
|
|
1325
|
+
const state = channel?.connected === true ? '✓ Connected'
|
|
1326
|
+
: channel?.connected === false ? '✗ Disconnected' : '? Unknown';
|
|
1327
|
+
const type = typeof channel?.channelType === 'string' ? ` (${channel.channelType})` : '';
|
|
1328
|
+
console.log(` ${name}: ${state}${type}`);
|
|
1329
|
+
}
|
|
1330
|
+
return true;
|
|
1331
|
+
}
|
|
1332
|
+
function localDayStartMs(now = new Date()) {
|
|
1333
|
+
return new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
|
|
1334
|
+
}
|
|
1335
|
+
function statusActivityJson(window) {
|
|
1336
|
+
return {
|
|
1337
|
+
received: window.received,
|
|
1338
|
+
sent: window.sent,
|
|
1339
|
+
completed: window.completed,
|
|
1340
|
+
errors: window.errors,
|
|
1341
|
+
interrupts: window.interrupts,
|
|
1342
|
+
avgResponseMs: window.avgResponseMs,
|
|
1343
|
+
modelCalls: window.modelCalls,
|
|
1344
|
+
tokens: window.tokens,
|
|
1345
|
+
cost: window.cost,
|
|
1346
|
+
};
|
|
1347
|
+
}
|
|
1348
|
+
function readLocalPackageVersion() {
|
|
1349
|
+
try {
|
|
1350
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(getPackageRoot(), 'package.json'), 'utf8'));
|
|
1351
|
+
return typeof pkg.version === 'string' ? pkg.version : null;
|
|
1352
|
+
}
|
|
1353
|
+
catch {
|
|
1354
|
+
return null;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
async function cmdStatusJson() {
|
|
1358
|
+
const p = resolvePaths();
|
|
1359
|
+
const started = Date.now();
|
|
1360
|
+
const instanceStatus = scanInstances();
|
|
1361
|
+
const aliveMains = instanceStatus.mains.filter(instance => instance.alive);
|
|
1362
|
+
let ipcError;
|
|
1363
|
+
const pingPromise = probeDaemon(p.socket, DAEMON_PROBE_TIMEOUT_MS, true).catch(error => {
|
|
1364
|
+
ipcError = error;
|
|
1365
|
+
return null;
|
|
1366
|
+
});
|
|
1367
|
+
const [ping, statusResponse, aidsResponse, agentsResponse, agentStatsResponse] = await Promise.all([
|
|
1368
|
+
pingPromise,
|
|
1369
|
+
ipcQuery(p.socket, { type: 'status' }).catch(() => null),
|
|
1370
|
+
ipcQuery(p.socket, { type: 'aun-aids' }).catch(() => null),
|
|
1371
|
+
ipcQuery(p.socket, { type: 'evolagent.list' }).catch(() => null),
|
|
1372
|
+
ipcQuery(p.socket, { type: 'agent-stats' }).catch(() => null),
|
|
1373
|
+
]);
|
|
1374
|
+
const now = Date.now();
|
|
1375
|
+
const runningPid = ping?.pid ?? aliveMains[0]?.record.pid ?? null;
|
|
1376
|
+
const mainRecord = runningPid ? aliveMains.find(instance => instance.record.pid === runningPid)?.record : undefined;
|
|
1377
|
+
const statusAvailable = !!statusResponse;
|
|
1378
|
+
const overallStatus = statusAvailable
|
|
1379
|
+
? 'running'
|
|
1380
|
+
: platform.isWindows && ipcError instanceof IpcTransportError
|
|
1381
|
+
&& ['ENOENT', 'ECONNREFUSED'].includes(ipcError.code)
|
|
1382
|
+
? 'stopped'
|
|
1383
|
+
: 'unknown';
|
|
1384
|
+
const todayStart = localDayStartMs(new Date(now));
|
|
1385
|
+
const lastHourActivity = queryStatusActivity(p.root, now - 3_600_000, now);
|
|
1386
|
+
const todayActivity = statusResponse?.activity?.today ?? queryStatusActivity(p.root, todayStart, now);
|
|
1387
|
+
const daemonLastHourActivity = statusResponse?.activity?.lastHour;
|
|
1388
|
+
const effectiveLastHourActivity = daemonLastHourActivity ?? lastHourActivity;
|
|
1389
|
+
const agents = agentsResponse?.agents ?? [];
|
|
1390
|
+
const agentStats = new Map((agentStatsResponse?.stats ?? []).map((item) => [item.aid, item]));
|
|
1391
|
+
const statusAgents = Array.isArray(statusResponse?.agents) ? statusResponse.agents : null;
|
|
1392
|
+
const agentUsage = statusAgents
|
|
1393
|
+
? new Map()
|
|
1394
|
+
: queryStatusActivityByAgent(p.root, todayStart, now, agents.map((agent) => String(agent.aid ?? agent.name ?? '')));
|
|
1395
|
+
const diagnostics = [];
|
|
1396
|
+
if (!statusAvailable) {
|
|
1397
|
+
diagnostics.push({ code: 'DAEMON_IPC_UNAVAILABLE', message: ipcError instanceof Error ? ipcError.message : 'daemon status unavailable' });
|
|
1398
|
+
}
|
|
1399
|
+
const agentItems = statusAgents ?? agents.map((agent) => {
|
|
1400
|
+
const aid = String(agent.aid ?? agent.name ?? '');
|
|
1401
|
+
const runtime = agentStats.get(aid);
|
|
1402
|
+
const usage = agentUsage.get(aid) ?? queryStatusActivity(p.root, todayStart, now, aid);
|
|
1403
|
+
return {
|
|
1404
|
+
aid,
|
|
1405
|
+
name: agent.name ?? aid,
|
|
1406
|
+
status: agent.status ?? 'unknown',
|
|
1407
|
+
baseagent: agent.baseagent ?? null,
|
|
1408
|
+
model: agent.model ?? null,
|
|
1409
|
+
effort: agent.effort ?? null,
|
|
1410
|
+
queue: runtime ? { pending: runtime.queued ?? 0, processing: runtime.processing ?? 0 } : null,
|
|
1411
|
+
usage: {
|
|
1412
|
+
calls: usage.modelCalls,
|
|
1413
|
+
tokens: usage.tokens,
|
|
1414
|
+
cost: usage.cost,
|
|
1415
|
+
},
|
|
1416
|
+
};
|
|
1417
|
+
});
|
|
1418
|
+
const channels = Object.entries(statusResponse?.channels ?? {})
|
|
1419
|
+
.filter(([, channel]) => channel?.channelType !== 'aun')
|
|
1420
|
+
.map(([name, channel]) => ({
|
|
1421
|
+
name,
|
|
1422
|
+
type: channel?.channelType ?? name,
|
|
1423
|
+
status: channel?.status ?? (channel?.connected ? 'connected' : 'disconnected'),
|
|
1424
|
+
connected: channel?.connected ?? false,
|
|
1425
|
+
}));
|
|
1426
|
+
const aunItems = (aidsResponse?.aids ?? []).map((aid) => ({
|
|
1427
|
+
aid: aid.aid,
|
|
1428
|
+
channelName: aid.channelName,
|
|
1429
|
+
status: aid.status ?? 'unknown',
|
|
1430
|
+
connected: aid.status === 'connected',
|
|
1431
|
+
queue: aid.queueStatus ? {
|
|
1432
|
+
pending: aid.queueStatus.queued ?? 0,
|
|
1433
|
+
processing: aid.queueStatus.processing ?? 0,
|
|
1434
|
+
} : null,
|
|
1435
|
+
reconnectCount: aid.reconnectCount ?? 0,
|
|
1436
|
+
}));
|
|
1437
|
+
const host = statusResponse?.host ?? readHostInfo(readLocalPackageVersion());
|
|
1438
|
+
const ecwebEntry = readEcwebInstanceEntries(p)[0];
|
|
1439
|
+
const ecweb = ecwebEntry
|
|
1440
|
+
? { source: 'instance-record', status: platform.isProcessRunning(ecwebEntry.record.pid) ? 'running' : 'unknown', port: ecwebEntry.record.port, url: `http://localhost:${ecwebEntry.record.port}` }
|
|
1441
|
+
: { source: 'instance-record', status: 'stopped', port: null, url: null };
|
|
1442
|
+
const triggerSummary = statusResponse?.triggers
|
|
1443
|
+
? { source: 'runtime+history', ...statusResponse.triggers }
|
|
1444
|
+
: { source: 'unavailable', enabled: null, today: { calls: null, failures: null } };
|
|
1445
|
+
const build = statusResponse?.build
|
|
1446
|
+
? { runtimeMode: statusResponse.build.runtimeMode, version: statusResponse.build.version ?? null }
|
|
1447
|
+
: null;
|
|
1448
|
+
const output = {
|
|
1449
|
+
schemaVersion: 1,
|
|
1450
|
+
generatedAt: new Date(now).toISOString(),
|
|
1451
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
1452
|
+
overall: {
|
|
1453
|
+
status: overallStatus,
|
|
1454
|
+
degraded: !statusAvailable || statusResponse?.agentRuntime?.state === 'error',
|
|
1455
|
+
},
|
|
1456
|
+
host,
|
|
1457
|
+
daemon: {
|
|
1458
|
+
pid: runningPid,
|
|
1459
|
+
uptimeMs: ping?.uptime ?? statusResponse?.uptime ?? null,
|
|
1460
|
+
ipc: { reachable: statusAvailable, latencyMs: Date.now() - started },
|
|
1461
|
+
runMode: statusResponse?.runMode ?? mainRecord?.runMode ?? null,
|
|
1462
|
+
build,
|
|
1463
|
+
queue: statusResponse?.queue ?? { pending: null, processing: null },
|
|
1464
|
+
},
|
|
1465
|
+
baseagents: statusResponse?.baseagents ?? { source: 'unavailable', items: [] },
|
|
1466
|
+
activity: {
|
|
1467
|
+
lastHour: statusActivityJson(effectiveLastHourActivity),
|
|
1468
|
+
today: statusActivityJson(todayActivity),
|
|
1469
|
+
},
|
|
1470
|
+
agents: {
|
|
1471
|
+
source: statusAvailable ? 'daemon+stats-db' : 'stats-db',
|
|
1472
|
+
items: agentItems,
|
|
1473
|
+
},
|
|
1474
|
+
aun: { source: aidsResponse ? 'daemon' : 'unavailable', items: aunItems },
|
|
1475
|
+
channels: { source: statusAvailable ? 'daemon' : 'unavailable', items: channels },
|
|
1476
|
+
controlAid: statusResponse?.controlAid ?? null,
|
|
1477
|
+
triggers: triggerSummary,
|
|
1478
|
+
ecweb,
|
|
1479
|
+
diagnostics,
|
|
1480
|
+
};
|
|
1481
|
+
console.log(JSON.stringify(output, null, 2));
|
|
1482
|
+
}
|
|
1483
|
+
export async function cmdStatus(options = {}) {
|
|
1484
|
+
if (options.format === 'json') {
|
|
1485
|
+
await cmdStatusJson();
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
1295
1488
|
const p = resolvePaths();
|
|
1296
1489
|
const status = scanInstances();
|
|
1297
1490
|
const aliveMains = status.mains.filter(m => m.alive);
|
|
@@ -1300,13 +1493,19 @@ export async function cmdStatus() {
|
|
|
1300
1493
|
// query can otherwise wait behind the same IPC/event-loop delay and make the
|
|
1301
1494
|
// total `ec status` time the sum of several individual timeouts.
|
|
1302
1495
|
let ipcFailure;
|
|
1496
|
+
let agentsQueryFailure;
|
|
1303
1497
|
const pingPromise = probeDaemon(p.socket, DAEMON_PROBE_TIMEOUT_MS, true).catch(error => {
|
|
1304
1498
|
ipcFailure = error;
|
|
1305
1499
|
return null;
|
|
1306
1500
|
});
|
|
1307
1501
|
const statusPromise = ipcQuery(p.socket, { type: 'status' }).catch(() => null);
|
|
1308
1502
|
const aidsPromise = ipcQuery(p.socket, { type: 'aun-aids' }).catch(() => null);
|
|
1309
|
-
const agentsPromise =
|
|
1503
|
+
const agentsPromise = process.env.EVOLCORE_SESSION_ID
|
|
1504
|
+
? Promise.resolve({ ok: false, error: 'per-agent listing requires a local control token' })
|
|
1505
|
+
: ipcQuery(p.socket, { type: 'evolagent.list' }, 5_000).catch(error => {
|
|
1506
|
+
agentsQueryFailure = error;
|
|
1507
|
+
return null;
|
|
1508
|
+
});
|
|
1310
1509
|
// Only the ping is needed to decide whether to show the live-daemon
|
|
1311
1510
|
// sections. The remaining responses continue in parallel while local
|
|
1312
1511
|
// process/session information is rendered.
|
|
@@ -1484,6 +1683,7 @@ export async function cmdStatus() {
|
|
|
1484
1683
|
// Channel status. A running daemon is authoritative and avoids reading
|
|
1485
1684
|
// protected config files from the CLI's potentially sandboxed process.
|
|
1486
1685
|
let agentsResponse = null;
|
|
1686
|
+
let liveAgentRuntime = null;
|
|
1487
1687
|
if (pid) {
|
|
1488
1688
|
console.log('');
|
|
1489
1689
|
const [statusResponse, aidsResponse, agentResponse] = await Promise.all([
|
|
@@ -1492,6 +1692,7 @@ export async function cmdStatus() {
|
|
|
1492
1692
|
agentsPromise,
|
|
1493
1693
|
]);
|
|
1494
1694
|
agentsResponse = agentResponse;
|
|
1695
|
+
liveAgentRuntime = statusResponse?.agentRuntime ?? null;
|
|
1495
1696
|
if (statusResponse) {
|
|
1496
1697
|
if (statusResponse.build) {
|
|
1497
1698
|
if (statusResponse.build.runtimeMode === 'source') {
|
|
@@ -1511,6 +1712,16 @@ export async function cmdStatus() {
|
|
|
1511
1712
|
console.log(` Build ID: runtime=unavailable (daemon 未提供 build identity) dist=${computeBuildId(path.join(getPackageRoot(), 'dist')) ?? '?'}`);
|
|
1512
1713
|
console.log(' ⚠ 当前 daemon 未提供 build ID;请重启到包含 build identity 的版本后再判断源码行为。');
|
|
1513
1714
|
}
|
|
1715
|
+
if (!showLiveChannels(statusResponse)) {
|
|
1716
|
+
const config = readStatusDefaultsConfig(p.defaultsConfig);
|
|
1717
|
+
if (config) {
|
|
1718
|
+
console.log('🔌 Channels (live status unavailable; configuration is stale):');
|
|
1719
|
+
showConfigChannels(config);
|
|
1720
|
+
}
|
|
1721
|
+
else {
|
|
1722
|
+
console.log('🔌 Channels: live status unavailable');
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1514
1725
|
// 🔑 AUN AIDs 表格(详细 AUN 实例状态)
|
|
1515
1726
|
try {
|
|
1516
1727
|
if (aidsResponse?.ok && aidsResponse.aids?.length > 0) {
|
|
@@ -1558,17 +1769,17 @@ export async function cmdStatus() {
|
|
|
1558
1769
|
if (pid) {
|
|
1559
1770
|
try {
|
|
1560
1771
|
const agentResult = agentsResponse;
|
|
1561
|
-
if (agentResult?.ok && agentResult.agents
|
|
1772
|
+
if (agentResult?.ok && Array.isArray(agentResult.agents)) {
|
|
1562
1773
|
const agents = agentResult.agents;
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
}
|
|
1774
|
+
console.log('');
|
|
1775
|
+
console.log('🤖 EvolAgents (live status):');
|
|
1776
|
+
if (agents.length === 0)
|
|
1777
|
+
console.log(' (no agents loaded)');
|
|
1778
|
+
for (const a of agents) {
|
|
1779
|
+
const statusIcon = a.status === 'running' ? '●' : a.status === 'error' ? '✗' : a.status === 'disabled' ? '○' : '◌';
|
|
1780
|
+
const channels = summarizeChannelFingerprints(a.channels || []);
|
|
1781
|
+
const shortName = a.name.replace(/\.agentid\.pub$/, '');
|
|
1782
|
+
console.log(` ${statusIcon} ${shortName.padEnd(20)} ${a.status.padEnd(10)} ${channels}`);
|
|
1572
1783
|
}
|
|
1573
1784
|
}
|
|
1574
1785
|
else {
|
|
@@ -1578,7 +1789,18 @@ export async function cmdStatus() {
|
|
|
1578
1789
|
const agents = diskRegistry.list();
|
|
1579
1790
|
if (agents.length > 0) {
|
|
1580
1791
|
console.log('');
|
|
1581
|
-
|
|
1792
|
+
const detail = typeof agentResult?.error === 'string'
|
|
1793
|
+
? agentResult.error
|
|
1794
|
+
: agentsQueryFailure instanceof Error ? agentsQueryFailure.message : 'IPC request failed';
|
|
1795
|
+
const running = Number.isFinite(liveAgentRuntime?.runningAgents) ? liveAgentRuntime.runningAgents : null;
|
|
1796
|
+
const runnable = Number.isFinite(liveAgentRuntime?.runnableAgents) ? liveAgentRuntime.runnableAgents : null;
|
|
1797
|
+
if (running !== null && runnable !== null) {
|
|
1798
|
+
console.log(`🤖 EvolAgents (live aggregate: ${running} running / ${runnable} runnable):`);
|
|
1799
|
+
console.log(` Per-agent details unavailable (${detail}); following entries are stale configuration only:`);
|
|
1800
|
+
}
|
|
1801
|
+
else {
|
|
1802
|
+
console.log(`🤖 EvolAgents (live status unavailable: ${detail}; stale configuration):`);
|
|
1803
|
+
}
|
|
1582
1804
|
for (const a of agents) {
|
|
1583
1805
|
const diskStatus = a.status === 'disabled' || a.status === 'error' ? a.status : 'unknown';
|
|
1584
1806
|
const channels = summarizeChannelFingerprints(a.channels || []);
|
|
@@ -2965,7 +3187,7 @@ async function printEcwebStatus(p) {
|
|
|
2965
3187
|
console.log('');
|
|
2966
3188
|
if (aliveEntries.length > 0) {
|
|
2967
3189
|
const visibleEntry = aliveEntries[0];
|
|
2968
|
-
console.log(`🔭 ECWeb: 进程存活 (PID: ${visibleEntry.record.pid}) 但 HTTP 未就绪 (端口 ${visibleEntry.record.port}),查看 logs/
|
|
3190
|
+
console.log(`🔭 ECWeb: 进程存活 (PID: ${visibleEntry.record.pid}) 但 HTTP 未就绪 (端口 ${visibleEntry.record.port}),查看 logs/ecweb-daemon.log`);
|
|
2969
3191
|
}
|
|
2970
3192
|
else if (occupiedPids.size > 0) {
|
|
2971
3193
|
console.log(`🔭 ECWeb: 端口仍被未登记进程占用 (PID: ${[...occupiedPids].join(', ')}),请先执行 ec restart`);
|
|
@@ -2973,6 +3195,9 @@ async function printEcwebStatus(p) {
|
|
|
2973
3195
|
else if (entries.length > 0) {
|
|
2974
3196
|
console.log('🔭 ECWeb: instance 记录存在,但宿主 PID 不可见且 HTTP 未就绪');
|
|
2975
3197
|
}
|
|
3198
|
+
else if (externalUrl) {
|
|
3199
|
+
console.log('🔭 ECWeb: 已启用但未运行,查看 logs/ecweb-daemon.log');
|
|
3200
|
+
}
|
|
2976
3201
|
else {
|
|
2977
3202
|
console.log('🔭 ECWeb: 未运行');
|
|
2978
3203
|
}
|