evolcore 0.0.31 → 0.0.33

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 (179) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/bin/install-codex-managed-hooks.mjs +124 -37
  3. package/dist/agents/claude-runner.js +29 -2
  4. package/dist/agents/codex/app-server-client.js +3 -0
  5. package/dist/agents/codex/diagnostics.js +76 -44
  6. package/dist/agents/codex-runner.js +51 -24
  7. package/dist/agents/ecagent-runner.js +9 -13
  8. package/dist/agents/gemini-runner.js +4 -0
  9. package/dist/aun/aid/store.js +0 -81
  10. package/dist/aun/group/fs-download.js +1 -10
  11. package/dist/aun/group/operations.js +0 -1
  12. package/dist/aun/msg/history.js +1 -0
  13. package/dist/aun/msg/managed-operation.js +130 -32
  14. package/dist/aun/msg/p2p.js +0 -1
  15. package/dist/aun/outbox.js +50 -1
  16. package/dist/aun/service-proxy.js +12 -18
  17. package/dist/aun/storage/index.js +29 -0
  18. package/dist/channels/aun.js +38 -137
  19. package/dist/channels/daemon.js +257 -2
  20. package/dist/cli/agent-command.js +64 -31
  21. package/dist/cli/agent-create.js +43 -24
  22. package/dist/cli/agent.js +16 -70
  23. package/dist/cli/aun-commands.js +512 -32
  24. package/dist/cli/contact.js +8 -2
  25. package/dist/cli/ctl-command.js +1 -2
  26. package/dist/cli/daemon-commands.js +82 -13
  27. package/dist/cli/debug-mode.js +154 -0
  28. package/dist/cli/diag.js +2 -2
  29. package/dist/cli/handoff-command.js +18 -5
  30. package/dist/cli/index.js +81 -64
  31. package/dist/cli/init.js +2 -2
  32. package/dist/cli/managed-command-guard.js +5 -0
  33. package/dist/cli/memory-command.js +93 -12
  34. package/dist/cli/model.js +14 -138
  35. package/dist/cli/queue-command.js +51 -0
  36. package/dist/cli/response.js +5 -54
  37. package/dist/cli/session-command.js +194 -0
  38. package/dist/cli/skill-command.js +85 -3
  39. package/dist/cli/stats.js +10 -4
  40. package/dist/cli/task-command.js +1 -0
  41. package/dist/cli/task-context.js +16 -0
  42. package/dist/cli/thread-command.js +620 -0
  43. package/dist/cli/trigger-command.js +76 -50
  44. package/dist/config/builtin-roles.js +9 -7
  45. package/dist/config/config-field-policy.js +2 -3
  46. package/dist/config/config-manager.js +7 -2
  47. package/dist/config/resolved-config-op.js +3 -0
  48. package/dist/config-store.js +15 -0
  49. package/dist/core/agent-ipc-registration.js +65 -22
  50. package/dist/core/auth/agent-delegation.js +42 -2
  51. package/dist/core/auth/debug-context.js +139 -0
  52. package/dist/core/auth/delegation-authorization.js +1 -0
  53. package/dist/core/auth/operation-authorizer.js +24 -1
  54. package/dist/core/auth/operation-catalog.js +44 -3
  55. package/dist/core/background-session/session-cleanup.js +212 -0
  56. package/dist/core/background-session/types.js +10 -0
  57. package/dist/core/bootstrap-messages.js +1 -1
  58. package/dist/core/bootstrap-service.js +6 -3
  59. package/dist/core/command/command-handler.js +224 -45
  60. package/dist/core/command/diag-service.js +5 -1
  61. package/dist/core/command/memory-slash.js +6 -2
  62. package/dist/core/command/menu-catalog.js +48 -1
  63. package/dist/core/command/menu-handler.js +92 -16
  64. package/dist/core/command/menu-protocol.js +24 -1
  65. package/dist/core/command/skill-slash.js +322 -0
  66. package/dist/core/command/slash-gate.js +6 -4
  67. package/dist/core/command/slash-handler.js +193 -13
  68. package/dist/core/command/topic-slash.js +528 -0
  69. package/dist/core/evolagent-registry.js +20 -5
  70. package/dist/core/handoff/ipc-registration.js +38 -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 +210 -9
  74. package/dist/core/memory/consolidation-context.js +49 -16
  75. package/dist/core/memory/consolidation-ops-records.js +35 -0
  76. package/dist/core/memory/consolidation-queue-format.js +21 -0
  77. package/dist/core/memory/consolidation.js +174 -180
  78. package/dist/core/message/aun-ipc-sender.js +207 -8
  79. package/dist/core/message/im-renderer.js +149 -6
  80. package/dist/core/message/message-bridge.js +13 -3
  81. package/dist/core/message/message-log.js +1 -0
  82. package/dist/core/message/message-queue.js +131 -3
  83. package/dist/core/message/peer-mode.js +6 -1
  84. package/dist/core/message/response-engine.js +379 -69
  85. package/dist/core/message/subtask-tool-projection.js +140 -0
  86. package/dist/core/model/catalog-service.js +17 -12
  87. package/dist/core/permission/ec-command-parser.js +126 -7
  88. package/dist/core/permission/sandbox-runtime.js +14 -1
  89. package/dist/core/session/session-idle-monitor.js +249 -22
  90. package/dist/core/session/session-manager.js +54 -9
  91. package/dist/core/skill/command-parser.js +13 -0
  92. package/dist/core/skill/index-generator.js +4 -1
  93. package/dist/core/skill/startup.js +41 -0
  94. package/dist/core/skill/switch-resolver.js +55 -29
  95. package/dist/core/task/task-recovery-service.js +2 -0
  96. package/dist/core/task/task-resume-operation.js +11 -0
  97. package/dist/core/thread/command-parser.js +125 -0
  98. package/dist/core/thread/index.js +1 -0
  99. package/dist/core/thread/ipc-operation.js +95 -0
  100. package/dist/core/thread/thread-context-storage.js +131 -0
  101. package/dist/core/thread/thread-operation.js +258 -0
  102. package/dist/core/thread/thread-route.js +33 -0
  103. package/dist/core/thread/thread-service.js +777 -0
  104. package/dist/core/thread/types.js +1 -0
  105. package/dist/eck/message-renderer.js +35 -0
  106. package/dist/index.js +10 -7
  107. package/dist/ipc.js +234 -17
  108. package/dist/paths.js +23 -0
  109. package/dist/response-system/engines/v1/proactive-flow.js +169 -80
  110. package/dist/trigger/authorization.js +59 -29
  111. package/dist/trigger/feedback.js +7 -1
  112. package/dist/trigger/ipc-service.js +49 -35
  113. package/dist/trigger/parser.js +63 -1
  114. package/dist/trigger/script-sandbox.js +58 -77
  115. package/dist/trigger/validation.js +14 -0
  116. package/dist/utils/error-utils.js +22 -1
  117. package/kits/docs/AUTHORING.md +1 -1
  118. package/kits/docs/channels/aun.md +8 -0
  119. package/kits/docs/context-assembly.md +1 -0
  120. package/kits/docs/evolcore/INDEX.md +3 -2
  121. package/kits/docs/evolcore/agent-create.md +39 -28
  122. package/kits/docs/evolcore/agent.md +19 -4
  123. package/kits/docs/evolcore/ec-capabilities.md +4 -0
  124. package/kits/docs/evolcore/group-collaboration.md +3 -5
  125. package/kits/docs/evolcore/group.md +3 -4
  126. package/kits/docs/evolcore/memory-consolidation.md +1 -1
  127. package/kits/docs/evolcore/menu-exec-schema-commands.md +2 -2
  128. package/kits/docs/evolcore/menu-protocol.md +7 -0
  129. package/kits/docs/evolcore/msg.md +5 -8
  130. package/kits/docs/evolcore/task.md +2 -0
  131. package/kits/docs/evolcore/thread-chain.md +267 -0
  132. package/kits/docs/evolcore/trigger.md +2 -2
  133. package/kits/docs/prompt-loading-architecture.md +1 -0
  134. package/kits/eck_manifest.json +61 -26
  135. package/kits/eck_message_manifest.json +169 -10
  136. package/kits/rules/01-overview.md +0 -9
  137. package/kits/rules/05-venue.md +1 -1
  138. package/kits/rules/06-channel.md +7 -1
  139. package/kits/rules/07-memory-and-thread.md +202 -0
  140. package/kits/schemas/relation-config.schema.9.json +18 -3
  141. package/kits/schemas/role-config.schema.1.json +6 -6
  142. package/kits/schemas/single-session.schema.1.json +6 -6
  143. package/kits/schemas/single-session.schema.2.json +6 -6
  144. package/kits/schemas/single-session.schema.3.json +6 -6
  145. package/kits/skills/.switches.json +12 -1
  146. package/kits/skills/ec-group/SKILL.md +234 -0
  147. package/kits/skills/ec-skill/SKILL.md +10 -1
  148. package/kits/skills/ec-skill/scripts/cli.mjs +15 -1
  149. package/kits/skills/scrapling-article-fetch/SKILL.md +128 -0
  150. package/kits/skills/scrapling-article-fetch/scripts/check_python_env.py +54 -0
  151. package/kits/skills/scrapling-article-fetch/scripts/render_markdown_reply.py +35 -0
  152. package/kits/skills/scrapling-article-fetch/scripts/run_pipeline.sh +16 -0
  153. package/kits/skills/scrapling-article-fetch/scripts/scrapling_fetch.py +344 -0
  154. package/kits/skills/thread-ops/SKILL.md +492 -0
  155. package/kits/skills/wechat-article-media-download/SKILL.md +65 -0
  156. package/kits/skills/wechat-article-media-download/scripts/download.py +163 -0
  157. package/kits/skills/wechat-article-reader/SKILL.md +97 -0
  158. package/kits/skills/wechat-article-reader/scripts/fetch.mjs +256 -0
  159. package/kits/templates/bootstrap-welcome.md +7 -7
  160. package/kits/templates/memory-consolidation/forget.md +5 -0
  161. package/kits/templates/memory-consolidation/generalize.md +5 -0
  162. package/kits/templates/memory-consolidation/profile.md +5 -0
  163. package/kits/templates/memory-consolidation/promote.md +5 -0
  164. package/kits/templates/message-fragments/item.md +2 -1
  165. package/kits/templates/message-fragments/thread-context.md +6 -0
  166. package/kits/templates/message-fragments/trigger-session.md +2 -0
  167. package/kits/templates/message-fragments/trigger-thread-check.md +2 -0
  168. package/kits/templates/roles/member.json +2 -0
  169. package/kits/templates/roles/visitor.json +2 -0
  170. package/kits/templates/system-fragments/bootstrap.md +66 -72
  171. package/kits/templates/system-fragments/channel.md +3 -6
  172. package/kits/templates/system-fragments/commands.md +2 -1
  173. package/kits/templates/system-fragments/managed-runtime.md +15 -0
  174. package/kits/templates/system-fragments/reply.md +3 -2
  175. package/kits/templates/system-fragments/session.md +5 -14
  176. package/package.json +3 -1
  177. package/kits/docs/evolcore/group-fs.md +0 -17
  178. package/kits/docs/venues/aun-group.md +0 -45
  179. package/kits/docs/venues/group.md +0 -43
