evolcore 0.0.27 → 0.0.29-test.0

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.
Files changed (195) hide show
  1. package/CHANGELOG.md +38 -15
  2. package/bin/ec-safe-output.js +270 -54
  3. package/dist/agents/baseagent-availability.js +37 -1
  4. package/dist/agents/baseagent.js +29 -14
  5. package/dist/agents/claude-runner.js +171 -13
  6. package/dist/agents/codex/app-server-client.js +13 -2
  7. package/dist/agents/codex/catalog.js +7 -1
  8. package/dist/agents/codex/diagnostics.js +4 -3
  9. package/dist/agents/codex-runner.js +444 -106
  10. package/dist/agents/gemini-runner.js +35 -17
  11. package/dist/aun/group/history.js +130 -90
  12. package/dist/aun/group/operations.js +1 -3
  13. package/dist/aun/menu/client.js +1 -0
  14. package/dist/aun/menu/transport.js +5 -3
  15. package/dist/aun/msg/managed-operation.js +70 -0
  16. package/dist/aun/msg/p2p.js +1 -3
  17. package/dist/aun/msg/upload.js +2 -2
  18. package/dist/aun/outbox.js +1 -37
  19. package/dist/channels/aun.js +262 -86
  20. package/dist/channels/daemon.js +18 -1
  21. package/dist/channels/feishu.js +1 -2
  22. package/dist/cli/agent-command.js +23 -3
  23. package/dist/cli/agent-create.js +68 -2
  24. package/dist/cli/agent.js +12 -2
  25. package/dist/cli/aun-commands.js +87 -13
  26. package/dist/cli/cli-argv.js +26 -0
  27. package/dist/cli/daemon-commands.js +116 -149
  28. package/dist/cli/data-command.js +4 -4
  29. package/dist/cli/diag.js +1 -1
  30. package/dist/cli/handoff-command.js +2 -0
  31. package/dist/cli/index.js +18 -1
  32. package/dist/cli/managed-command-guard.js +10 -0
  33. package/dist/cli/memory-command.js +441 -0
  34. package/dist/cli/menu-client.js +4 -0
  35. package/dist/cli/restart-monitor.js +127 -23
  36. package/dist/cli/skill-command.js +41 -0
  37. package/dist/cli/task-context.js +2 -23
  38. package/dist/cli/trigger-command.js +9 -1
  39. package/dist/cli/watch-msg-diag.js +209 -0
  40. package/dist/config/config-field-policy.js +52 -3
  41. package/dist/config/config-manager.js +17 -4
  42. package/dist/config/contact-book-store.js +2 -2
  43. package/dist/config/mention-mode.js +7 -2
  44. package/dist/config/merge.js +28 -9
  45. package/dist/config/resolved-config-op.js +1 -1
  46. package/dist/config/runtime-env.js +137 -0
  47. package/dist/config/schema-registry.js +11 -1
  48. package/dist/config-store.js +10 -10
  49. package/dist/core/audit/event-key.js +3 -1
  50. package/dist/core/audit/log-integrity.js +4 -0
  51. package/dist/core/auth/agent-delegation.js +2 -1
  52. package/dist/core/auth/auth-gateway.js +13 -6
  53. package/dist/core/auth/authorization-audit.js +54 -19
  54. package/dist/core/auth/operation-authorizer.js +17 -0
  55. package/dist/core/auth/operation-catalog.js +9 -0
  56. package/dist/core/causation/context.js +5 -1
  57. package/dist/core/command/agent-control.js +1 -2
  58. package/dist/core/command/command-handler.js +80 -24
  59. package/dist/core/command/diag-service.js +292 -27
  60. package/dist/core/command/memory-slash.js +270 -0
  61. package/dist/core/command/menu-catalog.js +1 -0
  62. package/dist/core/command/menu-handler.js +331 -79
  63. package/dist/core/command/menu-protocol.js +45 -4
  64. package/dist/core/command/slash-gate.js +10 -10
  65. package/dist/core/command/slash-handler.js +230 -79
  66. package/dist/core/data-migration.js +282 -505
  67. package/dist/core/event-catalog.js +26 -0
  68. package/dist/core/evolagent-registry.js +6 -0
  69. package/dist/core/evolagent.js +0 -10
  70. package/dist/core/handoff/store.js +1 -20
  71. package/dist/core/inference/text-inference.js +57 -1
  72. package/dist/core/memory/consolidation-context.js +505 -0
  73. package/dist/core/memory/consolidation-ops-records.js +124 -0
  74. package/dist/core/memory/consolidation-trigger.js +394 -0
  75. package/dist/core/memory/index-manager.js +308 -0
  76. package/dist/core/memory/launch-consolidation.js +395 -0
  77. package/dist/core/memory/memory-admin.js +234 -0
  78. package/dist/core/memory/memory-document.js +100 -0
  79. package/dist/core/memory/memory-session-policy.js +41 -0
  80. package/dist/core/memory/memory-signature.js +257 -0
  81. package/dist/core/memory/memory-writer.js +432 -0
  82. package/dist/core/memory/staleness.js +117 -0
  83. package/dist/core/message/auto-mention-gate.js +454 -0
  84. package/dist/core/message/im-renderer.js +90 -20
  85. package/dist/core/message/message-bridge.js +333 -23
  86. package/dist/core/message/message-log.js +1 -0
  87. package/dist/core/message/message-queue.js +114 -27
  88. package/dist/core/message/pending-hints.js +329 -161
  89. package/dist/core/message/response-engine.js +596 -90
  90. package/dist/core/permission/ec-command-parser.js +1044 -87
  91. package/dist/core/permission/protected-paths.js +376 -126
  92. package/dist/core/permission/sandbox-runtime.js +40 -12
  93. package/dist/core/permission/tool-error-code.js +96 -13
  94. package/dist/core/permission/tool-policy.js +277 -24
  95. package/dist/core/role/runtime-policy.js +3 -7
  96. package/dist/core/session/{runner-task-history.js → runner-event-summary.js} +1 -1
  97. package/dist/core/session/session-fs-store.js +0 -76
  98. package/dist/core/session/session-idle-monitor.js +355 -0
  99. package/dist/core/session/session-manager.js +482 -17
  100. package/dist/core/session/session-mapper.js +33 -16
  101. package/dist/core/session/session-renew.js +217 -155
  102. package/dist/core/session/{session-turns.js → session-transcript.js} +35 -6
  103. package/dist/core/skill/global-watcher.js +282 -0
  104. package/dist/core/skill/index-generator.js +84 -0
  105. package/dist/core/skill/startup.js +73 -0
  106. package/dist/core/skill/switch-resolver.js +115 -0
  107. package/dist/core/task/task-activity-store.js +219 -0
  108. package/dist/eck/kit-renderer.js +30 -3
  109. package/dist/eck/manifest-engine.js +26 -4
  110. package/dist/index.js +722 -171
  111. package/dist/ipc.js +564 -2
  112. package/dist/paths.js +30 -9
  113. package/dist/product.js +1 -0
  114. package/dist/response-system/engines/v1/proactive-flow.js +116 -15
  115. package/dist/response-system/modes/single-session/index.js +3 -0
  116. package/dist/trigger/feedback.js +1 -0
  117. package/dist/trigger/manager.js +0 -10
  118. package/dist/trigger/scheduler.js +11 -0
  119. package/dist/trigger/validation.js +22 -0
  120. package/dist/utils/atomic-write.js +98 -0
  121. package/dist/utils/avatar-upload.js +59 -18
  122. package/dist/utils/cross-platform.js +87 -16
  123. package/dist/utils/error-dict.json +6 -3
  124. package/dist/utils/error-utils.js +27 -0
  125. package/dist/utils/logger.js +32 -10
  126. package/dist/utils/media-cache.js +84 -0
  127. package/dist/utils/msg-diag.js +97 -0
  128. package/dist/utils/npm-ops.js +119 -4
  129. package/dist/utils/package-version-info.js +244 -0
  130. package/dist/utils/welcome.js +37 -8
  131. package/dist/utils/windows-shell-trust.js +37 -0
  132. package/kits/docs/AUTHORING.md +314 -0
  133. package/kits/docs/GUIDE.md +2 -0
  134. package/kits/docs/INDEX.md +2 -0
  135. package/kits/docs/aun/CHEATSHEET.md +4 -0
  136. package/kits/docs/aun/SDK.md +60 -0
  137. package/kits/docs/channels/aun.md +8 -0
  138. package/kits/docs/context-assembly.md +10 -6
  139. package/kits/docs/evolcore/INDEX.md +17 -3
  140. package/kits/docs/evolcore/agent-create.md +24 -0
  141. package/kits/docs/evolcore/agent.md +5 -2
  142. package/kits/docs/evolcore/config.md +1 -1
  143. package/kits/docs/evolcore/ec-capabilities.md +364 -0
  144. package/kits/docs/evolcore/group.md +34 -18
  145. package/kits/docs/evolcore/memory-architecture.md +78 -0
  146. package/kits/docs/evolcore/memory-consolidation-batches.md +133 -0
  147. package/kits/docs/evolcore/memory-consolidation.md +263 -0
  148. package/kits/docs/evolcore/memory-tags.md +63 -0
  149. package/kits/docs/evolcore/memory.md +110 -0
  150. package/kits/docs/evolcore/menu-client.md +27 -11
  151. package/kits/{schemas → docs/evolcore}/menu-exec-schema-commands.md +12 -6
  152. package/kits/docs/evolcore/menu-protocol.md +213 -0
  153. package/kits/docs/evolcore/msg.md +2 -0
  154. package/kits/docs/evolcore/trigger.md +7 -5
  155. package/kits/docs/path-registry.md +6 -8
  156. package/kits/docs/prompt-loading-architecture.md +5 -3
  157. package/kits/docs/venues/group.md +5 -4
  158. package/kits/eck_manifest.json +294 -88
  159. package/kits/eck_manifest.memory.json +257 -0
  160. package/kits/rules/03-identity.md +8 -8
  161. package/kits/rules/05-venue.md +4 -2
  162. package/kits/rules/06-channel.md +1 -1
  163. package/kits/schemas/_meta.json +276 -47
  164. package/kits/schemas/agent-config.schema.12.json +38 -2
  165. package/kits/schemas/agent-config.schema.13.json +591 -0
  166. package/kits/schemas/daemon.schema.6.json +9 -9
  167. package/kits/schemas/defaults.schema.5.json +29 -0
  168. package/kits/schemas/relation-config.schema.8.json +14 -1
  169. package/kits/schemas/relation-config.schema.9.json +129 -0
  170. package/kits/schemas/role-config.schema.1.json +3 -3
  171. package/kits/skills/.switches.json +3 -0
  172. package/kits/skills/ec-skill/SKILL.md +217 -0
  173. package/kits/skills/ec-skill/scripts/cli.mjs +128 -0
  174. package/kits/skills/ec-skill/scripts/deps.mjs +107 -0
  175. package/kits/skills/ec-skill/scripts/frontmatter.mjs +104 -0
  176. package/kits/skills/ec-skill/scripts/skill.mjs +629 -0
  177. package/kits/skills/ec-skill/scripts/template/SKILL.md.tmpl +30 -0
  178. package/kits/templates/decision/auto-mention.md +25 -0
  179. package/kits/templates/decision/session-renew.md +22 -0
  180. package/kits/templates/memory-consolidation/forget.md +104 -0
  181. package/kits/templates/memory-consolidation/generalize.md +76 -0
  182. package/kits/templates/memory-consolidation/notes.md +133 -0
  183. package/kits/templates/memory-consolidation/profile.md +58 -0
  184. package/kits/templates/memory-consolidation/promote.md +72 -0
  185. package/kits/templates/memory-consolidation/workflow.md +75 -0
  186. package/kits/templates/system-fragments/bootstrap.md +14 -5
  187. package/kits/templates/system-fragments/commands.md +1 -0
  188. package/kits/templates/system-fragments/group-history.md +6 -0
  189. package/kits/templates/system-fragments/identity.md +0 -3
  190. package/kits/templates/system-fragments/memory.md +79 -0
  191. package/kits/templates/system-fragments/reply.md +1 -0
  192. package/kits/templates/system-fragments/venue.md +1 -1
  193. package/package.json +4 -6
  194. package/dist/trigger/legacy-session-history.js +0 -19
  195. package/kits/templates/system-fragments/group-unread-history.md +0 -7
