evolcore 0.0.32 → 0.0.34

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 (214) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/bin/ec.js +3 -2
  3. package/bin/install-codex-managed-hooks.mjs +135 -37
  4. package/dist/agents/baseagent-availability.js +20 -36
  5. package/dist/agents/claude-runner.js +111 -15
  6. package/dist/agents/codex/app-server-client.js +3 -0
  7. package/dist/agents/codex/diagnostics.js +112 -54
  8. package/dist/agents/codex-runner.js +241 -63
  9. package/dist/agents/ecagent-runner.js +78 -33
  10. package/dist/agents/runner-types.js +5 -6
  11. package/dist/aun/aid/identity.js +1 -1
  12. package/dist/aun/group/operations.js +0 -1
  13. package/dist/aun/msg/history.js +1 -0
  14. package/dist/aun/msg/p2p.js +0 -1
  15. package/dist/aun/outbox.js +50 -1
  16. package/dist/channels/aun.js +44 -8
  17. package/dist/channels/daemon.js +261 -3
  18. package/dist/cli/agent-command.js +58 -24
  19. package/dist/cli/agent.js +1 -1
  20. package/dist/cli/aun-commands.js +368 -31
  21. package/dist/cli/contact.js +8 -2
  22. package/dist/cli/ctl-command.js +3 -1
  23. package/dist/cli/daemon-commands.js +197 -27
  24. package/dist/cli/debug-mode.js +154 -0
  25. package/dist/cli/fs-command.js +2 -1
  26. package/dist/cli/handoff-command.js +3 -0
  27. package/dist/cli/index.js +98 -67
  28. package/dist/cli/init.js +2 -2
  29. package/dist/cli/integrity-command.js +196 -0
  30. package/dist/cli/managed-command-guard.js +5 -0
  31. package/dist/cli/memory-command.js +166 -146
  32. package/dist/cli/queue-command.js +9 -4
  33. package/dist/cli/session-command.js +194 -0
  34. package/dist/cli/skill-command.js +78 -2
  35. package/dist/cli/task-context.js +1 -0
  36. package/dist/cli/thread-command.js +622 -0
  37. package/dist/cli/trigger-command.js +10 -3
  38. package/dist/config/builtin-roles.js +1 -0
  39. package/dist/config/config-field-policy.js +6 -3
  40. package/dist/config/config-manager.js +26 -2
  41. package/dist/config/contact-book-store.js +5 -0
  42. package/dist/config/resolved-config-op.js +3 -0
  43. package/dist/config/role-service.js +13 -0
  44. package/dist/config/runtime-env.js +16 -0
  45. package/dist/config-store.js +45 -0
  46. package/dist/core/audit/log-integrity.js +3 -1
  47. package/dist/core/auth/agent-delegation.js +133 -36
  48. package/dist/core/auth/debug-context.js +139 -0
  49. package/dist/core/auth/delegation-diagnostics.js +414 -0
  50. package/dist/core/auth/operation-authorizer.js +25 -2
  51. package/dist/core/auth/operation-catalog.js +49 -0
  52. package/dist/core/background-session/session-cleanup.js +212 -0
  53. package/dist/core/background-session/types.js +10 -0
  54. package/dist/core/bootstrap-messages.js +1 -1
  55. package/dist/core/bootstrap-service.js +6 -3
  56. package/dist/core/command/agent-control.js +18 -26
  57. package/dist/core/command/command-handler.js +197 -27
  58. package/dist/core/command/daemon-diagnostics.js +1 -0
  59. package/dist/core/command/memory-slash.js +6 -2
  60. package/dist/core/command/menu-catalog.js +51 -1
  61. package/dist/core/command/menu-handler.js +114 -23
  62. package/dist/core/command/menu-protocol.js +25 -1
  63. package/dist/core/command/skill-slash.js +322 -0
  64. package/dist/core/command/slash-gate.js +6 -4
  65. package/dist/core/command/slash-handler.js +195 -13
  66. package/dist/core/command/topic-slash.js +528 -0
  67. package/dist/core/daemon-bootstrap.js +4 -7
  68. package/dist/core/evolagent-registry.js +20 -5
  69. package/dist/core/file-integrity/read.js +61 -0
  70. package/dist/core/file-integrity/store.js +262 -0
  71. package/dist/core/handoff/runtime.js +5 -11
  72. package/dist/core/handoff/store.js +5 -0
  73. package/dist/core/ipc-registration.js +175 -3
  74. package/dist/core/memory/batch-meta.js +132 -0
  75. package/dist/core/memory/consolidation-context.js +83 -29
  76. package/dist/core/memory/consolidation-ops-records.js +49 -16
  77. package/dist/core/memory/consolidation-queue-format.js +21 -0
  78. package/dist/core/memory/consolidation.js +264 -205
  79. package/dist/core/memory/index-manager.js +19 -28
  80. package/dist/core/memory/memory-admin.js +19 -14
  81. package/dist/core/memory/memory-document.js +53 -9
  82. package/dist/core/memory/memory-writer.js +30 -15
  83. package/dist/core/message/aun-ipc-sender.js +161 -6
  84. package/dist/core/message/im-renderer.js +169 -10
  85. package/dist/core/message/message-bridge.js +15 -4
  86. package/dist/core/message/message-log.js +1 -0
  87. package/dist/core/message/peer-mode.js +6 -1
  88. package/dist/core/message/response-engine.js +929 -110
  89. package/dist/core/message/subtask-tool-projection.js +140 -0
  90. package/dist/core/model/catalog-service.js +17 -12
  91. package/dist/core/permission/ec-command-parser.js +217 -9
  92. package/dist/core/permission/protected-paths.js +5 -1
  93. package/dist/core/permission/readonly-shell-query.js +43 -5
  94. package/dist/core/permission/session-path-grants.js +334 -0
  95. package/dist/core/permission/tool-canonical.js +226 -0
  96. package/dist/core/permission/tool-policy.js +30 -62
  97. package/dist/core/role/runtime-policy.js +21 -10
  98. package/dist/core/session/session-fs-store.js +123 -8
  99. package/dist/core/session/session-idle-monitor.js +249 -22
  100. package/dist/core/session/session-manager.js +129 -14
  101. package/dist/core/skill/command-parser.js +13 -0
  102. package/dist/core/skill/index-generator.js +21 -4
  103. package/dist/core/skill/startup.js +41 -0
  104. package/dist/core/skill/switch-resolver.js +55 -29
  105. package/dist/core/system-session/grants.js +40 -0
  106. package/dist/core/system-session/memory.js +222 -0
  107. package/dist/core/system-session/registry.js +74 -0
  108. package/dist/core/system-session/types.js +14 -0
  109. package/dist/core/thread/command-parser.js +125 -0
  110. package/dist/core/thread/index.js +1 -0
  111. package/dist/core/thread/ipc-operation.js +95 -0
  112. package/dist/core/thread/thread-context-storage.js +131 -0
  113. package/dist/core/thread/thread-operation.js +258 -0
  114. package/dist/core/thread/thread-route.js +33 -0
  115. package/dist/core/thread/thread-service.js +770 -0
  116. package/dist/core/thread/types.js +1 -0
  117. package/dist/eck/kit-renderer.js +7 -2
  118. package/dist/eck/manifest-engine.js +24 -4
  119. package/dist/eck/message-renderer.js +35 -0
  120. package/dist/index.js +19 -7
  121. package/dist/ipc.js +140 -50
  122. package/dist/paths.js +93 -0
  123. package/dist/response-system/engines/v1/proactive-flow.js +169 -80
  124. package/dist/stats/billing.js +20 -8
  125. package/dist/trigger/authorization.js +57 -28
  126. package/dist/trigger/feedback.js +13 -2
  127. package/dist/trigger/parser.js +70 -1
  128. package/dist/trigger/system-definitions.js +3 -3
  129. package/dist/trigger/validation.js +14 -0
  130. package/dist/utils/cross-platform.js +11 -2
  131. package/dist/utils/error-dict.json +18 -4
  132. package/dist/utils/error-utils.js +143 -1
  133. package/dist/utils/instance-registry.js +13 -8
  134. package/dist/utils/log-writer.js +12 -0
  135. package/dist/utils/process-introspect.js +11 -0
  136. package/kits/docs/context-assembly.md +1 -1
  137. package/kits/docs/evolcore/INDEX.md +1 -0
  138. package/kits/docs/evolcore/agent-create.md +40 -28
  139. package/kits/docs/evolcore/agent.md +21 -6
  140. package/kits/docs/evolcore/config.md +2 -2
  141. package/kits/docs/evolcore/ctl.md +2 -2
  142. package/kits/docs/evolcore/ec-capabilities.md +5 -1
  143. package/kits/docs/evolcore/fs-architecture.md +4 -5
  144. package/kits/docs/evolcore/fs.md +1 -1
  145. package/kits/docs/evolcore/group-collaboration.md +4 -6
  146. package/kits/docs/evolcore/group.md +11 -12
  147. package/kits/docs/evolcore/memory-architecture.md +4 -5
  148. package/kits/docs/evolcore/memory-consolidation.md +19 -15
  149. package/kits/docs/evolcore/memory-tags.md +3 -1
  150. package/kits/docs/evolcore/memory.md +24 -12
  151. package/kits/docs/evolcore/menu-exec-schema-commands.md +2 -2
  152. package/kits/docs/evolcore/menu-protocol.md +7 -0
  153. package/kits/docs/evolcore/model.md +16 -0
  154. package/kits/docs/evolcore/msg.md +8 -11
  155. package/kits/docs/evolcore/thread-chain.md +267 -0
  156. package/kits/docs/prompt-loading-architecture.md +1 -1
  157. package/kits/eck_manifest.json +55 -40
  158. package/kits/eck_manifest.memory.json +0 -12
  159. package/kits/eck_message_manifest.json +169 -10
  160. package/kits/rules/01-overview.md +11 -0
  161. package/kits/rules/03-identity.md +6 -3
  162. package/kits/rules/05-venue.md +1 -1
  163. package/kits/rules/06-channel.md +1 -1
  164. package/kits/rules/07-memory-and-thread.md +199 -0
  165. package/kits/schemas/_meta.json +7 -1
  166. package/kits/schemas/agent-config.schema.13.json +1 -1
  167. package/kits/schemas/daemon.schema.7.json +140 -0
  168. package/kits/schemas/relation-config.schema.9.json +18 -3
  169. package/kits/schemas/role-config.schema.1.json +6 -6
  170. package/kits/schemas/single-session.schema.1.json +6 -6
  171. package/kits/schemas/single-session.schema.2.json +6 -6
  172. package/kits/schemas/single-session.schema.3.json +6 -6
  173. package/kits/skills/.switches.json +12 -1
  174. package/kits/skills/ec-group/SKILL.md +234 -0
  175. package/kits/skills/ec-skill/SKILL.md +10 -1
  176. package/kits/skills/ec-skill/scripts/cli.mjs +16 -2
  177. package/kits/skills/ec-skill/scripts/skill.mjs +1 -1
  178. package/kits/skills/scrapling-article-fetch/SKILL.md +128 -0
  179. package/kits/skills/scrapling-article-fetch/scripts/check_python_env.py +54 -0
  180. package/kits/skills/scrapling-article-fetch/scripts/render_markdown_reply.py +35 -0
  181. package/kits/skills/scrapling-article-fetch/scripts/run_pipeline.sh +16 -0
  182. package/kits/skills/scrapling-article-fetch/scripts/scrapling_fetch.py +344 -0
  183. package/kits/skills/thread-ops/SKILL.md +492 -0
  184. package/kits/skills/wechat-article-media-download/SKILL.md +65 -0
  185. package/kits/skills/wechat-article-media-download/scripts/download.py +163 -0
  186. package/kits/skills/wechat-article-reader/SKILL.md +97 -0
  187. package/kits/skills/wechat-article-reader/scripts/fetch.mjs +256 -0
  188. package/kits/templates/bootstrap-welcome.md +7 -7
  189. package/kits/templates/memory-consolidation/forget.md +7 -2
  190. package/kits/templates/memory-consolidation/generalize.md +9 -4
  191. package/kits/templates/memory-consolidation/notes.md +11 -11
  192. package/kits/templates/memory-consolidation/profile.md +8 -3
  193. package/kits/templates/memory-consolidation/promote.md +8 -3
  194. package/kits/templates/memory-consolidation/workflow.md +6 -6
  195. package/kits/templates/message-fragments/handoff-request-to-target.md +1 -1
  196. package/kits/templates/message-fragments/item.md +2 -1
  197. package/kits/templates/message-fragments/thread-context.md +6 -0
  198. package/kits/templates/message-fragments/trigger-session.md +2 -0
  199. package/kits/templates/message-fragments/trigger-thread-check.md +2 -0
  200. package/kits/templates/roles/member.json +2 -0
  201. package/kits/templates/roles/visitor.json +2 -0
  202. package/kits/templates/system-fragments/bootstrap.md +67 -72
  203. package/kits/templates/system-fragments/channel.md +3 -6
  204. package/kits/templates/system-fragments/commands.md +1 -0
  205. package/kits/templates/system-fragments/managed-runtime.md +15 -0
  206. package/kits/templates/system-fragments/memory.md +16 -9
  207. package/kits/templates/system-fragments/reply.md +7 -6
  208. package/kits/templates/system-fragments/session.md +5 -14
  209. package/package.json +6 -3
  210. package/dist/core/memory/memory-session-policy.js +0 -41
  211. package/dist/core/memory/memory-signature.js +0 -257
  212. package/kits/docs/evolcore/group-fs.md +0 -17
  213. package/kits/docs/venues/aun-group.md +0 -45
  214. package/kits/docs/venues/group.md +0 -43