@@ -0,0 +1 @@
1
+ export {};
@@ -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
@@ -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';
@@ -426,13 +426,15 @@ async function main() {
426
426
  getSessionById: sessionId => sessionManager.getSessionById(sessionId),
427
427
  isSessionBusy: sessionId => messageQueue.isProcessing(sessionId) || messageQueue.getQueueLength(sessionId) > 0,
428
428
  getSessionIdleTriggerIds: () => triggerSchedulers.sessionIdleTriggerIds(),
429
- getSessionIdleSeconds: readRelationSessionIdleSeconds,
429
+ getSessionIdleSeconds: readSessionLoopIdleSeconds,
430
430
  getSessionEncrypt: sessionId => sessionManager.getSessionEncrypt(sessionId),
431
+ isCurrentMainSession: session => sessionManager.getActiveSessionSync(session.channel, session.channelId)?.id === session.id,
431
432
  });
432
433
  sessionIdleMonitor.start();
433
434
  onConfigWrite(({ target, selector }) => {
434
- if (target === ConfigTarget.Relation && selector.self)
435
- sessionIdleMonitor.refresh();
435
+ if (target === ConfigTarget.Relation && selector.self && selector.peerKey) {
436
+ void sessionIdleMonitor.refreshRelation(selector.self, selector.peerKey);
437
+ }
436
438
  });