@@ -9,22 +9,23 @@ import { loadDefaults, loadAllAgents, loadDaemonConfig, saveDaemonConfig } from
9
9
  import { resolveEffective } from '../config/config-manager.js';
10
10
  import { resolveAnthropicConfig } from '../agents/baseagent.js';
11
11
  import { migrateProject } from '../config-store.js';
12
- import { ipcQuery } from '../ipc.js';
12
+ import { ipcQuery, IpcTransportError } from '../ipc.js';
13
13
  import { isHelpFlag } from './help.js';
14
14
  import { cmdInit, needsControlAidInit, initTail } from './init.js';
15
15
  import * as platform from '../utils/cross-platform.js';
16
16
  import { EventBus } from '../core/event-bus.js';
17
- import { tryUpgrade, tryUpgradeGlobalPkg, resolveGlobalPkg } from '../utils/npm-ops.js';
17
+ import { tryUpgradeGlobalPkg, resolveGlobalPkg } from '../utils/npm-ops.js';
18
+ import { ensureFreshPackageVersionInfo } from '../utils/package-version-info.js';
18
19
  import { ecwebVersionRequirementError, resolveEcwebLaunchCommand, fetchRemotePairingCode } from '../utils/ecweb-utils.js';
19
20
  import { isHostChinese } from '../utils/locale.js';
