@openclaw/codex 2026.5.10-beta.2 → 2026.5.10-beta.3

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,14 +1,14 @@
1
- import { l as resolveCodexPluginsPolicy, o as readCodexPluginConfig, s as resolveCodexAppServerRuntimeOptions, u as withMcpElicitationsApprovalPolicy } from "./config-CT01BBDc.js";
1
+ import { l as resolveCodexPluginsPolicy, o as readCodexPluginConfig, s as resolveCodexAppServerRuntimeOptions, u as withMcpElicitationsApprovalPolicy } from "./config-C7xdbzrp.js";
2
2
  import { i as readCodexDynamicToolCallParams, r as assertCodexTurnStartResponse, s as readCodexTurn } from "./protocol-validators-CeCyJaWj.js";
3
3
  import { t as isJsonObject } from "./protocol-C9UWI98H.js";
4
- import { i as isCodexAppServerConnectionClosedError, r as isCodexAppServerApprovalRequest } from "./client-CTzy3Y6M.js";
5
- import { d as formatCodexUsageLimitErrorMessage, i as formatCodexDisplayText } from "./request-DC1Dz3iZ.js";
6
- import { a as refreshCodexAppServerAuthTokens, c as resolveCodexAppServerAuthProfileIdForAgent, l as resolveCodexAppServerEnvApiKeyCacheKey, o as resolveCodexAppServerAuthAccountCacheKey, s as resolveCodexAppServerAuthProfileId, t as clearSharedCodexAppServerClientIfCurrent, u as resolveCodexAppServerHomeDir } from "./shared-client-p-TvEiNL.js";
7
- import { i as readCodexAppServerBinding } from "./session-binding-B44KIZM2.js";
8
- import { i as defaultCodexAppInventoryCache, r as buildCodexAppInventoryCacheKey } from "./plugin-activation-CweAZa7r.js";
9
- import { a as buildTurnStartParams, c as buildCodexPluginThreadConfig, d as createCodexDynamicToolBridge, f as filterCodexDynamicTools, l as buildCodexPluginThreadConfigInputFingerprint, n as buildDeveloperInstructions, o as codexDynamicToolsFingerprint, p as normalizeCodexDynamicToolName, s as startOrResumeThread, t as areCodexDynamicToolFingerprintsCompatible, u as shouldBuildCodexPluginThreadConfig } from "./thread-lifecycle-CGc-O_5d.js";
10
- import { n as defaultCodexAppServerClientFactory } from "./client-factory-BJL_efz4.js";
11
- import { n as rememberCodexRateLimits, r as ensureCodexComputerUse, t as readRecentCodexRateLimits } from "./rate-limit-cache-DbZvmrAD.js";
4
+ import { i as isCodexAppServerConnectionClosedError, r as isCodexAppServerApprovalRequest } from "./client-CpksBQ9l.js";
5
+ import { d as formatCodexUsageLimitErrorMessage, f as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as formatCodexDisplayText, p as CODEX_CONTROL_METHODS } from "./request-Bj4IRDU9.js";
6
+ import { a as refreshCodexAppServerAuthTokens, c as resolveCodexAppServerAuthProfileIdForAgent, l as resolveCodexAppServerEnvApiKeyCacheKey, o as resolveCodexAppServerAuthAccountCacheKey, s as resolveCodexAppServerAuthProfileId, t as clearSharedCodexAppServerClientIfCurrent, u as resolveCodexAppServerHomeDir } from "./shared-client-BRX9tReb.js";
7
+ import { i as readCodexAppServerBinding } from "./session-binding-BAaJ-7s-.js";
8
+ import { i as defaultCodexAppInventoryCache, r as buildCodexAppInventoryCacheKey } from "./plugin-activation-Dn14PX1W.js";
9
+ import { a as buildTurnStartParams, c as buildCodexPluginThreadConfig, d as createCodexDynamicToolBridge, f as filterCodexDynamicTools, l as buildCodexPluginThreadConfigInputFingerprint, n as buildDeveloperInstructions, o as codexDynamicToolsFingerprint, p as normalizeCodexDynamicToolName, s as startOrResumeThread, t as areCodexDynamicToolFingerprintsCompatible, u as shouldBuildCodexPluginThreadConfig } from "./thread-lifecycle-DRyCVHhL.js";
10
+ import { n as defaultCodexAppServerClientFactory } from "./client-factory-BHbKz0nI.js";
11
+ import { n as rememberCodexRateLimits, r as ensureCodexComputerUse, t as readRecentCodexRateLimits } from "./rate-limit-cache-BFTJlMhx.js";
12
12
  import { createHash } from "node:crypto";
13
13
  import nodeFs from "node:fs";