437
439
  onShutdown(() => sessionIdleMonitor.stop());
438
440
  const targetSessionLocks = new TargetSessionLockRegistry();
@@ -490,10 +492,11 @@ async function main() {
490
492
  sessionManager,
491
493
  getAgent: aid => agentRegistry.get(aid),
492
494
  agentMap,
493
- releaseSlot: aid => consolidationQueue.release(aid),
495
+ releaseSlot: (aid, sessionId) => consolidationQueue.release(aid, sessionId),
494
496
  enqueueConsolidation,
495
497
  sendFeedback: sendConsolidationFeedback,
496
498
  });
499
+ consolidationQueue.setFinalizer(finishConsolidationSession);
497
500
  registerConsolidationSessionEvents({
498
501
  eventBus,
499
502
  permissionGateway,
@@ -640,11 +643,11 @@ async function main() {
640
643
  getAgentRuntimeError: () => agentRuntimeError,
641
644
  daemonAid: daemonCfg.aid,
642
645
  getControlAidState: () => controlChannel?.getAidState(),
643
- }), async (cmd, sessionId, delegationToken, delegationCommandHash) => {
646
+ }), async (argv, sessionId, delegationToken, delegationCommandHash) => {
644
647
  const delegation = agentDelegationRegistry.validate(delegationToken, sessionId, delegationCommandHash);
645
648
  if (!delegation.ok)
646
649
  return { ok: false, code: delegation.code, error: delegation.reason };
647
- return cmdHandler.handleCtl(cmd, sessionId, delegation.grant);
650
+ return cmdHandler.handleManagedCliOperation(argv, sessionId, delegation.grant);
648
651
  });
649
652
  ipcServer.setDaemonRuntimeEpoch(agentDelegationRegistry.getRuntimeEpoch());