20
- import { scanInstances, cleanupInstances, findOrphanProcesses, killOrphans } from '../utils/instance-registry.js';
21
+ import { scanInstances, cleanupInstances, findOrphanProcesses } from '../utils/instance-registry.js';
21
22
  import { filterLogFiles, deriveLogTypes, computePreChecked, validateLogTypes, shortLogName as shortLogNameLocal, isWatchLogFile } from './watch-logs.js';
22
23
  import { displaySessionTitle } from '../core/session/session-title.js';
23
24
  import { isNonAgentSessionChannel } from '../core/system-channels.js';
24
25
  import { printCodeStats } from './code-stats.js';
25
26
  import { getProcessStartTime, startTimeMatches } from '../utils/process-introspect.js';
26
- import { readDelegationCredential } from '../core/auth/agent-delegation.js';
27
- import { WEB_CLI_BIN, WEB_PACKAGE_LATEST, WEB_PACKAGE_NAME } from '../product.js';
27
+ import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
28
+ import { RUNTIME_HOME_ENV, WEB_CLI_BIN, WEB_PACKAGE_LATEST, WEB_PACKAGE_NAME } from '../product.js';
28
29
  import { rotateStdoutLog } from '../utils/log-writer.js';
29
30
  import { inspectDataMigrationRequirement } from '../core/data-migration.js';
30
31
  import { isInitCancelledError, printInitCancelHint } from './init-cancel.js';
@@ -250,39 +251,54 @@ function runSourceBuild() {
250
251
  });
251
252
  });
252
253
  }
253
- /**
254
- * Spawn the restart monitor and confirm it actually reached its own code.
255
- *
256
- * The daemon is already stopped at this point, so a monitor that dies on
257
- * startup leaves nothing running and nobody watching — the exact silent
258
- * failure this mechanism exists to prevent.
259
- */
260
- async function spawnRestartMonitorAndConfirm(monitorEntry, reportLine) {
261
- const result = await platform.launchMonitorAndConfirm([...monitorEntry.args, 'restart-monitor'], { EVOLCORE_HOME: resolvePaths().root, ...(monitorEntry.env ?? {}) }, pid => scanInstances().restartMonitors.some(m => m.alive && m.record.pid === pid), pid => scanInstances().restartMonitors.some(m => m.alive && m.record.pid !== pid));
262
- if (result.ok)
263
- return { ok: true };
264
- for (const line of (result.stderrTail ?? '').split(/\r?\n/).filter(Boolean).slice(-8)) {
265
- reportLine(` | ${line}`);
266
- }
267
- return { ok: false, reason: result.reason ?? 'unknown' };
268
- }
269
254
  async function requireFreshSourceBuild() {
270
255
  if (!sourceBuildNeedsRefresh())
271
256
  return true;
272
257
  return await runSourceBuild();
273
258
  }
