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/diag.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
2
2
|
import { resolvePaths } from '../paths.js';
|
|
3
3
|
import { readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
4
4
|
import { parseDiagArgs } from '../core/command/diag-service.js';
|
|
@@ -13,13 +13,17 @@ export async function cmdDiag(args) {
|
|
|
13
13
|
let result;
|
|
14
14
|
try {
|
|
15
15
|
parseDiagArgs(args);
|
|
16
|
-
|
|
16
|
+
const { response, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
17
17
|
type: 'diag', argv,
|
|
18
18
|
...(process.env.EVOLCORE_SESSION_ID ? {
|
|
19
19
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
20
20
|
delegationToken: readDelegationCredential(),
|
|
21
21
|
} : {}),
|
|
22
|
-
}, 30_000)
|
|
22
|
+
}, 30_000);
|
|
23
|
+
result = response ?? {
|
|
24
|
+
ok: false, code: 'DAEMON_UNAVAILABLE',
|
|
25
|
+
message: daemonUnavailableMessage(transportError, 'daemon 未返回结果,请检查其运行状态;发送结果尚未确认'),
|
|
26
|
+
};
|
|
23
27
|
}
|
|
24
28
|
catch (error) {
|
|
25
29
|
result = { ok: false, code: 'INVALID_ARGUMENT', message: error.message };
|
package/dist/cli/fs-command.js
CHANGED
|
@@ -3,7 +3,7 @@ import path from 'path';
|
|
|
3
3
|
import { TextDecoder } from 'util';
|
|
4
4
|
import { getArgValue, isHelpFlag, wantsHelp } from './help.js';
|
|
5
5
|
import { agentmdGet, getAidStore, isValidAid, loadClient, SLOT } from '../aun/aid/index.js';
|
|
6
|
-
import {
|
|
6
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
7
7
|
import { resolvePaths } from '../paths.js';
|
|
8
8
|
import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
9
9
|
import { DEFAULT_FS_CAT_BYTES, MAX_FS_CAT_BYTES, FsReadBudgetError, downloadGroupFsBytes, readPersonalFsBytesWithinBudget, } from '../aun/group/fs-download.js';
|
|
@@ -222,14 +222,15 @@ async function runManagedFs(args, formatJson) {
|
|
|
222
222
|
fail('NO_SESSION', 'EVOLCORE_SESSION_ID is not set');
|
|
223
223
|
if (!delegationToken)
|
|
224
224
|
fail('DELEGATION_REQUIRED', `${AGENT_DELEGATION_TOKEN_ENV} is not set for the active task`);
|
|
225
|
-
const response = await
|
|
225
|
+
const { response, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
226
226
|
type: 'fs.op',
|
|
227
227
|
argv: ['fs', ...args],
|
|
228
228
|
sessionId,
|
|
229
229
|
delegationToken,
|
|
230
230
|
}, 30_000);
|
|
231
|
-
if (!response)
|
|
232
|
-
return fail('DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
|
|
231
|
+
if (!response) {
|
|
232
|
+
return fail('DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
|
|
233
|
+
}
|
|
233
234
|
if (!response.ok || !response.result)
|
|
234
235
|
fail(String(response.code || 'FS_OPERATION_FAILED'), response.error || 'Filesystem operation failed');
|
|
235
236
|
const result = response.result;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import { resolvePaths } from '../paths.js';
|
|
3
|
-
import {
|
|
3
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.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
6
|
import { isHelpFlag, wantsHelp } from './help.js';
|
|
@@ -191,7 +191,7 @@ Commands:
|
|
|
191
191
|
process.exitCode = 1;
|
|
192
192
|
return;
|
|
193
193
|
}
|
|
194
|
-
const result = await
|
|
194
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
195
195
|
type: 'handoff-return',
|
|
196
196
|
argv: ['handoff', ...args],
|
|
197
197
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
@@ -200,7 +200,7 @@ Commands:
|
|
|
200
200
|
delegationToken: readDelegationCredential(),
|
|
201
201
|
}, 5000);
|
|
202
202
|
if (!result) {
|
|
203
|
-
console.error('
|
|
203
|
+
console.error(`✗ ${daemonUnavailableMessage(transportError, 'daemon 暂时不可用')}`);
|
|
204
204
|
process.exitCode = 1;
|
|
205
205
|
return;
|
|
206
206
|
}
|
|
@@ -222,7 +222,7 @@ Commands:
|
|
|
222
222
|
process.exitCode = 1;
|
|
223
223
|
return;
|
|
224
224
|
}
|
|
225
|
-
const result = await
|
|
225
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
226
226
|
type: 'handoff-recover-return',
|
|
227
227
|
argv: ['handoff', ...args],
|
|
228
228
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
@@ -231,7 +231,7 @@ Commands:
|
|
|
231
231
|
delegationToken: readDelegationCredential(),
|
|
232
232
|
}, 5000);
|
|
233
233
|
if (!result) {
|
|
234
|
-
console.error('
|
|
234
|
+
console.error(`✗ ${daemonUnavailableMessage(transportError, 'daemon 暂时不可用')}`);
|
|
235
235
|
process.exitCode = 1;
|
|
236
236
|
return;
|
|
237
237
|
}
|
|
@@ -245,13 +245,13 @@ Commands:
|
|
|
245
245
|
process.exitCode = 1;
|
|
246
246
|
return;
|
|
247
247
|
}
|
|
248
|
-
const result = await
|
|
248
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
249
249
|
type: 'handoff-status', sessionId: process.env.EVOLCORE_SESSION_ID, handoffId,
|
|
250
250
|
argv: ['handoff', ...args],
|
|
251
251
|
delegationToken: readDelegationCredential(),
|
|
252
252
|
}, 5000);
|
|
253
253
|
if (!result) {
|
|
254
|
-
console.error('
|
|
254
|
+
console.error(`✗ ${daemonUnavailableMessage(transportError, 'daemon 暂时不可用')}`);
|
|
255
255
|
process.exitCode = 1;
|
|
256
256
|
return;
|
|
257
257
|
}
|
|
@@ -273,7 +273,7 @@ Commands:
|
|
|
273
273
|
process.exitCode = 1;
|
|
274
274
|
return;
|
|
275
275
|
}
|
|
276
|
-
const result = await
|
|
276
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
277
277
|
type: 'handoff-list',
|
|
278
278
|
argv: ['handoff', ...args],
|
|
279
279
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
@@ -284,7 +284,7 @@ Commands:
|
|
|
284
284
|
delegationToken: readDelegationCredential(),
|
|
285
285
|
}, 5000);
|
|
286
286
|
if (!result) {
|
|
287
|
-
console.error('
|
|
287
|
+
console.error(`✗ ${daemonUnavailableMessage(transportError, 'daemon 暂时不可用')}`);
|
|
288
288
|
process.exitCode = 1;
|
|
289
289
|
return;
|
|
290
290
|
}
|
|
@@ -318,7 +318,7 @@ Commands:
|
|
|
318
318
|
process.exitCode = 1;
|
|
319
319
|
return;
|
|
320
320
|
}
|
|
321
|
-
const result = await
|
|
321
|
+
const { response: result, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
322
322
|
type: 'handoff-trace',
|
|
323
323
|
argv: ['handoff', ...args],
|
|
324
324
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
@@ -328,7 +328,7 @@ Commands:
|
|
|
328
328
|
delegationToken: readDelegationCredential(),
|
|
329
329
|
}, 5000);
|
|
330
330
|
if (!result) {
|
|
331
|
-
console.error('
|
|
331
|
+
console.error(`✗ ${daemonUnavailableMessage(transportError, 'daemon 暂时不可用')}`);
|
|
332
332
|
process.exitCode = 1;
|
|
333
333
|
return;
|
|
334
334
|
}
|
package/dist/cli/help.js
CHANGED
|
@@ -11,7 +11,25 @@
|
|
|
11
11
|
* - 单层命令(如 cmdLinkRules、cmdAid 的具体 sub 处理块内)用 wantsHelp(args),
|
|
12
12
|
* 支持 option 风格帮助,同时不把 `--` 后的正文误判为帮助。
|
|
13
13
|
*/
|
|
14
|
+
import { IpcTransportError, ipcQuery } from '../ipc.js';
|
|
14
15
|
const HELP_TOKENS = new Set(['help', '--help', '-h']);
|
|
16
|
+
/** Query a daemon-backed command while preserving concrete transport failures. */
|
|
17
|
+
export async function queryDaemon(socketPath, command, timeoutMs = 3000) {
|
|
18
|
+
try {
|
|
19
|
+
return {
|
|
20
|
+
response: await ipcQuery(socketPath, command, timeoutMs, { throwOnError: true }),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
if (error instanceof IpcTransportError) {
|
|
25
|
+
return { response: null, transportError: error };
|
|
26
|
+
}
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function daemonUnavailableMessage(transportError, fallback) {
|
|
31
|
+
return transportError?.message ?? fallback;
|
|
32
|
+
}
|
|
15
33
|
export function isHelpFlag(token) {
|
|
16
34
|
return token !== undefined && HELP_TOKENS.has(token);
|
|
17
35
|
}
|
package/dist/cli/index.js
CHANGED
|
@@ -82,7 +82,7 @@ function printLifecycleHelp(command) {
|
|
|
82
82
|
start: `用法: ec start [--foreground] [--diagnose|-d] [--debug] [--as-mode dev|install]\n\n --foreground 前台运行,适合 systemd 或容器直接管理\n --diagnose, -d 以诊断模式启动 daemon\n --debug 调试模式:注册调试 IPC,可在宿主终端以任意 session 身份发命令\n --as-mode 覆盖运行模式判定(仅本次启动生效,不写配置):\n install = 按安装模式(校验随包文件完整性,篡改自动恢复)\n dev = 按开发模式(不校验随包文件)`,
|
|
83
83
|
stop: '用法: ec stop\n\n停止当前 EVOLCORE_HOME 下运行的 EvolCore 服务。',
|
|
84
84
|
restart: `用法: ec restart [--clear] [--diagnose|-d]\n\n --clear 同时清理跨 HOME 残留的 EvolCore 主进程\n --diagnose, -d 以诊断模式启动新 daemon`,
|
|
85
|
-
status: '用法: ec status\n\n查看 daemon、
|
|
85
|
+
status: '用法: ec status [--format json]\n\n查看 daemon、Agent、渠道与队列运行状态。JSON 模式输出结构化状态快照。',
|
|
86
86
|
logs: `用法: ec logs [选项]\n\n --level <error|warn|info|debug> 最低日志级别\n --module <name> 只显示指定模块\n --raw 原始输出\n --no-color 禁用颜色`,
|
|
87
87
|
watch: `用法: ec watch [logs|log|aid|msg|diag|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 diag 实时诊断消息生命周期(AUN→daemon→任务)\n ec watch web 安装/升级并启动 EC Web\n ec watch session ec watch web 的兼容别名`,
|
|
88
88
|
'restart-monitor': '用法: ec restart-monitor\n\n运行内 daemon 重启与升级监控器。',
|
|
@@ -266,21 +266,33 @@ export async function main(args) {
|
|
|
266
266
|
printLifecycleHelp('status');
|
|
267
267
|
break;
|
|
268
268
|
}
|
|
269
|
-
|
|
270
|
-
const
|
|
271
|
-
const
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
console.error(`❌ ${result?.error || 'status is not allowed in this task'}`);
|
|
269
|
+
{
|
|
270
|
+
const statusArgs = strippedArgs.slice(1);
|
|
271
|
+
const formatValue = getArgValue(statusArgs, '--format');
|
|
272
|
+
const validStatusArgs = statusArgs.length === 0
|
|
273
|
+
|| (statusArgs.length === 2 && statusArgs[0] === '--format' && formatValue === 'json');
|
|
274
|
+
if (!validStatusArgs) {
|
|
275
|
+
console.error('用法: ec status [--format json]');
|
|
277
276
|
process.exitCode = 1;
|
|
278
277
|
break;
|
|
279
278
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
279
|
+
const format = formatValue;
|
|
280
|
+
if (process.env.EVOLCORE_SESSION_ID) {
|
|
281
|
+
const sessionId = process.env.EVOLCORE_SESSION_ID;
|
|
282
|
+
const delegationToken = readDelegationCredential();
|
|
283
|
+
const result = await ipcQuery(resolvePaths().socket, {
|
|
284
|
+
type: 'status.auth', sessionId, delegationToken,
|
|
285
|
+
});
|
|
286
|
+
if (!result?.ok) {
|
|
287
|
+
console.error(`❌ ${result?.error || 'status is not allowed in this task'}`);
|
|
288
|
+
process.exitCode = 1;
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
await cmdStatus({ format });
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
await cmdStatus({ format });
|
|
295
|
+
}
|
|
284
296
|
}
|
|
285
297
|
break;
|
|
286
298
|
case 'logs':
|
package/dist/cli/init-channel.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import readline from 'readline';
|
|
9
9
|
import { cmdAidBind } from './aid-bind-command.js';
|
|
10
10
|
import { getOwners } from '../core/ownership/owner-resolver.js';
|
|
11
|
+
import { MAIN_CLI_BIN } from '../product.js';
|
|
11
12
|
import crypto from 'crypto';
|
|
12
13
|
import { selectInstance } from './init.js';
|
|
13
14
|
import { loadAllAgents, loadAgent, loadDaemonConfig } from '../config-store.js';
|
|
@@ -695,7 +696,7 @@ export async function cmdInitWechat() {
|
|
|
695
696
|
// ==================== AUN ====================
|
|
696
697
|
export async function cmdInitAun() {
|
|
697
698
|
console.log('AUN 协议 Owner 统一使用 ec aid bind <ownerAid> [--subject <subjectAid>]');
|
|
698
|
-
console.log(
|
|
699
|
+
console.log(`状态查询: ${MAIN_CLI_BIN} aid bind status [--subject <subjectAid>];邀约审批: ${MAIN_CLI_BIN} aid bind accept|reject <operationId>。`);
|
|
699
700
|
}
|
|
700
701
|
async function pickAunOwnerBindTarget(rl, daemonAid) {
|
|
701
702
|
const { agents } = loadAllAgents();
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import fs from 'node:fs';
|
|
15
15
|
import { resolvePaths } from '../paths.js';
|
|
16
|
-
import {
|
|
16
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
17
17
|
import { isHelpFlag, wantsHelp, getArgValue } from './help.js';
|
|
18
18
|
import { readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
19
19
|
import { canonicalizeEvolcoreCommandArgv } from '../core/permission/ec-command-parser.js';
|
|
@@ -43,11 +43,12 @@ ec memory note drop <slug>
|
|
|
43
43
|
ec memory note list
|
|
44
44
|
|
|
45
45
|
ec memory create --scope <relation|agent|owner> --slug <slug> --desc '<description>' \\
|
|
46
|
-
--tags '<tag1>,<tag2>' [--keywords '<kw1>,<kw2>'] [--replaces '<path1>,<path2>']
|
|
46
|
+
--tags '<tag1>,<tag2>' [--keywords '<kw1>,<kw2>'] [--replaces '<path1>,<path2>'] \\
|
|
47
|
+
[--peer <peerKey>] [--reason '<why>'] [--generalized-from <path>] [--promoted-from <path>] '<content>'
|
|
47
48
|
|
|
48
|
-
ec memory update <path> [--tags '<tag1>,<tag2>'] [--touch]
|
|
49
|
+
ec memory update <path> [--tags '<tag1>,<tag2>'] [--touch] [--reason '<why>']
|
|
49
50
|
|
|
50
|
-
ec memory archive <path...>
|
|
51
|
+
ec memory archive <path...> [--reason '<why>']
|
|
51
52
|
|
|
52
53
|
ec memory consolidate [--mode <notes|generalize|promote|profile|forget>]
|
|
53
54
|
|
|
@@ -168,8 +169,9 @@ export function resolveMemoryCommandArgv(argv) {
|
|
|
168
169
|
const kind = noteSub ? `note.${noteSub}` : argv[1];
|
|
169
170
|
const known = {
|
|
170
171
|
note: ['--slug', '--tags', '--speakers'], 'note.update': ['--slug', '--tags'],
|
|
171
|
-
'note.drop': [], 'note.list': [],
|
|
172
|
-
|
|
172
|
+
'note.drop': [], 'note.list': [],
|
|
173
|
+
create: ['--scope', '--slug', '--desc', '--tags', '--keywords', '--replaces', '--peer', '--reason', '--generalized-from', '--promoted-from'],
|
|
174
|
+
update: ['--tags', '--touch', '--reason'], archive: ['--reason'], demote: ['--scope'], consolidate: ['--mode'],
|
|
173
175
|
};
|
|
174
176
|
// feedback 已移除:旧会话/旧文档可能还在调用,给一句能照做的说明而不是泛化的非法命令。
|
|
175
177
|
if (kind === 'feedback') {
|
|
@@ -209,17 +211,19 @@ export function resolveMemoryCommandArgv(argv) {
|
|
|
209
211
|
throw new Error('--peer requires relation scope');
|
|
210
212
|
return { type, scope, slug: required(flags.get('--slug'), '--slug'), description: required(flags.get('--desc'), '--desc'),
|
|
211
213
|
content: required(content, 'content'), tags: parseTags(flags.get('--tags')), keywords: parseTags(flags.get('--keywords')),
|
|
212
|
-
replaces: parseTags(flags.get('--replaces')), targetPeerKey: flags.get('--peer')
|
|
214
|
+
replaces: parseTags(flags.get('--replaces')), targetPeerKey: flags.get('--peer'),
|
|
215
|
+
reason: flags.get('--reason'), generalizedFrom: flags.get('--generalized-from'), promotedFrom: flags.get('--promoted-from') };
|
|
213
216
|
}
|
|
214
217
|
if (kind === 'update') {
|
|
215
218
|
if (!flags.has('--tags') && !flags.has('--touch'))
|
|
216
219
|
throw new Error('No memory changes supplied');
|
|
217
|
-
return { type, filePath: required(positional[0], 'path'), tags: parseTags(flags.get('--tags')), touch: flags.has('--touch')
|
|
220
|
+
return { type, filePath: required(positional[0], 'path'), tags: parseTags(flags.get('--tags')), touch: flags.has('--touch'),
|
|
221
|
+
reason: flags.get('--reason') };
|
|
218
222
|
}
|
|
219
223
|
if (kind === 'archive') {
|
|
220
224
|
if (!positional.length)
|
|
221
225
|
throw new Error('Memory paths are required');
|
|
222
|
-
return { type, filePaths: positional };
|
|
226
|
+
return { type, filePaths: positional, reason: flags.get('--reason') };
|
|
223
227
|
}
|
|
224
228
|
if (kind === 'demote') {
|
|
225
229
|
const scope = flags.get('--scope') ?? 'agent';
|
|
@@ -240,9 +244,9 @@ const USAGE = {
|
|
|
240
244
|
note: "ec memory note --slug <slug> [--tags '<tag1>,<tag2>'] [--speakers '<aid1>,<aid2>'] '<正文>'",
|
|
241
245
|
noteUpdate: "ec memory note update <slug> [--slug <新slug>] [--tags '<tag1>,<tag2>'] ['<新正文>']",
|
|
242
246
|
noteDrop: 'ec memory note drop <slug>',
|
|
243
|
-
create: "ec memory create --scope <relation|agent|owner> --slug <slug> --desc '<描述>' --tags '<tag1>,<tag2>' [--keywords '<kw1>,<kw2>'] [--replaces '<路径1>,<路径2>'] [--peer <peerKey>] '<正文>'",
|
|
244
|
-
update: "ec memory update <路径> [--tags '<tag1>,<tag2>'] [--touch](至少给一项)",
|
|
245
|
-
archive:
|
|
247
|
+
create: "ec memory create --scope <relation|agent|owner> --slug <slug> --desc '<描述>' --tags '<tag1>,<tag2>' [--keywords '<kw1>,<kw2>'] [--replaces '<路径1>,<路径2>'] [--peer <peerKey>] [--reason '<为什么>'] [--generalized-from <路径>] [--promoted-from <路径>] '<正文>'",
|
|
248
|
+
update: "ec memory update <路径> [--tags '<tag1>,<tag2>'] [--touch] [--reason '<为什么>'](至少给一项)",
|
|
249
|
+
archive: "ec memory archive <路径...> [--reason '<为什么>']",
|
|
246
250
|
};
|
|
247
251
|
/**
|
|
248
252
|
* 统一失败出口。JSON 模式与 `ec fs` / `ec response` 一致:stdout 输出 `{ ok: false, code, error }`;
|
|
@@ -337,7 +341,7 @@ async function cmdMemoryNoteCreate(args, json) {
|
|
|
337
341
|
if (!content)
|
|
338
342
|
failWithUsage(json, '必须提供记忆内容(content)', USAGE.note);
|
|
339
343
|
const { socketPath, ...session } = requireManagedSession('ec memory note', flags, json);
|
|
340
|
-
const result = await
|
|
344
|
+
const result = await queryDaemon(socketPath, {
|
|
341
345
|
type: 'memory.note', argv: ['memory', 'note', ...args], ...session, slug, content, tags,
|
|
342
346
|
speakers: speakers && speakers.length > 0 ? speakers : undefined,
|
|
343
347
|
}, 15_000);
|
|
@@ -359,7 +363,7 @@ async function cmdMemoryNoteUpdate(args, json) {
|
|
|
359
363
|
failWithUsage(json, '至少提供一项要改的内容(--slug / --tags / 正文)', USAGE.noteUpdate);
|
|
360
364
|
}
|
|
361
365
|
const { socketPath, ...session } = requireManagedSession('ec memory note update', flags, json);
|
|
362
|
-
const result = await
|
|
366
|
+
const result = await queryDaemon(socketPath, {
|
|
363
367
|
type: 'memory.note.update', argv: ['memory', 'note', 'update', ...args], ...session, slug,
|
|
364
368
|
newSlug, tags, tagsProvided: tagsRaw !== undefined,
|
|
365
369
|
content: content || undefined,
|
|
@@ -375,7 +379,7 @@ async function cmdMemoryNoteDrop(args, json) {
|
|
|
375
379
|
if (!slug)
|
|
376
380
|
failWithUsage(json, '必须提供要撤销的 slug', USAGE.noteDrop);
|
|
377
381
|
const { socketPath, ...session } = requireManagedSession('ec memory note drop', flags, json);
|
|
378
|
-
const result = await
|
|
382
|
+
const result = await queryDaemon(socketPath, {
|
|
379
383
|
type: 'memory.note.drop', argv: ['memory', 'note', 'drop', ...args], ...session, slug,
|
|
380
384
|
}, 15_000);
|
|
381
385
|
reportResult(result, json, (r) => {
|
|
@@ -385,7 +389,7 @@ async function cmdMemoryNoteDrop(args, json) {
|
|
|
385
389
|
async function cmdMemoryNoteList(args, json) {
|
|
386
390
|
const { flags } = parseCliArgs(args, [], json);
|
|
387
391
|
const { socketPath, ...session } = requireManagedSession('ec memory note list', flags, json);
|
|
388
|
-
const result = await
|
|
392
|
+
const result = await queryDaemon(socketPath, {
|
|
389
393
|
type: 'memory.note.list', argv: ['memory', 'note', 'list', ...args], ...session,
|
|
390
394
|
}, 15_000);
|
|
391
395
|
reportResult(result, json, (r) => {
|
|
@@ -406,6 +410,7 @@ async function cmdMemoryNoteList(args, json) {
|
|
|
406
410
|
async function cmdMemoryCreate(args, json) {
|
|
407
411
|
const { flags, positional } = parseCliArgs(args, [
|
|
408
412
|
'--scope', '--slug', '--desc', '--tags', '--keywords', '--replaces', '--peer',
|
|
413
|
+
'--reason', '--generalized-from', '--promoted-from',
|
|
409
414
|
], json);
|
|
410
415
|
const content = positional.join(' ').trim();
|
|
411
416
|
const scope = flags.get('--scope');
|
|
@@ -415,6 +420,9 @@ async function cmdMemoryCreate(args, json) {
|
|
|
415
420
|
const keywordsRaw = flags.get('--keywords');
|
|
416
421
|
const replacesRaw = flags.get('--replaces');
|
|
417
422
|
const targetPeerKey = flags.get('--peer');
|
|
423
|
+
const reason = flags.get('--reason');
|
|
424
|
+
const generalizedFrom = flags.get('--generalized-from');
|
|
425
|
+
const promotedFrom = flags.get('--promoted-from');
|
|
418
426
|
if (!scope || !['agent', 'relation', 'owner'].includes(scope)) {
|
|
419
427
|
failWithUsage(json, '--scope 必须是 agent / relation / owner 之一', USAGE.create);
|
|
420
428
|
}
|
|
@@ -429,14 +437,23 @@ async function cmdMemoryCreate(args, json) {
|
|
|
429
437
|
if (targetPeerKey !== undefined && scope !== 'relation') {
|
|
430
438
|
failWithUsage(json, '--peer 只在 --scope relation 时有效', USAGE.create);
|
|
431
439
|
}
|
|
440
|
+
if (generalizedFrom !== undefined && scope !== 'agent') {
|
|
441
|
+
failWithUsage(json, '--generalized-from 只在 --scope agent 时有效', USAGE.create);
|
|
442
|
+
}
|
|
443
|
+
if (promotedFrom !== undefined && scope !== 'owner') {
|
|
444
|
+
failWithUsage(json, '--promoted-from 只在 --scope owner 时有效', USAGE.create);
|
|
445
|
+
}
|
|
432
446
|
const { socketPath, ...session } = requireManagedSession('ec memory create', flags, json);
|
|
433
|
-
const result = await
|
|
447
|
+
const result = await queryDaemon(socketPath, {
|
|
434
448
|
type: 'memory.create', argv: ['memory', 'create', ...args], ...session, scope, slug, description: desc,
|
|
435
449
|
content,
|
|
436
450
|
tags: parseTags(tagsRaw),
|
|
437
451
|
keywords: parseTags(keywordsRaw),
|
|
438
452
|
replaces: replacesRaw ? replacesRaw.split(',').map(s => s.trim()).filter(Boolean) : undefined,
|
|
439
453
|
targetPeerKey: targetPeerKey ?? undefined,
|
|
454
|
+
reason: reason ?? undefined,
|
|
455
|
+
generalizedFrom: generalizedFrom ?? undefined,
|
|
456
|
+
promotedFrom: promotedFrom ?? undefined,
|
|
440
457
|
}, 15_000);
|
|
441
458
|
reportResult(result, json, (r) => {
|
|
442
459
|
if (r.filePath)
|
|
@@ -447,30 +464,32 @@ async function cmdMemoryCreate(args, json) {
|
|
|
447
464
|
});
|
|
448
465
|
}
|
|
449
466
|
async function cmdMemoryConsolidatedUpdate(args, json) {
|
|
450
|
-
const { flags, positional } = parseCliArgs(args, ['--tags', '--touch'], json);
|
|
467
|
+
const { flags, positional } = parseCliArgs(args, ['--tags', '--touch', '--reason'], json);
|
|
451
468
|
const filePath = positional[0];
|
|
452
469
|
const tagsRaw = flags.get('--tags');
|
|
453
470
|
const touch = flags.has('--touch');
|
|
471
|
+
const reason = flags.get('--reason');
|
|
454
472
|
if (!filePath)
|
|
455
473
|
failWithUsage(json, '必须提供要修改的记忆文件路径', USAGE.update);
|
|
456
474
|
if (tagsRaw === undefined && !touch)
|
|
457
475
|
failWithUsage(json, '至少提供 --tags 或 --touch', USAGE.update);
|
|
458
476
|
const { socketPath, ...session } = requireManagedSession('ec memory update', flags, json);
|
|
459
|
-
const result = await
|
|
477
|
+
const result = await queryDaemon(socketPath, {
|
|
460
478
|
type: 'memory.update', argv: ['memory', 'update', ...args], ...session, filePath,
|
|
461
|
-
tags: parseTags(tagsRaw), touch,
|
|
479
|
+
tags: parseTags(tagsRaw), touch, reason: reason ?? undefined,
|
|
462
480
|
}, 15_000);
|
|
463
481
|
reportResult(result, json, () => {
|
|
464
482
|
console.log(`✓ 已更新: ${filePath}`);
|
|
465
483
|
});
|
|
466
484
|
}
|
|
467
485
|
async function cmdMemoryArchive(args, json) {
|
|
468
|
-
const { flags, positional } = parseCliArgs(args, [], json);
|
|
486
|
+
const { flags, positional } = parseCliArgs(args, ['--reason'], json);
|
|
469
487
|
if (positional.length === 0)
|
|
470
488
|
failWithUsage(json, '必须提供至少一个要归档的文件路径', USAGE.archive);
|
|
471
489
|
const { socketPath, ...session } = requireManagedSession('ec memory archive', flags, json);
|
|
472
|
-
const result = await
|
|
490
|
+
const result = await queryDaemon(socketPath, {
|
|
473
491
|
type: 'memory.archive', argv: ['memory', 'archive', ...args], ...session, filePaths: positional,
|
|
492
|
+
reason: flags.get('--reason') ?? undefined,
|
|
474
493
|
}, 15_000);
|
|
475
494
|
reportResult(result, json, (r) => {
|
|
476
495
|
const archived = r.archived ?? positional;
|
|
@@ -496,7 +515,7 @@ async function cmdMemoryDemote(args, json) {
|
|
|
496
515
|
fail(json, 'INVALID_ARGUMENT', '--scope 必须是 agent 或 owner', { text: '--scope 必须是 agent 或 owner' });
|
|
497
516
|
}
|
|
498
517
|
const { socketPath, ...session } = requireManagedSession('ec memory demote', flags, json);
|
|
499
|
-
const result = await
|
|
518
|
+
const result = await queryDaemon(socketPath, {
|
|
500
519
|
type: 'memory.demote', argv: ['memory', 'demote', ...args], ...session, slug, scope,
|
|
501
520
|
}, 15_000);
|
|
502
521
|
reportResult(result, json, (r) => {
|
|
@@ -528,7 +547,7 @@ async function cmdMemoryConsolidate(args, json) {
|
|
|
528
547
|
// JSON 模式下 stdout 只留结果对象
|
|
529
548
|
if (!json)
|
|
530
549
|
console.log(`正在触发记忆整理(mode=${mode})...`);
|
|
531
|
-
const result = await
|
|
550
|
+
const result = await queryDaemon(socketPath, {
|
|
532
551
|
type: 'memory.consolidate', argv: ['memory', 'consolidate', ...args], ...session, mode,
|
|
533
552
|
}, 30_000);
|
|
534
553
|
reportResult(result, json, (r) => {
|
|
@@ -551,10 +570,11 @@ async function cmdMemoryConsolidate(args, json) {
|
|
|
551
570
|
}
|
|
552
571
|
// ── 结果输出 ───────────────────────────────────────────────────────────────
|
|
553
572
|
function reportResult(result, json, ok) {
|
|
554
|
-
if (!result) {
|
|
555
|
-
|
|
573
|
+
if (!result.response) {
|
|
574
|
+
const message = daemonUnavailableMessage(result.transportError, '无法连接 evolcore 服务');
|
|
575
|
+
fail(json, 'DAEMON_UNAVAILABLE', message, { text: `错误: ${message}` });
|
|
556
576
|
}
|
|
557
|
-
const r = result;
|
|
577
|
+
const r = result.response;
|
|
558
578
|
if (!r.ok) {
|
|
559
579
|
const message = r.error || '操作失败';
|
|
560
580
|
fail(json, r.code || 'MEMORY_OPERATION_FAILED', message, { text: message });
|
package/dist/cli/model.js
CHANGED
|
@@ -16,7 +16,7 @@ import { resolveEffectiveFieldWithSource } from '../config/config-manager.js';
|
|
|
16
16
|
import { getCatalog, getModelInfo, catalogEfforts, resolveCatalogModel, assertCatalogSelectable } from '../core/model/model-catalog.js';
|
|
17
17
|
import { constrainResolvedModelForRole, filterModelsForRole, validateModelSelectionForRole, } from '../core/model/model-permission.js';
|
|
18
18
|
import { resolvePaths } from '../paths.js';
|
|
19
|
-
import {
|
|
19
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
20
20
|
import { parsePeerKey } from '../core/relation/peer-identity.js';
|
|
21
21
|
import { resolvePeerRoleDetail } from '../config/peer-role-resolver.js';
|
|
22
22
|
import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
@@ -50,11 +50,12 @@ async function runManagedCliOperation(args, formatJson, timeoutMs = 10_000) {
|
|
|
50
50
|
const delegationToken = readDelegationCredential();
|
|
51
51
|
if (!delegationToken)
|
|
52
52
|
fail(formatJson, 'DELEGATION_REQUIRED', `${AGENT_DELEGATION_TOKEN_ENV} 未设置`);
|
|
53
|
-
const response = await
|
|
53
|
+
const { response, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
54
54
|
type: 'ctl', argv: args, sessionId, delegationToken,
|
|
55
55
|
}, timeoutMs);
|
|
56
|
-
if (!response)
|
|
57
|
-
fail(formatJson, 'DAEMON_UNAVAILABLE', '无法连接 evolcore 服务');
|
|
56
|
+
if (!response) {
|
|
57
|
+
fail(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, '无法连接 evolcore 服务'));
|
|
58
|
+
}
|
|
58
59
|
if (!response.ok)
|
|
59
60
|
fail(formatJson, response.code || 'CTL_FAILED', response.error || '命令执行失败');
|
|
60
61
|
printCtlResult({ text: response.result || '', data: response.data }, formatJson);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolvePaths } from '../paths.js';
|
|
2
|
-
import {
|
|
2
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
3
3
|
import { readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
4
4
|
import { getArgValue, isHelpFlag, wantsHelp } from './help.js';
|
|
5
5
|
import { canonicalizeEvolcoreCommandArgv } from '../core/permission/ec-command-parser.js';
|
|
@@ -94,7 +94,7 @@ JSON 时间字段:
|
|
|
94
94
|
: undefined;
|
|
95
95
|
const socketPath = resolvePaths().socket;
|
|
96
96
|
const managed = process.env.EVOLCORE_SESSION_ID;
|
|
97
|
-
const result = await
|
|
97
|
+
const { response: result, transportError } = await queryDaemon(socketPath, managed ? {
|
|
98
98
|
type: 'queue.op',
|
|
99
99
|
argv: ['queue', ...args],
|
|
100
100
|
agent,
|
|
@@ -115,7 +115,7 @@ JSON 时间字段:
|
|
|
115
115
|
before,
|
|
116
116
|
});
|
|
117
117
|
if (!result) {
|
|
118
|
-
console.error('
|
|
118
|
+
console.error(`错误: ${daemonUnavailableMessage(transportError, '无法连接 evolcore 服务')}`);
|
|
119
119
|
process.exit(1);
|
|
120
120
|
}
|
|
121
121
|
const r = result;
|
package/dist/cli/response.js
CHANGED
|
@@ -15,7 +15,7 @@ import { readField, writeField, determineFieldScope, normalizePeer, ModelScopeEr
|
|
|
15
15
|
import { readFieldWithSource, resolveAgentConfig, ConfigTarget } from '../config/config-manager.js';
|
|
16
16
|
import { ResponseModeRegistry } from '../response-system/registry.js';
|
|
17
17
|
import { registerBuiltinModes } from '../response-system/modes/index.js';
|
|
18
|
-
import {
|
|
18
|
+
import { daemonUnavailableMessage, queryDaemon } from './help.js';
|
|
19
19
|
import { resolvePaths } from '../paths.js';
|
|
20
20
|
import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
21
21
|
const RESPONSE_MODE_FIELD = 'responseMode';
|
|
@@ -64,11 +64,12 @@ async function runManagedResponse(args, formatJson) {
|
|
|
64
64
|
fail(formatJson, 'NO_SESSION', 'EVOLCORE_SESSION_ID is not set');
|
|
65
65
|
if (!delegationToken)
|
|
66
66
|
fail(formatJson, 'DELEGATION_REQUIRED', `${AGENT_DELEGATION_TOKEN_ENV} is not set`);
|
|
67
|
-
const response = await
|
|
67
|
+
const { response, transportError } = await queryDaemon(resolvePaths().socket, {
|
|
68
68
|
type: 'ctl', argv: ['response', ...args], sessionId, delegationToken,
|
|
69
69
|
}, 10_000);
|
|
70
|
-
if (!response)
|
|
71
|
-
fail(formatJson, 'DAEMON_UNAVAILABLE', 'Unable to connect to the evolcore daemon');
|
|
70
|
+
if (!response) {
|
|
71
|
+
fail(formatJson, 'DAEMON_UNAVAILABLE', daemonUnavailableMessage(transportError, 'Unable to connect to the evolcore daemon'));
|
|
72
|
+
}
|
|
72
73
|
if (!response.ok)
|
|
73
74
|
fail(formatJson, response.code || 'CTL_FAILED', response.error || 'response operation failed');
|
|
74
75
|
emit(formatJson, response.data ?? { ok: true, result: response.result }, () => response.result || 'ok');
|
|
@@ -130,6 +130,18 @@ export async function cmdRestartMonitor() {
|
|
|
130
130
|
const hasCorrelatedRequest = requestId !== 'unknown';
|
|
131
131
|
const upgradeJobId = hasCorrelatedRequest ? readRestartRequest(pendingFile, requestId)?.upgradeJobId : undefined;
|
|
132
132
|
const upgradeJob = typeof upgradeJobId === 'string' ? readUpgradeJob(upgradeJobId) : null;
|
|
133
|
+
let configuredAutoUpgrade = true;
|
|
134
|
+
if (!upgradeJob && !process.argv.includes('--apply-package-upgrades') && !process.argv.includes('--skip-package-upgrades')) {
|
|
135
|
+
try {
|
|
136
|
+
configuredAutoUpgrade = loadDaemonConfig().upgrade?.autoOnStart !== false;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
configuredAutoUpgrade = false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const applyPackageUpgrades = !!upgradeJob
|
|
143
|
+
|| process.argv.includes('--apply-package-upgrades')
|
|
144
|
+
|| (!process.argv.includes('--skip-package-upgrades') && configuredAutoUpgrade);
|
|
133
145
|
if (upgradeJobId && (!upgradeJob || upgradeJob.restartRequestId !== requestId || upgradeJob.released || upgradeJob.deadline <= Date.now())) {
|
|
134
146
|
if (upgradeJob)
|
|
135
147
|
updateUpgradeJob(upgradeJob.jobId, { status: 'timeout', success: false, released: true, code: 'UPGRADE_TIMEOUT', reason: 'Update expired before restart preflight' }, '更新已超时,未执行重启');
|
|
@@ -371,16 +383,24 @@ export async function cmdRestartMonitor() {
|
|
|
371
383
|
const stoppedCodex = stopCodexAppServerOrphans();
|
|
372
384
|
if (stoppedCodex)
|
|
373
385
|
log(`Cleaned ${stoppedCodex} EvolCore codex app-server orphan(s)`);
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
386
|
+
let upgradeBackup = null;
|
|
387
|
+
let upgrade;
|
|
388
|
+
if (applyPackageUpgrades) {
|
|
389
|
+
// Apply only the preflight cache. There is no registry VERSION query after
|
|
390
|
+
// shutdown (npm still downloads the exact cached package when needed).
|
|
391
|
+
log('Applying cached version information...');
|
|
392
|
+
// 升级会原地替换整包,先留一个可回退的产物副本。备份放 EVOLCORE_HOME 而非包目录:
|
|
393
|
+
// Linux/macOS 的全局目录常常不可写,而 HOME 一定可写。
|
|
394
|
+
upgradeBackup = await backupDistForUpgrade(p, log);
|
|
395
|
+
[upgrade] = await applyCachedPackageUpgrades(undefined, {
|
|
396
|
+
log,
|
|
397
|
+
...(upgradeJob ? { target: upgradeJob.target, distTag: upgradeJob.distTag, npmConfig: upgradeJob.npmConfig } : {}),
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
log('Skipping cached package upgrade because upgrade.autoOnStart=false');
|
|
402
|
+
upgrade = { status: 'skipped', error: 'Automatic package upgrades disabled by autoOnStart' };
|
|
403
|
+
}
|
|
384
404
|
let upgradeRolledBack;
|
|
385
405
|
switch (upgrade.status) {
|
|
386
406
|
case 'upgraded':
|
|
@@ -405,9 +425,11 @@ export async function cmdRestartMonitor() {
|
|
|
405
425
|
log(`Already up to date (${upgrade.from})`);
|
|
406
426
|
break;
|
|
407
427
|
case 'skipped':
|
|
408
|
-
log(upgrade.error
|
|
409
|
-
? 'Skipped upgrade (
|
|
410
|
-
:
|
|
428
|
+
log(upgrade.error === 'Automatic package upgrades disabled by autoOnStart'
|
|
429
|
+
? 'Skipped package upgrade (autoOnStart=false)'
|
|
430
|
+
: upgrade.error
|
|
431
|
+
? 'Skipped upgrade (network unavailable)'
|
|
432
|
+
: 'Skipped upgrade check (dev mode)');
|
|
411
433
|
break;
|
|
412
434
|
case 'failed':
|
|
413
435
|
log(`⚠ Upgrade failed (${upgrade.from} → ${upgrade.to}): ${upgrade.error}`);
|