@@ -0,0 +1 @@
1
+ export {};
@@ -6,6 +6,7 @@ import { logger } from '../utils/logger.js';
6
6
  import { clearRoleStoreCache } from '../config/role-store.js';
7
7
  import { resolveAgentLifecycle } from '../config/lifecycle.js';
8
8
  import { loadManifest, loadManifestMeta, invalidateManifestCache, evaluateWhen, renderTemplate, renderLoopSection, resolvePathWithDiag, loadSectionFiles, loadChildTemplate, buildPathMappings, shortenPath, } from './manifest-engine.js';
9
+ import { SYSTEM_SESSION_TYPES } from '../core/system-session/types.js';
9
10
  export const DEFAULT_MANIFEST_FILE = 'eck_manifest.json';
10
11
  /**
11
12
  * 会话原型(sessionType)→ manifest 文件的内置映射。
@@ -16,9 +17,13 @@ export const BUILTIN_SESSION_MANIFESTS = {
16
17
  memory: 'eck_manifest.memory.json',
17
18
  auxiliary: 'eck_manifest.auxiliary.json',
18
19
  };
19
- /** 选择顺序:config 覆盖 → 内置映射 → 主 manifest。 */
20
+ /**
21
+ * 选择顺序:config 覆盖 → 内置映射 → 主 manifest。
22
+ * 系统会话类型不接受 config 覆盖:其 manifest 由 system-session 模块决定。
23
+ */
20
24
  export function resolveSessionManifest(sessionType, overrides) {
21
- return overrides?.[sessionType] ?? BUILTIN_SESSION_MANIFESTS[sessionType] ?? DEFAULT_MANIFEST_FILE;
25
+ const override = SYSTEM_SESSION_TYPES.includes(sessionType) ? undefined : overrides?.[sessionType];
26
+ return override ?? BUILTIN_SESSION_MANIFESTS[sessionType] ?? DEFAULT_MANIFEST_FILE;
22
27
  }
