@openclaw/codex 2026.5.16-beta.1 → 2026.5.16-beta.2

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.
@@ -1,28 +1,28 @@
1
- import { l as resolveCodexPluginsPolicy, o as readCodexPluginConfig, s as resolveCodexAppServerRuntimeOptions, u as withMcpElicitationsApprovalPolicy } from "./config-0rd3LnKg.js";
1
+ import { c as resolveCodexAppServerRuntimeOptions, d as withMcpElicitationsApprovalPolicy, i as isCodexAppServerApprovalPolicyAllowedByRequirements, s as readCodexPluginConfig, u as resolveCodexPluginsPolicy } from "./config-3ATInASk.js";
2
2
  import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse } from "./protocol-validators-CSY0BFBo.js";
3
3
  import { t as isJsonObject } from "./protocol-C9UWI98H.js";
4
- import { i as isCodexAppServerConnectionClosedError, r as isCodexAppServerApprovalRequest } from "./client-CoctX13d.js";
5
- import { n as buildCodexPluginAppCacheKey, r as CODEX_CONTROL_METHODS } from "./request-CKYiRqsN.js";
4
+ import { i as isCodexAppServerConnectionClosedError, r as isCodexAppServerApprovalRequest } from "./client-CA7amCZ8.js";
5
+ import { n as buildCodexPluginAppCacheKey, r as CODEX_CONTROL_METHODS } from "./request-Czoa60Nt.js";
6
6
  import { d as resolveCodexUsageLimitResetAtMs, f as shouldRefreshCodexRateLimitsForUsageLimitMessage, r as formatCodexDisplayText, u as formatCodexUsageLimitErrorMessage } from "./command-formatters-BRW7_Nu7.js";