14
14
  import { TOOL_PROGRESS_OUTPUT_MAX_CHARS, acquireSessionWriteLock, appendSessionTranscriptMessage, assembleHarnessContextEngine, bootstrapHarnessContextEngine, buildEmbeddedAttemptToolRunContext, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, callGatewayTool, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emitSessionTranscriptUpdate, finalizeHarnessContextEngineTurn, formatApprovalDisplayPath, formatErrorMessage, formatToolAggregate, formatToolProgressOutput, inferToolMetaFromArgs, isActiveHarnessContextEngine, isSubagentSessionKey, normalizeAgentRuntimeTools, normalizeUsage, registerNativeHookRelay, resolveAgentHarnessBeforePromptBuildResult, resolveAttemptSpawnWorkspaceDir, resolveBootstrapContextForRun, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, resolveSessionWriteLockAcquireTimeoutMs, resolveUserPath, runAgentCleanupStep, runAgentHarnessAfterCompactionHook, runAgentHarnessAgentEndHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessBeforeMessageWriteHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
@@ -19,7 +19,7 @@ import { appendRegularFile, pathExists } from "openclaw/plugin-sdk/security-runt
19
19
  import { AsyncLocalStorage } from "node:async_hooks";
20
20
  import { emitTrustedDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
21
21
  import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "@mariozechner/pi-coding-agent";
22
- import { redactSensitiveFieldValue, redactToolPayloadText } from "openclaw/plugin-sdk/text-runtime";
22
+ import { redactSensitiveFieldValue, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
23
23
  //#region extensions/codex/src/app-server/plugin-approval-roundtrip.ts
24
24
  const DEFAULT_CODEX_APPROVAL_TIMEOUT_MS = 12e4;
25
25
  const MAX_PLUGIN_APPROVAL_TITLE_LENGTH = 80;
@@ -1301,6 +1301,8 @@ var CodexAppServerEventProjector = class {
1301
1301
  this.toolTranscriptMessages = [];
1302
1302
  this.toolTranscriptCallIds = /* @__PURE__ */ new Set();
1303
1303
  this.toolTranscriptResultIds = /* @__PURE__ */ new Set();
1304
+ this.nativeGeneratedMediaUrls = /* @__PURE__ */ new Set();
1305
+ this.diagnosticToolStartedAtByItem = /* @__PURE__ */ new Map();
1304
1306
  this.assistantStarted = false;
1305
1307
  this.reasoningStarted = false;
1306
1308
  this.reasoningEnded = false;
@@ -1418,7 +1420,7 @@ var CodexAppServerEventProjector = class {
1418
1420
  messagingToolSentMediaUrls: toolTelemetry.messagingToolSentMediaUrls,
1419
1421
  messagingToolSentTargets: toolTelemetry.messagingToolSentTargets,
1420
1422
  heartbeatToolResponse: toolTelemetry.heartbeatToolResponse,
1421
- toolMediaUrls: toolTelemetry.toolMediaUrls,
1423
+ toolMediaUrls: this.buildToolMediaUrls(toolTelemetry),
1422
1424
  toolAudioAsVoice: toolTelemetry.toolAudioAsVoice,
1423
1425
  successfulCronAdds: toolTelemetry.successfulCronAdds,
1424
1426
  cloudCodeAssistFormatError: false,
@@ -1565,6 +1567,7 @@ var CodexAppServerEventProjector = class {
1565
1567
  this.rememberAssistantItem(item.id);
1566
1568
  this.assistantTextByItem.set(item.id, item.text);
1567
1569
  }
1570
+ this.recordNativeGeneratedMedia(item);
1568
1571
  if (item?.type === "plan" && typeof item.text === "string" && item.text) {
1569
1572
  this.planTextByItem.set(item.id, item.text);
1570
1573
  this.emitPlanUpdate({
@@ -1694,6 +1697,7 @@ var CodexAppServerEventProjector = class {
1694
1697
  this.rememberAssistantItem(item.id);
1695
1698
  this.assistantTextByItem.set(item.id, item.text);
1696
1699
  }
1700
+ this.recordNativeGeneratedMedia(item);
1697
1701
  if (item.type === "plan" && typeof item.text === "string" && item.text) {
1698
1702
  this.planTextByItem.set(item.id, item.text);
1699
1703
  this.emitPlanUpdate({
@@ -1752,6 +1756,16 @@ var CodexAppServerEventProjector = class {
1752
1756
  this.rememberAssistantItem(itemId);
1753
1757
  this.assistantTextByItem.set(itemId, text);
1754
1758
  }
1759
+ recordNativeGeneratedMedia(item) {
1760
+ if (item?.type !== "imageGeneration") return;
1761
+ const savedPath = readItemString(item, "savedPath")?.trim();
1762
+ if (savedPath) this.nativeGeneratedMediaUrls.add(savedPath);
1763
+ }
1764
+ buildToolMediaUrls(toolTelemetry) {
1765
+ const mediaUrls = new Set(toolTelemetry.toolMediaUrls?.map((url) => url.trim()).filter(Boolean) ?? []);
1766
+ if ((toolTelemetry.messagingToolSentMediaUrls?.length ?? 0) === 0) for (const mediaUrl of this.nativeGeneratedMediaUrls) mediaUrls.add(mediaUrl);
1767
+ return mediaUrls.size > 0 ? [...mediaUrls] : toolTelemetry.toolMediaUrls;
1768
+ }
1755
1769
  async maybeEndReasoning() {
1756
1770
  if (!this.reasoningStarted || this.reasoningEnded) return;
1757
1771
  this.reasoningEnded = true;
@@ -1799,6 +1813,12 @@ var CodexAppServerEventProjector = class {
1799
1813
  const meta = itemMeta(item, this.toolProgressDetailMode());
1800
1814
  const args = params.phase === "start" ? itemToolArgs(item) : void 0;
1801
1815
  const status = params.phase === "result" ? itemStatus(item) : "running";
1816
+ this.emitDiagnosticToolExecutionEvent({
1817
+ phase: params.phase,
1818
+ item,
1819
+ name,
1820
+ status
1821
+ });
1802
1822
  this.emitAgentEvent({
1803
1823
  stream: "tool",
1804
1824
  data: {
@@ -1816,6 +1836,42 @@ var CodexAppServerEventProjector = class {
1816
1836
  }
1817
1837
  });
1818
1838
  }
1839
+ emitDiagnosticToolExecutionEvent(params) {
1840
+ const base = {
1841
+ runId: this.params.runId,
1842
+ sessionId: this.params.sessionId,
1843
+ sessionKey: this.params.sessionKey,
1844
+ toolName: params.name,
1845
+ toolCallId: params.item.id
1846
+ };
1847
+ if (params.phase === "start") {
1848
+ this.diagnosticToolStartedAtByItem.set(params.item.id, Date.now());
1849
+ emitTrustedDiagnosticEvent({
1850
+ type: "tool.execution.started",
1851
+ ...base
1852
+ });
1853
+ return;
1854
+ }
1855
+ const startedAt = this.diagnosticToolStartedAtByItem.get(params.item.id);
1856
+ this.diagnosticToolStartedAtByItem.delete(params.item.id);
1857
+ const durationMs = (typeof params.item.durationMs === "number" ? params.item.durationMs : void 0) ?? (startedAt === void 0 ? 0 : Math.max(0, Date.now() - startedAt));
1858
+ const terminalEvent = params.status === "blocked" ? {
1859
+ type: "tool.execution.blocked",
1860
+ reason: "codex_native_tool_blocked",
1861
+ deniedReason: "codex_native_tool_blocked"
1862
+ } : params.status === "failed" ? {
1863
+ type: "tool.execution.error",
1864
+ durationMs,
1865
+ errorCategory: "codex_native_tool_error"
1866
+ } : {
1867
+ type: "tool.execution.completed",
1868
+ durationMs
1869
+ };
1870
+ emitTrustedDiagnosticEvent({
1871
+ ...base,
1872
+ ...terminalEvent
1873
+ });
1874
+ }
1819
1875
  emitToolResultSummary(item) {
1820
1876
  if (!item || !this.params.onToolResult || !this.shouldEmitToolResult()) return;
1821
1877
  const itemId = item.id;
@@ -1986,13 +2042,15 @@ var CodexAppServerEventProjector = class {
1986
2042
  };
1987
2043
  }
1988
2044
  createToolCallMessage(params) {
2045
+ const args = normalizeToolTranscriptArguments(params.arguments);
1989
2046
  return {
1990
2047
  role: "assistant",
1991
2048
  content: [{
1992
2049
  type: "toolCall",
1993
2050
  id: params.id,
1994
2051
  name: params.name,
1995
- arguments: normalizeToolTranscriptArguments(params.arguments)
2052
+ arguments: args,
2053
+ input: args
1996
2054
  }],
1997
2055
  api: this.params.model.api ?? "openai-codex-responses",
1998
2056
  provider: this.params.provider,
@@ -2011,6 +2069,9 @@ var CodexAppServerEventProjector = class {
2011
2069
  isError: params.isError,
2012
2070
  content: [{
2013
2071
  type: "toolResult",
2072
+ id: params.id,
2073
+ name: params.name,
2074
+ toolName: params.name,
2014
2075
  toolCallId: params.id,
2015
2076
  toolUseId: params.id,
2016
2077
  tool_use_id: params.id,
@@ -2745,6 +2806,7 @@ const CODEX_DYNAMIC_TOOL_MAX_TIMEOUT_MS = 6e5;
2745
2806
  const CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS = 6e4;
2746
2807
  const CODEX_APP_SERVER_STARTUP_CONNECTION_CLOSE_MAX_ATTEMPTS = 3;
2747
2808
  const CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS = 100;
2809
+ const CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS = 5e3;
2748
2810
  const CODEX_TURN_COMPLETION_IDLE_TIMEOUT_MS = 6e4;
2749
2811
  const CODEX_TURN_TERMINAL_IDLE_TIMEOUT_MS = 30 * 6e4;
2750
2812
  const CODEX_NATIVE_HOOK_RELAY_MIN_TTL_MS = 30 * 6e4;
@@ -3047,13 +3109,14 @@ async function runCodexAppServerAttempt(params, options = {}) {
3047
3109
  historyMessages = await readMirroredSessionHistoryMessages(params.sessionFile) ?? historyMessages;
3048
3110
  }
3049
3111
  const baseDeveloperInstructions = buildDeveloperInstructions(params);
3050
- const workspaceBootstrapInstructions = await buildCodexWorkspaceBootstrapInstructions({
3112
+ const workspaceBootstrapContext = await buildCodexWorkspaceBootstrapContext({
3051
3113
  params,
3052
3114
  resolvedWorkspace,
3053
3115
  effectiveWorkspace,
3054
3116
  sessionKey: sandboxSessionKey,
3055
3117
  sessionAgentId
3056
3118
  });
3119
+ const workspaceBootstrapInstructions = workspaceBootstrapContext.instructions;
3057
3120
  let promptText = params.prompt;
3058
3121
  let developerInstructions = joinPresentSections(baseDeveloperInstructions, workspaceBootstrapInstructions);
3059
3122
  let prePromptMessageCount = historyMessages.length;
@@ -3095,12 +3158,21 @@ async function runCodexAppServerAttempt(params, options = {}) {
3095
3158
  promptText = projection.promptText;
3096
3159
  prePromptMessageCount = projection.prePromptMessageCount;
3097
3160
  }
3161
+ promptText = prependCurrentTurnContext(promptText, params.currentTurnContext);
3098
3162
  const promptBuild = await resolveAgentHarnessBeforePromptBuildResult({
3099
3163
  prompt: promptText,
3100
3164
  developerInstructions,
3101
3165
  messages: historyMessages,
3102
3166
  ctx: hookContext
3103
3167
  });
3168
+ const systemPromptReport = buildCodexSystemPromptReport({
3169
+ attempt: params,
3170
+ sessionKey: sandboxSessionKey,
3171
+ workspaceDir: effectiveWorkspace,
3172
+ developerInstructions: promptBuild.developerInstructions,
3173
+ workspaceBootstrapContext,
3174
+ tools: toolBridge.specs
3175
+ });
3104
3176
  const trajectoryRecorder = createCodexTrajectoryRecorder({
3105
3177
  attempt: params,
3106
3178
  cwd: effectiveWorkspace,
@@ -3614,7 +3686,13 @@ async function runCodexAppServerAttempt(params, options = {}) {
3614
3686
  signal: runAbortController.signal
3615
3687
  }));
3616
3688
  } catch (error) {
3617
- const usageLimitError = formatCodexTurnStartUsageLimitError(error, pendingNotifications);
3689
+ const usageLimitError = await formatCodexTurnStartUsageLimitError({
3690
+ client,
3691
+ error,
3692
+ pendingNotifications,
3693
+ timeoutMs: appServer.requestTimeoutMs,
3694
+ signal: runAbortController.signal
3695
+ });
3618
3696
  const turnStartErrorMessage = usageLimitError ?? formatErrorMessage(error);
3619
3697
  emitCodexAppServerEvent(params, {
3620
3698
  stream: "codex_app_server.lifecycle",
@@ -3731,7 +3809,18 @@ async function runCodexAppServerAttempt(params, options = {}) {
3731
3809
  await completion;
3732
3810
  const result = activeProjector.buildResult(toolBridge.telemetry, { yieldDetected });
3733
3811
  const finalAborted = result.aborted || runAbortController.signal.aborted;
3734
- const finalPromptError = turnCompletionIdleTimedOut ? turnCompletionIdleTimeoutMessage : timedOut ? "codex app-server attempt timed out" : result.promptError;
3812
+ let finalPromptError = turnCompletionIdleTimedOut ? turnCompletionIdleTimeoutMessage : timedOut ? "codex app-server attempt timed out" : result.promptError;
3813
+ const finalPromptErrorMessage = typeof finalPromptError === "string" ? finalPromptError : finalPromptError ? formatErrorMessage(finalPromptError) : void 0;
3814
+ if (shouldRefreshCodexRateLimitsForUsageLimitMessage(finalPromptErrorMessage)) finalPromptError = await refreshCodexUsageLimitErrorMessage({
3815
+ client,
3816
+ source: {
3817
+ message: finalPromptErrorMessage,
3818
+ codexErrorInfo: "usageLimitExceeded",
3819
+ rateLimits: readRecentCodexRateLimits()
3820
+ },
3821
+ timeoutMs: appServer.requestTimeoutMs,
3822
+ signal: runAbortController.signal
3823
+ });
3735
3824
  const finalPromptErrorSource = timedOut ? "prompt" : result.promptErrorSource;
3736
3825
  recordCodexTrajectoryCompletion(trajectoryRecorder, {
3737
3826
  attempt: params,
@@ -3825,7 +3914,8 @@ async function runCodexAppServerAttempt(params, options = {}) {
3825
3914
  timedOut,
3826
3915
  aborted: finalAborted,
3827
3916
  promptError: finalPromptError,
3828
- promptErrorSource: finalPromptErrorSource
3917
+ promptErrorSource: finalPromptErrorSource,
3918
+ systemPromptReport
3829
3919
  };
3830
3920
  } finally {
3831
3921
  emitLifecycleTerminal({
@@ -4142,14 +4232,55 @@ function resolveCodexTurnTerminalIdleTimeoutMs(value) {
4142
4232
  function readDynamicToolCallParams(value) {
4143
4233
  return readCodexDynamicToolCallParams(value);
4144
4234
  }
4145
- function formatCodexTurnStartUsageLimitError(error, pendingNotifications) {
4235
+ async function formatCodexTurnStartUsageLimitError(params) {
4236
+ return refreshCodexUsageLimitErrorMessage({
4237
+ client: params.client,
4238
+ source: readCodexTurnStartUsageLimitErrorSource(params.error, params.pendingNotifications),
4239
+ timeoutMs: params.timeoutMs,
4240
+ signal: params.signal
4241
+ });
4242
+ }
4243
+ async function refreshCodexUsageLimitErrorMessage(params) {
4244
+ const initialMessage = formatCodexUsageLimitErrorMessage(params.source);
4245
+ if (!shouldRefreshCodexRateLimitsForUsageLimitMessage(initialMessage)) return initialMessage ?? void 0;
4246
+ const rateLimits = await readCodexRateLimitsFromAppServerForUsageLimitError({
4247
+ client: params.client,
4248
+ timeoutMs: params.timeoutMs,
4249
+ signal: params.signal
4250
+ });
4251
+ if (!rateLimits) return initialMessage;
4252
+ return formatCodexUsageLimitErrorMessage({
4253
+ message: params.source.message,
4254
+ codexErrorInfo: params.source.codexErrorInfo,
4255
+ rateLimits
4256
+ }) ?? initialMessage;
4257
+ }
4258
+ async function readCodexRateLimitsFromAppServerForUsageLimitError(params) {
4259
+ if (params.signal?.aborted) return;
4260
+ try {
4261
+ const rateLimits = await params.client.request(CODEX_CONTROL_METHODS.rateLimits, void 0, {
4262
+ timeoutMs: resolveCodexUsageLimitRateLimitRefreshTimeoutMs(params.timeoutMs),
4263
+ signal: params.signal
4264
+ });
4265
+ rememberCodexRateLimits(rateLimits);
4266
+ return rateLimits;
4267
+ } catch (error) {
4268
+ embeddedAgentLog.debug("codex app-server rate-limit refresh failed after usage-limit error", { error: formatErrorMessage(error) });
4269
+ return;
4270
+ }
4271
+ }
4272
+ function resolveCodexUsageLimitRateLimitRefreshTimeoutMs(timeoutMs) {
4273
+ if (timeoutMs === void 0 || !Number.isFinite(timeoutMs) || timeoutMs <= 0) return CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS;
4274
+ return Math.max(100, Math.min(timeoutMs, CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS));
4275
+ }
4276
+ function readCodexTurnStartUsageLimitErrorSource(error, pendingNotifications) {
4146
4277
  const notificationError = readLatestCodexErrorNotification(pendingNotifications);
4147
4278
  const errorPayload = readCodexErrorPayload(error);
4148
- return formatCodexUsageLimitErrorMessage({
4279
+ return {
4149
4280
  message: notificationError?.message ?? errorPayload.message ?? formatErrorMessage(error),
4150
4281
  codexErrorInfo: notificationError?.codexErrorInfo ?? errorPayload.codexErrorInfo,
4151
4282
  rateLimits: readLatestRateLimitNotificationPayload(pendingNotifications) ?? errorPayload.rateLimits ?? readRecentCodexRateLimits()
4152
- });
4283
+ };
4153
4284
  }
4154
4285
  function readLatestRateLimitNotificationPayload(notifications) {
4155
4286
  for (let index = notifications.length - 1; index >= 0; index -= 1) {
@@ -4238,9 +4369,9 @@ async function readMirroredSessionHistoryMessages(sessionFile) {
4238
4369
  if (!messages) embeddedAgentLog.warn("failed to read mirrored session history for codex harness hooks", { sessionFile });
4239
4370
  return messages;
4240
4371
  }
4241
- async function buildCodexWorkspaceBootstrapInstructions(params) {
4372
+ async function buildCodexWorkspaceBootstrapContext(params) {
4242
4373
  try {
4243
- const { contextFiles } = await resolveBootstrapContextForRun({
4374
+ const bootstrapContext = await resolveBootstrapContextForRun({
4244
4375
  workspaceDir: params.resolvedWorkspace,
4245
4376
  config: params.params.config,
4246
4377
  sessionKey: params.sessionKey,
@@ -4250,15 +4381,117 @@ async function buildCodexWorkspaceBootstrapInstructions(params) {
4250
4381
  contextMode: params.params.bootstrapContextMode,
4251
4382
  runKind: params.params.bootstrapContextRunKind
4252
4383
  });
4253
- return renderCodexWorkspaceBootstrapInstructions(contextFiles.map((file) => remapCodexContextFilePath({
4384
+ const contextFiles = bootstrapContext.contextFiles.map((file) => remapCodexContextFilePath({
4254
4385
  file,
4255
4386
  sourceWorkspaceDir: params.resolvedWorkspace,
4256
4387
  targetWorkspaceDir: params.effectiveWorkspace
4257
- })));
4388
+ }));
4389
+ return {
4390
+ ...bootstrapContext,
4391
+ contextFiles,
4392
+ instructions: renderCodexWorkspaceBootstrapInstructions(contextFiles)
4393
+ };
4258
4394
  } catch (error) {
4259
4395
  embeddedAgentLog.warn("failed to load codex workspace bootstrap instructions", { error });
4260
- return;
4396
+ return {
4397
+ bootstrapFiles: [],
4398
+ contextFiles: []
4399
+ };
4400
+ }
4401
+ }
4402
+ function buildCodexSystemPromptReport(params) {
4403
+ const toolEntries = params.tools.map(buildCodexToolReportEntry);
4404
+ const schemaChars = toolEntries.reduce((sum, tool) => sum + tool.schemaChars, 0);
4405
+ const projectContextChars = params.workspaceBootstrapContext.instructions?.length ?? 0;
4406
+ const bootstrapMaxChars = readPositiveNumber(params.attempt.config?.agents?.defaults?.bootstrapMaxChars);
4407
+ const bootstrapTotalMaxChars = readPositiveNumber(params.attempt.config?.agents?.defaults?.bootstrapTotalMaxChars);
4408
+ return {
4409
+ source: "run",
4410
+ generatedAt: Date.now(),
4411
+ sessionId: params.attempt.sessionId,
4412
+ sessionKey: params.sessionKey,
4413
+ provider: params.attempt.provider,
4414
+ model: params.attempt.modelId,
4415
+ workspaceDir: params.workspaceDir,
4416
+ ...bootstrapMaxChars ? { bootstrapMaxChars } : {},
4417
+ ...bootstrapTotalMaxChars ? { bootstrapTotalMaxChars } : {},
4418
+ systemPrompt: {
4419
+ chars: params.developerInstructions.length,
4420
+ projectContextChars,
4421
+ nonProjectContextChars: Math.max(0, params.developerInstructions.length - projectContextChars)
4422
+ },
4423
+ injectedWorkspaceFiles: buildCodexBootstrapInjectionStats({
4424
+ bootstrapFiles: params.workspaceBootstrapContext.bootstrapFiles,
4425
+ injectedFiles: params.workspaceBootstrapContext.contextFiles
4426
+ }),
4427
+ skills: {
4428
+ promptChars: 0,
4429
+ entries: []
4430
+ },
4431
+ tools: {
4432
+ listChars: 0,
4433
+ schemaChars,
4434
+ entries: toolEntries
4435
+ }
4436
+ };
4437
+ }
4438
+ function buildCodexToolReportEntry(tool) {
4439
+ const summary = tool.description.trim();
4440
+ if (tool.deferLoading === true) return {
4441
+ name: tool.name,
4442
+ summaryChars: summary.length,
4443
+ schemaChars: 0,
4444
+ propertiesCount: null
4445
+ };
4446
+ return {
4447
+ name: tool.name,
4448
+ summaryChars: summary.length,
4449
+ ...buildCodexToolSchemaStats(tool.inputSchema)
4450
+ };
4451
+ }
4452
+ function buildCodexToolSchemaStats(schema) {
4453
+ const schemaChars = (() => {
4454
+ try {
4455
+ return JSON.stringify(schema).length;
4456
+ } catch {
4457
+ return 0;
4458
+ }
4459
+ })();
4460
+ const properties = isJsonObject(schema) && isJsonObject(schema.properties) ? schema.properties : null;
4461
+ return {
4462
+ schemaChars,
4463
+ propertiesCount: properties ? Object.keys(properties).length : null
4464
+ };
4465
+ }
4466
+ function buildCodexBootstrapInjectionStats(params) {
4467
+ const injectedByPath = /* @__PURE__ */ new Map();
4468
+ const injectedByBaseName = /* @__PURE__ */ new Map();
4469
+ for (const file of params.injectedFiles) {
4470
+ const pathValue = readNonEmptyString(file.path);
4471
+ if (!pathValue) continue;
4472
+ if (!injectedByPath.has(pathValue)) injectedByPath.set(pathValue, file.content);
4473
+ const baseName = path.posix.basename(pathValue.replaceAll("\\", "/"));
4474
+ if (!injectedByBaseName.has(baseName)) injectedByBaseName.set(baseName, file.content);
4261
4475
  }
4476
+ return params.bootstrapFiles.map((file) => {
4477
+ const pathValue = readNonEmptyString(file.path) ?? file.name;
4478
+ const rawChars = file.missing ? 0 : (file.content ?? "").trimEnd().length;
4479
+ const injectedChars = (injectedByPath.get(pathValue) ?? injectedByPath.get(file.name) ?? injectedByBaseName.get(file.name))?.length ?? 0;
4480
+ return {
4481
+ name: file.name,
4482
+ path: pathValue,
4483
+ missing: file.missing,
4484
+ rawChars,
4485
+ injectedChars,
4486
+ truncated: !file.missing && injectedChars < rawChars
4487
+ };
4488
+ });
4489
+ }
4490
+ function readPositiveNumber(value) {
4491
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : void 0;
4492
+ }
4493
+ function readNonEmptyString(value) {
4494
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
4262
4495
  }
4263
4496
  function renderCodexWorkspaceBootstrapInstructions(contextFiles) {
4264
4497
  const files = contextFiles.filter((file) => {
@@ -4274,7 +4507,7 @@ function renderCodexWorkspaceBootstrapInstructions(contextFiles) {
4274
4507
  "",
4275
4508
  "The following project context files have been loaded:"
4276
4509
  ];
4277
- if (hasSoulFile) lines.push("If SOUL.md is present, embody its persona and tone. Avoid stiff, generic replies; follow its guidance unless higher-priority instructions override it.");
4510
+ if (hasSoulFile) lines.push("SOUL.md: persona/tone. Follow it unless higher-priority instructions override.");
4278
4511
  lines.push("");
4279
4512
  for (const file of files) lines.push(`## ${file.path}`, "", file.content, "");
4280
4513
  return lines.join("\n").trim();
@@ -4324,6 +4557,10 @@ function isNonEmptyString(value) {
4324
4557
  function joinPresentSections(...sections) {
4325
4558
  return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
4326
4559
  }
4560
+ function prependCurrentTurnContext(prompt, context) {
4561
+ const text = context?.text.trim();
4562
+ return text ? [text, prompt].filter(Boolean).join("\n\n") : prompt;
4563
+ }
4327
4564
  function handleApprovalRequest(params) {
4328
4565
  return handleCodexAppServerApprovalRequest({
4329
4566
  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-CT01BBDc.js";
2
+ import { a as normalizeCodexServiceTier } from "./config-C7xdbzrp.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";
@@ -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-CT01BBDc.js";
3
- import { a as MANAGED_CODEX_APP_SERVER_PACKAGE, o as resolveCodexAppServerSpawnEnv, t as CodexAppServerClient } from "./client-CTzy3Y6M.js";
2
+ import { n as codexAppServerStartOptionsKey, s as resolveCodexAppServerRuntimeOptions } from "./config-C7xdbzrp.js";
3
+ import { a as MANAGED_CODEX_APP_SERVER_PACKAGE, o as resolveCodexAppServerSpawnEnv, t as CodexAppServerClient } from "./client-CpksBQ9l.js";
4
4
  import { createRequire } from "node:module";
5
5
  import { createHash } from "node:crypto";
6
6
  import { constants, readFileSync } from "node:fs";
package/dist/test-api.js CHANGED
@@ -1,5 +1,5 @@
1
- import { s as resolveCodexAppServerRuntimeOptions } from "./config-CT01BBDc.js";
2
- import { a as buildTurnStartParams, d as createCodexDynamicToolBridge, f as filterCodexDynamicTools, i as buildThreadStartParams, n as buildDeveloperInstructions, r as buildThreadResumeParams } from "./thread-lifecycle-CGc-O_5d.js";
1
+ import { s as resolveCodexAppServerRuntimeOptions } from "./config-C7xdbzrp.js";
2
+ import { a as buildTurnStartParams, d as createCodexDynamicToolBridge, f as filterCodexDynamicTools, i as buildThreadStartParams, n as buildDeveloperInstructions, r as buildThreadResumeParams } from "./thread-lifecycle-DRyCVHhL.js";
3
3
  //#region extensions/codex/test-api.ts
4
4
  function resolveCodexPromptSnapshotAppServerOptions(pluginConfig) {
5
5
  return resolveCodexAppServerRuntimeOptions({
@@ -1,11 +1,11 @@
1
- import { l as resolveCodexPluginsPolicy, r as codexSandboxPolicyForTurn } from "./config-CT01BBDc.js";
1
+ import { l as resolveCodexPluginsPolicy, r as codexSandboxPolicyForTurn } from "./config-C7xdbzrp.js";
2
2
  import { n as assertCodexThreadStartResponse, t as assertCodexThreadResumeResponse } from "./protocol-validators-CeCyJaWj.js";
3
3
  import { t as isJsonObject } from "./protocol-C9UWI98H.js";
4
4
  import { CODEX_GPT5_HEARTBEAT_PROMPT_OVERLAY, renderCodexPromptOverlay } from "./prompt-overlay.js";
5
5
  import { isModernCodexModel } from "./provider.js";
6
- import { i as isCodexAppServerConnectionClosedError } from "./client-CTzy3Y6M.js";
7
- import { i as readCodexAppServerBinding, n as isCodexAppServerNativeAuthProfile, o as writeCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-B44KIZM2.js";
8
- import { i as defaultCodexAppInventoryCache, n as readCodexPluginInventory, t as ensureCodexPluginActivation } from "./plugin-activation-CweAZa7r.js";
6
+ import { i as isCodexAppServerConnectionClosedError } from "./client-CpksBQ9l.js";
7
+ import { i as readCodexAppServerBinding, n as isCodexAppServerNativeAuthProfile, o as writeCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-BAaJ-7s-.js";
8
+ import { i as defaultCodexAppInventoryCache, n as readCodexPluginInventory, t as ensureCodexPluginActivation } from "./plugin-activation-Dn14PX1W.js";
9
9
  import crypto from "node:crypto";
10
10
  import { HEARTBEAT_RESPONSE_TOOL_NAME, createAgentToolResultMiddlewareRunner, createCodexAppServerToolResultExtensionRunner, embeddedAgentLog, extractToolResultMediaArtifact, filterToolResultMediaUrls, isMessagingTool, isMessagingToolSendAction, isToolWrappedWithBeforeToolCallHook, normalizeHeartbeatToolResponse, runAgentHarnessAfterToolCallHook, wrapToolWithBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
11
11
  //#region extensions/codex/src/app-server/dynamic-tool-profile.ts
@@ -530,6 +530,10 @@ function stableStringify(value) {
530
530
  }
531
531
  //#endregion
532
532
  //#region extensions/codex/src/app-server/thread-lifecycle.ts
533
+ const CODEX_CODE_MODE_THREAD_CONFIG = {
534
+ "features.code_mode": true,
535
+ "features.code_mode_only": true
536
+ };
533
537
  async function startOrResumeThread(params) {
534
538
  const dynamicToolsFingerprint = fingerprintDynamicTools(params.dynamicTools);
535
539
  let binding = await readCodexAppServerBinding(params.params.sessionFile, {
@@ -699,7 +703,7 @@ function buildThreadStartParams(params, options) {
699
703
  sandbox: options.appServer.sandbox,
700
704
  ...options.appServer.serviceTier ? { serviceTier: options.appServer.serviceTier } : {},
701
705
  serviceName: "OpenClaw",
702
- ...options.config ? { config: options.config } : {},
706
+ config: buildCodexRuntimeThreadConfig(options.config),
703
707
  developerInstructions: options.developerInstructions ?? buildDeveloperInstructions(params),
704
708
  dynamicTools: options.dynamicTools,
705
709
  experimentalRawEvents: true,
@@ -722,11 +726,14 @@ function buildThreadResumeParams(params, options) {
722
726
  approvalsReviewer: options.appServer.approvalsReviewer,
723
727
  sandbox: options.appServer.sandbox,
724
728
  ...options.appServer.serviceTier ? { serviceTier: options.appServer.serviceTier } : {},
725
- ...options.config ? { config: options.config } : {},
729
+ config: buildCodexRuntimeThreadConfig(options.config),
726
730
  developerInstructions: options.developerInstructions ?? buildDeveloperInstructions(params),
727
731
  persistExtendedHistory: true
728
732
  };
729
733
  }
734
+ function buildCodexRuntimeThreadConfig(config) {
735
+ return mergeCodexThreadConfigs(config, CODEX_CODE_MODE_THREAD_CONFIG) ?? { ...CODEX_CODE_MODE_THREAD_CONFIG };
736
+ }
730
737
  function buildTurnStartParams(params, options) {
731
738
  return {
732
739
  threadId: options.threadId,
@@ -795,8 +802,8 @@ function compareJsonFingerprint(left, right) {
795
802
  }
796
803
  function buildDeveloperInstructions(params) {
797
804
  return [
798
- "You are running inside OpenClaw. Use OpenClaw dynamic tools for OpenClaw-specific integrations such as messaging, cron, sessions, media, gateway, and nodes when available.",
799
- "Preserve the user's existing channel/session context. If sending a channel reply, use the OpenClaw messaging tool instead of describing that you would reply.",
805
+ "Running inside OpenClaw. Use dynamic tools for messaging, cron, sessions, media, gateway, and nodes when available.",
806
+ "Preserve channel/session context. Visible channel replies: use `message`, do not describe would-reply.",
800
807
  renderCodexRuntimePromptOverlay(params),
801
808
  params.extraSystemPrompt,
802
809
  params.skillsSnapshot?.prompt
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/codex",
3
- "version": "2026.5.10-beta.2",
3
+ "version": "2026.5.10-beta.3",
4
4
  "description": "OpenClaw Codex harness and model provider plugin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -11,7 +11,8 @@
11
11
  "@mariozechner/pi-coding-agent": "0.73.1",
12
12
  "@openai/codex": "0.130.0",
13
13
  "ajv": "^8.20.0",
14
- "ws": "^8.20.0"
14
+ "ws": "^8.20.0",
15
+ "zod": "^4.4.3"
15
16
  },
16
17
  "devDependencies": {
17
18
  "@openclaw/plugin-sdk": "workspace:*"
@@ -26,10 +27,10 @@
26
27
  "minHostVersion": ">=2026.5.1-beta.1"
27
28
  },
28
29
  "compat": {
29
- "pluginApi": ">=2026.5.10-beta.2"
30
+ "pluginApi": ">=2026.5.10-beta.3"
30
31
  },
31
32
  "build": {
32
- "openclawVersion": "2026.5.10-beta.2"
33
+ "openclawVersion": "2026.5.10-beta.3"
33
34
  },
34
35
  "release": {
35
36
  "publishToClawHub": true,
@@ -44,7 +45,7 @@
44
45
  "openclaw.plugin.json"
45
46
  ],
46
47
  "peerDependencies": {
47
- "openclaw": ">=2026.5.10-beta.2"
48
+ "openclaw": ">=2026.5.10-beta.3"
48
49
  },
49
50
  "peerDependenciesMeta": {
50
51
  "openclaw": {