23
28
  // ── Caches ──
24
29
  const _sessionPathCache = new Map();
@@ -3,9 +3,10 @@
3
3
  // when 求值、模板渲染、路径解析、manifest 加载/缓存原语,避免两套实现漂移。
4
4
  import fs from 'fs';
5
5
  import path from 'path';
6
- import { kitsDir, resolveRoot, getPackageRoot } from '../paths.js';
6
+ import { kitsDir, resolveRoot, getPackageRoot, isDevMode } from '../paths.js';
7
7
  import { logger } from '../utils/logger.js';
8
8
  import { fileCache } from '../core/daemon-file-cache.js';
9
+ import { readVerifiedText, isShippedPath } from '../core/file-integrity/read.js';
9
10
  // ── 限额默认值 ──
10
11
  /** 单目录段默认最多文件数 */
11
12
  export const DIR_MAX_FILES = 20;
@@ -365,12 +366,31 @@ function sectionCacheOptions(resolvedPath, vars) {
365
366
  }
366
367
  return { policy: 'mtime', group: 'eck-runtime' };
367
368
  }
369
+ /**
370
+ * 读取一个 kits 文档,安装模式下先过台账校验。
371
+ *
372
+ * 为什么校验包在 loader 里:这些内容走 FileCache 的 `on-reload` 策略,缓存命中时
373
+ * 不会碰磁盘,校验只有包在这里才与"实际注入的那份内容"对齐;被篡改且恢复不了时
374
+ * 返回 null,条目本身也不会写进缓存。开发模式下 kits 由 agent 直接改写,不校验。
375
+ */
376
+ function loadKitsDoc(resolved, vars) {
377
+ const opts = sectionCacheOptions(resolved, vars);
378
+ if (!isShippedPath(resolved)) {
379
+ return fileCache.getText(resolved, opts);
380
+ }
381
+ const verify = !isDevMode();
382
+ return fileCache.get(resolved, () => {
383
+ const checked = readVerifiedText(resolved, { verify, tag: 'eck' });
384
+ // 校验不过就不进缓存:返回 null → fileCache 存 null,该段被丢弃
385
+ return checked ? checked.text : null;
386
+ }, opts);
387
+ }
368
388
  /** 加载 loop 的 child 子模板文件内容(路径解析 + fileCache)。找不到返回 null。 */
369
389
  export function loadChildTemplate(childFile, vars) {
370
390
  const resolved = resolvePath(childFile, vars);
371
391
  if (!resolved)
372
392
  return null;
373
- return fileCache.getText(resolved, sectionCacheOptions(resolved, vars));
393
+ return loadKitsDoc(resolved, vars);
374
394
  }
