@openclaw/codex 2026.5.24-beta.2 → 2026.5.25-beta.1

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 (26) hide show
  1. package/dist/{client-1sSy4p3z.js → client-SrtuTTVa.js} +10 -3
  2. package/dist/{client-factory-Bk6i4FnW.js → client-factory-A7DQkSLq.js} +1 -1
  3. package/dist/{command-handlers-CcTABuem.js → command-handlers-CLtPT37L.js} +10 -23
  4. package/dist/compact-acCua7zr.js +155 -0
  5. package/dist/{computer-use-Hdq1WgTA.js → computer-use-CVfE2Vfb.js} +2 -2
  6. package/dist/{config-DDMrwfJl.js → config-D6TUuyo2.js} +6 -3
  7. package/dist/{node-cli-sessions-9CAqnIaA.js → conversation-binding-B-GevkEb.js} +426 -434
  8. package/dist/{dynamic-tools-Bq717oJR.js → dynamic-tools-BXAE1U1-.js} +20 -11
  9. package/dist/harness.js +5 -5
  10. package/dist/index.js +451 -17
  11. package/dist/media-understanding-provider.js +7 -5
  12. package/dist/{models-DtGLkqMP.js → models-CC2IusQs.js} +3 -3
  13. package/dist/{notification-correlation-qKY_sgga.js → notification-correlation-D7tJW3FW.js} +26 -11
  14. package/dist/provider.js +3 -3
  15. package/dist/{request-D93E78SA.js → request-BO0z3vA8.js} +3 -3
  16. package/dist/{run-attempt-CT1N__qp.js → run-attempt-BjoI3hUJ.js} +279 -230
  17. package/dist/{session-binding-Bw_mfIW2.js → session-binding-CwNOIDP2.js} +1 -1
  18. package/dist/{shared-client-CFCUGEVs.js → shared-client-CZP1DjaN.js} +3 -4
  19. package/dist/{side-question-CYFMTA1O.js → side-question-Cb4COOQ9.js} +16 -11
  20. package/dist/test-api.js +3 -3
  21. package/dist/{thread-lifecycle-DGoaguJh.js → thread-lifecycle-CXMd9UgJ.js} +10 -12
  22. package/dist/{vision-tools-DOnxzH2y.js → vision-tools-CETeQgze.js} +16 -4
  23. package/npm-shrinkwrap.json +225 -238
  24. package/package.json +7 -7
  25. package/dist/compact-DnTgL6UT.js +0 -475
  26. package/dist/protocol-oeJQu4rs.js +0 -9
@@ -1,21 +1,21 @@
1
- import { c as readCodexPluginConfig, d as resolveCodexPluginsPolicy, f as withMcpElicitationsApprovalPolicy, i as isCodexAppServerApprovalPolicyAllowedByRequirements, l as resolveCodexAppServerRuntimeOptions, o as isCodexSandboxExecServerEnabled, u as resolveCodexComputerUseConfig } from "./config-DDMrwfJl.js";
1
+ import { t as defaultCodexAppServerClientFactory } from "./client-factory-A7DQkSLq.js";
2
+ import { c as readCodexPluginConfig, d as resolveCodexPluginsPolicy, f as shouldAutoApproveCodexAppServerApprovals, i as isCodexAppServerApprovalPolicyAllowedByRequirements, l as resolveCodexAppServerRuntimeOptions, o as isCodexSandboxExecServerEnabled, p as withMcpElicitationsApprovalPolicy, u as resolveCodexComputerUseConfig } from "./config-D6TUuyo2.js";
2
3
  import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse } from "./protocol-validators-_gKDcd0x.js";