7
- import { c as resolveCodexAppServerAuthAccountCacheKey, d as resolveCodexAppServerEnvApiKeyCacheKey, l as resolveCodexAppServerAuthProfileId, n as clearSharedCodexAppServerClientIfCurrent, s as refreshCodexAppServerAuthTokens, u as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-BwUqd3lh.js";
8
- import { i as readCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-CMTXuyoz.js";
9
- import { a as defaultCodexAppInventoryCache } from "./plugin-activation-aQOmRQwA.js";
10
- import { _ as resolveCodexContextEngineProjectionReserveTokens, b as normalizeCodexDynamicToolName, d as buildCodexPluginThreadConfig, f as buildCodexPluginThreadConfigInputFingerprint, g as resolveCodexContextEngineProjectionMaxChars, h as projectContextEngineAssemblyForCodex, m as shouldBuildCodexPluginThreadConfig, o as buildTurnStartParams, p as mergeCodexThreadConfigs, r as buildDeveloperInstructions, s as codexDynamicToolsFingerprint, t as areCodexDynamicToolFingerprintsCompatible, u as startOrResumeThread, v as createCodexDynamicToolBridge, y as filterCodexDynamicTools } from "./thread-lifecycle-BzY-GLGu.js";
11
- import { t as defaultCodexAppServerClientFactory } from "./client-factory-Be6RD28K.js";
12
- import { n as handleCodexAppServerElicitationRequest, r as handleCodexAppServerApprovalRequest, t as filterToolsForVisionInputs } from "./vision-tools-CyhFwJIY.js";
13
- import { t as ensureCodexComputerUse } from "./computer-use-DsJxRRtm.js";
7
+ import { c as resolveCodexAppServerAuthAccountCacheKey, d as resolveCodexAppServerEnvApiKeyCacheKey, l as resolveCodexAppServerAuthProfileId, n as clearSharedCodexAppServerClientIfCurrent, s as refreshCodexAppServerAuthTokens, u as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-CnbrvEfV.js";
8
+ import { i as readCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-DbdVqMzW.js";
9
+ import { a as defaultCodexAppInventoryCache } from "./plugin-activation-BDU4e-NA.js";
10
+ import { S as normalizeCodexDynamicToolName, _ as projectContextEngineAssemblyForCodex, b as createCodexDynamicToolBridge, c as codexDynamicToolsFingerprint, f as startOrResumeThread, g as shouldBuildCodexPluginThreadConfig, h as mergeCodexThreadConfigs, i as buildDeveloperInstructions, l as isContextEngineBindingCompatible, m as buildCodexPluginThreadConfigInputFingerprint, p as buildCodexPluginThreadConfig, r as buildContextEngineBinding, s as buildTurnStartParams, t as areCodexDynamicToolFingerprintsCompatible, v as resolveCodexContextEngineProjectionMaxChars, x as filterCodexDynamicTools, y as resolveCodexContextEngineProjectionReserveTokens } from "./thread-lifecycle-BMK4m_PL.js";
11
+ import { t as defaultCodexAppServerClientFactory } from "./client-factory-DwzPofwS.js";
12
+ import { n as handleCodexAppServerElicitationRequest, r as handleCodexAppServerApprovalRequest, t as filterToolsForVisionInputs } from "./vision-tools-Cm_YicZb.js";
13
+ import { t as ensureCodexComputerUse } from "./computer-use-BX02ojP4.js";
14
14
  import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-dvhq-4pi.js";
15
15
  import { createHash } from "node:crypto";
16
16
  import nodeFs from "node:fs";
17
- import { TOOL_PROGRESS_OUTPUT_MAX_CHARS, acquireSessionWriteLock, appendSessionTranscriptMessage, assembleHarnessContextEngine, bootstrapHarnessContextEngine, buildEmbeddedAttemptToolRunContext, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emitSessionTranscriptUpdate, finalizeHarnessContextEngineTurn, formatErrorMessage, formatToolAggregate, formatToolProgressOutput, inferToolMetaFromArgs, isActiveHarnessContextEngine, isSubagentSessionKey, loadCodexBundleMcpThreadConfig, normalizeAgentRuntimeTools, normalizeUsage, registerNativeHookRelay, resolveAgentHarnessBeforePromptBuildResult, resolveAttemptSpawnWorkspaceDir, resolveBootstrapContextForRun, resolveContextEngineOwnerPluginId, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, resolveSessionWriteLockAcquireTimeoutMs, resolveUserPath, runAgentCleanupStep, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessAgentEndHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessBeforeMessageWriteHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
17
+ import { TOOL_PROGRESS_OUTPUT_MAX_CHARS, acquireSessionWriteLock, appendSessionTranscriptMessage, assembleHarnessContextEngine, bootstrapHarnessContextEngine, buildEmbeddedAttemptToolRunContext, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emitSessionTranscriptUpdate, finalizeHarnessContextEngineTurn, formatErrorMessage, formatToolAggregate, formatToolProgressOutput, hasBeforeToolCallPolicy, inferToolMetaFromArgs, isActiveHarnessContextEngine, isSubagentSessionKey, loadCodexBundleMcpThreadConfig, normalizeAgentRuntimeTools, normalizeUsage, registerNativeHookRelay, resolveAgentHarnessBeforePromptBuildResult, resolveAttemptSpawnWorkspaceDir, resolveBootstrapContextForRun, resolveContextEngineOwnerPluginId, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, resolveSessionWriteLockAcquireTimeoutMs, resolveUserPath, runAgentCleanupStep, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessAgentEndHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessBeforeMessageWriteHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
18
18
  import fs from "node:fs/promises";
19
19
  import path from "node:path";
20
20
  import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1 } from "openclaw/plugin-sdk/agent-runtime";
21
21
  import { appendRegularFile, pathExists } from "openclaw/plugin-sdk/security-runtime";
22
+ import { redactSensitiveFieldValue, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
22
23
  import { emitTrustedDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
23
24
  import { createRunningTaskRun, finalizeTaskRunByRunId, recordTaskRunProgressByRunId } from "openclaw/plugin-sdk/codex-native-task-runtime";
24
25
  import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "@earendil-works/pi-coding-agent";
25
- import { redactSensitiveFieldValue, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
26
26
  //#region extensions/codex/src/app-server/native-subagent-task-mirror.ts
27
27
  const CODEX_NATIVE_SUBAGENT_RUNTIME = "subagent";
28
28
  const CODEX_NATIVE_SUBAGENT_TASK_KIND = "codex-native";
@@ -1732,22 +1732,40 @@ const CODEX_HOOK_EVENT_BY_NATIVE_EVENT = {
1732
1732
  permission_request: "PermissionRequest",
1733
1733
  before_agent_finalize: "Stop"
1734
1734
  };
1735
+ const CODEX_HOOK_KEY_LABEL_BY_NATIVE_EVENT = {
1736
+ pre_tool_use: "pre_tool_use",
1737
+ post_tool_use: "post_tool_use",
1738
+ permission_request: "permission_request",
1739
+ before_agent_finalize: "stop"
1740
+ };
1741
+ const CODEX_SESSION_FLAGS_HOOK_SOURCE_PATHS = ["/<session-flags>/config.toml", "<session-flags>/config.toml"];
1735
1742
  function buildCodexNativeHookRelayConfig(params) {
1736
1743
  const events = params.events?.length ? params.events : CODEX_NATIVE_HOOK_RELAY_EVENTS;
1737
1744
  const config = { "features.hooks": true };
1745
+ const hookState = {};
1738
1746
  for (const event of events) {
1739
1747
  const codexEvent = CODEX_HOOK_EVENT_BY_NATIVE_EVENT[event];
1740
- config[`hooks.${codexEvent}`] = [{
1741
- matcher: null,
1742
- hooks: [{
1743
- type: "command",
1744
- command: params.relay.commandForEvent(event),
1745
- timeout: normalizeHookTimeoutSec(params.hookTimeoutSec),
1746
- async: false,
1748
+ const command = params.relay.commandForEvent(event);
1749
+ const timeout = normalizeHookTimeoutSec(params.hookTimeoutSec);
1750
+ config[`hooks.${codexEvent}`] = [{ hooks: [{
1751
+ type: "command",
1752
+ command,
1753
+ timeout,
1754
+ async: false,
1755
+ statusMessage: "OpenClaw native hook relay"
1756
+ }] }];
1757
+ const state = {
1758
+ enabled: true,
1759
+ trusted_hash: codexCommandHookTrustedHash({
1760
+ event,
1761
+ command,
1762
+ timeout,
1747
1763
  statusMessage: "OpenClaw native hook relay"
1748
- }]
1749
- }];
1764
+ })
1765
+ };
1766
+ for (const sourcePath of CODEX_SESSION_FLAGS_HOOK_SOURCE_PATHS) hookState[`${sourcePath}:${CODEX_HOOK_KEY_LABEL_BY_NATIVE_EVENT[event]}:0:0`] = state;
1750
1767
  }
1768
+ config["hooks.state"] = hookState;
1751
1769
  return config;
1752
1770
  }
1753
1771
  function buildCodexNativeHookRelayDisabledConfig() {
@@ -1762,6 +1780,26 @@ function buildCodexNativeHookRelayDisabledConfig() {
1762
1780
  function normalizeHookTimeoutSec(value) {
1763
1781
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.ceil(value) : 5;
1764
1782
  }
1783
+ function codexCommandHookTrustedHash(params) {
1784
+ const identity = {
1785
+ event_name: CODEX_HOOK_KEY_LABEL_BY_NATIVE_EVENT[params.event],
1786
+ hooks: [{
1787
+ async: false,
1788
+ command: params.command,
1789
+ statusMessage: params.statusMessage,
1790
+ timeout: params.timeout,
1791
+ type: "command"
1792
+ }]
1793
+ };
1794
+ return `sha256:${createHash("sha256").update(JSON.stringify(sortJsonValue(identity))).digest("hex")}`;
1795
+ }
1796
+ function sortJsonValue(value) {
1797
+ if (!value || typeof value !== "object") return value;
1798
+ if (Array.isArray(value)) return value.map(sortJsonValue);
1799
+ const sorted = {};
1800
+ for (const key of Object.keys(value).toSorted()) sorted[key] = sortJsonValue(value[key]);
1801
+ return sorted;
1802
+ }
1765
1803
  //#endregion
1766
1804
  //#region extensions/codex/src/app-server/trajectory.ts
1767
1805
  const SENSITIVE_FIELD_RE = /(?:authorization|cookie|credential|key|password|passwd|secret|token)/iu;
@@ -2315,6 +2353,22 @@ function restrictCodexAppServerSandboxForOpenClawSandbox(appServer, sandbox) {
2315
2353
  sandbox: "workspace-write"
2316
2354
  };
2317
2355
  }
2356
+ function resolveCodexAppServerForOpenClawToolPolicy(params) {
2357
+ if (!params.shouldPromote || !params.canUseUntrustedApprovalPolicy || params.appServer.approvalPolicy !== "never") return params.appServer;
2358
+ const explicitMode = params.pluginConfig.appServer?.mode !== void 0 || isCodexAppServerPolicyMode(params.env.OPENCLAW_CODEX_APP_SERVER_MODE);
2359
+ const explicitApprovalPolicy = params.pluginConfig.appServer?.approvalPolicy !== void 0 || isCodexAppServerApprovalPolicy(params.env.OPENCLAW_CODEX_APP_SERVER_APPROVAL_POLICY);
2360
+ if (explicitMode || explicitApprovalPolicy) return params.appServer;
2361
+ return {
2362
+ ...params.appServer,
2363
+ approvalPolicy: "untrusted"
2364
+ };
2365
+ }
2366
+ function isCodexAppServerPolicyMode(value) {
2367
+ return value === "guardian" || value === "yolo";
2368
+ }
2369
+ function isCodexAppServerApprovalPolicy(value) {
2370
+ return value === "never" || value === "on-request" || value === "on-failure" || value === "untrusted";
2371
+ }
2318
2372
  async function runCodexAppServerAttempt(params, options = {}) {
2319
2373
  const attemptStartedAt = Date.now();
2320
2374
  const attemptClientFactory = options.clientFactory ?? defaultCodexAppServerClientFactory;
@@ -2330,7 +2384,13 @@ async function runCodexAppServerAttempt(params, options = {}) {
2330
2384
  });
2331
2385
  const effectiveWorkspace = sandbox?.enabled ? sandbox.workspaceAccess === "rw" ? resolvedWorkspace : sandbox.workspaceDir : resolvedWorkspace;
2332
2386
  await fs.mkdir(effectiveWorkspace, { recursive: true });
2333
- const appServer = restrictCodexAppServerSandboxForOpenClawSandbox(configuredAppServer, sandbox);
2387
+ const appServer = resolveCodexAppServerForOpenClawToolPolicy({
2388
+ appServer: restrictCodexAppServerSandboxForOpenClawSandbox(configuredAppServer, sandbox),
2389
+ pluginConfig,
2390
+ env: process.env,
2391
+ shouldPromote: hasBeforeToolCallPolicy(),
2392
+ canUseUntrustedApprovalPolicy: configuredAppServer.start.transport !== "stdio" || isCodexAppServerApprovalPolicyAllowedByRequirements("untrusted")
2393
+ });
2334
2394
  let pluginAppServer = appServer;
2335
2395
  const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
2336
2396
  configuredEvents: options.nativeHookRelay?.events,
@@ -2364,6 +2424,17 @@ async function runCodexAppServerAttempt(params, options = {}) {
2364
2424
  sessionKey: sandboxSessionKey,
2365
2425
  ...startupAuthProfileId ? { authProfileId: startupAuthProfileId } : {}
2366
2426
  };
2427
+ let activeSessionId = params.sessionId;
2428
+ let activeSessionFile = params.sessionFile;
2429
+ const buildActiveRunAttemptParams = () => ({
2430
+ ...runtimeParams,
2431
+ sessionId: activeSessionId,
2432
+ sessionFile: activeSessionFile
2433
+ });
2434
+ const adoptContextEngineCompactionTranscript = (compactResult) => {
2435
+ if (compactResult.result?.sessionId) activeSessionId = compactResult.result.sessionId;
2436
+ if (compactResult.result?.sessionFile) activeSessionFile = compactResult.result.sessionFile;
2437
+ };
2367
2438
  const startupAuthAccountCacheKey = await resolveCodexAppServerAuthAccountCacheKey({
2368
2439
  authProfileId: startupAuthProfileId,
2369
2440
  authProfileStore: params.authProfileStore,
@@ -2406,8 +2477,8 @@ async function runCodexAppServerAttempt(params, options = {}) {
2406
2477
  runId: params.runId
2407
2478
  }
2408
2479
  });
2409
- const hadSessionFile = await pathExists(params.sessionFile);
2410
- let historyMessages = await readMirroredSessionHistoryMessages(params.sessionFile) ?? [];
2480
+ const hadSessionFile = await pathExists(activeSessionFile);
2481
+ let historyMessages = await readMirroredSessionHistoryMessages(activeSessionFile) ?? [];
2411
2482
  const hookContextWindowFields = {
2412
2483
  ...params.contextWindowInfo?.tokens ? { contextTokenBudget: params.contextWindowInfo.tokens } : params.contextTokenBudget ? { contextTokenBudget: params.contextTokenBudget } : {},
2413
2484
  ...params.contextWindowInfo?.source ? { contextWindowSource: params.contextWindowInfo.source } : {},
@@ -2424,27 +2495,28 @@ async function runCodexAppServerAttempt(params, options = {}) {
2424
2495
  channelId: params.messageChannel ?? params.messageProvider ?? void 0,
2425
2496
  ...hookContextWindowFields
2426
2497
  };
2498
+ const activeContextEnginePluginId = activeContextEngine ? resolveContextEngineOwnerPluginId(activeContextEngine) : void 0;
2499
+ const buildActiveContextEngineRuntimeContext = () => buildHarnessContextEngineRuntimeContext({
2500
+ attempt: buildActiveRunAttemptParams(),
2501
+ workspaceDir: effectiveWorkspace,
2502
+ agentDir,
2503
+ activeAgentId: sessionAgentId,
2504
+ contextEnginePluginId: activeContextEnginePluginId,
2505
+ tokenBudget: params.contextTokenBudget
2506
+ });
2427
2507
  if (activeContextEngine) {
2428
- const activeContextEnginePluginId = resolveContextEngineOwnerPluginId(activeContextEngine);
2429
2508
  await bootstrapHarnessContextEngine({
2430
2509
  hadSessionFile,
2431
2510
  contextEngine: activeContextEngine,
2432
- sessionId: params.sessionId,
2511
+ sessionId: activeSessionId,
2433
2512
  sessionKey: sandboxSessionKey,
2434
- sessionFile: params.sessionFile,
2435
- runtimeContext: buildHarnessContextEngineRuntimeContext({
2436
- attempt: runtimeParams,
2437
- workspaceDir: effectiveWorkspace,
2438
- agentDir,
2439
- activeAgentId: sessionAgentId,
2440
- contextEnginePluginId: activeContextEnginePluginId,
2441
- tokenBudget: params.contextTokenBudget
2442
- }),
2513
+ sessionFile: activeSessionFile,
2514
+ runtimeContext: buildActiveContextEngineRuntimeContext(),
2443
2515
  runMaintenance: runHarnessContextEngineMaintenance,
2444
2516
  config: params.config,
2445
2517
  warn: (message) => embeddedAgentLog.warn(message)
2446
2518
  });
2447
- historyMessages = await readMirroredSessionHistoryMessages(params.sessionFile) ?? historyMessages;
2519
+ historyMessages = await readMirroredSessionHistoryMessages(activeSessionFile) ?? historyMessages;
2448
2520
  }
2449
2521
  const baseDeveloperInstructions = buildDeveloperInstructions(params);
2450
2522
  const workspaceBootstrapContext = await buildCodexWorkspaceBootstrapContext({
@@ -2458,10 +2530,18 @@ async function runCodexAppServerAttempt(params, options = {}) {
2458
2530
  let promptText = params.prompt;
2459
2531
  let developerInstructions = joinPresentSections(baseDeveloperInstructions, workspaceBootstrapInstructions);
2460
2532
  let prePromptMessageCount = historyMessages.length;
2461
- if (activeContextEngine) try {
2533
+ let contextEngineProjection;
2534
+ const resetCodexPromptInputs = () => {
2535
+ promptText = params.prompt;
2536
+ developerInstructions = joinPresentSections(baseDeveloperInstructions, workspaceBootstrapInstructions);
2537
+ prePromptMessageCount = historyMessages.length;
2538
+ contextEngineProjection = void 0;
2539
+ };
2540
+ const applyActiveContextEngineProjection = async (decisionStartupBinding) => {
2541
+ if (!activeContextEngine) return;
2462
2542
  const assembled = await assembleHarnessContextEngine({
2463
2543
  contextEngine: activeContextEngine,
2464
- sessionId: params.sessionId,
2544
+ sessionId: activeSessionId,
2465
2545
  sessionKey: sandboxSessionKey,
2466
2546
  messages: historyMessages,
2467
2547
  tokenBudget: params.contextTokenBudget,
@@ -2471,6 +2551,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
2471
2551
  prompt: params.prompt
2472
2552
  });
2473
2553
  if (!assembled) throw new Error("context engine assemble returned no result");
2554
+ contextEngineProjection = readContextEngineThreadBootstrapProjection(assembled.contextProjection);
2474
2555
  const projection = projectContextEngineAssemblyForCodex({
2475
2556
  assembledMessages: assembled.messages,
2476
2557
  originalHistoryMessages: historyMessages,
@@ -2479,11 +2560,41 @@ async function runCodexAppServerAttempt(params, options = {}) {
2479
2560
  maxRenderedContextChars: resolveCodexContextEngineProjectionMaxChars({
2480
2561
  contextTokenBudget: params.contextTokenBudget,
2481
2562
  reserveTokens: resolveCodexContextEngineProjectionReserveTokens({ config: params.config })
2482
- })
2563
+ }),
2564
+ toolPayloadMode: contextEngineProjection ? "preserve" : "elide"
2483
2565
  });
2484
- promptText = projection.promptText;
2566
+ const projectionDecision = contextEngineProjection ? resolveContextEngineBootstrapProjectionDecision({
2567
+ startupBinding: decisionStartupBinding,
2568
+ expectedBinding: buildContextEngineBinding(buildActiveRunAttemptParams(), contextEngineProjection),
2569
+ projection: contextEngineProjection,
2570
+ dynamicToolsFingerprint: codexDynamicToolsFingerprint(toolBridge.specs)
2571
+ }) : {
2572
+ project: true,
2573
+ reason: "per-turn-projection"
2574
+ };
2575
+ embeddedAgentLog.info("codex app-server context-engine projection decision", {
2576
+ sessionId: params.sessionId,
2577
+ sessionKey: sandboxSessionKey,
2578
+ engineId: activeContextEngine.info.id,
2579
+ mode: contextEngineProjection?.mode ?? assembled.contextProjection?.mode ?? "per_turn",
2580
+ epoch: contextEngineProjection?.epoch,
2581
+ fingerprint: contextEngineProjection?.fingerprint,
2582
+ previousThreadId: decisionStartupBinding?.threadId,
2583
+ previousEpoch: decisionStartupBinding?.contextEngine?.projection?.epoch,
2584
+ previousFingerprint: decisionStartupBinding?.contextEngine?.projection?.fingerprint,
2585
+ projected: projectionDecision.project,
2586
+ reason: projectionDecision.reason,
2587
+ assembledMessages: assembled.messages.length,
2588
+ originalHistoryMessages: historyMessages.length,
2589
+ projectedPromptChars: projection.promptText.length,
2590
+ developerInstructionAdditionChars: projection.developerInstructionAddition?.length ?? 0
2591
+ });
2592
+ promptText = projectionDecision.project ? projection.promptText : params.prompt;
2485
2593
  developerInstructions = joinPresentSections(baseDeveloperInstructions, workspaceBootstrapInstructions, projection.developerInstructionAddition);
2486
2594
  prePromptMessageCount = projection.prePromptMessageCount;
2595
+ };
2596
+ if (activeContextEngine) try {
2597
+ await applyActiveContextEngineProjection(startupBinding);
2487
2598
  } catch (assembleErr) {
2488
2599
  embeddedAgentLog.warn("context engine assemble failed; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
2489
2600
  }
@@ -2500,13 +2611,13 @@ async function runCodexAppServerAttempt(params, options = {}) {
2500
2611
  promptText = projection.promptText;
2501
2612
  prePromptMessageCount = projection.prePromptMessageCount;
2502
2613
  }
2503
- promptText = prependCurrentTurnContext(promptText, params.currentTurnContext);
2504
- const promptBuild = await resolveAgentHarnessBeforePromptBuildResult({
2505
- prompt: promptText,
2614
+ const buildPromptFromCurrentInputs = () => resolveAgentHarnessBeforePromptBuildResult({
2615
+ prompt: prependCurrentTurnContext(promptText, params.currentTurnContext),
2506
2616
  developerInstructions,
2507
2617
  messages: historyMessages,
2508
2618
  ctx: hookContext
2509
2619
  });
2620
+ let promptBuild = await buildPromptFromCurrentInputs();
2510
2621
  const systemPromptReport = buildCodexSystemPromptReport({
2511
2622
  attempt: params,
2512
2623
  sessionKey: sandboxSessionKey,
@@ -2588,9 +2699,9 @@ async function runCodexAppServerAttempt(params, options = {}) {
2588
2699
  timeoutMs: appServer.requestTimeoutMs,
2589
2700
  signal: runAbortController.signal
2590
2701
  });
2591
- const threadLifecycleParams = {
2702
+ const buildThreadLifecycleParams = () => ({
2592
2703
  client: startupClient,
2593
- params: runtimeParams,
2704
+ params: buildActiveRunAttemptParams(),
2594
2705
  agentId: sessionAgentId,
2595
2706
  cwd: effectiveWorkspace,
2596
2707
  dynamicTools: toolBridge.specs,
@@ -2599,6 +2710,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
2599
2710
  config: threadConfig,
2600
2711
  mcpServersFingerprint: bundleMcpThreadConfig.fingerprint,
2601
2712
  mcpServersFingerprintEvaluated: bundleMcpThreadConfig.evaluated,
2713
+ contextEngineProjection,
2602
2714
  pluginThreadConfig: pluginThreadConfigEnabled ? {
2603
2715
  enabled: true,
2604
2716
  inputFingerprint: pluginThreadConfigInputFingerprint,
@@ -2613,11 +2725,11 @@ async function runCodexAppServerAttempt(params, options = {}) {
2613
2725
  appCacheKey: pluginAppCacheKey
2614
2726
  })
2615
2727
  } : void 0
2616
- };
2617
- restartContextEngineCodexThread = () => startOrResumeThread(threadLifecycleParams);
2728
+ });
2729
+ restartContextEngineCodexThread = () => startOrResumeThread(buildThreadLifecycleParams());
2618
2730
  return {
2619
2731
  client: startupClient,
2620
- thread: await startOrResumeThread(threadLifecycleParams)
2732
+ thread: await startOrResumeThread(buildThreadLifecycleParams())
2621
2733
  };
2622
2734
  };
2623
2735
  for (let attempt = 1; attempt <= CODEX_APP_SERVER_STARTUP_CONNECTION_CLOSE_MAX_ATTEMPTS; attempt += 1) try {
@@ -2952,6 +3064,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
2952
3064
  if (isCurrentTurnNotification) updateActiveTurnItemIds(notification, activeTurnItemIds);
2953
3065
  const unblockedAssistantCompletionRelease = isCurrentTurnNotification && turnAssistantCompletionIdleWatchArmed && notification.method === "item/completed" && activeTurnItemIds.size === 0;
2954
3066
  const trackedDynamicToolCompletion = isTrackedOpenClawDynamicToolCompletionNotification(notification, activeOpenClawDynamicToolCallIds);
3067
+ const rawToolOutputCompletion = isRawToolOutputCompletionNotification(notification);
2955
3068
  const shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem = isCurrentTurnNotification && notification.method === "item/completed" && activeTurnItemIds.size === 0 && !trackedDynamicToolCompletion && !isCompletedAssistantNotification(notification);
2956
3069
  if (isCurrentTurnNotification && notification.method === "error") {
2957
3070
  if (isRetryableErrorNotification(notification.params)) disarmTurnCompletionIdleWatch();
@@ -2961,11 +3074,13 @@ async function runCodexAppServerAttempt(params, options = {}) {
2961
3074
  else if (isCurrentTurnNotification && isCompletedAssistantNotification(notification)) armTurnAssistantCompletionIdleWatch(describeNotificationActivity(notification));
2962
3075
  else if (unblockedAssistantCompletionRelease) armTurnAssistantCompletionIdleWatch(describeNotificationActivity(notification));
2963
3076
  else if (shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem) armTurnCompletionIdleWatch();
3077
+ else if (isCurrentTurnNotification && rawToolOutputCompletion) armTurnCompletionIdleWatch();
2964
3078
  else if (isCurrentTurnNotification && shouldDisarmAssistantCompletionIdleWatch(notification)) disarmTurnAssistantCompletionIdleWatch();
2965
- if (turnCompletionIdleWatchArmed && !turnCompletionIdleWatchPinnedByTerminalError && notification.method !== "turn/completed" && isCurrentTurnNotification && !trackedDynamicToolCompletion && !shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem) disarmTurnCompletionIdleWatch();
3079
+ if (turnCompletionIdleWatchArmed && !turnCompletionIdleWatchPinnedByTerminalError && notification.method !== "turn/completed" && isCurrentTurnNotification && !trackedDynamicToolCompletion && !rawToolOutputCompletion && !shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem) disarmTurnCompletionIdleWatch();
2966
3080
  const isTurnAbortMarker = isCurrentTurnNotification && isCodexTurnAbortMarkerNotification(notification, { currentPromptText: promptBuild.prompt });
2967
3081
  const isTurnTerminal = isTurnCompletion || isTurnAbortMarker;
2968
3082
  try {
3083
+ await waitForCodexNotificationDispatchTurn();
2969
3084
  await projector.handleNotification(notification);
2970
3085
  } catch (error) {
2971
3086
  embeddedAgentLog.debug("codex app-server projector notification threw", {
@@ -2985,6 +3100,11 @@ async function runCodexAppServerAttempt(params, options = {}) {
2985
3100
  }
2986
3101
  };
2987
3102
  const enqueueNotification = (notification) => {
3103
+ if (!projector || !turnId) {
3104
+ userInputBridge?.handleNotification(notification);
3105
+ pendingNotifications.push(notification);
3106
+ return Promise.resolve();
3107
+ }
2988
3108
  notificationQueue = notificationQueue.then(() => handleNotification(notification), () => handleNotification(notification));
2989
3109
  return notificationQueue;
2990
3110
  };
@@ -3117,7 +3237,76 @@ async function runCodexAppServerAttempt(params, options = {}) {
3117
3237
  touchTurnCompletionActivity(`request:${request.method}:response`, { arm: armCompletionWatchOnResponse });
3118
3238
  }
3119
3239
  });
3120
- const llmInputEvent = {
3240
+ const forceContextEngineCompactionForCodexOverflow = async (error) => {
3241
+ if (!activeContextEngine?.info.ownsCompaction) return false;
3242
+ embeddedAgentLog.warn("codex app-server context-engine turn overflowed; forcing context-engine compaction", {
3243
+ sessionId: activeSessionId,
3244
+ sessionKey: sandboxSessionKey,
3245
+ threadId: thread.threadId,
3246
+ engineId: activeContextEngine.info.id,
3247
+ tokenBudget: params.contextTokenBudget,
3248
+ error: formatErrorMessage(error)
3249
+ });
3250
+ try {
3251
+ const runtimeContext = buildActiveContextEngineRuntimeContext();
3252
+ const overflowTokenCount = params.contextTokenBudget ?? params.contextWindowInfo?.tokens;
3253
+ const compactResult = await activeContextEngine.compact({
3254
+ sessionId: activeSessionId,
3255
+ sessionKey: sandboxSessionKey,
3256
+ sessionFile: activeSessionFile,
3257
+ tokenBudget: params.contextTokenBudget,
3258
+ force: true,
3259
+ ...overflowTokenCount ? { currentTokenCount: overflowTokenCount } : {},
3260
+ compactionTarget: "threshold",
3261
+ runtimeContext: overflowTokenCount ? {
3262
+ ...runtimeContext,
3263
+ currentTokenCount: overflowTokenCount
3264
+ } : runtimeContext
3265
+ });
3266
+ embeddedAgentLog.info("codex app-server context-engine forced compaction result", {
3267
+ sessionId: activeSessionId,
3268
+ sessionKey: sandboxSessionKey,
3269
+ engineId: activeContextEngine.info.id,
3270
+ ok: compactResult.ok,
3271
+ compacted: compactResult.compacted,
3272
+ reason: compactResult.reason,
3273
+ tokensBefore: compactResult.result?.tokensBefore,
3274
+ tokensAfter: compactResult.result?.tokensAfter
3275
+ });
3276
+ if (!compactResult.ok || !compactResult.compacted) return false;
3277
+ adoptContextEngineCompactionTranscript(compactResult);
3278
+ const maintenanceRuntimeContext = buildActiveContextEngineRuntimeContext();
3279
+ await runHarnessContextEngineMaintenance({
3280
+ contextEngine: activeContextEngine,
3281
+ sessionId: activeSessionId,
3282
+ sessionKey: sandboxSessionKey,
3283
+ sessionFile: activeSessionFile,
3284
+ reason: "compaction",
3285
+ runtimeContext: maintenanceRuntimeContext,
3286
+ config: params.config
3287
+ });
3288
+ return true;
3289
+ } catch (compactErr) {
3290
+ embeddedAgentLog.warn("codex app-server context-engine forced compaction failed", {
3291
+ sessionId: params.sessionId,
3292
+ sessionKey: sandboxSessionKey,
3293
+ engineId: activeContextEngine.info.id,
3294
+ error: formatErrorMessage(compactErr)
3295
+ });
3296
+ return false;
3297
+ }
3298
+ };
3299
+ const rebuildPromptAfterContextEngineCompaction = async () => {
3300
+ historyMessages = await readMirroredSessionHistoryMessages(activeSessionFile) ?? historyMessages;
3301
+ resetCodexPromptInputs();
3302
+ try {
3303
+ await applyActiveContextEngineProjection(void 0);
3304
+ } catch (assembleErr) {
3305
+ embeddedAgentLog.warn("context engine assemble failed after forced compaction; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
3306
+ }
3307
+ promptBuild = await buildPromptFromCurrentInputs();
3308
+ };
3309
+ const buildLlmInputEvent = () => ({
3121
3310
  runId: params.runId,
3122
3311
  sessionId: params.sessionId,
3123
3312
  provider: params.provider,
@@ -3126,8 +3315,8 @@ async function runCodexAppServerAttempt(params, options = {}) {
3126
3315
  prompt: promptBuild.prompt,
3127
3316
  historyMessages,
3128
3317
  imagesCount: params.images?.length ?? 0
3129
- };
3130
- const turnStartFailureMessages = [...historyMessages, buildCodexUserPromptMessage({
3318
+ });
3319
+ const buildTurnStartFailureMessages = () => [...historyMessages, buildCodexUserPromptMessage({
3131
3320
  ...params,
3132
3321
  prompt: promptBuild.prompt
3133
3322
  })];
@@ -3143,7 +3332,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
3143
3332
  }));
3144
3333
  try {
3145
3334
  runAgentHarnessLlmInputHook({
3146
- event: llmInputEvent,
3335
+ event: buildLlmInputEvent(),
3147
3336
  ctx: hookContext
3148
3337
  });
3149
3338
  emitCodexAppServerEvent(params, {
@@ -3165,7 +3354,11 @@ async function runCodexAppServerAttempt(params, options = {}) {
3165
3354
  threadId: thread.threadId,
3166
3355
  error: formatErrorMessage(turnStartError)
3167
3356
  });
3168
- await clearCodexAppServerBinding(params.sessionFile);
3357
+ const preRetrySessionFile = activeSessionFile;
3358
+ const compactedForRetry = await forceContextEngineCompactionForCodexOverflow(turnStartError);
3359
+ await clearCodexAppServerBinding(preRetrySessionFile);
3360
+ if (activeSessionFile !== preRetrySessionFile) await clearCodexAppServerBinding(activeSessionFile);
3361
+ if (compactedForRetry) await rebuildPromptAfterContextEngineCompaction();
3169
3362
  thread = await restartContextEngineCodexThread();
3170
3363
  emitCodexAppServerEvent(params, {
3171
3364
  stream: "codex_app_server.lifecycle",
@@ -3219,7 +3412,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
3219
3412
  });
3220
3413
  runAgentHarnessAgentEndHook({
3221
3414
  event: {
3222
- messages: turnStartFailureMessages,
3415
+ messages: buildTurnStartFailureMessages(),
3223
3416
  success: false,
3224
3417
  error: turnStartErrorMessage,
3225
3418
  durationMs: Date.now() - attemptStartedAt
@@ -3248,7 +3441,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
3248
3441
  return buildCodexTurnStartFailureResult({
3249
3442
  params,
3250
3443
  message: usageLimitError.message,
3251
- messagesSnapshot: turnStartFailureMessages,
3444
+ messagesSnapshot: buildTurnStartFailureMessages(),
3252
3445
  systemPromptReport
3253
3446
  });
3254
3447
  }
@@ -3380,20 +3573,20 @@ async function runCodexAppServerAttempt(params, options = {}) {
3380
3573
  });
3381
3574
  if (activeContextEngine) {
3382
3575
  const activeContextEnginePluginId = resolveContextEngineOwnerPluginId(activeContextEngine);
3383
- const finalMessages = await readMirroredSessionHistoryMessages(params.sessionFile) ?? historyMessages.concat(result.messagesSnapshot);
3576
+ const finalMessages = await readMirroredSessionHistoryMessages(activeSessionFile) ?? historyMessages.concat(result.messagesSnapshot);
3384
3577
  await finalizeHarnessContextEngineTurn({
3385
3578
  contextEngine: activeContextEngine,
3386
3579
  promptError: Boolean(finalPromptError),
3387
3580
  aborted: finalAborted,
3388
3581
  yieldAborted: Boolean(result.yieldDetected),
3389
- sessionIdUsed: params.sessionId,
3582
+ sessionIdUsed: activeSessionId,
3390
3583
  sessionKey: sandboxSessionKey,
3391
- sessionFile: params.sessionFile,
3584
+ sessionFile: activeSessionFile,
3392
3585
  messagesSnapshot: finalMessages,
3393
3586
  prePromptMessageCount,
3394
3587
  tokenBudget: params.contextTokenBudget,
3395
3588
  runtimeContext: buildHarnessContextEngineRuntimeContextFromUsage({
3396
- attempt: runtimeParams,
3589
+ attempt: buildActiveRunAttemptParams(),
3397
3590
  workspaceDir: effectiveWorkspace,
3398
3591
  agentDir,
3399
3592
  activeAgentId: sessionAgentId,
@@ -3804,6 +3997,45 @@ function shouldProjectMirroredHistoryForCodexStart(params) {
3804
3997
  next: params.dynamicToolsFingerprint
3805
3998
  });
3806
3999
  }
4000
+ function readContextEngineThreadBootstrapProjection(projection) {
4001
+ if (projection?.mode !== "thread_bootstrap") return;
4002
+ const epoch = projection.epoch?.trim();
4003
+ if (!epoch) {
4004
+ embeddedAgentLog.warn("context engine requested Codex thread-bootstrap projection without an epoch; using per-turn projection");
4005
+ return;
4006
+ }
4007
+ const fingerprint = projection.fingerprint?.trim();
4008
+ return {
4009
+ mode: "thread_bootstrap",
4010
+ epoch,
4011
+ ...fingerprint ? { fingerprint } : {}
4012
+ };
4013
+ }
4014
+ function resolveContextEngineBootstrapProjectionDecision(params) {
4015
+ const bindingProjection = params.startupBinding?.contextEngine?.projection;
4016
+ if (!params.startupBinding?.threadId || !bindingProjection) return {
4017
+ project: true,
4018
+ reason: !params.startupBinding?.threadId ? "missing-thread-binding" : "missing-projection-binding"
4019
+ };
4020
+ if (!params.expectedBinding || !isContextEngineBindingCompatible(params.startupBinding.contextEngine, params.expectedBinding)) return {
4021
+ project: true,
4022
+ reason: "context-engine-binding-mismatch"
4023
+ };
4024
+ if (!areCodexDynamicToolFingerprintsCompatible({
4025
+ previous: params.startupBinding.dynamicToolsFingerprint,
4026
+ next: params.dynamicToolsFingerprint
4027
+ })) return {
4028
+ project: true,
4029
+ reason: "dynamic-tools-mismatch"
4030
+ };
4031
+ return bindingProjection.mode !== "thread_bootstrap" || bindingProjection.epoch !== params.projection.epoch || bindingProjection.fingerprint !== params.projection.fingerprint ? {
4032
+ project: true,
4033
+ reason: "projection-mismatch"
4034
+ } : {
4035
+ project: false,
4036
+ reason: "matching-thread-bootstrap-binding"
4037
+ };
4038
+ }
3807
4039
  async function withCodexStartupTimeout(params) {
3808
4040
  if (params.signal.aborted) throw new Error("codex app-server startup aborted");
3809
4041
  let timeout;
@@ -4004,6 +4236,11 @@ function isTrackedOpenClawDynamicToolCompletionNotification(notification, active
4004
4236
  const itemType = item ? readString(item, "type") : void 0;
4005
4237
  return itemType === void 0 || itemType === "dynamicToolCall";
4006
4238
  }
4239
+ function isRawToolOutputCompletionNotification(notification) {
4240
+ if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) return false;
4241
+ const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
4242
+ return item ? readString(item, "type") === "custom_tool_call_output" : false;
4243
+ }
4007
4244
  function readRawAssistantTextPreview(item) {
4008
4245
  if (readString(item, "role") !== "assistant" || !Array.isArray(item.content)) return;
4009
4246
  const text = item.content.flatMap((content) => {
@@ -4289,6 +4526,11 @@ function prependCurrentTurnContext(prompt, context) {
4289
4526
  const text = context?.text.trim();
4290
4527
  return text ? [text, prompt].filter(Boolean).join("\n\n") : prompt;
4291
4528
  }
4529
+ function waitForCodexNotificationDispatchTurn() {
4530
+ return new Promise((resolve) => {
4531
+ setImmediate(resolve);
4532
+ });
4533
+ }
4292
4534
  function handleApprovalRequest(params) {
4293
4535
  return handleCodexAppServerApprovalRequest({
4294
4536
  method: params.method,
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-DUslC3ob.js";
2
- import { a as normalizeCodexServiceTier } from "./config-0rd3LnKg.js";
2
+ import { o as normalizeCodexServiceTier } from "./config-3ATInASk.js";
3
3
  import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
4
4
  import fs from "node:fs/promises";
5
5
  import { ensureAuthProfileStore, resolveDefaultAgentDir, resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
@@ -103,7 +103,19 @@ function readContextEngineBinding(value) {
103
103
  return {
104
104
  schemaVersion: 1,
105
105
  engineId: record.engineId,
106
- policyFingerprint: record.policyFingerprint
106
+ policyFingerprint: record.policyFingerprint,
107
+ projection: readContextEngineProjectionBinding(record.projection)
108
+ };
109
+ }
110
+ function readContextEngineProjectionBinding(value) {
111
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
112
+ const record = value;
113
+ if (record.schemaVersion !== 1 || record.mode !== "thread_bootstrap" || typeof record.epoch !== "string" || !record.epoch.trim()) return;
114
+ return {
115
+ schemaVersion: 1,
116
+ mode: "thread_bootstrap",
117
+ epoch: record.epoch,
118
+ fingerprint: typeof record.fingerprint === "string" ? record.fingerprint : void 0
107
119
  };
108
120
  }
109
121
  function readPluginAppPolicyContext(value) {
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-DUslC3ob.js";
2
- import { n as codexAppServerStartOptionsKey, s as resolveCodexAppServerRuntimeOptions } from "./config-0rd3LnKg.js";
3
- import { a as MANAGED_CODEX_APP_SERVER_PACKAGE, o as resolveCodexAppServerSpawnEnv, t as CodexAppServerClient } from "./client-CoctX13d.js";
2
+ import { c as resolveCodexAppServerRuntimeOptions, n as codexAppServerStartOptionsKey } from "./config-3ATInASk.js";
3
+ import { a as MANAGED_CODEX_APP_SERVER_PACKAGE, o as resolveCodexAppServerSpawnEnv, t as CodexAppServerClient } from "./client-CA7amCZ8.js";
4
4
  import { createRequire } from "node:module";
5
5
  import { createHash } from "node:crypto";
6
6
  import { constants, readFileSync } from "node:fs";