274
- function requireCompletedDataMigration(root, action = 'start') {
259
+ async function launchPackageLifecycle(source, log, options = {}) {
260
+ if (!options.prepared)
261
+ await ensureFreshPackageVersionInfo(undefined, { source, log });
262
+ const root = resolvePaths().root;
263
+ const launch = platform.resolveMonitorLaunch(getPackageRoot(), path.join(root, 'data', 'monitor-stage'));
264
+ if (launch.note)
265
+ log(launch.note);
266
+ if (!fs.existsSync(launch.entry)) {
267
+ if (launch.stageDir)
268
+ platform.cleanupMonitorStage(launch.stageDir);
269
+ return { ok: false, reason: 'RESTART_ENTRY_MISSING' };
270
+ }
271
+ const args = [...launch.args, 'restart-monitor', ...(options.clear ? ['--clear'] : [])];
272
+ const env = { ...options.env, [RUNTIME_HOME_ENV]: root, ...launch.env, [AGENT_DELEGATION_TOKEN_ENV]: '' };
273
+ if (options.foreground) {
274
+ return new Promise(resolve => {
275
+ const child = spawn(process.execPath, [...args, '--foreground'], {
276
+ stdio: 'inherit', detached: false, windowsHide: true, env: { ...process.env, ...env },
277
+ });
278
+ child.once('error', () => {
279
+ if (launch.stageDir)
280
+ platform.cleanupMonitorStage(launch.stageDir);
281
+ resolve({ ok: false, reason: 'Foreground monitor could not start' });
282
+ });
283
+ child.once('exit', code => {
284
+ process.exitCode = code ?? 1;
285
+ resolve({ ok: code === 0, ...(code !== 0 ? { reason: 'Foreground lifecycle exited unsuccessfully' } : {}) });
286
+ });
287
+ });
288
+ }
289
+ const result = await platform.launchMonitorAndConfirm(args, env, pid => scanInstances().restartMonitors.some(item => item.alive && item.record.pid === pid), pid => scanInstances().restartMonitors.some(item => item.alive && item.record.pid !== pid));
290
+ if (!result.ok && launch.stageDir)
291
+ platform.cleanupMonitorStage(launch.stageDir);
292
+ return { ok: result.ok, ...(!result.ok ? { reason: result.reason } : {}) };
293
+ }
294
+ function requireCompletedDataMigration(root) {
275
295
  const requirement = inspectDataMigrationRequirement(root);
276
296
  if (!requirement.required)
277
297
  return true;
278
- console.error(action === 'restart'
279
- ? `❌ 检测到 ${requirement.operationCount} 项待确认的用户数据迁移,本次不停止当前服务。`
280
- : `❌ 检测到 ${requirement.operationCount} 项待确认的用户数据迁移,服务未启动。`);
298
+ console.error(`❌ 检测到 ${requirement.operationCount} 项待确认的用户数据迁移,服务未启动。`);
281
299
  console.error(' 先执行: ec data migrate --dry-run');
282
300
  console.error(' 确认后: ec data migrate --apply');
283
- console.error(' 迁移成功并校验后,再执行 ec start 或 ec restart。');
284
- if (action === 'restart')
285
- console.error(' 本次 ec restart 仅完成只读检查,未停止当前服务。');
301
+ console.error(' 迁移成功并校验后,再执行 ec start。');
286
302
  process.exitCode = 2;
287
303
  return false;
288
304
  }
@@ -291,7 +307,11 @@ function requireCompletedDataMigration(root, action = 'start') {
291
307
  * A failed upgrade is reported, but the currently installed version remains
292
308
  * usable and the caller continues with its normal lifecycle.
293
309
  */
294
- export async function runUpgradeChecks(upgradeFn = signal => tryUpgrade({ signal }), ecwebUpgradeFn = signal => tryUpgradeGlobalPkg(() => resolveGlobalPkg(WEB_PACKAGE_NAME), WEB_PACKAGE_NAME, { signal }), timeoutMs = 60_000) {
310
+ export async function runUpgradeChecks(upgradeFn, ecwebUpgradeFn, timeoutMs = 60_000) {
311
+ if (!upgradeFn || !ecwebUpgradeFn) {
312
+ await ensureFreshPackageVersionInfo(undefined, { source: 'start', log: console.log });
313
+ return;
314
+ }
295
315
  console.log('📦 Checking for updates...');
296
316
  const runWithTimeout = async (label, fn) => {
297
317
  const controller = new AbortController();
@@ -470,7 +490,9 @@ export async function cmdStart(opts = {}) {
470
490
  return;
471
491
  // A stopped container may miss the daily upgrade trigger. Check once on
472
492
  // every real start so the service does not stay on an old installation.
473
- await (opts.upgradeChecks ?? runUpgradeChecks)();
493
+ const versionInfo = await ensureFreshPackageVersionInfo(undefined, { source: 'start', log: console.log });
494
+ if (opts.upgradeChecks)
495
+ await opts.upgradeChecks();
474
496
  // 旧配置自动迁移(daemon.json → 新结构)
475
497
  const { autoMigrateIfNeeded } = await import('../config-store.js');
476
498
  autoMigrateIfNeeded();
@@ -595,6 +617,20 @@ export async function cmdStart(opts = {}) {
595
617
  return;
596
618
  }
597
619
  reportOrphans(orphans);
620
+ if (versionInfo.some(result => result.hasUpdate)) {
621
+ cleanEnv();
622
+ const launched = await launchPackageLifecycle('start', console.log, {
623
+ prepared: true, foreground: opts.foreground, env: buildDaemonEnv(p, opts),
624
+ });
625
+ if (!launched.ok) {
626
+ console.error(`❌ 启动事务未能建立:${launched.reason}`);
627
+ process.exitCode = 1;
628
+ }
629
+ else if (!opts.foreground) {
630
+ console.log('📦 已交由 restart-monitor 应用缓存版本并启动服务');
631
+ }
632
+ return;
633
+ }
598
634
  console.log('🚀 Starting EvolCore...');
599
635
  const stdoutRotation = rotateStdoutLog(p.logs);
600
636
  if (stdoutRotation.rotatedPath) {
@@ -883,126 +919,17 @@ export async function cmdRestart(opts = {}) {
883
919
  if (initialRuntimeOrphans.length === 0 && rejectPidIsolatedLifecycle('restart', initialStatus, ping))
884
920
  return;
885
921
  }
886
- // 构建交给 restart-monitor:它在 daemon 停止之后才编译,dist/ 不会被活进程
887
- // 占用,失败还能回滚到上一份产物。这里再编译一次会落在事务保护之外。
888
- // restart-monitor owns upgrade checks. Running them here as well caused a
889
- // normal restart to perform every registry lookup twice, and in installed
890
- // mode could race the monitor while it was preparing its rollback point.
891
- if (!requireCompletedDataMigration(resolveRoot(), 'restart'))
892
- return;
893
- // 停止所有活 main 进程(可能不止一个)
894
- const status = initialStatus;
895
- const aliveMains = status.mains.filter(m => m.alive);
896
- if (aliveMains.length > 0) {
897
- if (aliveMains.length > 1) {
898
- console.log(`⚠ 检测到 ${aliveMains.length} 个 main 实例,将一并停止: ${aliveMains.map(m => m.record.pid).join(', ')}`);
899
- }
900
- const mainPids = new Set(aliveMains.map(entry => entry.record.pid));
901
- const currentPing = await probeDaemon(socketPath);
902
- const gracefulPid = currentPing && mainPids.has(currentPing.pid)
903
- ? await requestDaemonShutdown(socketPath, DAEMON_SHUTDOWN_TIMEOUT_MS, 'ec restart', mainPids)
904
- : null;
905
- const stopped = await Promise.all(aliveMains.map(m => stopPid(m.record.pid, m.record.pid === gracefulPid, m.record.startedAt)));
906
- if (stopped.some(result => !result)) {
907
- console.error('❌ Restart aborted because an existing EvolCore process could not be stopped');
908
- process.exitCode = 1;
909
- return;
910
- }
911
- await sleep(500);
912
- }
913
- cleanupInstances();
914
- const remainingMainProcesses = scanInstances().mains.filter(entry => entry.alive);
915
- if (remainingMainProcesses.length > 0) {
916
- console.error(`❌ Restart aborted: EvolCore process still registered and alive (PID: ${remainingMainProcesses.map(entry => entry.record.pid).join(', ')})`);
922
+ // The shared launchPackageLifecycle path delegates to launchMonitorAndConfirm;
923
+ // the monitor retains shutdown, orphan checks, build and rollback ownership.
924
+ // restart-monitor performs the read-only preflight before stopping the
925
+ // current daemon, then applies the migration during the stopped window.
926
+ const launched = await launchPackageLifecycle('restart', console.log, { clear: opts.clear });
927
+ if (!launched.ok) {
928
+ console.error(`❌ 重启中止:restart-monitor 未能启动(${launched.reason});当前服务未主动停止`);
917
929
  process.exitCode = 1;
918
930
  return;
919
931
  }
920
- // 孤儿处理:同 HOME/同安装包的孤儿属于本运行时,先确认退出再替换;
921
- // 跨 HOME 的孤儿只在 --clear 时 kill,否则仅警告。findOrphanProcesses
922
- // 在 Windows 上需要一次 CIM 查询;保留一个快照,避免同一阶段重复扫描。
923
- {
924
- const orphans = findOrphanProcesses();
925
- const confirmedTestDaemons = orphans.filter(o => o.confirmedTestDaemon);
926
- if (confirmedTestDaemons.length > 0) {
927
- const killed = killOrphans(confirmedTestDaemons);
928
- console.log(`☠ 已清理 ${killed.length} 个泄漏的测试 daemon: ${killed.join(', ')}`);
929
- await sleep(500);
930
- }
931
- const runtimeOrphans = orphans.filter(o => isRuntimeOrphan(o));
932
- if (runtimeOrphans.length > 0) {
933
- console.log(`⚠ 检测到未登记的 EvolCore 进程,将一并停止: ${runtimeOrphans.map(o => o.pid).join(', ')}`);
934
- const orphanPids = new Set(runtimeOrphans.map(orphan => orphan.pid));
935
- const currentPing = await probeDaemon(socketPath);
936
- const gracefulPid = currentPing && orphanPids.has(currentPing.pid)
937
- ? await requestDaemonShutdown(socketPath, DAEMON_SHUTDOWN_TIMEOUT_MS, 'ec restart', orphanPids)
938
- : null;
939
- const stopped = await Promise.all(runtimeOrphans.map(o => stopPid(o.pid, o.pid === gracefulPid)));
940
- if (stopped.some(result => !result)) {
941
- console.error('❌ Restart aborted because an unregistered EvolCore process could not be stopped');
942
- process.exitCode = 1;
943
- return;
944
- }
945
- await sleep(500);
946
- }
947
- // stopPid() already waited for every runtime orphan above, so avoid a
948
- // second scan before handling cross-HOME records.
949
- const otherHome = orphans.filter(o => !o.confirmedTestDaemon && !isRuntimeOrphan(o));
950
- if (opts.clear && otherHome.length > 0) {
951
- const killed = killOrphans(otherHome);
952
- console.log(`☠ 已 SIGKILL ${killed.length} 个跨 HOME 孤儿进程: ${killed.join(', ')}`);
953
- await sleep(500);
954
- }
955
- else if (otherHome.length > 0) {
956
- reportOrphans(otherHome);
957
- }
958
- // Keep the post-stop ownership guard: a process that appeared during the
959
- // cleanup window must still block replacement.
960
- const remainingRuntimeOrphans = findOrphanProcesses().filter(o => isRuntimeOrphan(o));
961
- if (remainingRuntimeOrphans.length > 0) {
962
- console.error(`❌ Restart aborted: EvolCore process still running (PID: ${remainingRuntimeOrphans.map(o => o.pid).join(', ')})`);
963
- process.exitCode = 1;
964
- return;
965
- }
966
- }
967
- // 只清理 EvolCore 自己登记的 codex app-server,不能影响桌面端实例。
968
- {
969
- const killed = stopCodexAppServerOrphans();
970
- if (killed > 0) {
971
- console.log(`☠ 已清理 ${killed} 个 EvolCore codex app-server 孤儿进程`);
972
- await sleep(500);
973
- }
974
- }
975
- console.log(`⏱ restart prep done in ${((Date.now() - cmdStartedAt) / 1000).toFixed(1)}s, starting...`);
976
- // 通过 restart-monitor 启动,避免在 agent 内调用时自杀。
977
- // 开发仓下 monitor 从源码跑;安装包下先复制到 stage 目录,两种情况都让看门狗
978
- // 不住在会被替换的产物里。
979
- const monitorEntry = platform.resolveMonitorLaunch(getPackageRoot(), path.join(resolvePaths().root, 'data', 'monitor-stage'));
980
- if (monitorEntry.note)
981
- console.log(`ℹ ${monitorEntry.note}`);
982
- if (!fs.existsSync(monitorEntry.entry)) {
983
- console.error(`❌ 重启中止:找不到 restart-monitor 入口 ${monitorEntry.entry}`);
984
- console.error(' 请先执行 npm run build 重建产物');
985
- process.exitCode = 1;
986
- return;
987
- }
988
- const monitorStarted = await spawnRestartMonitorAndConfirm(monitorEntry, log => console.error(log));
989
- if (!monitorStarted.ok) {
990
- if (monitorEntry.stageDir)
991
- platform.cleanupMonitorStage(monitorEntry.stageDir);
992
- console.error(`❌ 重启中止:restart-monitor 未能启动(${monitorStarted.reason})`);
993
- if (fs.existsSync(path.join(getPackageRoot(), 'src', 'cli', 'index.ts'))) {
994
- console.error(' 源码可能存在语法错误导致 tsx 无法加载。请执行 npx tsc --noEmit 检查。');
995
- }
996
- console.error(' 服务已停止,请修复后执行 ec start。');
997
- process.exitCode = 1;
998
- return;
999
- }
1000
- console.log('🔄 Restart monitor started; service is coming back online in the background...');
1001
- // 代码统计(开发环境)
1002
- if (path.normalize(resolveRoot()) === path.normalize(getPackageRoot())) {
1003
- console.log('');
1004
- printCodeStats(getPackageRoot(), resolvePaths().logs);
1005
- }
932
+ console.log(`🔄 Restart monitor started (${((Date.now() - cmdStartedAt) / 1000).toFixed(1)}s); service is restarting...`);
1006
933
  }
1007
934
  function normalizeRuntimePath(value) {
1008
935
  return value.replace(/[\\/]+/g, '/').toLowerCase();
@@ -1310,8 +1237,13 @@ export async function cmdStatus() {
1310
1237
  console.log(' 请稍后再次执行 ec status。');
1311
1238
  }
1312
1239
  else {
1313
- console.log(ipcFailure ? '⚠ 无法确认 EvolCore 运行状态:IPC 不可用,且没有可见的存活 PID。' : '⚠ EvolCore is not running');
1314
- if (ipcFailure)
1240
+ // With no live main/monitor, a missing Windows pipe is the normal stopped
1241
+ // state. Preserve uncertainty for permissions, timeouts, unknown errors,
1242
+ // and Unix callers that may be isolated from the daemon's PID namespace.
1243
+ const stopped = !ipcFailure || (platform.isWindows && ipcFailure instanceof IpcTransportError
1244
+ && ['ENOENT', 'ECONNREFUSED'].includes(ipcFailure.code));
1245
+ console.log(stopped ? '⚠ EvolCore is not running' : '⚠ 无法确认 EvolCore 运行状态:IPC 不可用,且没有可见的存活 PID。');
1246
+ if (!stopped && ipcFailure)
1315
1247
  console.log(` ${ipcFailure instanceof Error ? ipcFailure.message : String(ipcFailure)}`);
1316
1248
  }
1317
1249
  // Session & Project statistics (从文件系统读)
@@ -1872,6 +1804,7 @@ async function cmdWatchMenu() {
1872
1804
  { key: 'log', label: 'log', desc: 'real-time log tail' },
1873
1805
  { key: 'aid', label: 'aid', desc: 'AID connection stats' },
1874
1806
  { key: 'msg', label: 'msg', desc: 'message inspector' },
1807
+ { key: 'diag', label: 'diag', desc: 'message lifecycle diagnostics (AUN→queue→task)' },
1875
1808
  { key: 'web', label: 'web', desc: 'browser dashboard (aid/msg/session)' },
1876
1809
  ];
1877
1810
  let index = 0;
@@ -1936,6 +1869,10 @@ async function cmdWatchMenu() {
1936
1869
  const { cmdWatchMsg } = await import('./watch-msg.js');
1937
1870
  await cmdWatchMsg();
1938
1871
  }
1872
+ else if (chosen === 'diag') {
1873
+ const { cmdWatchMsgDiag } = await import('./watch-msg-diag.js');
1874
+ await cmdWatchMsgDiag([]);
1875
+ }
1939
1876
  else if (chosen === 'web') {
1940
1877
  await cmdWatchWeb();
1941
1878
  }
@@ -3358,6 +3295,36 @@ export async function cmdWatchCommand(args) {
3358
3295
  const { cmdWatchMsg } = await import('./watch-msg.js');
3359
3296
  await cmdWatchMsg();
3360
3297
  }
3298
+ else if (args[0] === 'diag' || args[0] === 'msg-diag') {
3299
+ if (isHelpFlag(args[1])) {
3300
+ console.log(`用法: ec watch diag
3301
+
3302
+ 实时诊断消息生命周期,从 AUN SDK 入站到 daemon 处理全过程。
3303
+
3304
+ 显示内容:
3305
+ ✓ AUN入站 消息到达 AUN SDK
3306
+ → 队列入队 消息进入 daemon 队列
3307
+ ⚡ 任务创建 daemon 创建处理任务
3308
+ ✓ 任务完成 任务处理完成
3309
+ ← AUN出站 回复消息发送
3310
+
3311
+ 每条消息显示:
3312
+ - 时间戳(精确到毫秒)
3313
+ - 阶段标识
3314
+ - AID(前12字符)
3315
+ - 消息ID
3316
+ - 内容预览(前50字符)
3317
+
3318
+ 用途:
3319
+ 排查消息丢失、处理延迟、队列阻塞等问题
3320
+
3321
+ 操作:
3322
+ Ctrl+C 退出`);
3323
+ return;
3324
+ }
3325
+ const { cmdWatchMsgDiag } = await import('./watch-msg-diag.js');
3326
+ await cmdWatchMsgDiag(args.slice(1));
3327
+ }
3361
3328
  else if (args[0] === 'log' || args[0] === 'logs') {
3362
3329
  const requested = args.slice(1);
3363
3330
  if (requested.length > 0) {
@@ -99,7 +99,7 @@ export async function cmdData(args) {
99
99
  // when there is no legacy source to process.
100
100
  const existing = requestedId ? readDataMigration(root, requestedId) : undefined;
101
101
  let manifest = existing ?? planDataMigration(root);
102
- if (manifest.operations.length === 0 && Object.keys(manifest.supersededSourceHashes ?? {}).length === 0) {
102
+ if (manifest.operations.length === 0) {
103
103
  printSummary(manifest);
104
104
  console.log('No legacy data requires migration.');
105
105
  return;
@@ -119,9 +119,6 @@ export async function cmdData(args) {
119
119
  manifest = applyDataMigration(manifest);
120
120
  manifest = verifyDataMigration(manifest, { strictTargetContent: true });
121
121
  printSummary(manifest);
122
- if (manifest.state !== 'completed') {
123
- throw new Error(`migration is not fully verified; fix the listed operations and run ec data migrate --apply ${manifest.id}`);
124
- }
125
122
  }
126
123
  else {
127
124
  // A completed manifest may come from the previous copy-only workflow,
@@ -133,6 +130,9 @@ export async function cmdData(args) {
133
130
  console.log(`archive: ${finalization.archivePath}`);
134
131
  console.log(`archive-sha256: ${finalization.archiveSha256}`);
135
132
  console.log(`removed legacy sources: ${finalization.sourcePaths.length}`);
133
+ if (manifest.state !== 'completed') {
134
+ throw new Error(`migration is not fully verified; fix the listed operations and run ec data migrate --apply ${manifest.id}`);
135
+ }
136
136
  if (wasRunning) {
137
137
  console.log('Starting daemon and Agent runtimes after data migration...');
138
138
  await cmdStart();
package/dist/cli/diag.js CHANGED
@@ -5,7 +5,7 @@ import { parseDiagArgs } from '../core/command/diag-service.js';
5
5
  import { wantsHelp } from './help.js';
6
6
  export async function cmdDiag(args) {
7
7
  if (wantsHelp(args)) {
8
- console.log('用法:ec diag <问题描述> [--owner <daemonOwner-aid>] [--format json]\n ec diag stop [--format json]\n未指定 --owner 时联系本机 daemon.json.owners[0]。');
8
+ console.log('用法:ec diag <问题描述> [--owner <daemonOwner-aid>] [--format json]\n ec diag stop [--format json]\n未指定 --owner 时联系本机 daemon.json.owners[0];有效诊断期间再次执行会追加到原 case。');
9
9
  return;
10
10
  }
11
11
  const json = args.at(-2) === '--format' && args.at(-1) === 'json';
@@ -5,6 +5,7 @@ import { HANDOFF_QUERY_DEFAULT_LIMIT, HANDOFF_QUERY_MAX_LIMIT, HANDOFF_STATES }
5
5
  import { HANDOFF_ID_RE } from '../core/handoff/store.js';
6
6
  import { isHelpFlag, wantsHelp } from './help.js';
7
7
  import { readDelegationCredential } from '../core/auth/agent-delegation.js';
8
+ import { canonicalizeEvolcoreCommandArgv } from '../core/permission/ec-command-parser.js';
8
9
  function parseLimit(value) {
9
10
  const limit = Number(value);
10
11
  if (!value || !Number.isInteger(limit) || limit < 1 || limit > HANDOFF_QUERY_MAX_LIMIT) {
@@ -70,6 +71,7 @@ export function parseTrace(args) {
70
71
  return parsed;
71
72
  }
72
73
  export function parseReturn(args) {
74
+ args = canonicalizeEvolcoreCommandArgv(['ec', 'handoff', 'return', ...args]).slice(3);
73
75
  const dash = args.indexOf('--');
74
76
  if (dash >= 0) {
75
77
  const beforeDash = args.slice(0, dash);
package/dist/cli/index.js CHANGED
@@ -14,6 +14,7 @@ import { cmdRestartMonitor } from './restart-monitor.js';
14
14
  import { cmdAid, cmdRpc, cmdStorage, cmdMsg, cmdGroup } from './aun-commands.js';
15
15
  import { cmdAgent } from './agent-command.js';
16
16
  import { cmdCtl } from './ctl-command.js';
17
+ import { cmdMemory } from './memory-command.js';
17
18
  import { cmdQueue } from './queue-command.js';
18
19
  import { cmdStart, cmdStop, cmdRestart, cmdStatus, cmdLogs, cmdWatchCommand, cmdMv, cmdDiagnose } from './daemon-commands.js';
19
20
  import { logCliCommand } from './command-log.js';
@@ -80,7 +81,7 @@ function printLifecycleHelp(command) {
80
81
  restart: `用法: ec restart [--clear] [--diagnose|-d]\n\n --clear 同时清理跨 HOME 残留的 EvolCore 主进程\n --diagnose, -d 以诊断模式启动新 daemon`,
81
82
  status: '用法: ec status\n\n查看 daemon、agent、渠道与会话运行状态。',
82
83
  logs: `用法: ec logs [选项]\n\n --level <error|warn|info|debug> 最低日志级别\n --module <name> 只显示指定模块\n --raw 原始输出\n --no-color 禁用颜色`,
83
- watch: `用法: ec watch [logs|log|aid|msg|web|session]\n\n ec watch 打开监控选择菜单\n ec watch logs 选择日志类型后监控\n ec watch log <类型...> 直接监控指定日志类型\n ec watch aid 监控 AID 连接\n ec watch msg 打开消息 TUI\n ec watch web 安装/升级并启动 EC Web\n ec watch session ec watch web 的兼容别名`,
84
+ 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 的兼容别名`,
84
85
  'restart-monitor': '用法: ec restart-monitor\n\n运行内 daemon 重启与升级监控器。',
85
86
  diagnose: '用法: ec diagnose [--codex-hook]\n\n检查配置、数据库、进程和编译产物。\n\n --codex-hook 运行 Windows Codex managed hook 启动探针。',
86
87
  mv: '用法: ec mv <old-directory> <new-directory>\n\n迁移项目目录以及 Claude、Codex 和 EvolCore 会话路径。',
@@ -92,6 +93,14 @@ process.removeAllListeners('warning');
92
93
  process.on('warning', (w) => { if (w.name === 'ExperimentalWarning')
93
94
  return; process.stderr.write((w.stack ?? String(w)) + '\n'); });
94
95
  export async function main(args) {
96
+ // 托管任务里裸跑 `ec` 想问的是"有哪些命令",而不是要启动 daemon。
97
+ // 默认回落到 `start` 会让守卫抛出 "Command start is not available",
98
+ // 把用户引向进程生命周期,而真实意图是查用法。这里直接给帮助。
99
+ if (args.length === 0 && process.env.EVOLCORE_SESSION_ID) {
100
+ console.log(MAIN_HELP);
101
+ process.exitCode = 1;
102
+ return;
103
+ }
95
104
  const cmd = args[0] || 'start';
96
105
  try {
97
106
  assertManagedTopLevelCommandAllowed(cmd, args);
@@ -326,6 +335,9 @@ export async function main(args) {
326
335
  case 'ctl':
327
336
  await cmdCtl(args.slice(1));
328
337
  break;
338
+ case 'memory':
339
+ await cmdMemory(args.slice(1));
340
+ break;
329
341
  case 'queue':
330
342
  await cmdQueue(args.slice(1));
331
343
  break;
@@ -417,6 +429,11 @@ export async function main(args) {
417
429
  await cmdModel(args.slice(1));
418
430
  break;
419
431
  }
432
+ case 'skill': {
433
+ const { cmdSkill } = await import('./skill-command.js');
434
+ await cmdSkill(args.slice(1));
435
+ break;
436
+ }
420
437
  case 'response': {
421
438
  const { cmdResponse } = await import('./response.js');
422
439
  await cmdResponse(args.slice(1));
@@ -11,10 +11,20 @@ const MANAGED_TASK_COMMANDS = new Set([
11
11
  'fs',
12
12
  'group',
13
13
  'handoff',
14
+ // `memory` only works inside a managed task: both subcommands require
15
+ // EVOLCORE_SESSION_ID and authorize through their daemon IPC entrypoints.
16
+ 'memory',
14
17
  'model',
15
18
  'msg',
16
19
  'queue',
17
20
  'response',
21
+ // `skill` 管理 EC 技能(安装/开关/校验)。它的主要使用者就是 agent 自己——
22
+ // ec-skill 技能的 SKILL.md 明确指导 agent 调用它。脚本只读写
23
+ // $EVOLCORE_HOME/skills/ 与 kits/skills/ 下的技能文件,不触碰进程生命周期。
24
+ // 本白名单只负责让它进到脚本;具体某一级的读写权限由 skill.mjs 的
25
+ // assertPermission() 按会话上下文判定(群聊一律拒,Agent 级要 owner,
26
+ // 本机级要 daemonowner),故此处不额外收紧。
27
+ 'skill',
18
28
  // `stats` reads the usage database directly. It authorizes each managed call
19
29
  // against the task's relation role in `resolveManagedStatsScope`.
20
30
  'stats',