3
- import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
4
- import { a as isCodexAppServerConnectionClosedError, i as isCodexAppServerApprovalRequest, r as compareCodexAppServerVersions, s as MIN_CODEX_SANDBOX_EXEC_SERVER_APP_SERVER_VERSION } from "./client-1sSy4p3z.js";
5
- import { C as sanitizeCodexHistoryImagePayloads, D as resolveCodexContextEngineProjectionMaxChars, E as projectContextEngineAssemblyForCodex, O as resolveCodexContextEngineProjectionReserveTokens, _ as shouldBuildCodexPluginThreadConfig, c as buildTurnStartParams, g as mergeCodexThreadConfigs, h as buildCodexPluginThreadConfigInputFingerprint, i as buildDeveloperInstructions, l as codexDynamicToolsFingerprint, m as buildCodexPluginThreadConfig, p as startOrResumeThread, r as buildContextEngineBinding, s as buildTurnCollaborationMode, t as areCodexDynamicToolFingerprintsCompatible, u as isContextEngineBindingCompatible, x as defaultCodexAppInventoryCache } from "./thread-lifecycle-DGoaguJh.js";
6
- import { i as readCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-Bw_mfIW2.js";
7
- import { n as buildCodexPluginAppCacheKey, r as CODEX_CONTROL_METHODS } from "./request-D93E78SA.js";
8
- import { g as shouldRefreshCodexRateLimitsForUsageLimitMessage, h as resolveCodexUsageLimitResetAtMs, i as readCodexNotificationTurnId, m as formatCodexUsageLimitErrorMessage, n as isCodexNotificationForTurn, r as readCodexNotificationThreadId, s as formatCodexDisplayText, t as describeCodexNotificationCorrelation } from "./notification-correlation-qKY_sgga.js";
9
- import { c as resolveCodexAppServerAuthAccountCacheKey, d as resolveCodexAppServerEnvApiKeyCacheKey, f as resolveCodexAppServerHomeDir, l as resolveCodexAppServerAuthProfileId, s as refreshCodexAppServerAuthTokens, t as clearSharedCodexAppServerClientIfCurrent, u as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-CFCUGEVs.js";
4
+ import { a as isCodexAppServerConnectionClosedError, i as isCodexAppServerApprovalRequest, l as isJsonObject, r as compareCodexAppServerVersions, s as MIN_CODEX_SANDBOX_EXEC_SERVER_APP_SERVER_VERSION } from "./client-SrtuTTVa.js";
5
+ import { D as resolveCodexContextEngineProjectionMaxChars, E as projectContextEngineAssemblyForCodex, O as resolveCodexContextEngineProjectionReserveTokens, S as defaultCodexAppInventoryCache, _ as mergeCodexThreadConfigs, a as buildDeveloperInstructions, c as buildTurnCollaborationMode, d as isContextEngineBindingCompatible, g as buildCodexPluginThreadConfigInputFingerprint, h as buildCodexPluginThreadConfig, i as buildContextEngineBinding, l as buildTurnStartParams, m as startOrResumeThread, n as areCodexDynamicToolFingerprintsCompatible, u as codexDynamicToolsFingerprint, v as shouldBuildCodexPluginThreadConfig, w as sanitizeCodexHistoryImagePayloads } from "./thread-lifecycle-CXMd9UgJ.js";
6
+ import { i as readCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-CwNOIDP2.js";
7
+ import { n as buildCodexPluginAppCacheKey, r as CODEX_CONTROL_METHODS } from "./request-BO0z3vA8.js";
8
+ import { g as shouldRefreshCodexRateLimitsForUsageLimitMessage, h as resolveCodexUsageLimitResetAtMs, i as readCodexNotificationTurnId, m as formatCodexUsageLimitErrorMessage, n as isCodexNotificationForTurn, r as readCodexNotificationThreadId, s as formatCodexDisplayText, t as describeCodexNotificationCorrelation } from "./notification-correlation-D7tJW3FW.js";
9
+ import { c as resolveCodexAppServerAuthAccountCacheKey, d as resolveCodexAppServerEnvApiKeyCacheKey, f as resolveCodexAppServerHomeDir, l as resolveCodexAppServerAuthProfileId, s as refreshCodexAppServerAuthTokens, t as clearSharedCodexAppServerClientIfCurrent, u as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-CZP1DjaN.js";
10
10
  import { i as resolveCodexNativeExecutionPolicy } from "./sandbox-guard-CTnEWuor.js";
11
- import { a as resolveCodexDynamicToolsLoading, i as normalizeCodexDynamicToolName, n as filterCodexDynamicTools, r as isForcedPrivateQaCodexRuntime, t as createCodexDynamicToolBridge } from "./dynamic-tools-Bq717oJR.js";
12
- import { t as defaultCodexAppServerClientFactory } from "./client-factory-Bk6i4FnW.js";
13
- import { a as handleCodexAppServerElicitationRequest, c as emitDynamicToolTerminalDiagnostic, i as buildCodexNativeHookRelayDisabledConfig, l as handleCodexAppServerApprovalRequest, n as CODEX_NATIVE_HOOK_RELAY_EVENTS, o as emitDynamicToolErrorDiagnostic, r as buildCodexNativeHookRelayConfig, s as emitDynamicToolStartedDiagnostic, t as filterToolsForVisionInputs } from "./vision-tools-DOnxzH2y.js";
14
- import { t as ensureCodexComputerUse } from "./computer-use-Hdq1WgTA.js";
11
+ import { a as resolveCodexDynamicToolsLoading, i as normalizeCodexDynamicToolName, n as filterCodexDynamicTools, r as isForcedPrivateQaCodexRuntime, t as createCodexDynamicToolBridge } from "./dynamic-tools-BXAE1U1-.js";
12
+ import { a as handleCodexAppServerElicitationRequest, c as emitDynamicToolTerminalDiagnostic, i as buildCodexNativeHookRelayDisabledConfig, l as handleCodexAppServerApprovalRequest, n as CODEX_NATIVE_HOOK_RELAY_EVENTS, o as emitDynamicToolErrorDiagnostic, r as buildCodexNativeHookRelayConfig, s as emitDynamicToolStartedDiagnostic, t as filterToolsForVisionInputs } from "./vision-tools-CETeQgze.js";
13
+ import { t as ensureCodexComputerUse } from "./computer-use-CVfE2Vfb.js";
15
14
  import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-N66I-Rd7.js";
16
15
  import { createHash, randomUUID } from "node:crypto";
17
16
  import nodeFs from "node:fs";
18
- import { CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, PREEMPTIVE_OVERFLOW_ERROR_TEXT, TOOL_PROGRESS_OUTPUT_MAX_CHARS, acquireSessionWriteLock, appendSessionTranscriptMessage, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentHarnessAgentEndHook, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildEmbeddedAttemptToolRunContext, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, compactContextEngineWithSafetyTimeout, embeddedAgentLog, emitAgentEvent, emitSessionTranscriptUpdate, estimateRenderedLlmBoundaryTokenPressure, finalizeHarnessContextEngineTurn, formatErrorMessage, formatPrePromptPrecheckLog, formatToolAggregate, formatToolProgressOutput, hasBeforeToolCallPolicy, inferToolMetaFromArgs, isActiveHarnessContextEngine, isSubagentSessionKey, loadCodexBundleMcpThreadConfig, normalizeAgentRuntimeTools, normalizeUsage, registerNativeHookRelay, resolveAgentHarnessBeforePromptBuildResult, resolveAttemptSpawnWorkspaceDir, resolveBootstrapContextForRun, resolveCompactionTimeoutMs, resolveContextEngineOwnerPluginId, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, resolveSessionWriteLockOptions, resolveUserPath, runAgentCleanupStep, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessAgentEndHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessBeforeMessageWriteHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, shouldPreemptivelyCompactBeforePrompt, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
17
+ import { asBoolean, asFiniteNumber, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
18
+ import { CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, TOOL_PROGRESS_OUTPUT_MAX_CHARS, acquireSessionWriteLock, appendSessionTranscriptMessage, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentHarnessAgentEndHook, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildEmbeddedAttemptToolRunContext, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emitSessionTranscriptUpdate, finalizeHarnessContextEngineTurn, formatErrorMessage, formatToolAggregate, formatToolProgressOutput, getBeforeToolCallPolicyDiagnosticState, inferToolMetaFromArgs, isActiveHarnessContextEngine, isSubagentSessionKey, loadCodexBundleMcpThreadConfig, normalizeAgentRuntimeTools, normalizeUsage, registerNativeHookRelay, resolveAgentHarnessBeforePromptBuildResult, resolveAttemptSpawnWorkspaceDir, resolveBootstrapContextForRun, resolveContextEngineOwnerPluginId, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, resolveSessionWriteLockOptions, resolveUserPath, runAgentCleanupStep, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessAgentEndHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessBeforeMessageWriteHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
19
19
  import { spawn } from "node:child_process";
20
20
  import { once } from "node:events";
21
21
  import { WebSocketServer } from "ws";
@@ -25,7 +25,7 @@ import path, { posix } from "node:path";
25
25
  import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1 } from "openclaw/plugin-sdk/agent-runtime";
26
26
  import { isToolAllowed } from "openclaw/plugin-sdk/sandbox";
27
27
  import { appendRegularFile, pathExists } from "openclaw/plugin-sdk/security-runtime";
28
- import { emitTrustedDiagnosticEvent, hasPendingInternalDiagnosticEvent, onInternalDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
28
+ import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, hasPendingInternalDiagnosticEvent, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
29
29
  import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "@earendil-works/pi-coding-agent";
30
30
  import { createAgentHarnessTaskRuntime, deliverAgentHarnessTaskCompletion, isDurableAgentHarnessCompletionDelivery } from "openclaw/plugin-sdk/agent-harness-task-runtime";
31
31
  import { isIP } from "node:net";
@@ -102,10 +102,6 @@ function inferCodexDynamicToolMeta(call, detailMode) {
102
102
  //#endregion
103
103
  //#region extensions/codex/src/app-server/transcript-mirror.ts
104
104
  const MIRROR_IDENTITY_META_KEY = "mirrorIdentity";
105
- function normalizeOptionalString$1(value) {
106
- const normalized = value?.trim();
107
- return normalized ? normalized : void 0;
108
- }
109
105
  function buildSenderLabel(params) {
110
106
  const label = params.senderName ?? params.senderUsername ?? params.senderE164 ?? params.senderId;
111
107
  if (!label) return;
@@ -113,17 +109,17 @@ function buildSenderLabel(params) {
113
109
  return `${label} (${params.senderId})`;
114
110
  }
115
111
  function buildCodexUserPromptMessage(params) {
116
- const senderId = normalizeOptionalString$1(params.senderId);
117
- const senderName = normalizeOptionalString$1(params.senderName);
118
- const senderUsername = normalizeOptionalString$1(params.senderUsername);
119
- const senderE164 = normalizeOptionalString$1(params.senderE164);
112
+ const senderId = normalizeOptionalString(params.senderId);
113
+ const senderName = normalizeOptionalString(params.senderName);
114
+ const senderUsername = normalizeOptionalString(params.senderUsername);
115
+ const senderE164 = normalizeOptionalString(params.senderE164);
120
116
  const senderLabel = buildSenderLabel({
121
117
  senderId,
122
118
  senderName,
123
119
  senderUsername,
124
120
  senderE164
125
121
  });
126
- const sourceChannel = normalizeOptionalString$1(params.inputProvenance?.sourceChannel ?? params.messageChannel ?? params.messageProvider);
122
+ const sourceChannel = normalizeOptionalString(params.inputProvenance?.sourceChannel ?? params.messageChannel ?? params.messageProvider);
127
123
  return {
128
124
  role: "user",
129
125
  content: params.prompt,
@@ -183,12 +179,14 @@ async function mirrorCodexAppServerTranscript(params) {
183
179
  sessionFile: params.sessionFile,
184
180
  ...resolveSessionWriteLockOptions(params.config)
185
181
  });
182
+ const appendedUpdates = [];
186
183
  try {
187
- const existingIdempotencyKeys = await readTranscriptIdempotencyKeys(params.sessionFile);
184
+ const mirrorState = await readTranscriptMirrorState(params.sessionFile);
185
+ let nextMessageSeq = mirrorState.messageCount;
188
186
  for (const message of messages) {
189
187
  const dedupeIdentity = buildMirrorDedupeIdentity(message);
190
188
  const idempotencyKey = params.idempotencyScope ? `${params.idempotencyScope}:${dedupeIdentity}` : void 0;
191
- if (idempotencyKey && existingIdempotencyKeys.has(idempotencyKey)) continue;
189
+ if (idempotencyKey && mirrorState.idempotencyKeys.has(idempotencyKey)) continue;
192
190
  const nextMessage = runAgentHarnessBeforeMessageWriteHook({
193
191
  message: {
194
192
  ...message,
@@ -202,41 +200,57 @@ async function mirrorCodexAppServerTranscript(params) {
202
200
  ...nextMessage,
203
201
  idempotencyKey
204
202
  } : nextMessage;
205
- await appendSessionTranscriptMessage({
203
+ const { messageId, message: appendedMessage } = await appendSessionTranscriptMessage({
206
204
  transcriptPath: params.sessionFile,
207
205
  message: messageToAppend,
208
206
  config: params.config
209
207
  });
210
- if (idempotencyKey) existingIdempotencyKeys.add(idempotencyKey);
208
+ nextMessageSeq += 1;
209
+ appendedUpdates.push({
210
+ messageId,
211
+ message: appendedMessage,
212
+ messageSeq: nextMessageSeq
213
+ });
214
+ if (idempotencyKey) mirrorState.idempotencyKeys.add(idempotencyKey);
211
215
  }
212
216
  } finally {
213
217
  await lock.release();
214
218
  }
215
- if (params.sessionKey) emitSessionTranscriptUpdate({
219
+ for (const update of appendedUpdates) emitSessionTranscriptUpdate({
216
220
  sessionFile: params.sessionFile,
217
- sessionKey: params.sessionKey
221
+ ...params.sessionKey ? { sessionKey: params.sessionKey } : {},
222
+ message: update.message,
223
+ messageId: update.messageId,
224
+ messageSeq: update.messageSeq
218
225
  });
219
- else emitSessionTranscriptUpdate(params.sessionFile);
220
226
  }
221
- async function readTranscriptIdempotencyKeys(sessionFile) {
222
- const keys = /* @__PURE__ */ new Set();
227
+ async function readTranscriptMirrorState(sessionFile) {
228
+ const idempotencyKeys = /* @__PURE__ */ new Set();
229
+ let messageCount = 0;
223
230
  let raw;
224
231
  try {
225
232
  raw = await fs.readFile(sessionFile, "utf8");
226
233
  } catch (error) {
227
234
  if (error.code !== "ENOENT") throw error;
228
- return keys;
235
+ return {
236
+ idempotencyKeys,
237
+ messageCount
238
+ };
229
239
  }
230
240
  for (const line of raw.split(/\r?\n/)) {
231
241
  if (!line.trim()) continue;
232
242
  try {
233
243
  const parsed = JSON.parse(line);
234
- if (typeof parsed.message?.idempotencyKey === "string") keys.add(parsed.message.idempotencyKey);
244
+ if (parsed.type === "message") messageCount += 1;
245
+ if (typeof parsed.message?.idempotencyKey === "string") idempotencyKeys.add(parsed.message.idempotencyKey);
235
246
  } catch {
236
247
  continue;
237
248
  }
238
249
  }
239
- return keys;
250
+ return {
251
+ idempotencyKeys,
252
+ messageCount
253
+ };
240
254
  }
241
255
  //#endregion
242
256
  //#region extensions/codex/src/app-server/event-projector.ts
@@ -463,6 +477,12 @@ var CodexAppServerEventProjector = class {
463
477
  });
464
478
  }
465
479
  recordDynamicToolResult(params) {
480
+ const existingMeta = this.toolMetas.get(params.callId);
481
+ this.toolMetas.set(params.callId, {
482
+ toolName: params.tool,
483
+ ...existingMeta?.meta ? { meta: existingMeta.meta } : {},
484
+ ...existingMeta?.asyncStarted === true || params.asyncStarted === true ? { asyncStarted: true } : {}
485
+ });
466
486
  this.recordToolTranscriptResult({
467
487
  id: params.callId,
468
488
  name: params.tool,
@@ -832,7 +852,7 @@ var CodexAppServerEventProjector = class {
832
852
  if (savedPath) this.nativeGeneratedMediaUrls.add(savedPath);
833
853
  }
834
854
  buildToolMediaUrls(toolTelemetry) {
835
- const mediaUrls = new Set(toolTelemetry.toolMediaUrls?.map((url) => url.trim()).filter(Boolean) ?? []);
855
+ const mediaUrls = new Set(normalizeStringEntries(toolTelemetry.toolMediaUrls ?? []));
836
856
  if ((toolTelemetry.messagingToolSentMediaUrls?.length ?? 0) === 0) for (const mediaUrl of this.nativeGeneratedMediaUrls) mediaUrls.add(mediaUrl);
837
857
  return mediaUrls.size > 0 ? [...mediaUrls] : toolTelemetry.toolMediaUrls;
838
858
  }
@@ -1118,9 +1138,11 @@ var CodexAppServerEventProjector = class {
1118
1138
  const toolName = itemName(item);
1119
1139
  if (!toolName) return;
1120
1140
  const meta = itemMeta(item, this.toolProgressDetailMode());
1141
+ const existingMeta = this.toolMetas.get(item.id);
1121
1142
  this.toolMetas.set(item.id, {
1122
1143
  toolName,
1123
- ...meta ? { meta } : {}
1144
+ ...meta ? { meta } : {},
1145
+ ...existingMeta?.asyncStarted === true ? { asyncStarted: true } : {}
1124
1146
  });
1125
1147
  if (isSideEffectingNativeToolItem(item)) this.sideEffectingToolItemIds.add(item.id);
1126
1148
  else this.sideEffectingToolItemIds.delete(item.id);
@@ -1364,12 +1386,10 @@ function readNullableString$1(record, key) {
1364
1386
  return typeof value === "string" ? value : void 0;
1365
1387
  }
1366
1388
  function readNumber$1(record, key) {
1367
- const value = record[key];
1368
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1389
+ return asFiniteNumber(record[key]);
1369
1390
  }
1370
1391
  function readBoolean$1(record, key) {
1371
- const value = record[key];
1372
- return typeof value === "boolean" ? value : void 0;
1392
+ return asBoolean(record[key]);
1373
1393
  }
1374
1394
  function readBooleanAlias(record, keys) {
1375
1395
  for (const key of keys) {
@@ -2616,9 +2636,6 @@ function readString$2(record, key) {
2616
2636
  const value = record?.[key];
2617
2637
  return typeof value === "string" ? value : void 0;
2618
2638
  }
2619
- function normalizeOptionalString(value) {
2620
- return value?.trim() || void 0;
2621
- }
2622
2639
  function readStringArray(value) {
2623
2640
  if (!Array.isArray(value)) return [];
2624
2641
  return value.filter((entry) => typeof entry === "string" && entry.trim() !== "");
@@ -2741,8 +2758,7 @@ function readTranscriptParentThreadId(payload) {
2741
2758
  return readString$2(isJsonObject(subagent?.thread_spawn) ? subagent.thread_spawn : void 0, "parent_thread_id")?.trim();
2742
2759
  }
2743
2760
  function readNumber(record, key) {
2744
- const value = record[key];
2745
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
2761
+ return asFiniteNumber(record[key]);
2746
2762
  }
2747
2763
  function secondsToMillis(value) {
2748
2764
  return value === void 0 ? void 0 : Math.round(value * 1e3);
@@ -4669,6 +4685,13 @@ function readCodexAppServerRolloutTokenUsageLine(line) {
4669
4685
  return;
4670
4686
  }
4671
4687
  }
4688
+ function utf8JsonByteLength(value) {
4689
+ try {
4690
+ return Buffer.byteLength(JSON.stringify(value), "utf8");
4691
+ } catch {
4692
+ return;
4693
+ }
4694
+ }
4672
4695
  function maxFiniteNumber(values) {
4673
4696
  const nums = values.filter((value) => typeof value === "number" && Number.isFinite(value));
4674
4697
  if (nums.length === 0) return;
@@ -4724,10 +4747,18 @@ async function runCodexAgentEndHook(params, hookParams) {
4724
4747
  }
4725
4748
  async function runCodexAppServerAttempt(params, options = {}) {
4726
4749
  const attemptStartedAt = Date.now();
4750
+ const codexModelCallTrace = freezeDiagnosticTraceContext(createDiagnosticTraceContextFromActiveScope());
4751
+ const codexModelContentCapture = resolveDiagnosticModelContentCapturePolicy(params.config);
4752
+ const codexModelCallId = `${params.runId}:codex-model:1`;
4753
+ let codexModelCallStartedAt = attemptStartedAt;
4754
+ let codexModelCallStarted = false;
4755
+ let codexModelCallTerminalEmitted = false;
4756
+ let codexModelCallRequestPayloadBytes;
4727
4757
  const attemptClientFactory = options.clientFactory ?? defaultCodexAppServerClientFactory;
4728
4758
  const pluginConfig = readCodexPluginConfig(options.pluginConfig);
4729
4759
  const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig });
4730
4760
  const configuredAppServer = resolveCodexAppServerRuntimeOptions({ pluginConfig });
4761
+ const beforeToolCallPolicy = getBeforeToolCallPolicyDiagnosticState();
4731
4762
  const resolvedWorkspace = resolveUserPath(params.workspaceDir);
4732
4763
  await fs.mkdir(resolvedWorkspace, { recursive: true });
4733
4764
  const sandboxSessionKey = params.sandboxSessionKey?.trim() || params.sessionKey?.trim() || params.sessionId;
@@ -4743,9 +4774,15 @@ async function runCodexAppServerAttempt(params, options = {}) {
4743
4774
  appServer: configuredAppServer,
4744
4775
  pluginConfig,
4745
4776
  env: process.env,
4746
- shouldPromote: hasBeforeToolCallPolicy(),
4777
+ shouldPromote: beforeToolCallPolicy.hasBeforeToolCallHook || beforeToolCallPolicy.trustedToolPolicies.length > 0,
4747
4778
  canUseUntrustedApprovalPolicy: configuredAppServer.start.transport !== "stdio" || isCodexAppServerApprovalPolicyAllowedByRequirements("untrusted")
4748
4779
  });
4780
+ if (configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted") embeddedAgentLog.info("codex app-server approval policy promoted for OpenClaw tool policy", {
4781
+ from: "never",
4782
+ to: "untrusted",
4783
+ beforeToolCallHook: beforeToolCallPolicy.hasBeforeToolCallHook,
4784
+ trustedToolPolicies: beforeToolCallPolicy.trustedToolPolicies
4785
+ });
4749
4786
  let pluginAppServer = appServer;
4750
4787
  const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
4751
4788
  configuredEvents: options.nativeHookRelay?.events,
@@ -4794,10 +4831,6 @@ async function runCodexAppServerAttempt(params, options = {}) {
4794
4831
  sessionId: activeSessionId,
4795
4832
  sessionFile: activeSessionFile
4796
4833
  });
4797
- const adoptContextEngineCompactionTranscript = (compactResult) => {
4798
- if (compactResult.result?.sessionId) activeSessionId = compactResult.result.sessionId;
4799
- if (compactResult.result?.sessionFile) activeSessionFile = compactResult.result.sessionFile;
4800
- };
4801
4834
  const startupAuthAccountCacheKey = await resolveCodexAppServerAuthAccountCacheKey({
4802
4835
  authProfileId: startupAuthProfileId,
4803
4836
  authProfileStore: params.authProfileStore,
@@ -4832,21 +4865,22 @@ async function runCodexAppServerAttempt(params, options = {}) {
4832
4865
  });
4833
4866
  const hookChannelId = resolveCodexAppServerHookChannelId(params, sandboxSessionKey);
4834
4867
  let yieldDetected = false;
4868
+ const tools = await buildDynamicTools({
4869
+ params,
4870
+ resolvedWorkspace,
4871
+ effectiveWorkspace,
4872
+ sandboxSessionKey,
4873
+ sandbox,
4874
+ nativeToolSurfaceEnabled,
4875
+ runAbortController,
4876
+ sessionAgentId,
4877
+ pluginConfig,
4878
+ onYieldDetected: () => {
4879
+ yieldDetected = true;
4880
+ }
4881
+ });
4835
4882
  const toolBridge = createCodexDynamicToolBridge({
4836
- tools: await buildDynamicTools({
4837
- params,
4838
- resolvedWorkspace,
4839
- effectiveWorkspace,
4840
- sandboxSessionKey,
4841
- sandbox,
4842
- nativeToolSurfaceEnabled,
4843
- runAbortController,
4844
- sessionAgentId,
4845
- pluginConfig,
4846
- onYieldDetected: () => {
4847
- yieldDetected = true;
4848
- }
4849
- }),
4883
+ tools,
4850
4884
  registeredTools: await buildDynamicTools({
4851
4885
  params,
4852
4886
  resolvedWorkspace,
@@ -4902,65 +4936,6 @@ async function runCodexAppServerAttempt(params, options = {}) {
4902
4936
  contextEnginePluginId: activeContextEnginePluginId,
4903
4937
  tokenBudget: params.contextTokenBudget
4904
4938
  });
4905
- const forceContextEngineCompactionForCodexOverflow = async (error, options = {}) => {
4906
- if (!activeContextEngine?.info.ownsCompaction) return false;
4907
- embeddedAgentLog.warn("codex app-server context-engine prompt overflowed; forcing context-engine compaction", {
4908
- sessionId: activeSessionId,
4909
- sessionKey: contextSessionKey,
4910
- ...options.threadId ? { threadId: options.threadId } : {},
4911
- engineId: activeContextEngine.info.id,
4912
- tokenBudget: params.contextTokenBudget,
4913
- error: formatErrorMessage(error)
4914
- });
4915
- try {
4916
- const runtimeContext = buildActiveContextEngineRuntimeContext();
4917
- const overflowTokenCount = params.contextTokenBudget ?? params.contextWindowInfo?.tokens;
4918
- const compactResult = await compactContextEngineWithSafetyTimeout(activeContextEngine, {
4919
- sessionId: activeSessionId,
4920
- sessionKey: contextSessionKey,
4921
- sessionFile: activeSessionFile,
4922
- tokenBudget: params.contextTokenBudget,
4923
- force: true,
4924
- ...overflowTokenCount ? { currentTokenCount: overflowTokenCount } : {},
4925
- compactionTarget: "threshold",
4926
- runtimeContext: overflowTokenCount ? {
4927
- ...runtimeContext,
4928
- currentTokenCount: overflowTokenCount
4929
- } : runtimeContext
4930
- }, resolveCompactionTimeoutMs(params.config), runAbortController.signal);
4931
- embeddedAgentLog.info("codex app-server context-engine forced compaction result", {
4932
- sessionId: activeSessionId,
4933
- sessionKey: contextSessionKey,
4934
- engineId: activeContextEngine.info.id,
4935
- ok: compactResult.ok,
4936
- compacted: compactResult.compacted,
4937
- reason: compactResult.reason,
4938
- tokensBefore: compactResult.result?.tokensBefore,
4939
- tokensAfter: compactResult.result?.tokensAfter
4940
- });
4941
- if (!compactResult.ok || !compactResult.compacted) return false;
4942
- adoptContextEngineCompactionTranscript(compactResult);
4943
- const maintenanceRuntimeContext = buildActiveContextEngineRuntimeContext();
4944
- await runHarnessContextEngineMaintenance({
4945
- contextEngine: activeContextEngine,
4946
- sessionId: activeSessionId,
4947
- sessionKey: contextSessionKey,
4948
- sessionFile: activeSessionFile,
4949
- reason: "compaction",
4950
- runtimeContext: maintenanceRuntimeContext,
4951
- config: params.config
4952
- });
4953
- return true;
4954
- } catch (compactErr) {
4955
- embeddedAgentLog.warn("codex app-server context-engine forced compaction failed", {
4956
- sessionId: params.sessionId,
4957
- sessionKey: contextSessionKey,
4958
- engineId: activeContextEngine.info.id,
4959
- error: formatErrorMessage(compactErr)
4960
- });
4961
- return false;
4962
- }
4963
- };
4964
4939
  if (activeContextEngine) {
4965
4940
  await bootstrapHarnessContextEngine({
4966
4941
  hadSessionFile,
@@ -4992,12 +4967,6 @@ async function runCodexAppServerAttempt(params, options = {}) {
4992
4967
  let developerInstructions = baseDeveloperInstructions;
4993
4968
  let prePromptMessageCount = historyMessages.length;
4994
4969
  let contextEngineProjection;
4995
- const resetCodexPromptInputs = () => {
4996
- promptText = params.prompt;
4997
- developerInstructions = baseDeveloperInstructions;
4998
- prePromptMessageCount = historyMessages.length;
4999
- contextEngineProjection = void 0;
5000
- };
5001
4970
  const applyActiveContextEngineProjection = async (decisionStartupBinding) => {
5002
4971
  if (!activeContextEngine) return;
5003
4972
  const assembled = await assembleHarnessContextEngine({
@@ -5082,78 +5051,11 @@ async function runCodexAppServerAttempt(params, options = {}) {
5082
5051
  let promptBuild = await buildPromptFromCurrentInputs();
5083
5052
  const decorateCodexTurnPromptText = (prompt) => prependCodexOpenClawPromptContext(prompt, openClawPromptContext);
5084
5053
  let codexTurnPromptText = decorateCodexTurnPromptText(promptBuild.prompt);
5085
- const refreshCodexTurnPromptText = () => {
5086
- codexTurnPromptText = decorateCodexTurnPromptText(promptBuild.prompt);
5087
- };
5088
5054
  const buildCodexTurnCollaborationDeveloperInstructions = () => buildTurnCollaborationMode(params, {
5089
5055
  turnScopedDeveloperInstructions: workspaceBootstrapContext.turnScopedDeveloperInstructions,
5090
5056
  heartbeatCollaborationInstructions: workspaceBootstrapContext.heartbeatCollaborationInstructions
5091
5057
  }).settings.developer_instructions ?? void 0;
5092
5058
  const buildRenderedCodexDeveloperInstructions = () => joinPresentSections(promptBuild.developerInstructions, buildCodexTurnCollaborationDeveloperInstructions());
5093
- const rebuildPromptAfterContextEngineCompaction = async () => {
5094
- historyMessages = await readMirroredSessionHistoryMessages(activeSessionFile) ?? historyMessages;
5095
- resetCodexPromptInputs();
5096
- try {
5097
- await applyActiveContextEngineProjection(void 0);
5098
- } catch (assembleErr) {
5099
- embeddedAgentLog.warn("context engine assemble failed after forced compaction; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
5100
- }
5101
- promptBuild = await buildPromptFromCurrentInputs();
5102
- refreshCodexTurnPromptText();
5103
- };
5104
- const buildCodexProviderBoundaryPrecheck = () => {
5105
- const contextTokenBudget = typeof params.contextTokenBudget === "number" && Number.isFinite(params.contextTokenBudget) ? Math.floor(params.contextTokenBudget) : typeof params.contextWindowInfo?.tokens === "number" && Number.isFinite(params.contextWindowInfo.tokens) ? Math.floor(params.contextWindowInfo.tokens) : void 0;
5106
- if (!contextTokenBudget || contextTokenBudget <= 0) return;
5107
- const reserveTokens = resolveCodexContextEngineProjectionReserveTokens({ config: params.config }) ?? 2e4;
5108
- const renderedDeveloperInstructions = buildRenderedCodexDeveloperInstructions();
5109
- const renderedChars = codexTurnPromptText.length + renderedDeveloperInstructions.length;
5110
- return shouldPreemptivelyCompactBeforePrompt({
5111
- messages: historyMessages,
5112
- systemPrompt: renderedDeveloperInstructions,
5113
- prompt: codexTurnPromptText,
5114
- contextTokenBudget,
5115
- reserveTokens,
5116
- llmBoundaryTokenPressure: {
5117
- estimatedPromptTokens: estimateRenderedLlmBoundaryTokenPressure({
5118
- systemPrompt: renderedDeveloperInstructions,
5119
- prompt: codexTurnPromptText
5120
- }),
5121
- source: "codex_app_server_rendered_prompt",
5122
- renderedChars
5123
- }
5124
- });
5125
- };
5126
- const maybeCompactContextEngineForProviderBoundaryPrecheck = async () => {
5127
- if (!activeContextEngine?.info.ownsCompaction || !contextEngineProjection) return;
5128
- const precheck = buildCodexProviderBoundaryPrecheck();
5129
- if (!precheck) return;
5130
- embeddedAgentLog.debug(formatPrePromptPrecheckLog({
5131
- result: precheck,
5132
- provider: params.provider,
5133
- modelId: params.modelId,
5134
- messageCount: historyMessages.length,
5135
- contextTokenBudget: typeof params.contextTokenBudget === "number" ? params.contextTokenBudget : params.contextWindowInfo?.tokens ?? 0,
5136
- reserveTokens: resolveCodexContextEngineProjectionReserveTokens({ config: params.config }) ?? 2e4,
5137
- ...contextSessionKey ? { sessionKey: contextSessionKey } : {},
5138
- ...activeSessionId ? { sessionId: activeSessionId } : {},
5139
- ...activeSessionFile ? { sessionFile: activeSessionFile } : {}
5140
- }));
5141
- if (precheck.route === "fits") return;
5142
- if (!await forceContextEngineCompactionForCodexOverflow(PREEMPTIVE_OVERFLOW_ERROR_TEXT)) throw new Error(PREEMPTIVE_OVERFLOW_ERROR_TEXT);
5143
- await rebuildPromptAfterContextEngineCompaction();
5144
- const afterCompactionPrecheck = buildCodexProviderBoundaryPrecheck();
5145
- if (!afterCompactionPrecheck || afterCompactionPrecheck.route === "fits") return;
5146
- embeddedAgentLog.warn("codex app-server provider-boundary precheck still overflowed after compaction", {
5147
- sessionId: activeSessionId,
5148
- sessionKey: contextSessionKey,
5149
- route: afterCompactionPrecheck.route,
5150
- estimatedPromptTokens: afterCompactionPrecheck.estimatedPromptTokens,
5151
- promptBudgetBeforeReserve: afterCompactionPrecheck.promptBudgetBeforeReserve,
5152
- overflowTokens: afterCompactionPrecheck.overflowTokens
5153
- });
5154
- throw new Error(PREEMPTIVE_OVERFLOW_ERROR_TEXT);
5155
- };
5156
- await maybeCompactContextEngineForProviderBoundaryPrecheck();
5157
5059
  const systemPromptReport = buildCodexSystemPromptReport({
5158
5060
  attempt: params,
5159
5061
  sessionKey: contextSessionKey,
@@ -5990,6 +5892,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
5990
5892
  threadId: thread.threadId,
5991
5893
  turnId,
5992
5894
  nativeHookRelay,
5895
+ autoApprove: shouldAutoApproveCodexAppServerApprovals(appServer),
5993
5896
  signal: runAbortController.signal
5994
5897
  });
5995
5898
  }
@@ -6083,22 +5986,26 @@ async function runCodexAppServerAttempt(params, options = {}) {
6083
5986
  projector?.recordDynamicToolResult({
6084
5987
  callId: call.callId,
6085
5988
  tool: call.tool,
5989
+ asyncStarted: response.asyncStarted === true,
6086
5990
  success: protocolResponse.success,
6087
5991
  terminalType: response.diagnosticTerminalType ?? (protocolResponse.success ? "completed" : "error"),
6088
5992
  sideEffectEvidence: response.sideEffectEvidence === true,
6089
5993
  contentItems: protocolResponse.contentItems
6090
5994
  });
6091
- if (shouldEmitDynamicToolProgress) emitCodexAppServerEvent(params, {
6092
- stream: "tool",
6093
- data: {
6094
- phase: "result",
6095
- name: call.tool,
6096
- toolCallId: call.callId,
6097
- ...toolMeta ? { meta: toolMeta } : {},
6098
- isError: !protocolResponse.success,
6099
- result: sanitizeCodexToolResponse(protocolResponse)
6100
- }
6101
- });
5995
+ if (shouldEmitDynamicToolProgress) {
5996
+ const progressResponse = toCodexDynamicToolProgressResponse(response, protocolResponse);
5997
+ emitCodexAppServerEvent(params, {
5998
+ stream: "tool",
5999
+ data: {
6000
+ phase: "result",
6001
+ name: call.tool,
6002
+ toolCallId: call.callId,
6003
+ ...toolMeta ? { meta: toolMeta } : {},
6004
+ isError: !protocolResponse.success,
6005
+ result: sanitizeCodexToolResponse(progressResponse)
6006
+ }
6007
+ });
6008
+ }
6102
6009
  if (!terminalDiagnosticObserved && !hasPendingDynamicToolTerminalDiagnostic({
6103
6010
  call,
6104
6011
  runId: params.runId,
@@ -6161,27 +6068,99 @@ async function runCodexAppServerAttempt(params, options = {}) {
6161
6068
  systemPrompt: buildRenderedCodexDeveloperInstructions(),
6162
6069
  prompt: codexTurnPromptText,
6163
6070
  historyMessages,
6164
- imagesCount: params.images?.length ?? 0
6071
+ imagesCount: params.images?.length ?? 0,
6072
+ tools
6165
6073
  });
6166
6074
  const buildTurnStartFailureMessages = () => [...historyMessages, buildCodexUserPromptMessage({
6167
6075
  ...params,
6168
6076
  prompt: codexTurnPromptText
6169
6077
  })];
6078
+ const codexModelCallBaseFields = {
6079
+ runId: params.runId,
6080
+ callId: codexModelCallId,
6081
+ ...params.sessionKey ? { sessionKey: params.sessionKey } : {},
6082
+ sessionId: params.sessionId,
6083
+ provider: params.provider,
6084
+ model: params.modelId,
6085
+ api: params.model.api,
6086
+ transport: appServer.start.transport,
6087
+ ...hookContextWindowFields,
6088
+ trace: codexModelCallTrace
6089
+ };
6090
+ const codexDiagnosticToolDefinitions = codexModelContentCapture.toolDefinitions ? buildCodexDiagnosticToolDefinitions(tools) : void 0;
6091
+ const codexModelContentPrivateData = (modelContent) => modelContent && Object.keys(modelContent).length > 0 ? { modelContent } : void 0;
6092
+ const buildCodexModelCallDiagnosticContent = () => {
6093
+ const modelContent = {
6094
+ ...codexModelContentCapture.inputMessages ? { inputMessages: buildTurnStartFailureMessages() } : {},
6095
+ ...codexModelContentCapture.systemPrompt ? { systemPrompt: buildRenderedCodexDeveloperInstructions() } : {},
6096
+ ...codexDiagnosticToolDefinitions ? { toolDefinitions: codexDiagnosticToolDefinitions } : {}
6097
+ };
6098
+ return Object.keys(modelContent).length > 0 ? modelContent : void 0;
6099
+ };
6100
+ const emitCodexModelCallStarted = () => {
6101
+ codexModelCallStartedAt = Date.now();
6102
+ codexModelCallStarted = true;
6103
+ emitTrustedDiagnosticEventWithPrivateData({
6104
+ type: "model.call.started",
6105
+ ...codexModelCallBaseFields
6106
+ }, codexModelContentPrivateData(buildCodexModelCallDiagnosticContent()));
6107
+ };
6108
+ const emitCodexModelCallCompleted = (result) => {
6109
+ if (!codexModelCallStarted || codexModelCallTerminalEmitted) return;
6110
+ codexModelCallTerminalEmitted = true;
6111
+ emitTrustedDiagnosticEventWithPrivateData({
6112
+ type: "model.call.completed",
6113
+ ...codexModelCallBaseFields,
6114
+ durationMs: Math.max(0, Date.now() - codexModelCallStartedAt),
6115
+ ...codexModelCallRequestPayloadBytes !== void 0 ? { requestPayloadBytes: codexModelCallRequestPayloadBytes } : {}
6116
+ }, codexModelContentPrivateData({
6117
+ ...buildCodexModelCallDiagnosticContent(),
6118
+ ...codexModelContentCapture.outputMessages ? { outputMessages: result.lastAssistant ? [result.lastAssistant] : result.assistantTexts } : {}
6119
+ }));
6120
+ };
6121
+ const emitCodexModelCallError = (error, fields = {}) => {
6122
+ if (!codexModelCallStarted || codexModelCallTerminalEmitted) return;
6123
+ codexModelCallTerminalEmitted = true;
6124
+ emitTrustedDiagnosticEventWithPrivateData({
6125
+ type: "model.call.error",
6126
+ ...codexModelCallBaseFields,
6127
+ durationMs: Math.max(0, Date.now() - codexModelCallStartedAt),
6128
+ errorCategory: fields.failureKind ?? "error",
6129
+ ...fields.failureKind ? { failureKind: fields.failureKind } : {},
6130
+ ...codexModelCallRequestPayloadBytes !== void 0 ? { requestPayloadBytes: codexModelCallRequestPayloadBytes } : {}
6131
+ }, codexModelContentPrivateData({
6132
+ ...buildCodexModelCallDiagnosticContent(),
6133
+ ...codexModelContentCapture.outputMessages ? { outputMessages: [] } : {}
6134
+ }));
6135
+ embeddedAgentLog.debug("codex app-server model call diagnostic ended with error", { error: formatErrorMessage(error) });
6136
+ };
6137
+ const classifyCodexModelCallFailureKind = (error) => {
6138
+ if (timedOut || turnCompletionIdleTimedOut) return "timeout";
6139
+ const errorMessage = error ? formatErrorMessage(error).toLowerCase() : "";
6140
+ if (errorMessage.includes("timed out") || errorMessage.includes("timeout")) return "timeout";
6141
+ if (runAbortController.signal.aborted && !clientClosedAbort) return String(runAbortController.signal.reason ?? "").toLowerCase().includes("timeout") ? "timeout" : "aborted";
6142
+ return errorMessage.includes("aborted") ? "aborted" : void 0;
6143
+ };
6170
6144
  let turn;
6171
- const startCodexTurn = async () => assertCodexTurnStartResponse(await client.request("turn/start", buildTurnStartParams(params, {
6172
- threadId: thread.threadId,
6173
- cwd: codexExecutionCwd,
6174
- appServer: pluginAppServer,
6175
- promptText: codexTurnPromptText,
6176
- sandboxPolicy: codexSandboxPolicy,
6177
- environmentSelection: codexEnvironmentSelection,
6178
- turnScopedDeveloperInstructions: workspaceBootstrapContext.turnScopedDeveloperInstructions,
6179
- heartbeatCollaborationInstructions: workspaceBootstrapContext.heartbeatCollaborationInstructions
6180
- }), {
6181
- timeoutMs: params.timeoutMs,
6182
- signal: runAbortController.signal
6183
- }));
6145
+ const startCodexTurn = async () => {
6146
+ const turnStartParams = buildTurnStartParams(params, {
6147
+ threadId: thread.threadId,
6148
+ cwd: codexExecutionCwd,
6149
+ appServer: pluginAppServer,
6150
+ promptText: codexTurnPromptText,
6151
+ sandboxPolicy: codexSandboxPolicy,
6152
+ environmentSelection: codexEnvironmentSelection,
6153
+ turnScopedDeveloperInstructions: workspaceBootstrapContext.turnScopedDeveloperInstructions,
6154
+ heartbeatCollaborationInstructions: workspaceBootstrapContext.heartbeatCollaborationInstructions
6155
+ });
6156
+ codexModelCallRequestPayloadBytes = utf8JsonByteLength(turnStartParams);
6157
+ return assertCodexTurnStartResponse(await client.request("turn/start", turnStartParams, {
6158
+ timeoutMs: params.timeoutMs,
6159
+ signal: runAbortController.signal
6160
+ }));
6161
+ };
6184
6162
  try {
6163
+ emitCodexModelCallStarted();
6185
6164
  runAgentHarnessLlmInputHook({
6186
6165
  event: buildLlmInputEvent(),
6187
6166
  ctx: hookContext
@@ -6207,10 +6186,8 @@ async function runCodexAppServerAttempt(params, options = {}) {
6207
6186
  });
6208
6187
  try {
6209
6188
  const preRetrySessionFile = activeSessionFile;
6210
- const compactedForRetry = await forceContextEngineCompactionForCodexOverflow(turnStartError, { threadId: thread.threadId });
6211
6189
  await clearCodexAppServerBinding(preRetrySessionFile);
6212
6190
  if (activeSessionFile !== preRetrySessionFile) await clearCodexAppServerBinding(activeSessionFile);
6213
- if (compactedForRetry) await rebuildPromptAfterContextEngineCompaction();
6214
6191
  thread = await restartContextEngineCodexThread();
6215
6192
  emitCodexAppServerEvent(params, {
6216
6193
  stream: "codex_app_server.lifecycle",
@@ -6270,6 +6247,8 @@ async function runCodexAppServerAttempt(params, options = {}) {
6270
6247
  },
6271
6248
  ctx: hookContext
6272
6249
  });
6250
+ const turnStartFailureKind = classifyCodexModelCallFailureKind(turnStartError);
6251
+ emitCodexModelCallError(turnStartErrorMessage, turnStartFailureKind ? { failureKind: turnStartFailureKind } : {});
6273
6252
  await runCodexAgentEndHook(params, {
6274
6253
  event: {
6275
6254
  messages: buildTurnStartFailureMessages(),
@@ -6303,12 +6282,12 @@ async function runCodexAppServerAttempt(params, options = {}) {
6303
6282
  authProfileId: startupAuthProfileId,
6304
6283
  rateLimits: usageLimitError.rateLimitsForProfile
6305
6284
  });
6306
- return buildCodexTurnStartFailureResult({
6285
+ return { ...buildCodexTurnStartFailureResult({
6307
6286
  params,
6308
6287
  message: usageLimitError.message,
6309
6288
  messagesSnapshot: buildTurnStartFailureMessages(),
6310
6289
  systemPromptReport
6311
- });
6290
+ }) };
6312
6291
  }
6313
6292
  throw turnStartError;
6314
6293
  }
@@ -6380,10 +6359,18 @@ async function runCodexAppServerAttempt(params, options = {}) {
6380
6359
  queueMessage: async (text, options) => activeSteeringQueue.queue(text, options),
6381
6360
  isStreaming: () => !completed,
6382
6361
  isCompacting: () => projector?.isCompacting() ?? false,
6362
+ sourceReplyDeliveryMode: params.sourceReplyDeliveryMode,
6383
6363
  cancel: () => runAbortController.abort("cancelled"),
6384
6364
  abort: () => runAbortController.abort("aborted")
6385
6365
  };
6386
6366
  setActiveEmbeddedRun(params.sessionId, handle, params.sessionKey);
6367
+ mirrorPromptAtTurnStartBestEffort({
6368
+ params,
6369
+ agentId: sessionAgentId,
6370
+ sessionKey: sandboxSessionKey,
6371
+ threadId: thread.threadId,
6372
+ turnId: activeTurnId
6373
+ });
6387
6374
  turnAttemptIdleWatchArmed = true;
6388
6375
  turnTerminalIdleWatchArmed = true;
6389
6376
  touchTurnCompletionActivity("turn:start", { attemptProgress: true });
@@ -6432,6 +6419,10 @@ async function runCodexAppServerAttempt(params, options = {}) {
6432
6419
  result,
6433
6420
  turnCompletionIdleTimedOut
6434
6421
  });
6422
+ const modelCallFailureKind = classifyCodexModelCallFailureKind(finalPromptError) ?? (finalAborted ? "aborted" : void 0);
6423
+ if (modelCallFailureKind) emitCodexModelCallError(finalPromptError ?? "codex app-server attempt interrupted", { failureKind: modelCallFailureKind });
6424
+ else if (finalPromptError) emitCodexModelCallError(finalPromptError);
6425
+ else emitCodexModelCallCompleted(result);
6435
6426
  recordCodexTrajectoryCompletion(trajectoryRecorder, {
6436
6427
  attempt: params,
6437
6428
  result,
@@ -6542,6 +6533,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
6542
6533
  systemPromptReport
6543
6534
  };
6544
6535
  } finally {
6536
+ emitCodexModelCallError("codex app-server run completed without model-call terminal event");
6545
6537
  emitLifecycleTerminal({
6546
6538
  phase: "error",
6547
6539
  error: "codex app-server run completed without lifecycle terminal event"
@@ -6717,6 +6709,16 @@ function toCodexDynamicToolProtocolResponse(response) {
6717
6709
  success: response.success
6718
6710
  };
6719
6711
  }
6712
+ function toCodexDynamicToolProgressResponse(response, protocolResponse) {
6713
+ if (response.asyncStarted !== true) return protocolResponse;
6714
+ return {
6715
+ ...protocolResponse,
6716
+ details: {
6717
+ async: true,
6718
+ status: "started"
6719
+ }
6720
+ };
6721
+ }
6720
6722
  function shouldReleaseTurnAfterTerminalDynamicTool(state) {
6721
6723
  return !state.completed && !state.aborted && state.responseSuccess && !state.currentTurnHadNonTerminalDynamicToolResult && state.activeAppServerTurnRequests === 0 && state.activeTurnItemIdsCount === 0 && state.pendingOpenClawDynamicToolCompletionIdsCount === 0;
6722
6724
  }
@@ -7528,8 +7530,7 @@ function readString(record, key) {
7528
7530
  return typeof value === "string" ? value : void 0;
7529
7531
  }
7530
7532
  function readBoolean(record, key) {
7531
- const value = record[key];
7532
- return typeof value === "boolean" ? value : void 0;
7533
+ return asBoolean(record[key]);
7533
7534
  }
7534
7535
  async function readMirroredSessionHistoryMessages(sessionFile) {
7535
7536
  const messages = await readCodexMirroredSessionHistoryMessages(sessionFile);
@@ -7596,7 +7597,8 @@ function buildCodexSystemPromptReport(params) {
7596
7597
  systemPrompt: {
7597
7598
  chars: params.developerInstructions.length,
7598
7599
  projectContextChars: 0,
7599
- nonProjectContextChars: params.developerInstructions.length
7600
+ nonProjectContextChars: params.developerInstructions.length,
7601
+ hash: sha256Text(params.developerInstructions)
7600
7602
  },
7601
7603
  injectedWorkspaceFiles: buildCodexBootstrapInjectionStats({
7602
7604
  bootstrapFiles: params.workspaceBootstrapContext.bootstrapFiles,
@@ -7605,6 +7607,7 @@ function buildCodexSystemPromptReport(params) {
7605
7607
  }),
7606
7608
  skills: {
7607
7609
  promptChars: skillsPrompt.length,
7610
+ hash: sha256Text(skillsPrompt),
7608
7611
  entries: buildCodexSkillReportEntries(skillsPrompt)
7609
7612
  },
7610
7613
  tools: {
@@ -7621,17 +7624,30 @@ function buildCodexSkillReportEntries(skillsPrompt) {
7621
7624
  blockChars: block.length
7622
7625
  })).filter((entry) => entry.blockChars > 0);
7623
7626
  }
7627
+ function readCodexDiagnosticToolParameters(tool) {
7628
+ return tool.inputSchema ?? tool.parameters;
7629
+ }
7630
+ function buildCodexDiagnosticToolDefinitions(tools) {
7631
+ return tools.map((tool) => ({
7632
+ name: tool.name,
7633
+ description: tool.description,
7634
+ parameters: readCodexDiagnosticToolParameters(tool)
7635
+ }));
7636
+ }
7624
7637
  function buildCodexToolReportEntry(tool) {
7625
7638
  const summary = tool.description.trim();
7626
7639
  if (tool.deferLoading === true) return {
7627
7640
  name: tool.name,
7628
7641
  summaryChars: summary.length,
7642
+ summaryHash: sha256Text(summary),
7629
7643
  schemaChars: 0,
7644
+ schemaHash: stableJsonHash(null),
7630
7645
  propertiesCount: null
7631
7646
  };
7632
7647
  return {
7633
7648
  name: tool.name,
7634
7649
  summaryChars: summary.length,
7650
+ summaryHash: sha256Text(summary),
7635
7651
  ...buildCodexToolSchemaStats(tool.inputSchema)
7636
7652
  };
7637
7653
  }
@@ -7646,9 +7662,24 @@ function buildCodexToolSchemaStats(schema) {
7646
7662
  const properties = isJsonObject(schema) && isJsonObject(schema.properties) ? schema.properties : null;
7647
7663
  return {
7648
7664
  schemaChars,
7665
+ schemaHash: stableJsonHash(schema),
7649
7666
  propertiesCount: properties ? Object.keys(properties).length : null
7650
7667
  };
7651
7668
  }
7669
+ function sha256Text(value) {
7670
+ return createHash("sha256").update(value).digest("hex");
7671
+ }
7672
+ function normalizeForStableHash(value) {
7673
+ if (Array.isArray(value)) return value.map((entry) => normalizeForStableHash(entry));
7674
+ if (value && typeof value === "object") {
7675
+ const record = value;
7676
+ return Object.fromEntries(Object.keys(record).toSorted((left, right) => left.localeCompare(right)).map((key) => [key, normalizeForStableHash(record[key])]));
7677
+ }
7678
+ return value;
7679
+ }
7680
+ function stableJsonHash(value) {
7681
+ return sha256Text(JSON.stringify(normalizeForStableHash(value)) ?? "null");
7682
+ }
7652
7683
  function buildCodexBootstrapInjectionStats(params) {
7653
7684
  const injectedIndex = indexCodexContextFileContent(params.injectedFiles);
7654
7685
  const developerInstructionIndex = indexCodexContextFileContent(params.developerInstructionFiles ?? []);
@@ -7822,9 +7853,11 @@ function isMissingCodexBootstrapContextFile(file) {
7822
7853
  function remapCodexContextFilePath(params) {
7823
7854
  const relativePath = path.relative(params.sourceWorkspaceDir, params.file.path);
7824
7855
  if (!relativePath || relativePath === ".." || relativePath.startsWith(`..${path.sep}`) || path.isAbsolute(relativePath) || params.sourceWorkspaceDir === params.targetWorkspaceDir) return params.file;
7856
+ const targetUsesPosixSeparators = params.targetWorkspaceDir.includes("/") && !params.targetWorkspaceDir.includes("\\");
7857
+ const normalizedRelativePath = targetUsesPosixSeparators ? relativePath.replaceAll("\\", "/") : relativePath.replaceAll("/", "\\");
7825
7858
  return {
7826
7859
  ...params.file,
7827
- path: path.join(params.targetWorkspaceDir, relativePath)
7860
+ path: targetUsesPosixSeparators ? path.posix.join(params.targetWorkspaceDir, normalizedRelativePath) : path.win32.join(params.targetWorkspaceDir, normalizedRelativePath)
7828
7861
  };
7829
7862
  }
7830
7863
  function compareCodexContextFiles(left, right) {
@@ -7861,6 +7894,21 @@ async function mirrorTranscriptBestEffort(params) {
7861
7894
  embeddedAgentLog.warn("failed to mirror codex app-server transcript", { error });
7862
7895
  }
7863
7896
  }
7897
+ async function mirrorPromptAtTurnStartBestEffort(params) {
7898
+ if (params.params.suppressNextUserMessagePersistence) return;
7899
+ try {
7900
+ await mirrorCodexAppServerTranscript({
7901
+ sessionFile: params.params.sessionFile,
7902
+ agentId: params.agentId,
7903
+ sessionKey: params.sessionKey,
7904
+ messages: [attachCodexMirrorIdentity(buildCodexUserPromptMessage(params.params), `${params.turnId}:prompt`)],
7905
+ idempotencyScope: `codex-app-server:${params.threadId}`,
7906
+ config: params.params.config
7907
+ });
7908
+ } catch (error) {
7909
+ embeddedAgentLog.warn("failed to mirror codex app-server prompt at turn start", { error });
7910
+ }
7911
+ }
7864
7912
  function isNonEmptyString(value) {
7865
7913
  return typeof value === "string" && value.length > 0;
7866
7914
  }
@@ -7907,6 +7955,7 @@ function handleApprovalRequest(params) {
7907
7955
  threadId: params.threadId,
7908
7956
  turnId: params.turnId,
7909
7957
  nativeHookRelay: params.nativeHookRelay,
7958
+ autoApprove: params.autoApprove,
7910
7959
  signal: params.signal
7911
7960
  });
7912
7961
  }