375
395
  /**
376
396
  * 返回 [filePath, rawContent][]。kits 文件跨 session 缓存到 reload;运行时文件
@@ -401,7 +421,7 @@ function loadFileSection(filePath, vars, sessionCache) {
401
421
  const resolved = resolvePath(filePath, vars);
402
422
  if (!resolved)
403
423
  return null;
404
- const content = fileCache.getText(resolved, sectionCacheOptions(resolved, vars));
424
+ const content = loadKitsDoc(resolved, vars);
405
425
  return content === null ? null : [resolved, content];
406
426
  }
407
427
  /**
@@ -435,7 +455,7 @@ function readDirectoryFiles(dirPath, pattern, maxFiles, maxBytes, vars) {
435
455
  break;
436
456
  }
437
457
  const fp = path.join(dirPath, f);
438
- const content = fileCache.getText(fp, sectionCacheOptions(fp, vars));
458
+ const content = loadKitsDoc(fp, vars);
439
459
  if (content === null)
440
460
  continue;
441
461
  // 字节限额(至少加载一个文件,避免单个超大文件导致空目录)
@@ -50,6 +50,8 @@ function renderOneItem(item, sessionVars, sessionCache, contentSentinel) {
50
50
  };
51
51
  const isOwnerHint = item.kind === 'owner-hint';
52
52
  const isHandoff = item.kind === 'handoff';
53
+ const isThreadContext = item.kind === 'thread-context';
54
+ const isTriggerMsg = item.kind === 'trigger';
53
55
  const handoffPreviousSentinel = `\x00ECMSG-HANDOFF-PREV-${randomUUID()}\x00`;
54
56
  const requiredReplacements = (item.handoff?.requiredEntries ?? []).map(entry => ({
55
57
  entry,
@@ -131,6 +133,39 @@ function renderOneItem(item, sessionVars, sessionCache, contentSentinel) {
131
133
  injectTime: isOwnerHint
132
134
  ? formatLocalTime(item.injectTime ?? item.timestamp ?? Date.now(), sessionVars.timezone ? String(sessionVars.timezone) : undefined)
133
135
  : undefined,
136
+ // T4: 跨会话上下文(thread-inbox 注入)
137
+ isThreadContext,
138
+ threadContextOriginThreadId: item.threadContext?.originThreadId,
139
+ threadContextOriginPeer: item.threadContext?.originPeer,
140
+ threadContextTime: item.timestamp !== undefined
141
+ ? formatLocalTime(item.timestamp, sessionVars.timezone ? String(sessionVars.timezone) : undefined)
142
+ : undefined,
143
+ threadContextGapHasNewMessages: item.threadContext?.gapDetection.hasNewMessages === true,
144
+ threadContextGapCount: item.threadContext?.gapDetection.count,
145
+ // M1: 空洞检测失败(来源话题的 messages.jsonl 缺失/损坏)时,gapDetection 保守返回
146
+ // hasNewMessages=false,与"确实无新消息"渲染结果相同。透出 error 让模板提示"无法检测",
147
+ // 避免 agent 把检测失败误读成"来源话题无更新"。
148
+ threadContextGapError: item.threadContext?.gapDetection.error,
149
+ threadContextGapRange: (() => {
150
+ const g = item.threadContext?.gapDetection;
151
+ if (!g?.hasNewMessages || g.firstTimestamp === undefined || g.lastTimestamp === undefined)
152
+ return undefined;
153
+ const tz = sessionVars.timezone ? String(sessionVars.timezone) : undefined;
154
+ return `${formatLocalTime(g.firstTimestamp, tz)} - ${formatLocalTime(g.lastTimestamp, tz)}`;
155
+ })(),
156
+ threadContextTriggerId: item.threadContext?.triggerId,
157
+ // T9: trigger 消息专属信封变量
158
+ isTriggerMsg,
159
+ triggerMsgId: isTriggerMsg ? item.triggerInfo?.triggerId : undefined,
160
+ triggerMsgName: isTriggerMsg ? item.triggerInfo?.triggerName : undefined,
161
+ triggerMsgFireTime: isTriggerMsg && item.triggerInfo?.fireTime !== undefined
162
+ ? formatLocalTime(item.triggerInfo.fireTime, sessionVars.timezone ? String(sessionVars.timezone) : undefined)
163
+ : undefined,
164
+ // T10: labels 路由 key(默认 'default')+ 动态展开 triggerMsgLabel_<key>
165
+ triggerMsgKind: isTriggerMsg ? (item.triggerInfo?.labels?.kind ?? 'default') : undefined,
166
+ ...(isTriggerMsg && item.triggerInfo?.labels
167
+ ? Object.fromEntries(Object.entries(item.triggerInfo.labels).map(([k, v]) => [`triggerMsgLabel_${k}`, v]))
168
+ : {}),
134
169
  // msg send 跨会话一次性上下文
135
170
  isHandoff,
136
171
  handoffKind: item.handoff?.kind,
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // 【重要】最先加载环境变量,确保后续模块初始化时可用
2
2
  import dotenv from 'dotenv';
3
3
  import path from 'path';
4
- import { ensureDataDirs, resolvePaths, eckDebugDir, daemonControlDir, daemonQueuePath, daemonMessageDedupPath } from './paths.js';
4
+ import { ensureDataDirs, resolvePaths, eckDebugDir, daemonControlDir, daemonQueuePath, daemonMessageDedupPath, isDevMode } from './paths.js';
5
5
  // 立即加载 .env 文件(在其他模块导入之前)
6
6
  try {
7
7
  dotenv.config({ path: path.join(resolvePaths().root, '.env') });
@@ -22,7 +22,7 @@ import { createSessionIdentityResolver } from './config/peer-role-resolver.js';
22
22
  import { initializeStartupConfig, prepareStartupConfig, recordStartupConfig } from './config/boot-log.js';
23
23
  import { CONFIG_SCHEMA_VERSION } from './types.js';
24
24
  import { SessionManager } from './core/session/session-manager.js';
25
- import { SessionIdleMonitor, readRelationSessionIdleSeconds } from './core/session/session-idle-monitor.js';
25
+ import { SessionIdleMonitor, readSessionLoopIdleSeconds } from './core/session/session-idle-monitor.js';
26
26
  import { ClaudeAgentPlugin } from './agents/claude-runner.js';
27
27
  import { CodexAgentPlugin } from './agents/codex-runner.js';
28
28
  import { GeminiAgentPlugin } from './agents/gemini-runner.js';
@@ -57,6 +57,7 @@ import { StatsCollector } from './utils/stats.js';
57
57
  import { AidStatsCollector } from './utils/stats.js';
58
58
  import { initializeStatsPersistence } from './stats/writer.js';
59
59
  import { PermissionGateway } from './core/permission/approval-gateway.js';
60
+ import { releaseSessionPathGrants } from './core/permission/session-path-grants.js';
60
61
  import { InteractionRouter } from './core/interaction-router.js';
61
62
  import { GroupInviteReviewService } from './aun/group/invite-service.js';
62
63
  import { AgentDelegationRegistry, } from './core/auth/agent-delegation.js';
@@ -138,8 +139,10 @@ async function main() {
138
139
  }
139
140
  // 立即登记自己(让其他并发启动者能看见我)
140
141
  const launchedBy = process.env.EVOLCORE_LAUNCHED_BY || 'start';
142
+ // 本次运行模式在这里定下(首次求值时会读走并删除 `ec start --as-mode` 的覆盖文件)
143
+ const devMode = isDevMode();
141
144
  writeMain(launchedBy);
142
- logger.info(`✓ Instance record written: main-${process.pid}.json`);
145
+ logger.info(`✓ Instance record written: main-${process.pid}.json runMode=${devMode ? 'dev' : 'install'}`);
143
146
  // post-write 自检:写完 record 后再扫一次,发现并发对手时按 (startedAt, pid) 选赢家
144
147
  {
145
148
  const verdict = isMainWinner();
@@ -240,6 +243,12 @@ async function main() {
240
243
  if (event.nameChanged)
241
244
  agentRegistry?.invalidateAgentDisplayCache?.(event.aid);
242
245
  });
246
+ // 运行时路径授权以会话为归属:会话被删除后不再有身份去消费它,随之释放。
247
+ // 只挂 session:deleted——session:idle 只表示空闲,会话仍会继续服务。
248
+ eventBus.subscribe('session:deleted', (event) => {
249
+ if ('sessionId' in event && event.sessionId)
250
+ releaseSessionPathGrants(event.sessionId);
251
+ });
243
252
  // 统计收集器(近 1 小时滚动统计)
244
253
  const statsCollector = new StatsCollector(eventBus);
245
254
  // Per-AID 消息统计收集器(累计,供 watch aid 实时展示)
@@ -426,13 +435,15 @@ async function main() {
426
435
  getSessionById: sessionId => sessionManager.getSessionById(sessionId),
427
436
  isSessionBusy: sessionId => messageQueue.isProcessing(sessionId) || messageQueue.getQueueLength(sessionId) > 0,
428
437
  getSessionIdleTriggerIds: () => triggerSchedulers.sessionIdleTriggerIds(),
429
- getSessionIdleSeconds: readRelationSessionIdleSeconds,
438
+ getSessionIdleSeconds: readSessionLoopIdleSeconds,
430
439
  getSessionEncrypt: sessionId => sessionManager.getSessionEncrypt(sessionId),
440
+ isCurrentMainSession: session => sessionManager.getActiveSessionSync(session.channel, session.channelId)?.id === session.id,
431
441
  });
432
442
  sessionIdleMonitor.start();
433
443
  onConfigWrite(({ target, selector }) => {
434
- if (target === ConfigTarget.Relation && selector.self)
435
- sessionIdleMonitor.refresh();
444
+ if (target === ConfigTarget.Relation && selector.self && selector.peerKey) {
445
+ void sessionIdleMonitor.refreshRelation(selector.self, selector.peerKey);
446
+ }
436
447
  });
437
448
  onShutdown(() => sessionIdleMonitor.stop());
438
449
  const targetSessionLocks = new TargetSessionLockRegistry();
@@ -490,10 +501,11 @@ async function main() {
490
501
  sessionManager,
491
502
  getAgent: aid => agentRegistry.get(aid),
492
503
  agentMap,
493
- releaseSlot: aid => consolidationQueue.release(aid),
504
+ releaseSlot: (aid, sessionId) => consolidationQueue.release(aid, sessionId),
494
505
  enqueueConsolidation,
495
506
  sendFeedback: sendConsolidationFeedback,
496
507
  });
508
+ consolidationQueue.setFinalizer(finishConsolidationSession);
497
509
  registerConsolidationSessionEvents({
498
510
  eventBus,
499
511
  permissionGateway,
package/dist/ipc.js CHANGED
@@ -17,11 +17,13 @@ import { getProcessStartTime, isSameOrOlderProcess } from './utils/process-intro
17
17
  import { classifyProcessTree, ProcessTreeSampler, readProcessMetrics } from './utils/process-tree-stats.js';
18
18
  import { readSystemMemoryUsage } from './utils/system-memory.js';
19
19
  import { hashCurrentDelegatedCommand, hashDelegatedCommandArgv } from './core/auth/agent-delegation.js';
20
+ import { resolveSkillRefreshArgv } from './core/skill/command-parser.js';
20
21
  import { normalizeAunMentionEntries } from './aun/msg/mention-schema.js';
21
22
  import { remoteAccessService } from './core/auth/remote-access-store.js';
22
23
  import { setModelCatalogDaemonOwner } from './core/model/model-catalog.js';
23
24
  import { RUNTIME_ENVIRONMENT_NAMES, setRuntimeEnvironmentOverride } from './config/runtime-env.js';
24
25
  import { MAIN_CLI_BIN } from './product.js';
26
+ import { delegationDiagnosticMessage, withDelegationDiagnosticContext, } from './core/auth/delegation-diagnostics.js';
25
27
  const isWindows = process.platform === 'win32';
26
28
  const isNamedPipe = (p) => isWindows && p.toLowerCase().startsWith('\\\\.\\pipe\\');
27
29
  const CPU_SAMPLE_INTERVAL_MS = 1000;
@@ -78,12 +80,12 @@ const LOCAL_CONTROL_COMMANDS = new Set([
78
80
  ]);
79
81
  const MEMORY_COMMAND_ENDPOINTS = new Set([
80
82
  'memory.note', 'memory.note.update', 'memory.note.drop', 'memory.note.list',
81
- 'memory.create', 'memory.update', 'memory.archive', 'memory.demote', 'memory.consolidate', 'memory.feedback',
83
+ 'memory.create', 'memory.update', 'memory.archive', 'memory.demote', 'memory.consolidate',
82
84
  ]);
83
85
  const DELEGATED_ARGV_ENDPOINTS = new Set([
84
86
  'agent.op', 'config.op', 'contact.op', 'aid.op', 'group.op', 'msg.op', 'fs.op',
85
87
  'ctl', 'diag', 'menu-client.request', 'task.resume', 'queue.op', 'storage.auth', 'storage.upload',
86
- 'trigger.op', 'local-command-context', 'evolagent.bootstrapComplete', ...MEMORY_COMMAND_ENDPOINTS,
88
+ 'trigger.op', 'skill.refresh', 'thread.op', 'local-command-context', 'evolagent.bootstrapComplete', ...MEMORY_COMMAND_ENDPOINTS,
87
89
  'handoff-return', 'handoff-recover-return', 'handoff-status', 'handoff-list', 'handoff-trace',
88
90
  ]);
89
91
  let ipcQuerySequence = 0;
@@ -105,9 +107,17 @@ function nextIpcQueryId(cmd) {
105
107
  function requiresLocalControlToken(cmd) {
106
108
  // Managed calls use task delegation. Standalone queries must not gain
107
109
  // management scope merely by omitting (or emptying) sessionId.
108
- return cmd.type === 'evolagent.initialize' || LOCAL_CONTROL_COMMANDS.has(String(cmd.type ?? ''))
109
- || (['evolagent.bootstrapComplete', 'diag', 'handoff-status', 'handoff-list', 'handoff-trace', 'task.resume'].includes(String(cmd.type))
110
- && !(typeof cmd.sessionId === 'string' && cmd.sessionId.trim()));
110
+ const type = String(cmd.type ?? '');
111
+ const sessionId = typeof cmd.sessionId === 'string' && cmd.sessionId.trim();
112
+ const delegated = typeof cmd.delegationToken === 'string' && cmd.delegationToken.trim();
113
+ if (cmd.type === 'evolagent.initialize' || LOCAL_CONTROL_COMMANDS.has(type))
114
+ return true;
115
+ if (type === 'debug-issue-token')
116
+ return true;
117
+ if (type === 'skill.refresh' || type === 'thread.op')
118
+ return !sessionId || !delegated;
119
+ return ['evolagent.bootstrapComplete', 'diag', 'handoff-status', 'handoff-list', 'handoff-trace', 'task.resume'].includes(type)
120
+ && !sessionId;
111
121
  }
112
122
  /** Preserve the pipe DACL and grant only the provisioned Codex users data I/O. */