650
653
  const { reloadHooks, reloadCoordinator } = createAgentReloadRuntime({
package/dist/ipc.js CHANGED
@@ -17,10 +17,12 @@ 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';
25
+ import { MAIN_CLI_BIN } from './product.js';
24
26
  const isWindows = process.platform === 'win32';
25
27
  const isNamedPipe = (p) => isWindows && p.toLowerCase().startsWith('\\\\.\\pipe\\');
26
28
  const CPU_SAMPLE_INTERVAL_MS = 1000;
@@ -75,6 +77,16 @@ const LOCAL_CONTROL_COMMANDS = new Set([
75
77
  'remote-auth.redeem',
76
78
  'remote-auth.validate',
77
79
  ]);
80
+ const MEMORY_COMMAND_ENDPOINTS = new Set([
81
+ 'memory.note', 'memory.note.update', 'memory.note.drop', 'memory.note.list',
82
+ 'memory.create', 'memory.update', 'memory.archive', 'memory.demote', 'memory.consolidate', 'memory.feedback',
83
+ ]);
84
+ const DELEGATED_ARGV_ENDPOINTS = new Set([
85
+ 'agent.op', 'config.op', 'contact.op', 'aid.op', 'group.op', 'msg.op', 'fs.op',
86
+ 'ctl', 'diag', 'menu-client.request', 'task.resume', 'queue.op', 'storage.auth', 'storage.upload',
87
+ 'trigger.op', 'skill.refresh', 'thread.op', 'local-command-context', 'evolagent.bootstrapComplete', ...MEMORY_COMMAND_ENDPOINTS,
88
+ 'handoff-return', 'handoff-recover-return', 'handoff-status', 'handoff-list', 'handoff-trace',
89
+ ]);
78
90
  let ipcQuerySequence = 0;
79
91
  function ipcLogToken(value, fallback = 'unknown') {
80
92
  const token = String(value ?? '').replace(/[^A-Za-z0-9_.:-]/g, '_').slice(0, 128);
@@ -94,9 +106,17 @@ function nextIpcQueryId(cmd) {
94
106
  function requiresLocalControlToken(cmd) {
95
107
  // Managed calls use task delegation. Standalone queries must not gain
96
108
  // management scope merely by omitting (or emptying) sessionId.
97
- return cmd.type === 'evolagent.initialize' || LOCAL_CONTROL_COMMANDS.has(String(cmd.type ?? ''))
98
- || (['evolagent.bootstrapComplete', 'diag', 'handoff-status', 'handoff-list', 'handoff-trace', 'task.resume'].includes(String(cmd.type))
99
- && !(typeof cmd.sessionId === 'string' && cmd.sessionId.trim()));
109
+ const type = String(cmd.type ?? '');
110
+ const sessionId = typeof cmd.sessionId === 'string' && cmd.sessionId.trim();
111
+ const delegated = typeof cmd.delegationToken === 'string' && cmd.delegationToken.trim();
112
+ if (cmd.type === 'evolagent.initialize' || LOCAL_CONTROL_COMMANDS.has(type))
113
+ return true;
114
+ if (type === 'debug-issue-token')
115
+ return true;
116
+ if (type === 'skill.refresh' || type === 'thread.op')
117
+ return !sessionId || !delegated;
118
+ return ['evolagent.bootstrapComplete', 'diag', 'handoff-status', 'handoff-list', 'handoff-trace', 'task.resume'].includes(type)
119
+ && !sessionId;
100
120
  }
101
121
  /** Preserve the pipe DACL and grant only the provisioned Codex users data I/O. */
102
122
  function grantWindowsSandboxPipeAccess(endpoint) {
@@ -153,6 +173,7 @@ export class IpcServer {
153
173
  aunAidStatsRecorder;
154
174
  menuExecutor;
155
175
  agentOperationExecutor;
176
+ skillRefreshExecutor;
156
177
  initializationExecutor;
157
178
  statsProvider;
158
179
  agentStatsProvider;
@@ -171,6 +192,7 @@ export class IpcServer {
171
192
  shutdownExecutor;
172
193
  taskRuntimeContextProvider;
173
194
  debugTaskRuntimeContextProvider;
195
+ debugIssueTokenExecutor;
174
196
  taskRuntimeContextAuthorizer;
175
197
  codexPreToolUseExecutor;
176
198
  aunMsgSender;
@@ -188,6 +210,7 @@ export class IpcServer {
188
210
  groupOperationExecutor;
189
211
  msgOperationExecutor;
190
212
  fsOperationExecutor;
213
+ threadOperationExecutor;
191
214
  dingtalkContactBindExecutor;
192
215
  feishuContactBindExecutor;
193
216
  qqbotContactBindExecutor;
@@ -275,6 +298,9 @@ export class IpcServer {
275
298
  setAgentOperationExecutor(executor) {
276
299
  this.agentOperationExecutor = executor;
277
300
  }
301
+ setSkillRefreshExecutor(executor) {
302
+ this.skillRefreshExecutor = executor;
303
+ }
278
304
  setConfigOperationExecutor(executor) {
279
305
  this.configOperationExecutor = executor;
280
306
  }
@@ -293,6 +319,9 @@ export class IpcServer {
293
319
  setFsOperationExecutor(executor) {
294
320
  this.fsOperationExecutor = executor;
295
321
  }
322
+ setThreadOperationExecutor(executor) {
323
+ this.threadOperationExecutor = executor;
324
+ }
296
325
  setAgentReloadExecutor(executor) {
297
326
  this.agentReloadExecutor = executor;
298
327
  }
@@ -428,7 +457,7 @@ export class IpcServer {
428
457
  setTriggerExecutor(executor) {
429
458
  this.triggerExecutor = executor;
430
459
  }
431
- /** Inject daemon-level consolidation launcher that uses the real trigger scheduler. */
460
+ /** Inject daemon-level consolidation launcher (BackgroundSessionLauncher, via executor closure). */
432
461
  setConsolidationLaunchExecutor(executor) {
433
462
  this.consolidationLaunchExecutor = executor;
434
463
  }
@@ -444,15 +473,17 @@ export class IpcServer {
444
473
  setTaskRuntimeContextProvider(provider) {
445
474
  this.taskRuntimeContextProvider = provider;
446
475
  }
447
- /** 仅开发仓(npm link)安装注册;正式安装不调用,debug 请求一律走正常路径。 */
448
476
  setDebugTaskRuntimeContextProvider(provider) {
449
477
  this.debugTaskRuntimeContextProvider = provider;
450
478
  }
479
+ /** debug 模式:注册 debug-issue-token executor,仅 EVOLCORE_DEBUG_MODE=1 时由 index.ts 调用。 */
480
+ setDebugIssueTokenExecutor(executor) {
481
+ this.debugIssueTokenExecutor = executor;
482
+ }
451
483
  /**
452
- * memory 命令取运行时上下文:先查正在运行的任务;没有且请求带 debug 时,
453
- * 再由开发仓专用的 provider 从会话文件重建。
484
+ * memory 命令取运行时上下文:查正在运行的任务。
454
485
  */
455
- async resolveMemoryTaskCtx(sessionId, debug) {
486
+ async resolveMemoryTaskCtx(sessionId, debug = false) {
456
487
  const active = this.taskRuntimeContextProvider?.({ sessionId });
457
488
  if (active || !debug || !this.debugTaskRuntimeContextProvider)
458
489
  return active;
@@ -468,6 +499,14 @@ export class IpcServer {
468
499
  setAunMsgSender(sender) {
469
500
  this.aunMsgSender = sender;
470
501
  }
502
+ hasAunMsgSender() {
503
+ return this.aunMsgSender !== undefined;
504
+ }
505
+ async sendAunMsg(params) {
506
+ if (!this.aunMsgSender)
507
+ throw new Error('aunMsgSender not configured');
508
+ return this.aunMsgSender(params);
509
+ }
471
510
  setDiagExecutor(executor) { this.diagExecutor = executor; }
472
511
  setMenuClientExecutor(executor) { this.menuClientExecutor = executor; }
473
512
  /** Inject internal handoff result return executor for `ec handoff return`. */
@@ -917,6 +956,7 @@ export class IpcServer {
917
956
  }
918
957
  if (typeof cmd.delegationToken === 'string' && cmd.delegationToken
919
958
  && this.daemonRuntimeEpoch
959
+ && cmd.daemonRuntimeEpoch !== undefined
920
960
  && cmd.daemonRuntimeEpoch !== this.daemonRuntimeEpoch) {
921
961
  logger.warn(`[IPC] stale delegation rejected: session=${ipcLogToken(cmd.sessionId ?? cmd.originSessionId ?? cmd.actorSessionId)} type=${ipcLogToken(cmd.type)} cause=daemon_runtime_epoch_mismatch`);
922
962
  return {
@@ -925,6 +965,75 @@ export class IpcServer {
925
965
  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',
926
966
  };
927
967
  }
968
+ if (typeof cmd.delegationToken === 'string'
969
+ && (DELEGATED_ARGV_ENDPOINTS.has(cmd.type) || (cmd.type === 'aun-msg-send' && cmd.argv !== undefined))) {
970
+ if (!Array.isArray(cmd.argv) || cmd.argv.some(value => typeof value !== 'string')) {
971
+ return { ok: false, code: 'INVALID_REQUEST', error: 'Invalid command argv' };
972
+ }
973
+ const expectedHash = hashDelegatedCommandArgv([
974
+ MAIN_CLI_BIN,
975
+ ...(cmd.type === 'menu-client.request' ? ['menu-client'] : []),
976
+ ...cmd.argv,
977
+ ]);
978
+ if (!expectedHash || cmd.delegationCommandHash !== expectedHash) {
979
+ return { ok: false, code: 'INVALID_DELEGATION', error: 'Command hash does not match the submitted argv' };
980
+ }
981
+ }
982
+ if (cmd.argv !== undefined && ['handoff-status', 'handoff-list', 'handoff-trace'].includes(cmd.type)) {
983
+ try {
984
+ const { parseList, parseTrace } = await import('./cli/handoff-command.js');
985
+ if (!Array.isArray(cmd.argv) || cmd.argv[0] !== 'handoff' || `handoff-${cmd.argv[1]}` !== cmd.type) {
986
+ return { ok: false, code: 'INVALID_REQUEST', error: 'Handoff endpoint does not match argv' };
987
+ }
988
+ if (cmd.type === 'handoff-list') {
989
+ const parsed = parseList(cmd.argv.slice(2));
990
+ cmd = { ...cmd, agent: parsed.agent, state: parsed.state, filterSessionId: parsed.sessionId, limit: parsed.limit };
991
+ }
992
+ else {
993
+ const parsed = parseTrace(cmd.argv.slice(2));
994
+ if (cmd.type === 'handoff-status' && cmd.argv.length !== 3)
995
+ throw new Error('Invalid handoff status arguments');
996
+ cmd = { ...cmd, agent: parsed.agent, handoffId: parsed.handoffId, limit: parsed.limit };
997
+ }
998
+ }
999
+ catch (error) {
1000
+ return { ok: false, code: 'INVALID_ARGUMENT', error: error instanceof Error ? error.message : String(error) };
1001
+ }
1002
+ }
1003
+ if (MEMORY_COMMAND_ENDPOINTS.has(cmd.type)) {
1004
+ if (typeof cmd.sessionId !== 'string' || !cmd.sessionId)
1005
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId' };
1006
+ if (cmd.debug === true) {
1007
+ if (cmd.delegationToken || !this.hasValidControlToken(cmd.controlToken)) {
1008
+ return { ok: false, code: 'INVALID_CONTROL_TOKEN', error: 'Memory debug requires a local control token, not task delegation' };
1009
+ }
1010
+ }
1011
+ else {
1012
+ if (!this.taskRuntimeContextAuthorizer)
1013
+ return { ok: false, code: 'DELEGATION_REQUIRED', error: 'Memory authorization is not configured' };
1014
+ if (!Array.isArray(cmd.argv) || cmd.argv.some((value) => typeof value !== 'string') || cmd.argv.includes('--debug')) {
1015
+ return { ok: false, code: 'INVALID_REQUEST', error: 'Managed memory requires argv without --debug' };
1016
+ }
1017
+ const authorization = this.taskRuntimeContextAuthorizer({
1018
+ sessionId: cmd.sessionId, delegationToken: cmd.delegationToken,
1019
+ delegationCommandHash: cmd.delegationCommandHash, consumeApproval: true,
1020
+ });
1021
+ if (!authorization.ok)
1022
+ return authorization;
1023
+ }
1024
+ if (cmd.argv !== undefined) {
1025
+ try {
1026
+ const { resolveMemoryCommandArgv } = await import('./cli/memory-command.js');
1027
+ const operation = resolveMemoryCommandArgv(cmd.argv);
1028
+ if (operation.type !== cmd.type)
1029
+ return { ok: false, code: 'INVALID_REQUEST', error: 'Memory endpoint does not match argv' };
1030
+ cmd = { ...operation, sessionId: cmd.sessionId, debug: cmd.debug === true };
1031
+ }
1032
+ catch (error) {
1033
+ return { ok: false, code: 'INVALID_ARGUMENT', error: error instanceof Error ? error.message : String(error) };
1034
+ }
1035
+ }
1036
+ }
928
1037
  switch (cmd.type) {
929
1038
  case 'diag':
930
1039
  return this.diagExecutor ? this.diagExecutor(cmd) : { ok: false, code: 'NOT_CONFIGURED', message: '诊断入口未配置' };
@@ -1168,6 +1277,7 @@ export class IpcServer {
1168
1277
  sessionId: cmd.sessionId,
1169
1278
  delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
1170
1279
  delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
1280
+ argv: Array.isArray(cmd.argv) ? cmd.argv : undefined,
1171
1281
  });
1172
1282
  }
1173
1283
  case 'status.auth': {
@@ -1191,6 +1301,7 @@ export class IpcServer {
1191
1301
  return { ok: false, code: 'INVALID_REQUEST', error: 'invalid storage operation' };
1192
1302
  }
1193
1303
  return await this.storageAuthorizationExecutor({
1304
+ argv: cmd.argv,
1194
1305
  sessionId: cmd.sessionId,
1195
1306
  aid: cmd.aid,
1196
1307
  operation: cmd.operation,
@@ -1208,6 +1319,7 @@ export class IpcServer {
1208
1319
  return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId, aid, localFile, or remotePath' };
1209
1320
  }
1210
1321
  return await this.storageUploadExecutor({
1322
+ argv: cmd.argv,
1211
1323
  sessionId: cmd.sessionId,
1212
1324
  aid: cmd.aid,
1213
1325
  localFile: cmd.localFile,
@@ -1235,9 +1347,10 @@ export class IpcServer {
1235
1347
  }
1236
1348
  }
1237
1349
  case 'task.resume': {
1238
- const allowed = new Set(['type', 'targetSessionId', 'sessionId', 'delegationToken',
1350
+ const allowed = new Set(['type', 'argv', 'targetSessionId', 'sessionId', 'delegationToken',
1239
1351
  'delegationCommandHash', 'controlToken', 'daemonRuntimeEpoch', 'requestId', 'id']);
1240
1352
  if (Object.keys(cmd).some(key => !allowed.has(key))
1353
+ || (cmd.argv !== undefined && (!Array.isArray(cmd.argv) || cmd.argv.some((value) => typeof value !== 'string')))
1241
1354
  || typeof cmd.targetSessionId !== 'string' || !cmd.targetSessionId.trim()
1242
1355
  || (cmd.sessionId !== undefined && (typeof cmd.sessionId !== 'string' || !cmd.sessionId.trim()))) {
1243
1356
  return { ok: false, code: 'INVALID_REQUEST', error: 'task.resume accepts only a target session and caller credentials' };
@@ -1250,6 +1363,7 @@ export class IpcServer {
1250
1363
  try {
1251
1364
  return await this.taskResumeExecutor({
1252
1365
  targetSessionId: cmd.targetSessionId,
1366
+ argv: Array.isArray(cmd.argv) ? cmd.argv : undefined,
1253
1367
  sessionId: cmd.sessionId,
1254
1368
  delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
1255
1369
  delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
@@ -1260,6 +1374,34 @@ export class IpcServer {
1260
1374
  return { ok: false, code: 'TASK_RESUME_FAILED', error: error instanceof Error ? error.message : String(error) };
1261
1375
  }
1262
1376
  }
1377
+ case 'local-command-context': {
1378
+ if (!Array.isArray(cmd.argv) || cmd.argv.some((value) => typeof value !== 'string')
1379
+ || !['skill', 'stats'].includes(cmd.argv[0]) || typeof cmd.sessionId !== 'string' || !cmd.sessionId
1380
+ || typeof cmd.delegationToken !== 'string' || !cmd.delegationToken) {
1381
+ return { ok: false, code: 'INVALID_REQUEST', error: 'Local command requires argv and task credentials' };
1382
+ }
1383
+ if (!this.taskRuntimeContextAuthorizer || !this.taskRuntimeContextProvider) {
1384
+ return { ok: false, code: 'DELEGATION_REQUIRED', error: 'Command authorization is unavailable' };
1385
+ }
1386
+ const authorization = this.taskRuntimeContextAuthorizer({
1387
+ sessionId: cmd.sessionId, delegationToken: cmd.delegationToken,
1388
+ delegationCommandHash: cmd.delegationCommandHash, consumeApproval: true,
1389
+ });
1390
+ if (!authorization.ok)
1391
+ return authorization;
1392
+ const context = this.taskRuntimeContextProvider({ sessionId: cmd.sessionId });
1393
+ if (!context?.selfAid || !context.peerRole || context.peerRole === 'none') {
1394
+ return { ok: false, code: 'NOT_ALLOWED', error: 'Current task identity and role are unavailable' };
1395
+ }
1396
+ if (cmd.argv[0] === 'stats' && cmd.argv.some((value) => /^--(?:sql|rebuild)(?:=|$)/.test(value))) {
1397
+ return { ok: false, code: 'NOT_ALLOWED', error: 'Managed stats cannot use --sql or --rebuild' };
1398
+ }
1399
+ if (cmd.argv[0] === 'skill' && context.permissionMode === 'readonly'
1400
+ && ['create', 'install', 'remove', 'enable', 'disable'].includes(cmd.argv[1])) {
1401
+ return { ok: false, code: 'NOT_ALLOWED', error: 'Readonly tasks cannot modify skills' };
1402
+ }
1403
+ return { ok: true, context };
1404
+ }
1263
1405
  case 'task-runtime-context': {
1264
1406
  if (!this.taskRuntimeContextProvider)
1265
1407
  return { ok: false, error: 'task runtime context not configured' };
@@ -1272,13 +1414,35 @@ export class IpcServer {
1272
1414
  sessionId: cmd.sessionId,
1273
1415
  delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
1274
1416
  delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
1417
+ consumeApproval: false,
1275
1418
  });
1276
1419
  if (!authorization.ok)
1277
1420
  return authorization;
1278
1421
  const context = this.taskRuntimeContextProvider({ sessionId: cmd.sessionId }) ?? null;
1279
1422
  return { ok: true, context };
1280
1423
  }
1424
+ case 'debug-issue-token': {
1425
+ if (cmd.delegationToken)
1426
+ return { ok: false, code: 'NOT_ALLOWED', error: 'Managed tasks cannot issue debug tokens' };
1427
+ // 仅 EVOLCORE_DEBUG_MODE=1 时由 index.ts 注册 executor;非 debug 模式直接拒绝
1428
+ if (!this.debugIssueTokenExecutor) {
1429
+ return { ok: false, error: 'debug mode is not enabled; start daemon with: ec start --debug' };
1430
+ }
1431
+ if (typeof cmd.sessionId !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(cmd.sessionId)) {
1432
+ return { ok: false, error: 'missing sessionId' };
1433
+ }
1434
+ return this.debugIssueTokenExecutor({ sessionId: cmd.sessionId });
1435
+ }
1281
1436
  case 'aun-msg-send': {
1437
+ if (cmd.argv !== undefined) {
1438
+ if (!this.aunMsgSender)
1439
+ return { ok: false, code: 'NOT_CONFIGURED', error: 'AUN sender is not configured' };
1440
+ return this.aunMsgSender({
1441
+ aid: '', to: '', scope: 'msg', argv: cmd.argv,
1442
+ originSessionId: cmd.originSessionId, originMessageId: cmd.originMessageId,
1443
+ delegationToken: cmd.delegationToken, delegationCommandHash: cmd.delegationCommandHash,
1444
+ });
1445
+ }
1282
1446
  if (cmd.handoffContext !== undefined && (typeof cmd.handoffContext !== 'string'
1283
1447
  || !cmd.handoffContext.trim() || cmd.handoffContext.length > 64 * 1024 || cmd.scope === 'group')) {
1284
1448
  return { ok: false, code: 'INVALID_HANDOFF_CONTEXT', error: 'Private handoff context must contain 1–65536 characters' };
@@ -1336,7 +1500,6 @@ export class IpcServer {
1336
1500
  : undefined,
1337
1501
  encrypt: typeof cmd.encrypt === 'boolean' ? cmd.encrypt : undefined,
1338
1502
  thread: typeof cmd.thread === 'string' ? cmd.thread : undefined,
1339
- returnPolicy: cmd.returnPolicy === 'required' || cmd.returnPolicy === 'none' ? cmd.returnPolicy : undefined,
1340
1503
  handoffContext: cmd.handoffContext,
1341
1504
  originSessionId: typeof cmd.originSessionId === 'string' ? cmd.originSessionId : undefined,
1342
1505
  originMessageId: typeof cmd.originMessageId === 'string' ? cmd.originMessageId : undefined,
@@ -1356,6 +1519,7 @@ export class IpcServer {
1356
1519
  return { ok: false, code: 'HANDOFF_RETURN_CONTENT_REQUIRED', error: 'missing content' };
1357
1520
  try {
1358
1521
  return await this.handoffReturnExecutor({
1522
+ argv: cmd.argv,
1359
1523
  sessionId: typeof cmd.sessionId === 'string' ? cmd.sessionId : undefined,
1360
1524
  handoffId: typeof cmd.handoffId === 'string' ? cmd.handoffId : undefined,
1361
1525
  content: cmd.content,
@@ -1378,6 +1542,7 @@ export class IpcServer {
1378
1542
  return { ok: false, code: 'HANDOFF_RETURN_CONTENT_REQUIRED', error: 'missing content' };
1379
1543
  try {
1380
1544
  return await this.handoffRecoverReturnExecutor({
1545
+ argv: cmd.argv,
1381
1546
  sessionId: cmd.sessionId,
1382
1547
  handoffId: cmd.handoffId,
1383
1548
  content: cmd.content,
@@ -1444,10 +1609,13 @@ export class IpcServer {
1444
1609
  case 'ctl': {
1445
1610
  if (!this.commandExecutor)
1446
1611
  return { ok: false, error: 'ctl not configured' };
1447
- const { cmd: slashCmd, sessionId } = cmd;
1448
- if (!slashCmd || !sessionId)
1449
- return { ok: false, error: 'missing cmd or sessionId' };
1450
- return await this.commandExecutor(slashCmd, sessionId, typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
1612
+ const { sessionId, argv } = cmd;
1613
+ if (!sessionId || !Array.isArray(argv))
1614
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing argv or sessionId' };
1615
+ if (argv.some(value => typeof value !== 'string')) {
1616
+ return { ok: false, code: 'INVALID_REQUEST', error: 'Invalid command argv' };
1617
+ }
1618
+ return await this.commandExecutor(argv, sessionId, typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
1451
1619
  }
1452
1620
  case 'memory.note': {
1453
1621
  const { sessionId, slug, content, tags, speakers } = cmd;
@@ -1577,6 +1745,7 @@ export class IpcServer {
1577
1745
  contextFilePath: r.contextFilePath,
1578
1746
  ...(r.logFile ? { logFile: r.logFile } : {}),
1579
1747
  mode: effectiveMode,
1748
+ ...(r.queued ? { queued: r.queued } : {}),
1580
1749
  };
1581
1750
  }
1582
1751
  catch (e) {
@@ -1845,6 +2014,16 @@ export class IpcServer {
1845
2014
  }
1846
2015
  return await this.fsOperationExecutor(argv, sessionId, delegationToken, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
1847
2016
  }
2017
+ case 'thread.op': {
2018
+ if (!this.threadOperationExecutor)
2019
+ return { ok: false, code: 'NOT_CONFIGURED', error: 'thread.op not configured' };
2020
+ const delegated = typeof cmd.delegationToken === 'string' && cmd.delegationToken.trim();
2021
+ const req = {
2022
+ ...cmd,
2023
+ localControl: !delegated && this.hasValidControlToken(cmd.controlToken),
2024
+ };
2025
+ return await this.threadOperationExecutor(req);
2026
+ }
1848
2027
  case 'evolagent.initialize': {
1849
2028
  if (cmd.sessionId || cmd.delegationToken)
1850
2029
  return { ok: false, code: 'NOT_ALLOWED', error: 'Managed callers must use agent.op' };
@@ -1864,11 +2043,38 @@ export class IpcServer {
1864
2043
  }
1865
2044
  return await this.agentOperationExecutor(argv, sessionId, delegationToken, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
1866
2045
  }
2046
+ case 'skill.refresh': {
2047
+ if (!this.skillRefreshExecutor) {
2048
+ return { ok: false, code: 'NOT_CONFIGURED', error: 'skill.refresh not configured' };
2049
+ }
2050
+ let { aid } = cmd;
2051
+ const { sessionId, delegationToken } = cmd;
2052
+ if (typeof aid !== 'string' || !aid) {
2053
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing aid' };
2054
+ }
2055
+ if (sessionId !== undefined && typeof sessionId !== 'string') {
2056
+ return { ok: false, code: 'INVALID_REQUEST', error: 'sessionId must be a string' };
2057
+ }
2058
+ if (delegationToken !== undefined && typeof delegationToken !== 'string') {
2059
+ return { ok: false, code: 'INVALID_DELEGATION', error: 'delegationToken must be a string' };
2060
+ }
2061
+ if (sessionId && !delegationToken)
2062
+ return { ok: false, code: 'DELEGATION_REQUIRED', error: 'Managed skill refresh requires delegation' };
2063
+ try {
2064
+ if (!Array.isArray(cmd.argv))
2065
+ throw new Error('Skill refresh requires argv');
2066
+ aid = resolveSkillRefreshArgv(cmd.argv);
2067
+ }
2068
+ catch (error) {
2069
+ return { ok: false, code: 'INVALID_REQUEST', error: error instanceof Error ? error.message : String(error) };
2070
+ }
2071
+ return await this.skillRefreshExecutor(aid, sessionId, delegationToken, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
2072
+ }
2073
+ case 'trigger.op':
1867
2074
  case 'trigger.list':
1868
2075
  case 'trigger.show':
1869
2076
  case 'trigger.history':
1870
2077
  case 'trigger.eventCatalog':
1871
- case 'trigger.authorizeLocalFiles':
1872
2078
  case 'trigger.create':
1873
2079
  case 'trigger.update':
1874
2080
  case 'trigger.setEnabled':
@@ -1917,6 +2123,17 @@ export class IpcServer {
1917
2123
  const aid = cmd.aid;
1918
2124
  if (!aid || typeof aid !== 'string')
1919
2125
  return { ok: false, error: 'missing aid' };
2126
+ if (cmd.argv !== undefined) {
2127
+ if (!Array.isArray(cmd.argv) || cmd.argv.some((value) => typeof value !== 'string')) {
2128
+ return { ok: false, code: 'INVALID_REQUEST', error: 'Invalid command argv' };
2129
+ }
2130
+ const argv = cmd.argv;
2131
+ const validFormat = argv.length === 3
2132
+ || (argv.length === 5 && argv[3] === '--format' && argv[4] === 'json');
2133
+ if (argv[0] !== 'agent' || argv[1] !== 'ready' || argv[2] !== aid || !validFormat) {
2134
+ return { ok: false, code: 'INVALID_REQUEST', error: 'agent ready endpoint does not match argv' };
2135
+ }
2136
+ }
1920
2137
  if (!this.bootstrapCompleteExecutor)
1921
2138
  return { ok: false, error: 'bootstrap complete executor not configured' };
1922
2139
  try {
@@ -2333,7 +2550,7 @@ export async function ipcQuery(socketPath, cmd, timeoutMs = 3000, options = {})
2333
2550
  function ipcQueryOnce(socketPath, cmd, timeoutMs = 3000) {
2334
2551
  let authenticatedCmd = cmd;
2335
2552
  if (!process.env.EVOLCORE_SESSION_ID
2336
- && requiresLocalControlToken(cmd)
2553
+ && (requiresLocalControlToken(cmd) || (MEMORY_COMMAND_ENDPOINTS.has(cmd.type) && cmd.debug === true))
2337
2554
  && typeof cmd.controlToken !== 'string') {
2338
2555
  try {
2339
2556
  const controlToken = fs.readFileSync(resolvePaths().controlToken, 'utf8').trim();
@@ -2345,7 +2562,7 @@ function ipcQueryOnce(socketPath, cmd, timeoutMs = 3000) {
2345
2562
  const requestArgv = Array.isArray(authenticatedCmd.argv)
2346
2563
  && authenticatedCmd.argv.every((value) => typeof value === 'string')
2347
2564
  ? [
2348
- 'ec',
2565
+ MAIN_CLI_BIN,
2349
2566
  ...(authenticatedCmd.type === 'menu-client.request' ? ['menu-client'] : []),
2350
2567
  ...authenticatedCmd.argv,
2351
2568
  ]
package/dist/paths.js CHANGED
@@ -208,6 +208,26 @@ export function channelStatePath(channelKey, ...parts) {
208
208
  export function agentTriggersDir(aid) {
209
209
  return path.join(agentDir(aid), 'triggers');
210
210
  }
211
+ /** 话题数据的统一根目录:索引、摘要、续读锚点、跨会话收件箱都收在这里。 */
212
+ export function agentThreadsDir(aid) {
213
+ return path.join(agentDataDir(aid), 'threads');
214
+ }
215
+ export function agentThreadIndexPath(aid) {
216
+ return path.join(agentThreadsDir(aid), 'index.json');
217
+ }
218
+ export function agentThreadSummariesDir(aid) {
219
+ return path.join(agentThreadsDir(aid), 'summaries');
220
+ }
221
+ export function agentThreadSummaryPath(aid, sessionId) {
222
+ return path.join(agentThreadSummariesDir(aid), `${sessionId}.summary.jsonl`);
223
+ }
224
+ /** Thread Context 收件箱:跨话题发送后在目标会话侧留下的注入提醒。 */
225
+ export function agentThreadInboxDir(aid) {
226
+ return path.join(agentThreadsDir(aid), 'inbox');
227
+ }
228
+ export function agentThreadInboxPath(aid, targetSessionId) {
229
+ return path.join(agentThreadInboxDir(aid), `${targetSessionId}.jsonl`);
230
+ }
211
231
  function stripTrailingWindowsSeparators(value) {
212
232
  const stripped = value.replace(/[\\/]+$/g, '');
213
233
  // Keep a drive-root separator. `C:` is a drive-relative path on Windows.
@@ -414,6 +434,9 @@ export function kitsSchemasDir() {
414
434
  export function eckDebugDir() {
415
435
  return path.join(resolveRoot(), 'data', 'eck-debug');
416
436
  }
437
+ export function debugSessionsDir() {
438
+ return path.join(resolveRoot(), 'data', 'debug-sessions');
439
+ }
417
440
  export function getPackageRoot() {
418
441
  // import.meta.dirname is available in Node.js 21.2+ and always returns
419
442
  // the correct OS-native path, regardless of Git Bash or MSYS2 environment.