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
@@ -13,7 +13,7 @@ import fs from 'fs';
13
13
  import os from 'os';
14
14
  import crypto from 'crypto';
15
15
  import { logger } from '../utils/logger.js';
16
- import { createClaudeStartupArgumentsTooLongError, isClaudeStartupArgumentsTooLong, } from '../utils/error-utils.js';
16
+ import { createClaudeStartupArgumentsTooLongError, isClaudeStartupArgumentsTooLong, createClaudeCodeStartupError, isClaudeCodeStartupProcessError, } from '../utils/error-utils.js';
17
17
  import { requestDangerousCommandPermission } from '../core/permission/approval-gateway.js';
18
18
  import { checkDangerousCommand, checkReadonly, evaluateToolPreflight } from '../core/permission/tool-policy.js';
19
19
  import { sanitizeShellExecutionEnvironment } from '../core/permission/shell-environment.js';
@@ -34,6 +34,85 @@ import { contextTokensForUsage, usageForContext, isClaudeContextUsageModel, isOn
34
34
  import { hasContextWindowSuffix, stripContextWindowSuffix } from '../core/model/context-window-suffix.js';
35
35
  const resolveModule = createRequire(import.meta.url);
36
36
  const CLAUDE_INTERRUPT_TIMEOUT_MS = 5_000;
37
+ export function summarizeClaudeQueryOptions(options, context) {
38
+ const sha256 = (value) => crypto.createHash('sha256').update(value).digest('hex');
39
+ const rawBaseUrl = options.env?.ANTHROPIC_BASE_URL;
40
+ let baseUrl = { source: 'sdk_default' };
41
+ let queryParameterNames = [];
42
+ if (rawBaseUrl) {
43
+ try {
44
+ const parsed = new URL(rawBaseUrl);
45
+ queryParameterNames = [...new Set(parsed.searchParams.keys())].sort();
46
+ baseUrl = {
47
+ source: 'env',
48
+ origin: parsed.origin,
49
+ pathLength: parsed.pathname.length,
50
+ pathSha256: sha256(parsed.pathname),
51
+ };
52
+ }
53
+ catch {
54
+ baseUrl = { source: 'env', invalid: true };
55
+ }
56
+ }
57
+ const headers = (options.env?.ANTHROPIC_CUSTOM_HEADERS ?? '').split(/\r?\n/u).flatMap(line => {
58
+ const separator = line.indexOf(':');
59
+ if (separator < 1)
60
+ return [];
61
+ const name = line.slice(0, separator).trim();
62
+ if (!/^[!#$%&'*+.^_`|~0-9a-z-]+$/iu.test(name))
63
+ return [];
64
+ const normalizedName = name.toLowerCase();
65
+ const rawValue = line.slice(separator + 1).trim();
66
+ const safeValue = ((normalizedName === 'content-type' || normalizedName === 'accept')
67
+ && ['application/json', 'text/event-stream'].includes(rawValue))
68
+ || (normalizedName === 'anthropic-version' && /^\d{4}-\d{2}-\d{2}$/u.test(rawValue))
69
+ || (normalizedName === 'x-evolcore-base-agent' && rawValue === 'claude')
70
+ || (normalizedName === 'x-evolcore-agent-aid' && rawValue === context.agentAid);
71
+ return [{ name, value: safeValue ? rawValue : '[REDACTED]' }];
72
+ });
73
+ const systemPrompt = options.systemPrompt;
74
+ const append = typeof systemPrompt === 'string'
75
+ ? systemPrompt
76
+ : !Array.isArray(systemPrompt) && systemPrompt?.type === 'preset'
77
+ ? systemPrompt.append ?? ''
78
+ : '';
79
+ const sandbox = options.sandbox
80
+ ?? (typeof options.settings === 'object' ? options.settings.sandbox : undefined);
81
+ return {
82
+ type: 'claude_sdk_query_options',
83
+ evidence: 'sdk_options',
84
+ wireRequestCaptured: false,
85
+ sessionId: context.sessionId,
86
+ taskId: context.taskId ?? null,
87
+ inputId: context.inputId,
88
+ agentAid: context.agentAid ?? null,
89
+ callModel: context.callModel ?? null,
90
+ sdkModel: options.model ?? null,
91
+ effort: options.effort ?? null,
92
+ resumeId: options.resume ?? null,
93
+ resumeAt: {
94
+ present: !!options.resumeSessionAt,
95
+ sha256: options.resumeSessionAt ? sha256(options.resumeSessionAt) : null,
96
+ },
97
+ baseUrl,
98
+ queryParameterNames,
99
+ headers,
100
+ permissionMode: options.permissionMode ?? null,
101
+ evolcorePermissionMode: context.permissionMode ?? null,
102
+ sandbox: {
103
+ source: sandbox ? 'options' : typeof options.settings === 'string' ? 'settings_file' : 'none',
104
+ executionState: context.executionSandboxState ?? null,
105
+ enabled: sandbox?.enabled ?? null,
106
+ allowUnsandboxedCommands: sandbox?.allowUnsandboxedCommands ?? null,
107
+ denyReadCount: sandbox?.filesystem?.denyRead?.length ?? null,
108
+ denyWriteCount: sandbox?.filesystem?.denyWrite?.length ?? null,
109
+ },
110
+ settingSources: options.settingSources?.slice() ?? [],
111
+ promptAppend: { length: append.length, sha256: sha256(append) },
112
+ queryOptionNames: Object.keys(options).sort(),
113
+ nativeDebugOptionsEnabled: options.debug === true || !!options.debugFile,
114
+ };
115
+ }
37
116
  /**
38
117
  * Resolve the platform package explicitly instead of relying on the SDK's
39
118
  * internal optional-dependency lookup. The latter is sensitive to the module
@@ -105,15 +184,15 @@ const CLAUDE_BUILTIN_TOOLS = new Set([
105
184
  'WebSearch',
106
185
  'Write',
107
186
  ]);
108
- function spawnClaudeWithHClassGuard(options, root, onStderr) {
109
- const preflight = collectSandboxGuardDiagnostics(root);
187
+ function spawnClaudeWithHClassGuard(options, root, onStderr, selfAid) {
188
+ const preflight = collectSandboxGuardDiagnostics(root, { selfAid });
110
189
  logger.info(`[ClaudeSandbox] H-class guard preflight ${JSON.stringify(summarizeSandboxGuardDiagnostics(preflight))}`);
111
- const guarded = buildHClassGuardCommand(options.command, options.args, root);
190
+ const guarded = buildHClassGuardCommand(options.command, options.args, root, { selfAid });
112
191
  if (!guarded) {
113
192
  throw new Error('Claude owner bypass 缺少 EvolCore H 类路径隔离运行时,已拒绝启动');
114
193
  }
115
194
  const launch = summarizeBubblewrapArgsForLog(guarded.args);
116
- const postBuild = collectSandboxGuardDiagnostics(root);
195
+ const postBuild = collectSandboxGuardDiagnostics(root, { selfAid });
117
196
  logger.info(`[ClaudeSandbox] H-class guard launch ${JSON.stringify({
118
197
  ...launch,
119
198
  diagnostics: summarizeSandboxGuardDiagnostics(postBuild),
@@ -482,7 +561,7 @@ class MessageStream {
482
561
  }
483
562
  export class AgentRunner {
484
563
  name = 'claude';
485
- capabilities = { taskRecovery: true, fullaccess: true, clear: true, compact: true, fork: true, forkAtTurn: true, askUserQuestion: true, planApproval: true, fileRewind: 'checkpoint' };
564
+ capabilities = { taskRecovery: true, fullaccess: true, clear: true, compact: true, fork: true, forkAtTurn: true, forkAtMessage: true, askUserQuestion: true, planApproval: true, fileRewind: 'checkpoint' };
486
565
  apiKey;
487
566
  model;
488
567
  effort;
@@ -593,7 +672,8 @@ export class AgentRunner {
593
672
  this.onSessionIdUpdate = onSessionIdUpdate;
594
673
  this.claudeExecutablePath = resolveBundledClaudeExecutable();
595
674
  if (config) {
596
- const anthropic = resolveAnthropicConfig(config);
675
+ const anthropic = resolveAnthropicConfig(this.getRuntimeGatewayConfig(), undefined, this.getRuntimeGatewayScope());
676
+ this.apiKey = apiKey || anthropic.apiKey;
597
677
  this.claudeExecutablePath = anthropic.pathToClaudeCodeExecutable || this.claudeExecutablePath;
598
678
  this.customHeaders = buildModelRequestHeaders({
599
679
  baseagent: 'claude',
@@ -604,6 +684,28 @@ export class AgentRunner {
604
684
  this.customQueryParams = anthropic.queryParams;
605
685
  }
606
686
  }
687
+ getRuntimeGatewayScope(projectPath) {
688
+ const configuredProjectPath = this.agentConfig?.projects?.defaultPath;
689
+ return {
690
+ ...(this.agentAid ? { agentAid: this.agentAid } : {}),
691
+ ...(typeof projectPath === 'string' && projectPath.trim()
692
+ ? { projectPath: projectPath.trim() }
693
+ : typeof configuredProjectPath === 'string' && configuredProjectPath.trim()
694
+ ? { projectPath: configuredProjectPath.trim() }
695
+ : {}),
696
+ };
697
+ }
698
+ getRuntimeGatewayConfig() {
699
+ if (!this.agentAid)
700
+ return this.config;
701
+ try {
702
+ const raw = resolveEffective({ self: this.agentAid }, { cache: true, expand: false });
703
+ return { agents: { claude: raw.baseagents?.claude ?? this.config?.agents?.claude } };
704
+ }
705
+ catch {
706
+ return this.config;
707
+ }
708
+ }
607
709
  getAgentEnv(runtimeEnv, evolcoreSessionId, permissionMode) {
608
710
  const anthropicBaseUrl = appendQueryParams(this.baseUrl, this.customQueryParams);
609
711
  const env = sanitizeShellExecutionEnvironment({
@@ -1396,6 +1498,26 @@ export class AgentRunner {
1396
1498
  const activatedBeforeEvent = await activatePendingSession(false);
1397
1499
  if (activatedBeforeEvent)
1398
1500
  yield { type: 'session_id', sessionId: activatedBeforeEvent };
1501
+ const responseMessage = event.type === 'assistant'
1502
+ ? event.message
1503
+ : event.type === 'stream_event' && event.event?.type === 'message_start'
1504
+ ? event.event.message
1505
+ : undefined;
1506
+ if (responseMessage) {
1507
+ logger.info('[ClaudeResponseDiagnostic]', JSON.stringify({
1508
+ type: 'claude_sdk_response',
1509
+ evidence: 'sdk_response',
1510
+ wireRequestCaptured: false,
1511
+ sessionId,
1512
+ taskId: turn?.taskId ?? this.permissionContexts.get(sessionId)?.taskId ?? null,
1513
+ inputId,
1514
+ agentAid: this.agentAid ?? null,
1515
+ backendSessionId: typeof event.session_id === 'string' ? event.session_id : null,
1516
+ eventType: event.type,
1517
+ requestId: typeof event.request_id === 'string' ? event.request_id : null,
1518
+ responseModel: typeof responseMessage.model === 'string' ? responseMessage.model : null,
1519
+ }));
1520
+ }
1399
1521
  // 提取 session_id(任意 SDK 事件都可能携带)
1400
1522
  if (event.session_id && event.session_id !== lastSessionId) {
1401
1523
  lastSessionId = event.session_id;
@@ -1681,6 +1803,7 @@ export class AgentRunner {
1681
1803
  yield {
1682
1804
  type: 'tool_result', name: toolName, result: resultContent, isError: true,
1683
1805
  error: detail.message, errorCode: 'CAPABILITY_UNAVAILABLE', callId: block.tool_use_id,
1806
+ assistantUuid: event.uuid,
1684
1807
  correlationId: block.tool_use_id, decision: 'error', decisionSource: 'infrastructure',
1685
1808
  policyCode: SANDBOX_INITIALIZATION_FAILED, executed: false, executionState: 'blocked',
1686
1809
  };
@@ -1697,6 +1820,7 @@ export class AgentRunner {
1697
1820
  isError: block.is_error === true,
1698
1821
  error: block.is_error === true ? resultContent : undefined,
1699
1822
  callId: block.tool_use_id,
1823
+ assistantUuid: event.uuid,
1700
1824
  };
1701
1825
  }
1702
1826
  }
@@ -2287,6 +2411,7 @@ export class AgentRunner {
2287
2411
  channel: permCtx?.channel,
2288
2412
  peerId: permCtx?.userId,
2289
2413
  role: permCtx?.role,
2414
+ selfAid: permCtx?.selfAid ?? this.agentAid,
2290
2415
  allowProtectedMetadata: false,
2291
2416
  allowReadonlySourceDiagnostics: permCtx?.allowReadonlySourceDiagnostics === true,
2292
2417
  };
@@ -2463,6 +2588,7 @@ export class AgentRunner {
2463
2588
  channel: permCtx?.channel,
2464
2589
  peerId: permCtx?.userId,
2465
2590
  role: permCtx?.role,
2591
+ selfAid: permCtx?.selfAid ?? this.agentAid,
2466
2592
  allowProtectedMetadata: false,
2467
2593
  allowReadonlySourceDiagnostics: permCtx?.allowReadonlySourceDiagnostics === true,
2468
2594
  };
@@ -2559,6 +2685,7 @@ export class AgentRunner {
2559
2685
  ensureClaudeGitWorktreeConfig(projectPath);
2560
2686
  const enableWeakerNestedSandbox = shouldEnableClaudeWeakerNestedSandbox();
2561
2687
  const sandboxFilesystem = buildClaudeProtectedFilesystem(resolvePaths().root, {
2688
+ selfAid: runPermissionContext?.selfAid ?? this.agentAid,
2562
2689
  denyLClassRead: callPermissionMode === 'readonly',
2563
2690
  });
2564
2691
  const sandboxUnixSockets = buildClaudeUnixSocketAllowlist(projectPath, {
@@ -2631,7 +2758,7 @@ export class AgentRunner {
2631
2758
  ...(callEffort ? { effort: callEffort } : {}),
2632
2759
  ...(this.claudeExecutablePath ? { pathToClaudeCodeExecutable: this.claudeExecutablePath } : {}),
2633
2760
  ...(executionSandbox.state === 'off' && callPermissionMode !== 'fullaccess' && process.platform === 'linux' ? {
2634
- spawnClaudeCodeProcess: (options) => spawnClaudeWithHClassGuard(options, resolvePaths().root, handleClaudeStderr),
2761
+ spawnClaudeCodeProcess: (options) => spawnClaudeWithHClassGuard(options, resolvePaths().root, handleClaudeStderr, runPermissionContext?.selfAid ?? this.agentAid),
2635
2762
  } : {}),
2636
2763
  autoCompactWindow: sdkAutoCompactWindowForModel(sdkModel),
2637
2764
  advisorModel: 'haiku',
@@ -2677,6 +2804,17 @@ export class AgentRunner {
2677
2804
  throw new Error(`[ClaudeSandbox] failed to externalize Windows settings: ${error instanceof Error ? error.message : String(error)}`);
2678
2805
  }
2679
2806
  }
2807
+ const logQueryOptions = (options) => {
2808
+ logger.info('[ClaudeQueryDiagnostic]', JSON.stringify(summarizeClaudeQueryOptions(options, {
2809
+ sessionId,
2810
+ inputId,
2811
+ taskId: modelOverride?.turn?.taskId ?? runPermissionContext?.taskId,
2812
+ agentAid: this.agentAid,
2813
+ callModel,
2814
+ permissionMode: callPermissionMode,
2815
+ executionSandboxState: executionSandbox.state,
2816
+ })));
2817
+ };
2680
2818
  const createQuery = (promptInput, resumeSessionId, resumeAt) => {
2681
2819
  if (useSettingSources) {
2682
2820
  const queryOptions = {
@@ -2696,6 +2834,7 @@ export class AgentRunner {
2696
2834
  delete queryOptions.sandbox;
2697
2835
  queryOptions.settings = sandboxSettingsFile;
2698
2836
  }
2837
+ logQueryOptions(queryOptions);
2699
2838
  return query({
2700
2839
  prompt: promptInput,
2701
2840
  options: queryOptions
@@ -2746,18 +2885,27 @@ export class AgentRunner {
2746
2885
  delete queryOptions.sandbox;
2747
2886
  queryOptions.settings = sandboxSettingsFile;
2748
2887
  }
2888
+ logQueryOptions(queryOptions);
2749
2889
  return query({
2750
2890
  prompt: promptInput,
2751
2891
  options: queryOptions
2752
2892
  });
2753
2893
  }
2754
2894
  };
2755
- // 检查待处理的 resumeAt(由 /rewind N chat 设置)
2895
+ // 检查待处理的 resumeAt(由 /rewind N chat 设置)。话题字段必须
2896
+ // 通过 SessionManager 的专用 CAS 消费,不能落入通用 metadata writer。
2756
2897
  let resumeAt;
2757
2898
  if (sessionManager && agentSessionId) {
2758
2899
  try {
2759
2900
  const currentSession = await sessionManager.getSessionById?.(sessionId);
2760
- if (currentSession?.metadata?.resumeAt) {
2901
+ if (currentSession?.threadId && topicBinding && typeof sessionManager.consumeTopicResumeAt === 'function') {
2902
+ resumeAt = await sessionManager.consumeTopicResumeAt({
2903
+ sessionId,
2904
+ expectedThreadId: currentSession.threadId,
2905
+ expectedAgentSessionId: agentSessionId,
2906
+ });
2907
+ }
2908
+ else if (currentSession?.metadata?.resumeAt) {
2761
2909
  resumeAt = currentSession.metadata.resumeAt;
2762
2910
  if (typeof sessionManager.patchSessionMetadata === 'function') {
2763
2911
  await sessionManager.patchSessionMetadata(sessionId, { resumeAt: undefined });
@@ -2767,10 +2915,16 @@ export class AgentRunner {
2767
2915
  delete newMeta.resumeAt;
2768
2916
  await sessionManager.updateSession(sessionId, { metadata: newMeta });
2769
2917
  }
2770
- logger.info(`[AgentRunner] Consuming resumeAt: ${resumeAt}`);
2918
+ }
2919
+ if (resumeAt) {
2920
+ logger.info('[AgentRunner] Consuming resumeAt sha256=', crypto.createHash('sha256').update(resumeAt).digest('hex'));
2771
2921
  }
2772
2922
  }
2773
2923
  catch (err) {
2924
+ if (topicBinding) {
2925
+ logger.error('[AgentRunner] Failed to consume topic resumeAt:', err);
2926
+ throw err;
2927
+ }
2774
2928
  logger.warn('[AgentRunner] Failed to check resumeAt:', err);
2775
2929
  }
2776
2930
  }
@@ -2792,6 +2946,8 @@ export class AgentRunner {
2792
2946
  const stderr = this.recentStderr.get(sessionId) ?? [];
2793
2947
  if (isClaudeStartupArgumentsTooLong(error))
2794
2948
  throw createClaudeStartupArgumentsTooLongError(error);
2949
+ if (isClaudeCodeStartupProcessError(error))
2950
+ throw createClaudeCodeStartupError(error);
2795
2951
  if (isSandboxInitializationFailure(error, stderr)) {
2796
2952
  const { detail } = await this.recordSandboxInfrastructureFailure(sessionId, inputId, callPermissionMode, error, stderr);
2797
2953
  throw detail;
@@ -2810,6 +2966,8 @@ export class AgentRunner {
2810
2966
  const stderr = this.recentStderr.get(sessionId) ?? [];
2811
2967
  if (isClaudeStartupArgumentsTooLong(error))
2812
2968
  throw createClaudeStartupArgumentsTooLongError(error);
2969
+ if (isClaudeCodeStartupProcessError(error))
2970
+ throw createClaudeCodeStartupError(error);
2813
2971
  if (isSandboxInitializationFailure(error, stderr)) {
2814
2972
  const { detail } = await this.recordSandboxInfrastructureFailure(sessionId, inputId, callPermissionMode, error, stderr);
2815
2973
  throw detail;
@@ -3341,8 +3499,8 @@ export class ClaudeAgentPlugin {
3341
3499
  }
3342
3500
  createAgent(agent, callbacks) {
3343
3501
  const override = agent.config.baseagents?.claude;
3344
- const syntheticConfig = { agents: { claude: override } };
3345
- const anthropic = resolveAnthropicConfig(syntheticConfig, override);
3502
+ const rawConfig = resolveEffective({ self: agent.aid }, { cache: true, expand: false });
3503
+ const anthropic = resolveAnthropicConfig({ agents: { claude: rawConfig.baseagents?.claude } }, undefined, { agentAid: agent.aid, projectPath: agent.projectPath });
3346
3504
  const merged = {
3347
3505
  agents: { claude: { ...(override || {}) } },
3348
3506
  };
@@ -216,6 +216,9 @@ export class CodexAppServerClient {
216
216
  async threadRollback(threadId, numTurns) {
217
217
  return this.request('thread/rollback', { threadId, numTurns });
218
218
  }
219
+ async threadRevert(threadId, beforeTurnId) {
220
+ return this.request('thread/revert', { threadId, beforeTurnId });
221
+ }
219
222
  async threadFork(threadId, projectPath, title, options) {
220
223
  const effort = options?.effort ?? this.options.effort;
221
224
  const configUsesPermissionProfile = hasPermissionProfile(options?.config);
@@ -492,19 +495,20 @@ export class CodexAppServerClient {
492
495
  let commandArgs = launchCommand.args;
493
496
  if (process.platform === 'linux') {
494
497
  const guardRoot = resolvePaths().root;
495
- const preflightDiagnostics = collectSandboxGuardDiagnostics(guardRoot);
498
+ const preflightDiagnostics = collectSandboxGuardDiagnostics(guardRoot, { selfAid: this.options.selfAid });
496
499
  logger.info(`[CodexAppServer] H-class guard preflight ${JSON.stringify(summarizeSandboxGuardDiagnostics(preflightDiagnostics))}`);
497
500
  const managedRequirements = this.ensureManagedHookRuntime();
498
501
  const guardedCommand = buildHClassGuardCommand(command, commandArgs, guardRoot, {
499
502
  managedCodexRequirements: managedRequirements,
500
503
  protectEvolcoreFilesystem: this.options.protectEvolcoreFilesystem !== false,
504
+ selfAid: this.options.selfAid,
501
505
  });
502
506
  if (!guardedCommand) {
503
507
  throw new Error('Codex 缺少 EvolCore managed-hook 隔离运行时,已拒绝启动 app-server');
504
508
  }
505
509
  command = guardedCommand.command;
506
510
  commandArgs = guardedCommand.args;
507
- const launchDiagnostics = collectSandboxGuardDiagnostics(guardRoot);
511
+ const launchDiagnostics = collectSandboxGuardDiagnostics(guardRoot, { selfAid: this.options.selfAid });
508
512
  logger.info(`[CodexAppServer] H-class guard launch ${JSON.stringify({
509
513
  ...summarizeBubblewrapArgsForLog(commandArgs),
510
514
  diagnostics: summarizeSandboxGuardDiagnostics(launchDiagnostics),
@@ -17,7 +17,8 @@ export function checkCodexProjectPath(value, options = {}) {
17
17
  if (projectPath.startsWith('\\\\')) {
18
18
  warnings.push('Windows UNC/network project path may be unavailable to Codex sandboxed processes.');
19
19
  }
20
- const systemRoot = process.env.SystemRoot ? path.resolve(process.env.SystemRoot).toLowerCase() : '';
20
+ const configuredSystemRoot = options.systemRoot ?? process.env.SystemRoot;
21
+ const systemRoot = configuredSystemRoot ? path.resolve(configuredSystemRoot).toLowerCase() : '';
21
22
  if (systemRoot && projectPath.toLowerCase().startsWith(`${systemRoot}${path.sep}`)) {
22
23
  warnings.push('Project path is under the Windows system directory; use a dedicated workspace when possible.');
23
24
  }
@@ -91,8 +92,6 @@ export function runCodexHookLaunchDiagnostic(options = {}) {
91
92
  };
92
93
  }
93
94
  const requirements = path.resolve(options.requirements || paths.requirements);
94
- const managedDir = path.resolve(options.managedDir || paths.managedDir);
95
- const hookPath = path.join(managedDir, 'pre-tool-use.mjs');
96
95
  const output = path.resolve(options.output
97
96
  || path.join(process.env.CODEX_HOME || path.join(os.homedir(), '.codex'), 'log', 'evolcore-hook-diagnostic.json'));
98
97
  const runtimeLog = output + '.runtime.jsonl';
@@ -101,6 +100,8 @@ export function runCodexHookLaunchDiagnostic(options = {}) {
101
100
  const configuredDir = config.hooks?.windows_managed_dir ?? config.hooks?.managed_dir;
102
101
  if (typeof configuredDir !== 'string')
103
102
  throw new Error('No Windows managed hook directory configured.');
103
+ const managedDir = path.resolve(options.managedDir || configuredDir);
104
+ const hookPath = path.join(managedDir, 'pre-tool-use.mjs');
104
105
  const expected = expectedWindowsHookCommand(nodePath, hookPath);
105
106
  const handlers = Array.isArray(config.hooks?.PreToolUse)
106
107
  ? config.hooks.PreToolUse.flatMap((group) => group?.hooks || [])