evolcore 0.0.28 → 0.0.29

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 (183) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/bin/ec-safe-output.js +270 -54
  3. package/dist/agents/baseagent-availability.js +37 -1
  4. package/dist/agents/baseagent.js +19 -9
  5. package/dist/agents/claude-runner.js +171 -13
  6. package/dist/agents/codex/app-server-client.js +6 -2
  7. package/dist/agents/codex/diagnostics.js +4 -3
  8. package/dist/agents/codex-runner.js +396 -95
  9. package/dist/agents/gemini-runner.js +35 -17
  10. package/dist/aun/group/history.js +130 -90
  11. package/dist/aun/group/operations.js +1 -3
  12. package/dist/aun/menu/transport.js +5 -3
  13. package/dist/aun/msg/managed-operation.js +70 -0
  14. package/dist/aun/msg/p2p.js +1 -3
  15. package/dist/aun/msg/upload.js +2 -2
  16. package/dist/aun/outbox.js +1 -37
  17. package/dist/channels/aun.js +249 -89
  18. package/dist/channels/daemon.js +18 -1
  19. package/dist/channels/feishu.js +1 -2
  20. package/dist/cli/agent-command.js +23 -3
  21. package/dist/cli/agent-create.js +68 -2
  22. package/dist/cli/agent.js +12 -2
  23. package/dist/cli/aun-commands.js +87 -13
  24. package/dist/cli/cli-argv.js +26 -0
  25. package/dist/cli/daemon-commands.js +40 -10
  26. package/dist/cli/data-command.js +4 -4
  27. package/dist/cli/handoff-command.js +2 -0
  28. package/dist/cli/index.js +18 -1
  29. package/dist/cli/managed-command-guard.js +10 -0
  30. package/dist/cli/memory-command.js +441 -0
  31. package/dist/cli/restart-monitor.js +62 -6
  32. package/dist/cli/skill-command.js +41 -0
  33. package/dist/cli/task-context.js +2 -23
  34. package/dist/cli/trigger-command.js +9 -1
  35. package/dist/cli/watch-msg-diag.js +209 -0
  36. package/dist/config/config-field-policy.js +52 -3
  37. package/dist/config/config-manager.js +17 -4
  38. package/dist/config/contact-book-store.js +2 -2
  39. package/dist/config/mention-mode.js +7 -2
  40. package/dist/config/merge.js +28 -9
  41. package/dist/config/resolved-config-op.js +1 -1
  42. package/dist/config/runtime-env.js +137 -0
  43. package/dist/config/schema-registry.js +11 -1
  44. package/dist/config-store.js +10 -10
  45. package/dist/core/audit/event-key.js +3 -1
  46. package/dist/core/audit/log-integrity.js +4 -0
  47. package/dist/core/auth/agent-delegation.js +2 -1
  48. package/dist/core/auth/auth-gateway.js +13 -6
  49. package/dist/core/auth/authorization-audit.js +54 -19
  50. package/dist/core/auth/operation-authorizer.js +17 -0
  51. package/dist/core/auth/operation-catalog.js +9 -0
  52. package/dist/core/causation/context.js +5 -1
  53. package/dist/core/command/agent-control.js +1 -2
  54. package/dist/core/command/command-handler.js +51 -23
  55. package/dist/core/command/memory-slash.js +270 -0
  56. package/dist/core/command/menu-catalog.js +1 -0
  57. package/dist/core/command/menu-handler.js +315 -60
  58. package/dist/core/command/menu-protocol.js +42 -4
  59. package/dist/core/command/slash-gate.js +10 -10
  60. package/dist/core/command/slash-handler.js +206 -64
  61. package/dist/core/data-migration.js +282 -505
  62. package/dist/core/event-catalog.js +26 -0
  63. package/dist/core/evolagent-registry.js +6 -0
  64. package/dist/core/evolagent.js +0 -10
  65. package/dist/core/handoff/store.js +1 -20
  66. package/dist/core/inference/text-inference.js +57 -1
  67. package/dist/core/memory/consolidation-context.js +505 -0
  68. package/dist/core/memory/consolidation-ops-records.js +124 -0
  69. package/dist/core/memory/consolidation-trigger.js +394 -0
  70. package/dist/core/memory/index-manager.js +308 -0
  71. package/dist/core/memory/launch-consolidation.js +395 -0
  72. package/dist/core/memory/memory-admin.js +234 -0
  73. package/dist/core/memory/memory-document.js +100 -0
  74. package/dist/core/memory/memory-session-policy.js +41 -0
  75. package/dist/core/memory/memory-signature.js +257 -0
  76. package/dist/core/memory/memory-writer.js +432 -0
  77. package/dist/core/memory/staleness.js +117 -0
  78. package/dist/core/message/auto-mention-gate.js +454 -0
  79. package/dist/core/message/im-renderer.js +69 -16
  80. package/dist/core/message/message-bridge.js +287 -21
  81. package/dist/core/message/message-log.js +1 -0
  82. package/dist/core/message/message-queue.js +114 -27
  83. package/dist/core/message/pending-hints.js +329 -161
  84. package/dist/core/message/response-engine.js +567 -80
  85. package/dist/core/permission/ec-command-parser.js +1029 -80
  86. package/dist/core/permission/protected-paths.js +376 -126
  87. package/dist/core/permission/sandbox-runtime.js +40 -12
  88. package/dist/core/permission/tool-error-code.js +96 -13
  89. package/dist/core/permission/tool-policy.js +276 -23
  90. package/dist/core/role/runtime-policy.js +3 -7
  91. package/dist/core/session/{runner-task-history.js → runner-event-summary.js} +1 -1
  92. package/dist/core/session/session-fs-store.js +0 -76
  93. package/dist/core/session/session-idle-monitor.js +355 -0
  94. package/dist/core/session/session-manager.js +478 -17
  95. package/dist/core/session/session-mapper.js +33 -16
  96. package/dist/core/session/session-renew.js +217 -155
  97. package/dist/core/session/{session-turns.js → session-transcript.js} +35 -6
  98. package/dist/core/skill/global-watcher.js +282 -0
  99. package/dist/core/skill/index-generator.js +84 -0
  100. package/dist/core/skill/startup.js +73 -0
  101. package/dist/core/skill/switch-resolver.js +115 -0
  102. package/dist/core/task/task-activity-store.js +219 -0
  103. package/dist/eck/kit-renderer.js +30 -3
  104. package/dist/eck/manifest-engine.js +26 -4
  105. package/dist/index.js +708 -18
  106. package/dist/ipc.js +564 -2
  107. package/dist/paths.js +30 -9
  108. package/dist/response-system/engines/v1/proactive-flow.js +116 -15
  109. package/dist/response-system/modes/single-session/index.js +3 -0
  110. package/dist/trigger/feedback.js +1 -0
  111. package/dist/trigger/manager.js +0 -10
  112. package/dist/trigger/scheduler.js +11 -0
  113. package/dist/trigger/validation.js +22 -0
  114. package/dist/utils/avatar-upload.js +59 -18
  115. package/dist/utils/error-dict.json +6 -3
  116. package/dist/utils/error-utils.js +27 -0
  117. package/dist/utils/logger.js +32 -10
  118. package/dist/utils/media-cache.js +84 -0
  119. package/dist/utils/msg-diag.js +97 -0
  120. package/dist/utils/welcome.js +37 -8
  121. package/kits/docs/AUTHORING.md +314 -0
  122. package/kits/docs/GUIDE.md +2 -0
  123. package/kits/docs/INDEX.md +2 -0
  124. package/kits/docs/aun/CHEATSHEET.md +4 -0
  125. package/kits/docs/aun/SDK.md +60 -0
  126. package/kits/docs/context-assembly.md +10 -6
  127. package/kits/docs/evolcore/INDEX.md +17 -3
  128. package/kits/docs/evolcore/agent-create.md +24 -0
  129. package/kits/docs/evolcore/agent.md +5 -2
  130. package/kits/docs/evolcore/config.md +1 -1
  131. package/kits/docs/evolcore/ec-capabilities.md +364 -0
  132. package/kits/docs/evolcore/group.md +34 -18
  133. package/kits/docs/evolcore/memory-architecture.md +78 -0
  134. package/kits/docs/evolcore/memory-consolidation-batches.md +133 -0
  135. package/kits/docs/evolcore/memory-consolidation.md +263 -0
  136. package/kits/docs/evolcore/memory-tags.md +63 -0
  137. package/kits/docs/evolcore/memory.md +110 -0
  138. package/kits/docs/evolcore/menu-client.md +27 -11
  139. package/kits/{schemas → docs/evolcore}/menu-exec-schema-commands.md +12 -6
  140. package/kits/docs/evolcore/menu-protocol.md +213 -0
  141. package/kits/docs/evolcore/msg.md +2 -0
  142. package/kits/docs/evolcore/trigger.md +7 -5
  143. package/kits/docs/path-registry.md +6 -8
  144. package/kits/docs/prompt-loading-architecture.md +5 -3
  145. package/kits/docs/venues/group.md +5 -4
  146. package/kits/eck_manifest.json +294 -88
  147. package/kits/eck_manifest.memory.json +257 -0
  148. package/kits/rules/03-identity.md +8 -8
  149. package/kits/rules/05-venue.md +4 -2
  150. package/kits/rules/06-channel.md +1 -1
  151. package/kits/schemas/_meta.json +276 -47
  152. package/kits/schemas/agent-config.schema.12.json +38 -2
  153. package/kits/schemas/agent-config.schema.13.json +591 -0
  154. package/kits/schemas/daemon.schema.6.json +9 -9
  155. package/kits/schemas/defaults.schema.5.json +29 -0
  156. package/kits/schemas/relation-config.schema.8.json +14 -1
  157. package/kits/schemas/relation-config.schema.9.json +129 -0
  158. package/kits/schemas/role-config.schema.1.json +3 -3
  159. package/kits/skills/.switches.json +3 -0
  160. package/kits/skills/ec-skill/SKILL.md +217 -0
  161. package/kits/skills/ec-skill/scripts/cli.mjs +128 -0
  162. package/kits/skills/ec-skill/scripts/deps.mjs +107 -0
  163. package/kits/skills/ec-skill/scripts/frontmatter.mjs +104 -0
  164. package/kits/skills/ec-skill/scripts/skill.mjs +629 -0
  165. package/kits/skills/ec-skill/scripts/template/SKILL.md.tmpl +30 -0
  166. package/kits/templates/decision/auto-mention.md +25 -0
  167. package/kits/templates/decision/session-renew.md +22 -0
  168. package/kits/templates/memory-consolidation/forget.md +104 -0
  169. package/kits/templates/memory-consolidation/generalize.md +76 -0
  170. package/kits/templates/memory-consolidation/notes.md +133 -0
  171. package/kits/templates/memory-consolidation/profile.md +58 -0
  172. package/kits/templates/memory-consolidation/promote.md +72 -0
  173. package/kits/templates/memory-consolidation/workflow.md +75 -0
  174. package/kits/templates/system-fragments/bootstrap.md +14 -5
  175. package/kits/templates/system-fragments/commands.md +1 -0
  176. package/kits/templates/system-fragments/group-history.md +6 -0
  177. package/kits/templates/system-fragments/identity.md +0 -3
  178. package/kits/templates/system-fragments/memory.md +79 -0
  179. package/kits/templates/system-fragments/reply.md +1 -0
  180. package/kits/templates/system-fragments/venue.md +1 -1
  181. package/package.json +4 -6
  182. package/dist/trigger/legacy-session-history.js +0 -19
  183. package/kits/templates/system-fragments/group-unread-history.md +0 -7
