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
@@ -113,10 +113,11 @@ export const MENU_NAME_COMMANDS = Object.freeze({
113
113
  model: '/model',
114
114
  effort: '/effort',
115
115
  chatmode: '/chatmode',
116
- mentionmode: '/mentionmode',
116
+ mentionmode: '/mention',
117
117
  group: '/group',
118
118
  permission: '/perm',
119
119
  activity: '/activity',
120
+ task: '/task',
120
121
  dispatch: '/dispatch',
121
122
  observable: '/observable',
122
123
  system: '/system',
@@ -215,7 +216,7 @@ export function isEvolMenuVersionGateEnabled() {
215
216
  export function isAunMenuTokenRequired() {
216
217
  return loadDaemonConfig().aun?.menuTokenRequired === true;
217
218
  }
218
- export function evolMenuResponseTransportMetadata(sdkVersion) {
219
+ export function evolMenuResponseTransportMetadata(sdkVersion, volatileCapability) {
219
220
  return {
220
221
  // Clear inherited request state so AUNChannel applies daemon aun.defaultEncrypt.
221
222
  encrypted: undefined,
@@ -226,6 +227,7 @@ export function evolMenuResponseTransportMetadata(sdkVersion) {
226
227
  ...(typeof sdkVersion === 'string' && sdkVersion.trim()
227
228
  ? { menuClientSdkVersion: sdkVersion.trim() }
228
229
  : {}),
230
+ ...(volatileCapability === '1' ? { menuClientVolatileV1: true } : {}),
229
231
  };
230
232
  }
231
233
  const EXPLICIT_SCOPE_UPDATE_NAMES = new Set([
@@ -243,7 +245,7 @@ const EXPLICIT_SCOPE_UPDATE_COMMANDS = new Set([
243
245
  '/effort',
244
246
  '/chatmode',
245
247
  '/dispatch',
246
- '/mentionmode',
248
+ '/mention',
247
249
  '/group',
248
250
  '/perm',
249
251
  '/activity',
@@ -315,6 +317,16 @@ export function validateMenuRequest(request) {
315
317
  if (request.args !== undefined && (!request.args || typeof request.args !== 'object' || Array.isArray(request.args))) {
316
318
  return { code: 'INVALID_ARGUMENT', message: 'Menu request args must be an object' };
317
319
  }
320
+ if (request.name === 'task' || request.cmd === '/task') {
321
+ if (type !== 'menu.query')
322
+ return { code: 'NOT_SUPPORTED', message: 'task only supports menu.query' };
323
+ const taskError = validateTaskActivityQueryArgs(request.args);
324
+ if (taskError)
325
+ return taskError;
326
+ }
327
+ if (type === 'menu.list' && Object.hasOwn(request, 'context')) {
328
+ return { code: 'INVALID_ARGUMENT', message: 'menu.list context must be inside args.context (for a daemon catalog, use args.context.kind=process)' };
329
+ }
318
330
  if (type === 'menu.update') {
319
331
  const args = request.args;
320
332
  const scopeError = validateConfigWriteScope(request.name, args)
@@ -350,6 +362,32 @@ export function validateMenuRequest(request) {
350
362
  }
351
363
  return null;
352
364
  }
365
+ export function validateTaskActivityQueryArgs(value) {
366
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
367
+ return { code: 'INVALID_ARGUMENT', message: 'task query requires args' };
368
+ }
369
+ const args = value;
370
+ if (args.view !== 'activities' && args.view !== 'activity') {
371
+ return { code: 'INVALID_ARGUMENT', message: 'task query requires args.view=activities or activity' };
372
+ }
373
+ const allowed = args.view === 'activities' ? ['view', 'taskId', 'offset', 'limit'] : ['view', 'taskId', 'activityId'];
374
+ if (Object.keys(args).some(key => !allowed.includes(key))) {
375
+ return { code: 'INVALID_ARGUMENT', message: 'unsupported task query argument' };
376
+ }
377
+ if (typeof args.taskId !== 'string' || !/^task-[A-Za-z0-9._:-]+$/.test(args.taskId)) {
378
+ return { code: 'INVALID_ARGUMENT', message: 'invalid taskId' };
379
+ }
380
+ if (args.view === 'activity') {
381
+ if (typeof args.activityId !== 'string' || !/^activity-[A-Za-z0-9._:-]+$/.test(args.activityId)) {
382
+ return { code: 'INVALID_ARGUMENT', message: 'invalid activityId' };
383
+ }
384
+ }
385
+ else if ((args.offset !== undefined && (!Number.isSafeInteger(args.offset) || args.offset < 0))
386
+ || (args.limit !== undefined && (!Number.isSafeInteger(args.limit) || args.limit < 1 || args.limit > 100))) {
387
+ return { code: 'INVALID_ARGUMENT', message: 'offset must be a non-negative integer and limit must be between 1 and 100' };
388
+ }
389
+ return null;
390
+ }
353
391
  export function menuSuccess(header, data) {
354
392
  return {
355
393
  type: 'menu.response',
@@ -370,7 +408,9 @@ export function menuFailure(header, error) {
370
408
  },
371
409
  };
372
410
  }
373
- export function enforceMenuResponseSize(response, maxBytes = 128 * 1024) {
411
+ export const MENU_RESPONSE_MAX_BYTES = 384 * 1024;
412
+ export const MENU_RESPONSE_SAFETY_MARGIN_BYTES = 1024;
413
+ export function enforceMenuResponseSize(response, maxBytes = MENU_RESPONSE_MAX_BYTES) {
374
414
  let bytes;
375
415
  try {
376
416
  bytes = Buffer.byteLength(JSON.stringify(response), 'utf8');
@@ -405,6 +445,7 @@ const STABLE_CODES = new Set([
405
445
  'RATE_LIMITED', 'CATALOG_STALE', 'DATA_MIGRATION_REQUIRED',
406
446
  'INVALID_CLIENT', 'REMOTE_ACCESS_TOKEN_INVALID', 'ECWEB_TOKEN_INVALID', 'CLIENT_BUSY', 'INVALID_RESPONSE', 'TIMEOUT',
407
447
  'RESPONSE_TOO_LARGE',
448
+ 'ACTIVITY_NOT_FOUND', 'ACTIVITY_EXPIRED',
408
449
  'TOPIC_SESSION_NOT_FOUND', 'TOPIC_SESSION_LOOKUP_FAILED',
409
450
  'ROOT_NOT_FOUND', 'ROOT_FORBIDDEN', 'ROOT_EXPIRED', 'ROOT_SCOPE_MISMATCH', 'ROOT_PEER_MISMATCH',
410
451
  'INVALID_ROOT_ID', 'MISSING_ROOT_ID', 'INVALID_ROOT_PATH', 'NOT_A_DIRECTORY', 'FILE_TOO_LARGE',
@@ -43,7 +43,7 @@ export function probeSessionActivity(evidence, probes) {
43
43
  return evaluateSessionActivity(collected);
44
44
  }
45
45
  // 支持的命令列表
46
- const commands = ['/new', '/pwd', '/help', '/evolhelp', '/status', '/restart', '/reload', '/model', '/effort', '/baseagent', '/slist', '/session', '/rename', '/stop', '/pause', '/compact', '/renew', '/repair', '/fork', '/del', '/perm', '/file', '/check', '/rewind', '/activity', '/observable', '/chatmode', '/mentionmode', '/ask', '/resume', '/aid', '/rpc', '/storage', '/agent', '/trigger', '/upgrade', '/pair'];
46
+ const commands = ['/new', '/pwd', '/help', '/evolhelp', '/status', '/restart', '/reload', '/model', '/effort', '/baseagent', '/slist', '/session', '/rename', '/stop', '/pause', '/compact', '/renew', '/repair', '/fork', '/del', '/perm', '/file', '/check', '/rewind', '/activity', '/observable', '/chatmode', '/mention', '/ask', '/resume', '/aid', '/rpc', '/storage', '/agent', '/trigger', '/upgrade', '/pair', '/memory'];
47
47
  const deprecatedCommands = ['/clear'];
48
48
  commands.push('/diag');
49
49
  const exactBoundaryCommands = new Set(['/pause', '/resume', '/stop', '/pair', '/diag']);
@@ -64,10 +64,11 @@ const aliases = {
64
64
  '/name': '/rename',
65
65
  '/rw': '/rewind',
66
66
  '/base': '/baseagent',
67
+ '/mentionmode': '/mention',
67
68
  };
68
- const GROUP_READ_ONLY_COMMANDS = new Set(['/mentionmode', '/model', '/effort', '/perm', '/baseagent']);
69
+ const GROUP_READ_ONLY_COMMANDS = new Set(['/model', '/effort', '/perm', '/baseagent']);
69
70
  const GROUP_TASK_COMMANDS = new Set([
70
- '/help', '/evolhelp', '/status', '/check', '/ask', '/pause', '/resume', '/stop', '/compact', '/renew',
71
+ '/help', '/evolhelp', '/status', '/check', '/ask', '/pause', '/resume', '/stop', '/compact', '/renew', '/mention', '/memory',
71
72
  ]);
72
73
  /** Group slash policy applies to every role, including old command-card clicks. */
73
74
  export function guardGroupSlashCommand(content, chatType) {
@@ -94,7 +95,7 @@ export function guardGroupSlashCommand(content, chatType) {
94
95
  };
95
96
  }
96
97
  // 命令快速路径前缀(所有命令都不进入消息队列)
97
- const quickCommandPrefixes = ['/new', '/pwd', '/help', '/evolhelp', '/status', '/restart', '/reload', '/model', '/effort', '/baseagent', '/slist', '/session', '/rename', '/repair', '/fork', '/stop', '/pause', '/clear', '/compact', '/renew', '/del', '/perm', '/file', '/check', '/s ', '/name', '/rewind', '/rw', '/rw ', '/activity', '/observable', '/chatmode', '/mentionmode', '/ask', '/resume', '/base ', '/aid', '/rpc', '/storage', '/agent', '/trigger', '/upgrade', '/pair'];
98
+ const quickCommandPrefixes = ['/new', '/pwd', '/help', '/evolhelp', '/status', '/restart', '/reload', '/model', '/effort', '/baseagent', '/slist', '/session', '/rename', '/repair', '/fork', '/stop', '/pause', '/clear', '/compact', '/renew', '/del', '/perm', '/file', '/check', '/s ', '/name', '/rewind', '/rw', '/rw ', '/activity', '/observable', '/chatmode', '/mention', '/ask', '/resume', '/base ', '/aid', '/rpc', '/storage', '/agent', '/trigger', '/upgrade', '/pair', '/memory'];
98
99
  quickCommandPrefixes.push('/diag');
99
100
  /**
100
101
  * 计算两个字符串的 Levenshtein 距离(编辑距离)
@@ -149,8 +150,7 @@ export function guardThreadCommand(content, threadId) {
149
150
  const threadBlocked = ['/new', '/slist', '/s', '/session', '/fork', '/del', '/repair'];
150
151
  const hasCommandArgument = (command) => new RegExp(`^${command.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?:\\s|$)`).test(content);
151
152
  const isBlocked = threadBlocked.some(hasCommandArgument);
152
- const isRewindMutation = /^\/rewind\s/.test(content);
153
- if (!isBlocked && !isRewindMutation)
153
+ if (!isBlocked)
154
154
  return undefined;
155
155
  return { kind: 'command.error', text: '⚠️ 话题中不支持此命令' };
156
156
  }
@@ -159,9 +159,9 @@ export function guardRoleCommand(content, activeChatType, isAdmin) {
159
159
  return undefined;
160
160
  // visitor/member 在群聊和私聊中均可访问的只读命令:纯查询形态(带参写操作由各 handler 内部守卫拦截)
161
161
  const userGroupCommands = [
162
- '/status', '/help', '/evolhelp', '/check', '/chatmode', '/mentionmode',
162
+ '/status', '/help', '/evolhelp', '/check', '/chatmode', '/mention',
163
163
  '/model', '/effort', '/baseagent', '/perm', '/activity', '/stop', '/pause',
164
- '/resume', '/trigger', '/file', '/ask',
164
+ '/resume', '/trigger', '/file', '/ask', '/memory',
165
165
  ];
166
166
  const userCommands = activeChatType === 'group' && !isAdmin
167
167
  ? userGroupCommands
@@ -186,14 +186,14 @@ export async function guardIdleCommand(opts) {
186
186
  // - 始终需要 idle(无参即写):/compact /repair /fork /new
187
187
  // - 仅带参时需要 idle(无参是列表/用法):/session /baseagent /rewind
188
188
  // - /chatmode:在 handler 内部自行做写操作的 idle 检查
189
- // - /mentionmode:在 handler 内部自行做写操作的 idle 检查
189
+ // - /mention:在 handler 内部自行做写操作的 idle 检查
190
190
  // /renew owns a stronger gate + authoritative probe and deliberately skips
191
191
  // this realtime precheck so delayed retries can return their committed
192
192
  // idempotent result even while later work is busy.
193
193
  const idleAlways = ['/compact', '/repair', '/fork', '/new'];
194
194
  const idleWhenArg = ['/session', '/baseagent', '/rewind'];
195
195
  const usesTopicBackendBoundary = !!opts.threadId
196
- && opts.content === '/compact'
196
+ && (opts.content === '/compact' || opts.content.startsWith('/rewind '))
197
197
  && typeof opts.messageQueue?.withSessionBarrier === 'function';
198
198
  const needsIdle = !usesTopicBackendBoundary && (idleAlways.some(cmd => opts.content === cmd || opts.content.startsWith(cmd + ' ')) ||
199
199
  idleWhenArg.some(cmd => opts.content.startsWith(cmd + ' ')));