113
123
  function grantWindowsSandboxPipeAccess(endpoint) {
@@ -164,6 +174,7 @@ export class IpcServer {
164
174
  aunAidStatsRecorder;
165
175
  menuExecutor;
166
176
  agentOperationExecutor;
177
+ skillRefreshExecutor;
167
178
  initializationExecutor;
168
179
  statsProvider;
169
180
  agentStatsProvider;
@@ -182,7 +193,9 @@ export class IpcServer {
182
193
  shutdownExecutor;
183
194
  taskRuntimeContextProvider;
184
195
  debugTaskRuntimeContextProvider;
196
+ debugIssueTokenExecutor;
185
197
  taskRuntimeContextAuthorizer;
198
+ systemSessionCommandGate;
186
199
  codexPreToolUseExecutor;
187
200
  aunMsgSender;
188
201
  diagExecutor;
@@ -199,6 +212,7 @@ export class IpcServer {
199
212
  groupOperationExecutor;
200
213
  msgOperationExecutor;
201
214
  fsOperationExecutor;
215
+ threadOperationExecutor;
202
216
  dingtalkContactBindExecutor;
203
217
  feishuContactBindExecutor;
204
218
  qqbotContactBindExecutor;
@@ -206,6 +220,7 @@ export class IpcServer {
206
220
  wechatContactBindExecutor;
207
221
  controlToken;
208
222
  daemonRuntimeEpoch;
223
+ delegationFailureRecorder;
209
224
  remoteAccessService = remoteAccessService;
210
225
  /** Current daemon owner used to bind locally issued ECWeb pairing codes. */
211
226
  remoteAccessOwnerProvider;
@@ -276,6 +291,9 @@ export class IpcServer {
276
291
  setDaemonRuntimeEpoch(epoch) {
277
292
  this.daemonRuntimeEpoch = epoch;
278
293
  }
294
+ setDelegationFailureRecorder(recorder) {
295
+ this.delegationFailureRecorder = recorder;
296
+ }
279
297
  /** Inject menu.* executor (ECWeb Control proxies menu requests through this) */
280
298
  setMenuExecutor(executor) {
281
299
  this.menuExecutor = executor;
@@ -286,6 +304,9 @@ export class IpcServer {
286
304
  setAgentOperationExecutor(executor) {
287
305
  this.agentOperationExecutor = executor;
288
306
  }
307
+ setSkillRefreshExecutor(executor) {
308
+ this.skillRefreshExecutor = executor;
309
+ }
289
310
  setConfigOperationExecutor(executor) {
290
311
  this.configOperationExecutor = executor;
291
312
  }
@@ -304,6 +325,9 @@ export class IpcServer {
304
325
  setFsOperationExecutor(executor) {
305
326
  this.fsOperationExecutor = executor;
306
327
  }
328
+ setThreadOperationExecutor(executor) {
329
+ this.threadOperationExecutor = executor;
330
+ }
307
331
  setAgentReloadExecutor(executor) {
308
332
  this.agentReloadExecutor = executor;
309
333
  }
@@ -439,7 +463,7 @@ export class IpcServer {
439
463
  setTriggerExecutor(executor) {
440
464
  this.triggerExecutor = executor;
441
465
  }
442
- /** Inject daemon-level consolidation launcher that uses the real trigger scheduler. */
466
+ /** Inject daemon-level consolidation launcher (BackgroundSessionLauncher, via executor closure). */
443
467
  setConsolidationLaunchExecutor(executor) {
444
468
  this.consolidationLaunchExecutor = executor;
445
469
  }
@@ -455,15 +479,17 @@ export class IpcServer {
455
479
  setTaskRuntimeContextProvider(provider) {
456
480
  this.taskRuntimeContextProvider = provider;
457
481
  }
458
- /** 仅开发仓(npm link)安装注册;正式安装不调用,debug 请求一律走正常路径。 */
459
482
  setDebugTaskRuntimeContextProvider(provider) {
460
483
  this.debugTaskRuntimeContextProvider = provider;
461
484
  }
485
+ /** debug 模式:注册 debug-issue-token executor,仅 EVOLCORE_DEBUG_MODE=1 时由 index.ts 调用。 */
486
+ setDebugIssueTokenExecutor(executor) {
487
+ this.debugIssueTokenExecutor = executor;
488
+ }
462
489
  /**
463
- * memory 命令取运行时上下文:先查正在运行的任务;没有且请求带 debug 时,
464
- * 再由开发仓专用的 provider 从会话文件重建。
490
+ * memory 命令取运行时上下文:查正在运行的任务。
465
491
  */
466
- async resolveMemoryTaskCtx(sessionId, debug) {
492
+ async resolveMemoryTaskCtx(sessionId, debug = false) {
467
493
  const active = this.taskRuntimeContextProvider?.({ sessionId });
468
494
  if (active || !debug || !this.debugTaskRuntimeContextProvider)
469
495
  return active;
@@ -472,6 +498,9 @@ export class IpcServer {
472
498
  setTaskRuntimeContextAuthorizer(authorizer) {
473
499
  this.taskRuntimeContextAuthorizer = authorizer;
474
500
  }
501
+ setSystemSessionCommandGate(gate) {
502
+ this.systemSessionCommandGate = gate;
503
+ }
475
504
  setCodexPreToolUseExecutor(executor) {
476
505
  this.codexPreToolUseExecutor = executor;
477
506
  }
@@ -479,6 +508,14 @@ export class IpcServer {
479
508
  setAunMsgSender(sender) {
480
509
  this.aunMsgSender = sender;
481
510
  }
511
+ hasAunMsgSender() {
512
+ return this.aunMsgSender !== undefined;
513
+ }
514
+ async sendAunMsg(params) {
515
+ if (!this.aunMsgSender)
516
+ throw new Error('aunMsgSender not configured');
517
+ return this.aunMsgSender(params);
518
+ }
482
519
  setDiagExecutor(executor) { this.diagExecutor = executor; }
483
520
  setMenuClientExecutor(executor) { this.menuClientExecutor = executor; }
484
521
  /** Inject internal handoff result return executor for `ec handoff return`. */
@@ -923,18 +960,36 @@ export class IpcServer {
923
960
  }
924
961
  }
925
962
  async handleCommand(cmd, requestSignal, receivedAtMono = performance.now()) {
963
+ return withDelegationDiagnosticContext({
964
+ sessionId: typeof cmd.sessionId === 'string' ? cmd.sessionId : undefined,
965
+ requestId: nextIpcQueryId(cmd),
966
+ correlationId: typeof cmd.correlationId === 'string' ? ipcLogToken(cmd.correlationId) : undefined,
967
+ operation: ipcLogToken(cmd.type),
968
+ }, () => this.dispatchCommand(cmd, requestSignal, receivedAtMono));
969
+ }
970
+ diagnosticRejection(cause, cmd) {
971
+ const failure = this.delegationFailureRecorder?.(cause, typeof (cmd.sessionId ?? cmd.originSessionId ?? cmd.actorSessionId) === 'string'
972
+ ? cmd.sessionId ?? cmd.originSessionId ?? cmd.actorSessionId : undefined, typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
973
+ const diagnosticCause = failure?.diagnosticCause ?? cause;
974
+ return {
975
+ ok: false,
976
+ code: diagnosticCause === 'missing_token' ? 'DELEGATION_REQUIRED'
977
+ : diagnosticCause === 'daemon_restarted' ? 'DAEMON_RESTARTED' : 'INVALID_DELEGATION',
978
+ error: failure?.reason ?? delegationDiagnosticMessage(diagnosticCause),
979
+ diagnosticCause,
980
+ ...(failure?.diagnosticEventId ? { diagnosticEventId: failure.diagnosticEventId } : {}),
981
+ };
982
+ }
983
+ async dispatchCommand(cmd, requestSignal, receivedAtMono = performance.now()) {
926
984
  if (requiresLocalControlToken(cmd) && !this.hasValidControlToken(cmd.controlToken)) {
927
985
  return { ok: false, code: 'INVALID_CONTROL_TOKEN', error: 'valid local control token is required' };
928
986
  }
929
987
  if (typeof cmd.delegationToken === 'string' && cmd.delegationToken
930
988
  && this.daemonRuntimeEpoch
989
+ && cmd.daemonRuntimeEpoch !== undefined
931
990
  && cmd.daemonRuntimeEpoch !== this.daemonRuntimeEpoch) {
932
991
  logger.warn(`[IPC] stale delegation rejected: session=${ipcLogToken(cmd.sessionId ?? cmd.originSessionId ?? cmd.actorSessionId)} type=${ipcLogToken(cmd.type)} cause=daemon_runtime_epoch_mismatch`);
933
- return {
934
- ok: false,
935
- code: 'DAEMON_RESTARTED',
936
- error: 'The task delegation token belongs to a previous daemon runtime; start a new task authorization and do not retry this command in the current task',
937
- };
992
+ return this.diagnosticRejection('daemon_restarted', cmd);
938
993
  }
939
994
  if (typeof cmd.delegationToken === 'string'
940
995
  && (DELEGATED_ARGV_ENDPOINTS.has(cmd.type) || (cmd.type === 'aun-msg-send' && cmd.argv !== undefined))) {
@@ -947,9 +1002,26 @@ export class IpcServer {
947
1002
  ...cmd.argv,
948
1003
  ]);
949
1004
  if (!expectedHash || cmd.delegationCommandHash !== expectedHash) {
950
- return { ok: false, code: 'INVALID_DELEGATION', error: 'Command hash does not match the submitted argv' };
1005
+ return this.diagnosticRejection('command_hash_mismatch', cmd);
951
1006
  }
952
1007
  }
1008
+ // 系统会话统一闸门:带系统会话 delegation 的请求只看模块 checkCommand,拒绝即返回
1009
+ if (this.systemSessionCommandGate
1010
+ && typeof cmd.delegationToken === 'string' && cmd.delegationToken
1011
+ && typeof cmd.sessionId === 'string' && cmd.sessionId) {
1012
+ const argv = Array.isArray(cmd.argv) && cmd.argv.every((value) => typeof value === 'string')
1013
+ ? cmd.argv
1014
+ : undefined;
1015
+ const gate = await this.systemSessionCommandGate({
1016
+ sessionId: cmd.sessionId,
1017
+ delegationToken: cmd.delegationToken,
1018
+ ...(typeof cmd.delegationCommandHash === 'string' ? { delegationCommandHash: cmd.delegationCommandHash } : {}),
1019
+ type: cmd.type,
1020
+ ...(argv ? { argv } : {}),
1021
+ });
1022
+ if (gate && !gate.allow)
1023
+ return { ok: false, code: 'NOT_ALLOWED', policyCode: gate.code, error: gate.reason };
1024
+ }
953
1025
  if (cmd.argv !== undefined && ['handoff-status', 'handoff-list', 'handoff-trace'].includes(cmd.type)) {
954
1026
  try {
955
1027
  const { parseList, parseTrace } = await import('./cli/handoff-command.js');
@@ -1385,12 +1457,25 @@ export class IpcServer {
1385
1457
  sessionId: cmd.sessionId,
1386
1458
  delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
1387
1459
  delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
1460
+ consumeApproval: false,
1388
1461
  });
1389
1462
  if (!authorization.ok)
1390
1463
  return authorization;
1391
1464
  const context = this.taskRuntimeContextProvider({ sessionId: cmd.sessionId }) ?? null;
1392
1465
  return { ok: true, context };
1393
1466
  }
1467
+ case 'debug-issue-token': {
1468
+ if (cmd.delegationToken)
1469
+ return { ok: false, code: 'NOT_ALLOWED', error: 'Managed tasks cannot issue debug tokens' };
1470
+ // 仅 EVOLCORE_DEBUG_MODE=1 时由 index.ts 注册 executor;非 debug 模式直接拒绝
1471
+ if (!this.debugIssueTokenExecutor) {
1472
+ return { ok: false, error: 'debug mode is not enabled; start daemon with: ec start --debug' };
1473
+ }
1474
+ if (typeof cmd.sessionId !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(cmd.sessionId)) {
1475
+ return { ok: false, error: 'missing sessionId' };
1476
+ }
1477
+ return this.debugIssueTokenExecutor({ sessionId: cmd.sessionId });
1478
+ }
1394
1479
  case 'aun-msg-send': {
1395
1480
  if (cmd.argv !== undefined) {
1396
1481
  if (!this.aunMsgSender)
@@ -1458,7 +1543,6 @@ export class IpcServer {
1458
1543
  : undefined,
1459
1544
  encrypt: typeof cmd.encrypt === 'boolean' ? cmd.encrypt : undefined,
1460
1545
  thread: typeof cmd.thread === 'string' ? cmd.thread : undefined,
1461
- returnPolicy: cmd.returnPolicy === 'required' || cmd.returnPolicy === 'none' ? cmd.returnPolicy : undefined,
1462
1546
  handoffContext: cmd.handoffContext,
1463
1547
  originSessionId: typeof cmd.originSessionId === 'string' ? cmd.originSessionId : undefined,
1464
1548
  originMessageId: typeof cmd.originMessageId === 'string' ? cmd.originMessageId : undefined,
@@ -1704,6 +1788,7 @@ export class IpcServer {
1704
1788
  contextFilePath: r.contextFilePath,
1705
1789
  ...(r.logFile ? { logFile: r.logFile } : {}),
1706
1790
  mode: effectiveMode,
1791
+ ...(r.queued ? { queued: r.queued } : {}),
1707
1792
  };
1708
1793
  }
1709
1794
  catch (e) {
@@ -1869,37 +1954,6 @@ export class IpcServer {
1869
1954
  return { ok: false, error: e?.message || String(e) };
1870
1955
  }
1871
1956
  }
1872
- case 'memory.feedback': {
1873
- const { sessionId, text } = cmd;
1874
- if (!sessionId)
1875
- return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId' };
1876
- if (typeof text !== 'string' || !text.trim()) {
1877
- return { ok: false, code: 'INVALID_REQUEST', error: 'missing feedback text' };
1878
- }
1879
- try {
1880
- const taskCtx = await this.resolveMemoryTaskCtx(sessionId, cmd.debug === true);
1881
- if (!taskCtx)
1882
- return { ok: false, code: 'SESSION_NOT_FOUND', error: `未找到会话 ${sessionId} 的运行时上下文` };
1883
- // 只有整理会话可以记录反馈
1884
- if (taskCtx.sessionType !== 'memory') {
1885
- return { ok: false, code: 'NOT_MEMORY_SESSION', error: '`ec memory feedback` 只能在整理会话内调用' };
1886
- }
1887
- const batchDir = taskCtx.consolidationBatchDir;
1888
- if (!batchDir) {
1889
- return { ok: false, code: 'BATCH_DIR_NOT_FOUND', error: '整理会话缺少 consolidationBatchDir' };
1890
- }
1891
- const { appendOpsRecord } = await import('./core/memory/consolidation-ops-records.js');
1892
- appendOpsRecord(batchDir, {
1893
- ts: new Date().toISOString(),
1894
- op: 'feedback-set',
1895
- text,
1896
- });
1897
- return { ok: true };
1898
- }
1899
- catch (e) {
1900
- return { ok: false, error: e?.message || String(e) };
1901
- }
1902
- }
1903
1957
  case 'config.op': {
1904
1958
  if (!this.configOperationExecutor)
1905
1959
  return { ok: false, code: 'NOT_CONFIGURED', error: 'config.op not configured' };
@@ -1972,6 +2026,16 @@ export class IpcServer {
1972
2026
  }
1973
2027
  return await this.fsOperationExecutor(argv, sessionId, delegationToken, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
1974
2028
  }
2029
+ case 'thread.op': {
2030
+ if (!this.threadOperationExecutor)
2031
+ return { ok: false, code: 'NOT_CONFIGURED', error: 'thread.op not configured' };
2032
+ const delegated = typeof cmd.delegationToken === 'string' && cmd.delegationToken.trim();
2033
+ const req = {
2034
+ ...cmd,
2035
+ localControl: !delegated && this.hasValidControlToken(cmd.controlToken),
2036
+ };
2037
+ return await this.threadOperationExecutor(req);
2038
+ }
1975
2039
  case 'evolagent.initialize': {
1976
2040
  if (cmd.sessionId || cmd.delegationToken)
1977
2041
  return { ok: false, code: 'NOT_ALLOWED', error: 'Managed callers must use agent.op' };
@@ -1991,6 +2055,33 @@ export class IpcServer {
1991
2055
  }
1992
2056
  return await this.agentOperationExecutor(argv, sessionId, delegationToken, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
1993
2057
  }
2058
+ case 'skill.refresh': {
2059
+ if (!this.skillRefreshExecutor) {
2060
+ return { ok: false, code: 'NOT_CONFIGURED', error: 'skill.refresh not configured' };
2061
+ }
2062
+ let { aid } = cmd;
2063
+ const { sessionId, delegationToken } = cmd;
2064
+ if (typeof aid !== 'string' || !aid) {
2065
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing aid' };
2066
+ }
2067
+ if (sessionId !== undefined && typeof sessionId !== 'string') {
2068
+ return { ok: false, code: 'INVALID_REQUEST', error: 'sessionId must be a string' };
2069
+ }
2070
+ if (delegationToken !== undefined && typeof delegationToken !== 'string') {
2071
+ return { ok: false, code: 'INVALID_DELEGATION', error: 'delegationToken must be a string' };
2072
+ }
2073
+ if (sessionId && !delegationToken)
2074
+ return { ok: false, code: 'DELEGATION_REQUIRED', error: 'Managed skill refresh requires delegation' };
2075
+ try {
2076
+ if (!Array.isArray(cmd.argv))
2077
+ throw new Error('Skill refresh requires argv');
2078
+ aid = resolveSkillRefreshArgv(cmd.argv);
2079
+ }
2080
+ catch (error) {
2081
+ return { ok: false, code: 'INVALID_REQUEST', error: error instanceof Error ? error.message : String(error) };
2082
+ }
2083
+ return await this.skillRefreshExecutor(aid, sessionId, delegationToken, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
2084
+ }
1994
2085
  case 'trigger.op':
1995
2086
  case 'trigger.list':
1996
2087
  case 'trigger.show':
@@ -2343,8 +2434,7 @@ export class IpcServer {
2343
2434
  const { rebuildIndex } = await import('./core/memory/index-manager.js');
2344
2435
  const mc = this.agentRegistry?.get(taskCtx.selfAid ?? '')?.config?.memory;
2345
2436
  const maxBytes = mc?.indexMaxBytes ?? 5 * 1024;
2346
- const buildResult = await rebuildIndex(dirs.consolidatedDir, path.join(dirs.memoryDir, 'MEMORY.md'), scope, path.join(dirs.memoryDir, 'archive', 'invalid'), undefined, // 验签门控尚未开启,不传 verifyFn
2347
- maxBytes);
2437
+ const buildResult = await rebuildIndex(dirs.consolidatedDir, path.join(dirs.memoryDir, 'MEMORY.md'), scope, maxBytes);
2348
2438
  // 索引重建后顺手检查这一层有没有超期记忆 —— 有则建触发器拉一个独立的遗忘会话。
2349
2439
  await this.maybeTriggerForget(taskCtx, scope, dirs.consolidatedDir, mc, buildResult.verifiedFiles);
2350
2440
  }