package/dist/ipc.js CHANGED
@@ -16,10 +16,11 @@ import { getPackageRoot, getWindowsInstanceSocketPathCandidates, normalizeIpcEnd
16
16
  import { getProcessStartTime, isSameOrOlderProcess } from './utils/process-introspect.js';
17
17
  import { classifyProcessTree, ProcessTreeSampler, readProcessMetrics } from './utils/process-tree-stats.js';
18
18
  import { readSystemMemoryUsage } from './utils/system-memory.js';
19
- import { hashCurrentDelegatedCommand } from './core/auth/agent-delegation.js';
19
+ import { hashCurrentDelegatedCommand, hashDelegatedCommandArgv } from './core/auth/agent-delegation.js';
20
20
  import { normalizeAunMentionEntries } from './aun/msg/mention-schema.js';
21
21
  import { remoteAccessService } from './core/auth/remote-access-store.js';
22
22
  import { setModelCatalogDaemonOwner } from './core/model/model-catalog.js';
23
+ import { RUNTIME_ENVIRONMENT_NAMES, setRuntimeEnvironmentOverride } from './config/runtime-env.js';
23
24
  const isWindows = process.platform === 'win32';
24
25
  const isNamedPipe = (p) => isWindows && p.toLowerCase().startsWith('\\\\.\\pipe\\');
25
26
  const CPU_SAMPLE_INTERVAL_MS = 1000;
@@ -30,6 +31,22 @@ const EVENT_LOOP_LAG_WARN_MS = 100;
30
31
  const SAMPLE_WARN_LOG_INTERVAL_MS = 60_000;
31
32
  const PROCESS_TREE_WORKER_REQUEST_TIMEOUT_MS = 15_000;
32
33
  const finiteTimestamp = (value) => (typeof value === 'number' && Number.isFinite(value) ? value : undefined);
34
+ function parseRuntimeEnvironmentInput(value) {
35
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
36
+ return { ok: false, error: 'runtimeEnv must be an object' };
37
+ }
38
+ const values = {};
39
+ for (const name of RUNTIME_ENVIRONMENT_NAMES) {
40
+ if (!Object.prototype.hasOwnProperty.call(value, name))
41
+ continue;
42
+ const item = value[name];
43
+ if (item !== null && item !== undefined && typeof item !== 'string') {
44
+ return { ok: false, error: `${name} must be a string or null` };
45
+ }
46
+ values[name] = item;
47
+ }
48
+ return { ok: true, values };
49
+ }
33
50
  const LOCAL_CONTROL_COMMANDS = new Set([
34
51
  'bind.begin',
35
52
  'bind.status',
@@ -40,6 +57,7 @@ const LOCAL_CONTROL_COMMANDS = new Set([
40
57
  'wecom.contact-bind.register',
41
58
  'wechat.contact-bind.register',
42
59
  'queue-snapshot',
60
+ 'memory.check-consolidation',
43
61
  'aun-aid-stats-record-outbound',
44
62
  'evolagent.list',
45
63
  'evolagent.show',
@@ -146,10 +164,13 @@ export class IpcServer {
146
164
  storageAuthorizationExecutor;
147
165
  storageUploadExecutor;
148
166
  triggerExecutor;
167
+ consolidationLaunchExecutor;
168
+ consolidationCheckExecutor;
149
169
  bootstrapCompleteExecutor;
150
170
  agentReloadExecutor;
151
171
  shutdownExecutor;
152
172
  taskRuntimeContextProvider;
173
+ debugTaskRuntimeContextProvider;
153
174
  taskRuntimeContextAuthorizer;
154
175
  codexPreToolUseExecutor;
155
176
  aunMsgSender;
@@ -407,6 +428,14 @@ export class IpcServer {
407
428
  setTriggerExecutor(executor) {
408
429
  this.triggerExecutor = executor;
409
430
  }
431
+ /** Inject daemon-level consolidation launcher that uses the real trigger scheduler. */
432
+ setConsolidationLaunchExecutor(executor) {
433
+ this.consolidationLaunchExecutor = executor;
434
+ }
435
+ /** 注入定时检查 executor:跑候选检查并入队(整理队列在 index.ts)。 */
436
+ setConsolidationCheckExecutor(executor) {
437
+ this.consolidationCheckExecutor = executor;
438
+ }
410
439
  /** Complete an agent bootstrap in the daemon so disk and runtime state change together. */
411
440
  setBootstrapCompleteExecutor(executor) {
412
441
  this.bootstrapCompleteExecutor = executor;
@@ -415,6 +444,20 @@ export class IpcServer {
415
444
  setTaskRuntimeContextProvider(provider) {
416
445
  this.taskRuntimeContextProvider = provider;
417
446
  }
447
+ /** 仅开发仓(npm link)安装注册;正式安装不调用,debug 请求一律走正常路径。 */
448
+ setDebugTaskRuntimeContextProvider(provider) {
449
+ this.debugTaskRuntimeContextProvider = provider;
450
+ }
451
+ /**
452
+ * memory 命令取运行时上下文:先查正在运行的任务;没有且请求带 debug 时,
453
+ * 再由开发仓专用的 provider 从会话文件重建。
454
+ */
455
+ async resolveMemoryTaskCtx(sessionId, debug) {
456
+ const active = this.taskRuntimeContextProvider?.({ sessionId });
457
+ if (active || !debug || !this.debugTaskRuntimeContextProvider)
458
+ return active;
459
+ return this.debugTaskRuntimeContextProvider({ sessionId });
460
+ }
418
461
  setTaskRuntimeContextAuthorizer(authorizer) {
419
462
  this.taskRuntimeContextAuthorizer = authorizer;
420
463
  }
@@ -1406,6 +1449,330 @@ export class IpcServer {
1406
1449
  return { ok: false, error: 'missing cmd or sessionId' };
1407
1450
  return await this.commandExecutor(slashCmd, sessionId, typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
1408
1451
  }
1452
+ case 'memory.note': {
1453
+ const { sessionId, slug, content, tags, speakers } = cmd;
1454
+ if (!sessionId)
1455
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId' };
1456
+ if (typeof slug !== 'string' || !slug)
1457
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing slug' };
1458
+ if (typeof content !== 'string' || !content)
1459
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing content' };
1460
+ try {
1461
+ const taskCtx = await this.resolveMemoryTaskCtx(sessionId, cmd.debug === true);
1462
+ if (!taskCtx)
1463
+ return { ok: false, code: 'SESSION_NOT_FOUND', error: `未找到会话 ${sessionId} 的运行时上下文` };
1464
+ const memoryConfig = taskCtx.selfAid
1465
+ ? this.agentRegistry?.get(taskCtx.selfAid)?.config?.memory
1466
+ : undefined;
1467
+ const { writeMemoryNote } = await import('./core/memory/memory-writer.js');
1468
+ return await writeMemoryNote({
1469
+ content, slug,
1470
+ tags: Array.isArray(tags) ? tags : undefined,
1471
+ speakers: Array.isArray(speakers) ? speakers : undefined,
1472
+ taskCtx, memoryConfig,
1473
+ });
1474
+ }
1475
+ catch (e) {
1476
+ return { ok: false, error: e?.message || String(e) };
1477
+ }
1478
+ }
1479
+ case 'memory.note.update': {
1480
+ const { sessionId, slug, newSlug, tags, tagsProvided, content } = cmd;
1481
+ if (!sessionId)
1482
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId' };
1483
+ try {
1484
+ const taskCtx = await this.resolveMemoryTaskCtx(sessionId, cmd.debug === true);
1485
+ if (!taskCtx)
1486
+ return { ok: false, code: 'SESSION_NOT_FOUND', error: `未找到会话 ${sessionId} 的运行时上下文` };
1487
+ const memoryConfig = taskCtx.selfAid
1488
+ ? this.agentRegistry?.get(taskCtx.selfAid)?.config?.memory
1489
+ : undefined;
1490
+ const { updateMemoryNote } = await import('./core/memory/memory-writer.js');
1491
+ return await updateMemoryNote({
1492
+ taskCtx, target: slug, newSlug,
1493
+ tags: tagsProvided ? (Array.isArray(tags) ? tags : []) : undefined,
1494
+ content, memoryConfig,
1495
+ });
1496
+ }
1497
+ catch (e) {
1498
+ return { ok: false, error: e?.message || String(e) };
1499
+ }
1500
+ }
1501
+ case 'memory.note.drop': {
1502
+ const { sessionId, slug } = cmd;
1503
+ if (!sessionId)
1504
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId' };
1505
+ try {
1506
+ const taskCtx = await this.resolveMemoryTaskCtx(sessionId, cmd.debug === true);
1507
+ if (!taskCtx)
1508
+ return { ok: false, code: 'SESSION_NOT_FOUND', error: `未找到会话 ${sessionId} 的运行时上下文` };
1509
+ const memoryConfig = taskCtx.selfAid
1510
+ ? this.agentRegistry?.get(taskCtx.selfAid)?.config?.memory
1511
+ : undefined;
1512
+ const { dropMemoryNote } = await import('./core/memory/memory-writer.js');
1513
+ return await dropMemoryNote({ taskCtx, target: slug, memoryConfig });
1514
+ }
1515
+ catch (e) {
1516
+ return { ok: false, error: e?.message || String(e) };
1517
+ }
1518
+ }
1519
+ case 'memory.note.list': {
1520
+ const { sessionId } = cmd;
1521
+ if (!sessionId)
1522
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId' };
1523
+ try {
1524
+ const taskCtx = await this.resolveMemoryTaskCtx(sessionId, cmd.debug === true);
1525
+ if (!taskCtx)
1526
+ return { ok: false, code: 'SESSION_NOT_FOUND', error: `未找到会话 ${sessionId} 的运行时上下文` };
1527
+ const memoryConfig = taskCtx.selfAid
1528
+ ? this.agentRegistry?.get(taskCtx.selfAid)?.config?.memory
1529
+ : undefined;
1530
+ const { listMemoryNotes } = await import('./core/memory/memory-writer.js');
1531
+ return await listMemoryNotes({ taskCtx, memoryConfig });
1532
+ }
1533
+ catch (e) {
1534
+ return { ok: false, error: e?.message || String(e) };
1535
+ }
1536
+ }
1537
+ case 'memory.consolidate': {
1538
+ const { sessionId, mode } = cmd;
1539
+ if (!sessionId)
1540
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId' };
1541
+ if (!this.taskRuntimeContextProvider)
1542
+ return { ok: false, code: 'NOT_CONFIGURED', error: 'task runtime context not configured' };
1543
+ try {
1544
+ const { CONSOLIDATION_MODES } = await import('./core/memory/consolidation-context.js');
1545
+ const effectiveMode = (mode ?? 'notes');
1546
+ if (!CONSOLIDATION_MODES.includes(effectiveMode)) {
1547
+ return { ok: false, code: 'INVALID_REQUEST', error: `mode must be one of ${CONSOLIDATION_MODES.join(' / ')}` };
1548
+ }
1549
+ const taskCtx = await this.resolveMemoryTaskCtx(sessionId, cmd.debug === true);
1550
+ if (!taskCtx)
1551
+ return { ok: false, code: 'SESSION_NOT_FOUND', error: `未找到会话 ${sessionId} 的运行时上下文` };
1552
+ const mc = this.agentRegistry?.get(taskCtx.selfAid ?? '')?.config?.memory;
1553
+ const disabled = this.checkMemoryEnabled(mc, effectiveMode, taskCtx);
1554
+ if (disabled)
1555
+ return disabled;
1556
+ const ownerAid = taskCtx.selfAid
1557
+ ? this.agentRegistry?.get(taskCtx.selfAid)?.config?.owners?.[0]
1558
+ : undefined;
1559
+ const { launchConsolidation } = await import('./core/memory/launch-consolidation.js');
1560
+ if (!this.consolidationLaunchExecutor) {
1561
+ // daemon 未注入 launcher —— 无法直接创建整理会话,明确报错而不是静默失败
1562
+ return { ok: false, code: 'NOT_CONFIGURED', error: 'daemon 未注入整理会话 launcher' };
1563
+ }
1564
+ const r = await this.consolidationLaunchExecutor({
1565
+ taskCtx,
1566
+ mode: effectiveMode,
1567
+ triggeredBy: 'manual',
1568
+ ownerAid,
1569
+ forgetAfterDays: mc?.forgetAfterDays,
1570
+ });
1571
+ return {
1572
+ ok: true,
1573
+ triggerId: r.triggerId,
1574
+ executionSessionId: r.executionSessionId,
1575
+ agentSessionId: r.agentSessionId,
1576
+ contextFile: r.contextFile,
1577
+ contextFilePath: r.contextFilePath,
1578
+ ...(r.logFile ? { logFile: r.logFile } : {}),
1579
+ mode: effectiveMode,
1580
+ };
1581
+ }
1582
+ catch (e) {
1583
+ return { ok: false, error: e?.message || String(e) };
1584
+ }
1585
+ }
1586
+ case 'memory.create': {
1587
+ const { sessionId, scope, slug, description, content, tags, keywords, replaces, targetPeerKey, generalizedFrom, promotedFrom } = cmd;
1588
+ if (!sessionId)
1589
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId' };
1590
+ try {
1591
+ const guard = await this.assertMemoryWriteSession(sessionId, scope, 'create', replaces, cmd.debug === true);
1592
+ if ('error' in guard)
1593
+ return guard.error;
1594
+ const { createMemory } = await import('./core/memory/memory-writer.js');
1595
+ const { appendOpsRecord } = await import('./core/memory/consolidation-ops-records.js');
1596
+ let createResult;
1597
+ try {
1598
+ createResult = await createMemory({
1599
+ taskCtx: guard.taskCtx,
1600
+ scope: scope,
1601
+ ownerAid: guard.ownerAid,
1602
+ slug, description, content,
1603
+ tags: Array.isArray(tags) ? tags : [],
1604
+ keywords: Array.isArray(keywords) ? keywords : undefined,
1605
+ replaces: Array.isArray(replaces) ? replaces : undefined,
1606
+ targetPeerKey: typeof targetPeerKey === 'string' ? targetPeerKey : undefined,
1607
+ generalizedFrom: typeof generalizedFrom === 'string' ? generalizedFrom : undefined,
1608
+ promotedFrom: typeof promotedFrom === 'string' ? promotedFrom : undefined,
1609
+ });
1610
+ }
1611
+ catch (e) {
1612
+ const batchDir = guard.taskCtx.consolidationBatchDir;
1613
+ if (batchDir)
1614
+ appendOpsRecord(batchDir, { ts: new Date().toISOString(), op: 'create', scope: scope ?? '', target: slug ?? '', ok: false, error: e?.message });
1615
+ throw e;
1616
+ }
1617
+ const batchDir = guard.taskCtx.consolidationBatchDir;
1618
+ if (batchDir)
1619
+ appendOpsRecord(batchDir, { ts: new Date().toISOString(), op: 'create', scope: scope ?? '', target: slug ?? '', filePath: createResult.filePath, archivedFiles: createResult.archived.map((dest, i) => ({ source: (Array.isArray(replaces) ? replaces : [])[i] ?? dest, archivedTo: dest })), tags: Array.isArray(tags) ? tags : [], memoryDir: createResult.scopeDirs.memoryDir, ok: true });
1620
+ return { ok: true, filePath: createResult.filePath, archived: createResult.archived };
1621
+ }
1622
+ catch (e) {
1623
+ return { ok: false, error: e?.message || String(e) };
1624
+ }
1625
+ }
1626
+ case 'memory.update': {
1627
+ const { sessionId, filePath, tags, touch } = cmd;
1628
+ if (!sessionId)
1629
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId' };
1630
+ try {
1631
+ const guard = await this.assertMemoryWriteSession(sessionId, undefined, 'update', undefined, cmd.debug === true);
1632
+ if ('error' in guard)
1633
+ return guard.error;
1634
+ const { updateMemory } = await import('./core/memory/memory-writer.js');
1635
+ const { appendOpsRecord } = await import('./core/memory/consolidation-ops-records.js');
1636
+ let updateResult;
1637
+ try {
1638
+ updateResult = await updateMemory({
1639
+ taskCtx: guard.taskCtx,
1640
+ scope: guard.writeScope,
1641
+ ownerAid: guard.ownerAid,
1642
+ target: filePath,
1643
+ tags: Array.isArray(tags) ? tags : undefined,
1644
+ touch: !!touch,
1645
+ });
1646
+ }
1647
+ catch (e) {
1648
+ const batchDir = guard.taskCtx.consolidationBatchDir;
1649
+ if (batchDir)
1650
+ appendOpsRecord(batchDir, { ts: new Date().toISOString(), op: 'update', scope: guard.writeScope, target: filePath ?? '', ok: false, error: e?.message });
1651
+ throw e;
1652
+ }
1653
+ const batchDirU = guard.taskCtx.consolidationBatchDir;
1654
+ if (batchDirU)
1655
+ appendOpsRecord(batchDirU, { ts: new Date().toISOString(), op: 'update', scope: guard.writeScope, target: filePath ?? '', tags: Array.isArray(tags) ? tags : undefined, prevTags: updateResult.prevTags, memoryDir: updateResult.scopeDirs.memoryDir, ok: true });
1656
+ return { ok: true, filePath: updateResult.filePath };
1657
+ }
1658
+ catch (e) {
1659
+ return { ok: false, error: e?.message || String(e) };
1660
+ }
1661
+ }
1662
+ case 'memory.archive': {
1663
+ const { sessionId, filePaths } = cmd;
1664
+ if (!sessionId)
1665
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId' };
1666
+ try {
1667
+ const guard = await this.assertMemoryWriteSession(sessionId, undefined, 'archive', undefined, cmd.debug === true);
1668
+ if ('error' in guard)
1669
+ return guard.error;
1670
+ const { archiveMemory } = await import('./core/memory/memory-writer.js');
1671
+ const { appendOpsRecord } = await import('./core/memory/consolidation-ops-records.js');
1672
+ let archiveResult;
1673
+ try {
1674
+ archiveResult = await archiveMemory({
1675
+ taskCtx: guard.taskCtx,
1676
+ scope: guard.writeScope,
1677
+ ownerAid: guard.ownerAid,
1678
+ targets: Array.isArray(filePaths) ? filePaths : [],
1679
+ });
1680
+ }
1681
+ catch (e) {
1682
+ const batchDir = guard.taskCtx.consolidationBatchDir;
1683
+ if (batchDir)
1684
+ appendOpsRecord(batchDir, { ts: new Date().toISOString(), op: 'archive', scope: guard.writeScope, target: (Array.isArray(filePaths) ? filePaths : []).join(', '), ok: false, error: e?.message });
1685
+ throw e;
1686
+ }
1687
+ const batchDirA = guard.taskCtx.consolidationBatchDir;
1688
+ if (batchDirA) {
1689
+ for (let i = 0; i < archiveResult.archived.length; i++) {
1690
+ const archivedTo = archiveResult.archived[i];
1691
+ const sourceFile = (Array.isArray(filePaths) ? filePaths : [])[i] ?? archivedTo;
1692
+ appendOpsRecord(batchDirA, { ts: new Date().toISOString(), op: 'archive', scope: guard.writeScope, target: archivedTo, sourceFile, archivedTo, memoryDir: archiveResult.scopeDirs.memoryDir, ok: true });
1693
+ }
1694
+ }
1695
+ return { ok: true, archived: archiveResult.archived };
1696
+ }
1697
+ catch (e) {
1698
+ return { ok: false, error: e?.message || String(e) };
1699
+ }
1700
+ }
1701
+ case 'memory.demote': {
1702
+ const { sessionId, slug, scope } = cmd;
1703
+ if (!sessionId)
1704
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId' };
1705
+ try {
1706
+ const taskCtx = await this.resolveMemoryTaskCtx(sessionId, cmd.debug === true);
1707
+ if (!taskCtx)
1708
+ return { ok: false, code: 'SESSION_NOT_FOUND', error: `未找到会话 ${sessionId} 的运行时上下文` };
1709
+ if (scope !== 'agent' && scope !== 'owner') {
1710
+ return { ok: false, code: 'INVALID_REQUEST', error: 'scope 必须是 agent 或 owner' };
1711
+ }
1712
+ const { demoteMemory } = await import('./core/memory/memory-writer.js');
1713
+ const ownerAid = taskCtx.ownerAid;
1714
+ const result = await demoteMemory({ taskCtx, slug, scope: scope, ownerAid });
1715
+ await this.rebuildMemoryIndexFor(taskCtx, result.srcScopeDirs, ownerAid);
1716
+ // 重建目标层索引:从 destMemoryDir 推导出 consolidatedDir 和 memoryDir
1717
+ const destConsolidatedDir = path.join(result.destMemoryDir, 'consolidated');
1718
+ await this.rebuildMemoryIndexFor(taskCtx, { memoryDir: result.destMemoryDir, consolidatedDir: destConsolidatedDir }, ownerAid);
1719
+ return {
1720
+ ok: true,
1721
+ destPath: result.destPath,
1722
+ ...(result.conflictArchived ? { conflictArchived: result.conflictArchived, note: '目标层已有同名文件,当前记忆已归档' } : {}),
1723
+ };
1724
+ }
1725
+ catch (e) {
1726
+ return { ok: false, error: e?.message || String(e) };
1727
+ }
1728
+ }
1729
+ case 'memory.check-consolidation': {
1730
+ const { selfAid } = cmd;
1731
+ if (typeof selfAid !== 'string' || !selfAid) {
1732
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing selfAid' };
1733
+ }
1734
+ if (!this.consolidationCheckExecutor) {
1735
+ return { ok: false, code: 'NOT_CONFIGURED', error: 'daemon 未注入整理检查 executor' };
1736
+ }
1737
+ try {
1738
+ const result = await this.consolidationCheckExecutor({ selfAid });
1739
+ return { ok: true, ...result };
1740
+ }
1741
+ catch (e) {
1742
+ return { ok: false, error: e?.message || String(e) };
1743
+ }
1744
+ }
1745
+ case 'memory.feedback': {
1746
+ const { sessionId, text } = cmd;
1747
+ if (!sessionId)
1748
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId' };
1749
+ if (typeof text !== 'string' || !text.trim()) {
1750
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing feedback text' };
1751
+ }
1752
+ try {
1753
+ const taskCtx = await this.resolveMemoryTaskCtx(sessionId, cmd.debug === true);
1754
+ if (!taskCtx)
1755
+ return { ok: false, code: 'SESSION_NOT_FOUND', error: `未找到会话 ${sessionId} 的运行时上下文` };
1756
+ // 只有整理会话可以记录反馈
1757
+ if (taskCtx.sessionType !== 'memory') {
1758
+ return { ok: false, code: 'NOT_MEMORY_SESSION', error: '`ec memory feedback` 只能在整理会话内调用' };
1759
+ }
1760
+ const batchDir = taskCtx.consolidationBatchDir;
1761
+ if (!batchDir) {
1762
+ return { ok: false, code: 'BATCH_DIR_NOT_FOUND', error: '整理会话缺少 consolidationBatchDir' };
1763
+ }
1764
+ const { appendOpsRecord } = await import('./core/memory/consolidation-ops-records.js');
1765
+ appendOpsRecord(batchDir, {
1766
+ ts: new Date().toISOString(),
1767
+ op: 'feedback-set',
1768
+ text,
1769
+ });
1770
+ return { ok: true };
1771
+ }
1772
+ catch (e) {
1773
+ return { ok: false, error: e?.message || String(e) };
1774
+ }
1775
+ }
1409
1776
  case 'config.op': {
1410
1777
  if (!this.configOperationExecutor)
1411
1778
  return { ok: false, code: 'NOT_CONFIGURED', error: 'config.op not configured' };
@@ -1568,6 +1935,12 @@ export class IpcServer {
1568
1935
  const name = cmd.name;
1569
1936
  if (!name || typeof name !== 'string')
1570
1937
  return { ok: false, error: 'missing name' };
1938
+ const runtimeEnv = cmd.runtimeEnv === undefined ? undefined : parseRuntimeEnvironmentInput(cmd.runtimeEnv);
1939
+ if (runtimeEnv && !runtimeEnv.ok)
1940
+ return { ok: false, code: 'INVALID_REQUEST', error: runtimeEnv.error };
1941
+ const target = this.agentRegistry?.get(name);
1942
+ if (runtimeEnv?.ok && target)
1943
+ setRuntimeEnvironmentOverride(target.aid, runtimeEnv.values);
1571
1944
  if (this.agentApplicationService) {
1572
1945
  const result = await this.agentApplicationService.reload(name, { force: cmd.force === true });
1573
1946
  if (!result.ok) {
@@ -1622,6 +1995,15 @@ export class IpcServer {
1622
1995
  }
1623
1996
  }
1624
1997
  case 'evolagent.resync': {
1998
+ const runtimeEnv = cmd.runtimeEnv === undefined ? undefined : parseRuntimeEnvironmentInput(cmd.runtimeEnv);
1999
+ if (runtimeEnv && !runtimeEnv.ok)
2000
+ return { ok: false, code: 'INVALID_REQUEST', error: runtimeEnv.error };
2001
+ if (runtimeEnv?.ok) {
2002
+ setRuntimeEnvironmentOverride(undefined, runtimeEnv.values);
2003
+ for (const agent of this.agentRegistry?.list() ?? []) {
2004
+ setRuntimeEnvironmentOverride(agent.aid, runtimeEnv.values);
2005
+ }
2006
+ }
1625
2007
  if (this.agentApplicationService) {
1626
2008
  const result = await this.agentApplicationService.resync();
1627
2009
  return result.ok
@@ -1663,6 +2045,15 @@ export class IpcServer {
1663
2045
  const actorAid = typeof suppliedAuth?.actorAid === 'string' && suppliedAuth.actorAid.trim()
1664
2046
  ? suppliedAuth.actorAid.trim()
1665
2047
  : null;
2048
+ const ecwebRequestId = typeof suppliedAuth?.ecwebRequestId === 'string' && suppliedAuth.ecwebRequestId.trim()
2049
+ ? suppliedAuth.ecwebRequestId.trim()
2050
+ : undefined;
2051
+ const endpoint = typeof suppliedAuth?.endpoint === 'string' && suppliedAuth.endpoint.trim()
2052
+ ? suppliedAuth.endpoint.trim()
2053
+ : undefined;
2054
+ const logicalToolName = typeof suppliedAuth?.logicalToolName === 'string' && suppliedAuth.logicalToolName.trim()
2055
+ ? suppliedAuth.logicalToolName.trim()
2056
+ : undefined;
1666
2057
  const response = await this.menuExecutor(cmd.payload, {
1667
2058
  source: 'ecweb',
1668
2059
  // The ECWeb process resolved this actor from its bearer token. The
@@ -1670,6 +2061,9 @@ export class IpcServer {
1670
2061
  // menu handler still checks that actorAid remains a configured owner.
1671
2062
  actorAid,
1672
2063
  localDirect: suppliedAuth?.localDirect === true,
2064
+ ecwebRequestId,
2065
+ endpoint,
2066
+ logicalToolName,
1673
2067
  // Reaching this handler means the control token gate succeeded.
1674
2068
  // Never trust an authenticated flag supplied by the caller.
1675
2069
  authenticated: true,
@@ -1712,6 +2106,164 @@ export class IpcServer {
1712
2106
  return { error: `unknown command: ${cmd.type}` };
1713
2107
  }
1714
2108
  }
2109
+ // ── 记忆整理辅助 ──────────────────────────────────────────────────────────
2110
+ /**
2111
+ * 检查记忆开关。relation 是总开关:它关闭则整个记忆系统停用。
2112
+ * 返回 null 表示可用,否则返回错误响应。
2113
+ */
2114
+ checkMemoryEnabled(mc, mode, taskCtx) {
2115
+ if (mc?.enableRelation === false) {
2116
+ return { ok: false, code: 'SCOPE_DISABLED', error: '记忆系统已停用(memory.enableRelation=false)' };
2117
+ }
2118
+ if (mode === 'generalize' && mc?.enableAgent === false) {
2119
+ return { ok: false, code: 'SCOPE_DISABLED', error: '泛化模式已停用(memory.enableAgent=false)' };
2120
+ }
2121
+ if (mode === 'promote' && mc?.enableOwner === false) {
2122
+ return { ok: false, code: 'SCOPE_DISABLED', error: '提升模式已停用(memory.enableOwner=false)' };
2123
+ }
2124
+ if (mode === 'promote' && !taskCtx.selfAid) {
2125
+ return { ok: false, code: 'INVALID_REQUEST', error: '无法确定当前 agent AID' };
2126
+ }
2127
+ return null;
2128
+ }
2129
+ /**
2130
+ * 写正式记忆前的会话校验:必须是整理会话(sessionType=memory),
2131
+ * 且模式与作用域匹配。返回授权后的上下文。
2132
+ */
2133
+ async assertMemoryWriteSession(sessionId, requestedScope, op, replaces, debug = false) {
2134
+ if (!this.taskRuntimeContextProvider) {
2135
+ return { error: { ok: false, code: 'NOT_CONFIGURED', error: 'task runtime context not configured' } };
2136
+ }
2137
+ const taskCtx = await this.resolveMemoryTaskCtx(sessionId, debug);
2138
+ if (!taskCtx) {
2139
+ return { error: { ok: false, code: 'SESSION_NOT_FOUND', error: `未找到会话 ${sessionId} 的运行时上下文` } };
2140
+ }
2141
+ // 只有整理会话能写正式记忆
2142
+ const sessionType = taskCtx?.sessionType;
2143
+ if (sessionType !== 'memory') {
2144
+ return {
2145
+ error: {
2146
+ ok: false, code: 'ROLE_ACCESS_DENIED',
2147
+ error: `${op} 只能由整理会话(sessionType=memory)调用;主会话请用 \`ec memory note\``,
2148
+ },
2149
+ };
2150
+ }
2151
+ const mode = taskCtx?.memoryMode;
2152
+ const { MODE_SCOPE, CONSOLIDATION_MODES } = await import('./core/memory/consolidation-context.js');
2153
+ if (!mode || !CONSOLIDATION_MODES.includes(mode)) {
2154
+ return { error: { ok: false, code: 'INVALID_REQUEST', error: '当前会话没有有效的 memoryMode' } };
2155
+ }
2156
+ // forget 是分层审查:一次会话只审一层,允许写哪个作用域取决于会话带下来的
2157
+ // memoryScope(关系级索引重建 → relation;agent 级 → agent;owner 级 → owner)。
2158
+ // 其余四种模式由 MODE_SCOPE 唯一决定。
2159
+ const sessionScope = taskCtx?.memoryScope;
2160
+ const allowed = mode === 'forget' ? sessionScope : MODE_SCOPE[mode];
2161
+ if (!allowed) {
2162
+ return {
2163
+ error: {
2164
+ ok: false, code: 'INVALID_REQUEST',
2165
+ error: mode === 'forget'
2166
+ ? 'forget 会话缺少 memoryScope,无法确定该写哪个作用域'
2167
+ : `${mode} 模式没有可写作用域`,
2168
+ },
2169
+ };
2170
+ }
2171
+ if (op === 'create' && requestedScope !== allowed) {
2172
+ return {
2173
+ error: {
2174
+ ok: false, code: 'ROLE_ACCESS_DENIED',
2175
+ error: `${mode} 模式只能写 --scope ${allowed},收到 ${requestedScope ?? '(空)'}`,
2176
+ },
2177
+ };
2178
+ }
2179
+ // 二次查开关
2180
+ const mc = this.agentRegistry?.get(taskCtx.selfAid ?? '')?.config?.memory;
2181
+ const disabled = this.checkMemoryEnabled(mc, mode, taskCtx);
2182
+ if (disabled)
2183
+ return { error: disabled };
2184
+ const ownerAid = taskCtx.selfAid
2185
+ ? this.agentRegistry?.get(taskCtx.selfAid)?.config?.owners?.[0]
2186
+ : undefined;
2187
+ if (allowed === 'owner' && !ownerAid) {
2188
+ return { error: { ok: false, code: 'INVALID_REQUEST', error: '当前 agent 未配置 owner' } };
2189
+ }
2190
+ return { taskCtx, writeScope: allowed, ownerAid };
2191
+ }
2192
+ /** 保存成功后重建对应作用域的索引。失败不影响写入结果。 */
2193
+ async rebuildMemoryIndexFor(taskCtx, dirs, ownerAid) {
2194
+ try {
2195
+ // owner: .../memory/owner/<ownerAid> → dirname 的 basename 是 'owner'
2196
+ // relation: .../relations/<peerKey>/memory → dirname 的 basename 是 peerKey,不是 'relations'
2197
+ // 用路径段列表判断,比看直接父目录名可靠。
2198
+ const memParts = dirs.memoryDir.split(path.sep);
2199
+ const scope = path.basename(path.dirname(dirs.memoryDir)) === 'owner'
2200
+ ? 'owner'
2201
+ : memParts.includes('relations')
2202
+ ? 'relation'
2203
+ : 'agent';
2204
+ const { rebuildIndex } = await import('./core/memory/index-manager.js');
2205
+ const mc = this.agentRegistry?.get(taskCtx.selfAid ?? '')?.config?.memory;
2206
+ const maxBytes = mc?.indexMaxBytes ?? 5 * 1024;
2207
+ const buildResult = await rebuildIndex(dirs.consolidatedDir, path.join(dirs.memoryDir, 'MEMORY.md'), scope, path.join(dirs.memoryDir, 'archive', 'invalid'), undefined, // 验签门控尚未开启,不传 verifyFn
2208
+ maxBytes);
2209
+ // 索引重建后顺手检查这一层有没有超期记忆 —— 有则建触发器拉一个独立的遗忘会话。
2210
+ await this.maybeTriggerForget(taskCtx, scope, dirs.consolidatedDir, mc, buildResult.verifiedFiles);
2211
+ }
2212
+ catch { /* 索引重建失败下次整理时会补上 */ }
2213
+ }
2214
+ /**
2215
+ * 重建索引后检查超期记忆;有到期的就建触发器拉起遗忘会话。
2216
+ *
2217
+ * 判据与定时检查共用 staleness.ts:mtime 决定进不进候选,
2218
+ * updatedAt 决定是否真的交给模型审查。未到期的长期记忆在这里被刷新 mtime(减速)。
2219
+ */
2220
+ async maybeTriggerForget(taskCtx, scope, consolidatedDir, mc,
2221
+ /** 本次索引重建中验签通过的文件名;其余文件不做审查 */
2222
+ verifiedFiles) {
2223
+ const selfAid = taskCtx.selfAid;
2224
+ if (!selfAid)
2225
+ return;
2226
+ const { collectCandidates, isDueForReview, deferCandidate } = await import('./core/memory/staleness.js');
2227
+ const thresholds = { forgetAfterDays: mc?.forgetAfterDays ?? 3 };
2228
+ const now = Date.now();
2229
+ const verified = new Set(verifiedFiles);
2230
+ let due = 0;
2231
+ try {
2232
+ for (const info of collectCandidates(consolidatedDir, thresholds, now)) {
2233
+ // 验签失败的记忆不审查、不减速、也不进候选
2234
+ if (!verified.has(info.name))
2235
+ continue;
2236
+ if (isDueForReview(info, thresholds, now))
2237
+ due++;
2238
+ else {
2239
+ try {
2240
+ deferCandidate(info.filePath, now);
2241
+ }
2242
+ catch { /* ignore */ }
2243
+ }
2244
+ }
2245
+ }
2246
+ catch {
2247
+ return;
2248
+ }
2249
+ if (due === 0)
2250
+ return;
2251
+ // 该层有超期记忆 → 经统一队列拉独立遗忘会话
2252
+ try {
2253
+ if (!this.consolidationLaunchExecutor)
2254
+ return;
2255
+ const ownerAid = this.agentRegistry?.get(selfAid)?.config?.owners?.[0];
2256
+ await this.consolidationLaunchExecutor({
2257
+ taskCtx,
2258
+ mode: 'forget',
2259
+ triggeredBy: 'manual',
2260
+ ownerAid,
2261
+ forgetAfterDays: mc?.forgetAfterDays,
2262
+ scopeOverride: scope,
2263
+ });
2264
+ }
2265
+ catch { /* 触发失败不影响本次写入结果 */ }
2266
+ }
1715
2267
  hasValidControlToken(value) {
1716
2268
  if (!this.controlToken || typeof value !== 'string')
1717
2269
  return false;
@@ -1789,9 +2341,19 @@ function ipcQueryOnce(socketPath, cmd, timeoutMs = 3000) {
1789
2341
  }
1790
2342
  catch { }
1791
2343
  }
2344
+ const requestArgv = Array.isArray(authenticatedCmd.argv)
2345
+ && authenticatedCmd.argv.every((value) => typeof value === 'string')
2346
+ ? [
2347
+ 'ec',
2348
+ ...(authenticatedCmd.type === 'menu-client.request' ? ['menu-client'] : []),
2349
+ ...authenticatedCmd.argv,
2350
+ ]
2351
+ : undefined;
1792
2352
  const delegationCommandHash = typeof authenticatedCmd.delegationToken === 'string'
1793
2353
  && typeof authenticatedCmd.delegationCommandHash !== 'string'
1794
- ? hashCurrentDelegatedCommand()
2354
+ ? requestArgv
2355
+ ? hashDelegatedCommandArgv(requestArgv)
2356
+ : hashCurrentDelegatedCommand()
1795
2357
  : undefined;
1796
2358
  const request = {
1797
2359
  ...(delegationCommandHash ? { ...authenticatedCmd, delegationCommandHash } : authenticatedCmd),