@openclaw/codex 2026.5.14-beta.2 → 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.
Files changed (25) hide show
  1. package/dist/{client-CoctX13d.js → client-CA7amCZ8.js} +1 -1
  2. package/dist/{client-factory-Be6RD28K.js → client-factory-DwzPofwS.js} +1 -1
  3. package/dist/{command-formatters-DRJaVHhN.js → command-formatters-BRW7_Nu7.js} +10 -2
  4. package/dist/{command-handlers-CXxykxjq.js → command-handlers-D6UDzndR.js} +7 -7
  5. package/dist/compact-96QPqIAu.js +329 -0
  6. package/dist/{computer-use-DsJxRRtm.js → computer-use-BX02ojP4.js} +2 -2
  7. package/dist/{config-0rd3LnKg.js → config-3ATInASk.js} +7 -1
  8. package/dist/harness.js +9 -6
  9. package/dist/index.js +7 -7
  10. package/dist/media-understanding-provider.js +3 -3
  11. package/dist/{models-GCYf5s8J.js → models-BHS-8DS_.js} +1 -1
  12. package/dist/{node-cli-sessions-CiexDHeV.js → node-cli-sessions-BLDFnUEF.js} +5 -5
  13. package/dist/{plugin-activation-aQOmRQwA.js → plugin-activation-BDU4e-NA.js} +1 -1
  14. package/dist/provider.js +2 -2
  15. package/dist/{request-CKYiRqsN.js → request-Czoa60Nt.js} +3 -3
  16. package/dist/{run-attempt-DG9NQab2.js → run-attempt-B6gN6CrO.js} +364 -77
  17. package/dist/{session-binding-CMTXuyoz.js → session-binding-DbdVqMzW.js} +14 -2
  18. package/dist/{shared-client-BwUqd3lh.js → shared-client-CnbrvEfV.js} +2 -2
  19. package/dist/{side-question-CVWPOkY-.js → side-question-CFcVH8fj.js} +7 -7
  20. package/dist/test-api.js +2 -2
  21. package/dist/{thread-lifecycle-DrbViNpf.js → thread-lifecycle-BMK4m_PL.js} +159 -34
  22. package/dist/{vision-tools-CzTdigBu.js → vision-tools-Cm_YicZb.js} +107 -7
  23. package/openclaw.plugin.json +1 -1
  24. package/package.json +4 -4
  25. package/dist/compact-DWa8cylR.js +0 -256
@@ -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";
@@ -1,12 +1,12 @@
1
- import { o as readCodexPluginConfig, s as resolveCodexAppServerRuntimeOptions } from "./config-0rd3LnKg.js";
1
+ import { c as resolveCodexAppServerRuntimeOptions, s as readCodexPluginConfig } from "./config-3ATInASk.js";
2
2
  import { a as readCodexDynamicToolCallParams, i as assertCodexTurnStartResponse, l as readCodexTurnCompletedNotification, t as assertCodexThreadForkResponse } from "./protocol-validators-CSY0BFBo.js";
3
3
  import { t as isJsonObject } from "./protocol-C9UWI98H.js";
4
- import { r as isCodexAppServerApprovalRequest } from "./client-CoctX13d.js";
5
- import { u as formatCodexUsageLimitErrorMessage } from "./command-formatters-DRJaVHhN.js";
6
- import { i as getSharedCodexAppServerClient, s as refreshCodexAppServerAuthTokens } from "./shared-client-BwUqd3lh.js";
7
- import { i as readCodexAppServerBinding } from "./session-binding-CMTXuyoz.js";
8
- import { c as resolveCodexAppServerModelProvider, l as resolveReasoningEffort, n as buildCodexRuntimeThreadConfig, v as createCodexDynamicToolBridge, y as filterCodexDynamicTools } from "./thread-lifecycle-DrbViNpf.js";
9
- import { n as handleCodexAppServerElicitationRequest, r as handleCodexAppServerApprovalRequest, t as filterToolsForVisionInputs } from "./vision-tools-CzTdigBu.js";
4
+ import { r as isCodexAppServerApprovalRequest } from "./client-CA7amCZ8.js";
5
+ import { u as formatCodexUsageLimitErrorMessage } from "./command-formatters-BRW7_Nu7.js";
6
+ import { i as getSharedCodexAppServerClient, s as refreshCodexAppServerAuthTokens } from "./shared-client-CnbrvEfV.js";
7
+ import { i as readCodexAppServerBinding } from "./session-binding-DbdVqMzW.js";
8
+ import { b as createCodexDynamicToolBridge, d as resolveReasoningEffort, n as buildCodexRuntimeThreadConfig, u as resolveCodexAppServerModelProvider, x as filterCodexDynamicTools } from "./thread-lifecycle-BMK4m_PL.js";
9
+ import { n as handleCodexAppServerElicitationRequest, r as handleCodexAppServerApprovalRequest, t as filterToolsForVisionInputs } from "./vision-tools-Cm_YicZb.js";
10
10
  import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-dvhq-4pi.js";
11
11
  import { embeddedAgentLog, formatErrorMessage, resolveAgentDir, resolveAttemptSpawnWorkspaceDir, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
12
12
  //#region extensions/codex/src/app-server/side-question.ts
package/dist/test-api.js CHANGED
@@ -1,5 +1,5 @@
1
- import { s as resolveCodexAppServerRuntimeOptions } from "./config-0rd3LnKg.js";
2
- import { a as buildThreadStartParams, i as buildThreadResumeParams, o as buildTurnStartParams, r as buildDeveloperInstructions, v as createCodexDynamicToolBridge, y as filterCodexDynamicTools } from "./thread-lifecycle-DrbViNpf.js";
1
+ import { c as resolveCodexAppServerRuntimeOptions } from "./config-3ATInASk.js";
2
+ import { a as buildThreadResumeParams, b as createCodexDynamicToolBridge, i as buildDeveloperInstructions, o as buildThreadStartParams, s as buildTurnStartParams, x as filterCodexDynamicTools } from "./thread-lifecycle-BMK4m_PL.js";
3
3
  //#region extensions/codex/test-api.ts
4
4
  function resolveCodexPromptSnapshotAppServerOptions(pluginConfig) {
5
5
  return resolveCodexAppServerRuntimeOptions({
@@ -1,14 +1,15 @@
1
- import { l as resolveCodexPluginsPolicy, r as codexSandboxPolicyForTurn } from "./config-0rd3LnKg.js";
1
+ import { r as codexSandboxPolicyForTurn, u as resolveCodexPluginsPolicy } from "./config-3ATInASk.js";
2
2
  import { n as assertCodexThreadResumeResponse, r as assertCodexThreadStartResponse } from "./protocol-validators-CSY0BFBo.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-CoctX13d.js";
7
- import { i as readCodexAppServerBinding, n as isCodexAppServerNativeAuthProfile, o as writeCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-CMTXuyoz.js";
8
- import { a as defaultCodexAppInventoryCache, r as readCodexPluginInventory, t as ensureCodexPluginActivation } from "./plugin-activation-aQOmRQwA.js";
6
+ import { i as isCodexAppServerConnectionClosedError } from "./client-CA7amCZ8.js";
7
+ import { i as readCodexAppServerBinding, n as isCodexAppServerNativeAuthProfile, o as writeCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-DbdVqMzW.js";
8
+ import { a as defaultCodexAppInventoryCache, r as readCodexPluginInventory, t as ensureCodexPluginActivation } from "./plugin-activation-BDU4e-NA.js";
9
9
  import crypto from "node:crypto";
10
10
  import { HEARTBEAT_RESPONSE_TOOL_NAME, createAgentToolResultMiddlewareRunner, createCodexAppServerToolResultExtensionRunner, embeddedAgentLog, extractToolResultMediaArtifact, filterToolResultMediaUrls, isActiveHarnessContextEngine, isMessagingTool, isMessagingToolSendAction, isToolWrappedWithBeforeToolCallHook, normalizeHeartbeatToolResponse, runAgentHarnessAfterToolCallHook, wrapToolWithBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
11
11
  import { buildCodexUserMcpServersThreadConfigPatch } from "openclaw/plugin-sdk/codex-mcp-projection";
12
+ import { redactSensitiveFieldValue, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
12
13
  //#region extensions/codex/src/app-server/dynamic-tool-profile.ts
13
14
  const CODEX_APP_SERVER_OWNED_DYNAMIC_TOOL_EXCLUDES = [
14
15
  "read",
@@ -17,7 +18,11 @@ const CODEX_APP_SERVER_OWNED_DYNAMIC_TOOL_EXCLUDES = [
17
18
  "apply_patch",
18
19
  "exec",
19
20
  "process",
20
- "update_plan"
21
+ "update_plan",
22
+ "tool_search_code",
23
+ "tool_search",
24
+ "tool_describe",
25
+ "tool_call"
21
26
  ];
22
27
  const DYNAMIC_TOOL_NAME_ALIASES = {
23
28
  bash: "exec",
@@ -365,7 +370,10 @@ function projectContextEngineAssemblyForCodex(params) {
365
370
  const prompt = params.prompt.trim();
366
371
  const contextMessages = dropDuplicateTrailingPrompt(params.assembledMessages, prompt);
367
372
  const maxRenderedContextChars = normalizeRenderedContextMaxChars(params.maxRenderedContextChars);
368
- const renderedContext = renderMessagesForCodexContext(contextMessages, { maxTextPartChars: resolveTextPartMaxChars(maxRenderedContextChars) });
373
+ const renderedContext = renderMessagesForCodexContext(contextMessages, {
374
+ maxTextPartChars: resolveTextPartMaxChars(maxRenderedContextChars),
375
+ toolPayloadMode: params.toolPayloadMode ?? "elide"
376
+ });
369
377
  const promptText = renderedContext ? [
370
378
  CONTEXT_HEADER,
371
379
  CONTEXT_SAFETY_NOTE,
@@ -436,10 +444,88 @@ function renderMessagePart(part, options) {
436
444
  const type = typeof record.type === "string" ? record.type : void 0;
437
445
  if (type === "text") return typeof record.text === "string" ? truncateText(record.text.trim(), options.maxTextPartChars) : "";
438
446
  if (type === "image") return "[image omitted]";
439
- if (type === "toolCall" || type === "tool_use") return `tool call${typeof record.name === "string" ? `: ${record.name}` : ""} [input omitted]`;
440
- if (type === "toolResult" || type === "tool_result") return `${typeof record.toolUseId === "string" ? `tool result: ${record.toolUseId}` : "tool result"} [content omitted]`;
447
+ if (type === "toolCall" || type === "tool_use") {
448
+ const label = `tool call${typeof record.name === "string" ? `: ${record.name}` : ""}`;
449
+ if (options.toolPayloadMode === "preserve") return truncateText(`${label}\n${stableJson(renderToolCallPayload(record))}`, options.maxTextPartChars);
450
+ return `${label} [input omitted]`;
451
+ }
452
+ if (type === "toolResult" || type === "tool_result") {
453
+ const label = typeof record.toolUseId === "string" ? `tool result: ${record.toolUseId}` : "tool result";
454
+ if (options.toolPayloadMode === "preserve") return truncateText(`${label}\n${stableJson(renderToolResultPayload(record))}`, options.maxTextPartChars);
455
+ return `${label} [content omitted]`;
456
+ }
441
457
  return `[${type ?? "non-text"} content omitted]`;
442
458
  }
459
+ function renderToolCallPayload(record) {
460
+ const payload = pickToolPayloadMetadata(record);
461
+ const input = record.input ?? record.arguments;
462
+ if (input !== void 0) payload.inputShape = summarizeToolInputShape(input);
463
+ return payload;
464
+ }
465
+ function renderToolResultPayload(record) {
466
+ const payload = pickToolPayloadMetadata(record);
467
+ for (const [key, value] of Object.entries(record)) {
468
+ if (TOOL_PAYLOAD_METADATA_KEYS.has(key)) continue;
469
+ payload[key] = redactPreservedToolValue(key, value);
470
+ }
471
+ return payload;
472
+ }
473
+ const TOOL_PAYLOAD_METADATA_KEYS = new Set([
474
+ "type",
475
+ "name",
476
+ "id",
477
+ "callId",
478
+ "toolCallId",
479
+ "toolUseId"
480
+ ]);
481
+ function pickToolPayloadMetadata(record) {
482
+ const payload = {};
483
+ for (const key of TOOL_PAYLOAD_METADATA_KEYS) {
484
+ const value = record[key];
485
+ if (typeof value === "string" && value.trim()) payload[key] = redactSensitiveFieldValue(key, value);
486
+ }
487
+ return payload;
488
+ }
489
+ function summarizeToolInputShape(value, seen = /* @__PURE__ */ new WeakSet()) {
490
+ if (value === null) return null;
491
+ if (Array.isArray(value)) {
492
+ if (seen.has(value)) return "[Circular]";
493
+ seen.add(value);
494
+ return value.map((entry) => summarizeToolInputShape(entry, seen));
495
+ }
496
+ if (value && typeof value === "object") {
497
+ if (seen.has(value)) return "[Circular]";
498
+ seen.add(value);
499
+ const out = {};
500
+ for (const [key, child] of Object.entries(value)) out[key] = summarizeToolInputShape(child, seen);
501
+ return out;
502
+ }
503
+ return `[${typeof value}]`;
504
+ }
505
+ function redactPreservedToolValue(key, value, seen = /* @__PURE__ */ new WeakSet()) {
506
+ if (typeof value === "string") return redactSensitiveFieldValue(key, redactToolPayloadText(value));
507
+ if (value === null || value === void 0 || typeof value === "number" || typeof value === "boolean") return value;
508
+ if (Array.isArray(value)) {
509
+ if (seen.has(value)) return "[Circular]";
510
+ seen.add(value);
511
+ return value.map((entry) => redactPreservedToolValue(key, entry, seen));
512
+ }
513
+ if (value && typeof value === "object") {
514
+ if (seen.has(value)) return "[Circular]";
515
+ seen.add(value);
516
+ const out = {};
517
+ for (const [childKey, child] of Object.entries(value)) out[childKey] = redactPreservedToolValue(childKey, child, seen);
518
+ return out;
519
+ }
520
+ return `[${typeof value}]`;
521
+ }
522
+ function stableJson(value) {
523
+ try {
524
+ return JSON.stringify(value, null, 2) ?? "";
525
+ } catch {
526
+ return "[unserializable payload omitted]";
527
+ }
528
+ }
443
529
  function extractMessageText(message) {
444
530
  if (!hasMessageContent(message)) return "";
445
531
  if (typeof message.content === "string") return message.content;
@@ -704,8 +790,8 @@ const CODEX_CODE_MODE_THREAD_CONFIG = {
704
790
  const CODEX_LIGHTWEIGHT_CONTEXT_THREAD_CONFIG = { project_doc_max_bytes: 0 };
705
791
  async function startOrResumeThread(params) {
706
792
  const dynamicToolsFingerprint = fingerprintDynamicTools(params.dynamicTools);
707
- const contextEngineBinding = buildContextEngineBinding(params.params);
708
- const userMcpServersConfigPatch = buildCodexUserMcpServersThreadConfigPatch(params.params.config);
793
+ const contextEngineBinding = buildContextEngineBinding(params.params, params.contextEngineProjection);
794
+ const userMcpServersConfigPatch = buildCodexUserMcpServersThreadConfigPatch(params.params.config, { agentId: params.agentId ?? params.params.agentId });
709
795
  const userMcpServersFingerprint = fingerprintUserMcpServersConfigPatch(userMcpServersConfigPatch);
710
796
  let binding = await readCodexAppServerBinding(params.params.sessionFile, {
711
797
  authProfileStore: params.params.authProfileStore,
@@ -720,7 +806,13 @@ async function startOrResumeThread(params) {
720
806
  embeddedAgentLog.debug("codex app-server context-engine binding changed; starting a new thread", {
721
807
  threadId: binding.threadId,
722
808
  engineId: contextEngineBinding?.engineId,
723
- previousEngineId: binding.contextEngine?.engineId
809
+ previousEngineId: binding.contextEngine?.engineId,
810
+ epoch: contextEngineBinding?.projection?.epoch,
811
+ previousEpoch: binding.contextEngine?.projection?.epoch,
812
+ fingerprint: contextEngineBinding?.projection?.fingerprint,
813
+ previousFingerprint: binding.contextEngine?.projection?.fingerprint,
814
+ policyFingerprint: contextEngineBinding?.policyFingerprint,
815
+ previousPolicyFingerprint: binding.contextEngine?.policyFingerprint
724
816
  });
725
817
  await clearCodexAppServerBinding(params.params.sessionFile);
726
818
  binding = void 0;
@@ -816,6 +908,15 @@ async function startOrResumeThread(params) {
816
908
  agentDir: params.params.agentDir,
817
909
  config: params.params.config
818
910
  });
911
+ if (contextEngineBinding) embeddedAgentLog.info("codex app-server wrote context-engine thread binding", {
912
+ sessionId: params.params.sessionId,
913
+ sessionKey: params.params.sessionKey,
914
+ threadId: response.thread.id,
915
+ engineId: contextEngineBinding.engineId,
916
+ epoch: contextEngineBinding.projection?.epoch,
917
+ fingerprint: contextEngineBinding.projection?.fingerprint,
918
+ action: "resumed"
919
+ });
819
920
  return {
820
921
  ...binding,
821
922
  threadId: response.thread.id,
@@ -855,25 +956,36 @@ async function startOrResumeThread(params) {
855
956
  });
856
957
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
857
958
  const nextMcpServersFingerprint = params.mcpServersFingerprintEvaluated === true ? params.mcpServersFingerprint : void 0;
858
- if (!preserveExistingBinding) await writeCodexAppServerBinding(params.params.sessionFile, {
859
- threadId: response.thread.id,
860
- cwd: params.cwd,
861
- authProfileId: params.params.authProfileId,
862
- model: response.model ?? params.params.modelId,
863
- modelProvider: response.modelProvider ?? modelProvider,
864
- dynamicToolsFingerprint,
865
- userMcpServersFingerprint,
866
- mcpServersFingerprint: nextMcpServersFingerprint,
867
- pluginAppsFingerprint: pluginThreadConfig?.fingerprint,
868
- pluginAppsInputFingerprint: pluginThreadConfig?.inputFingerprint,
869
- pluginAppPolicyContext: pluginThreadConfig?.policyContext,
870
- contextEngine: contextEngineBinding,
871
- createdAt
872
- }, {
873
- authProfileStore: params.params.authProfileStore,
874
- agentDir: params.params.agentDir,
875
- config: params.params.config
876
- });
959
+ if (!preserveExistingBinding) {
960
+ await writeCodexAppServerBinding(params.params.sessionFile, {
961
+ threadId: response.thread.id,
962
+ cwd: params.cwd,
963
+ authProfileId: params.params.authProfileId,
964
+ model: response.model ?? params.params.modelId,
965
+ modelProvider: response.modelProvider ?? modelProvider,
966
+ dynamicToolsFingerprint,
967
+ userMcpServersFingerprint,
968
+ mcpServersFingerprint: nextMcpServersFingerprint,
969
+ pluginAppsFingerprint: pluginThreadConfig?.fingerprint,
970
+ pluginAppsInputFingerprint: pluginThreadConfig?.inputFingerprint,
971
+ pluginAppPolicyContext: pluginThreadConfig?.policyContext,
972
+ contextEngine: contextEngineBinding,
973
+ createdAt
974
+ }, {
975
+ authProfileStore: params.params.authProfileStore,
976
+ agentDir: params.params.agentDir,
977
+ config: params.params.config
978
+ });
979
+ if (contextEngineBinding) embeddedAgentLog.info("codex app-server wrote context-engine thread binding", {
980
+ sessionId: params.params.sessionId,
981
+ sessionKey: params.params.sessionKey,
982
+ threadId: response.thread.id,
983
+ engineId: contextEngineBinding.engineId,
984
+ epoch: contextEngineBinding.projection?.epoch,
985
+ fingerprint: contextEngineBinding.projection?.fingerprint,
986
+ action: rotatedContextEngineBinding ? "rotated" : "started"
987
+ });
988
+ }
877
989
  return {
878
990
  schemaVersion: 1,
879
991
  threadId: response.thread.id,
@@ -897,7 +1009,7 @@ async function startOrResumeThread(params) {
897
1009
  }
898
1010
  };
899
1011
  }
900
- function buildContextEngineBinding(params) {
1012
+ function buildContextEngineBinding(params, projection) {
901
1013
  const contextEngine = isActiveHarnessContextEngine(params.contextEngine) ? params.contextEngine : void 0;
902
1014
  const engineId = contextEngine?.info?.id?.trim();
903
1015
  if (!contextEngine || !engineId) return;
@@ -916,11 +1028,24 @@ function buildContextEngineBinding(params) {
916
1028
  contextTokenBudget: params.contextTokenBudget,
917
1029
  reserveTokens: resolveCodexContextEngineProjectionReserveTokens({ config: params.config })
918
1030
  })
919
- })
1031
+ }),
1032
+ projection: projection ? buildContextEngineProjectionBinding(projection) : void 0
1033
+ };
1034
+ }
1035
+ function buildContextEngineProjectionBinding(projection) {
1036
+ return {
1037
+ schemaVersion: 1,
1038
+ mode: "thread_bootstrap",
1039
+ epoch: projection.epoch,
1040
+ fingerprint: projection.fingerprint
920
1041
  };
921
1042
  }
922
1043
  function isContextEngineBindingCompatible(previous, next) {
923
- return previous?.schemaVersion === next.schemaVersion && previous.engineId === next.engineId && previous.policyFingerprint === next.policyFingerprint;
1044
+ return previous?.schemaVersion === next.schemaVersion && previous.engineId === next.engineId && previous.policyFingerprint === next.policyFingerprint && areContextEngineProjectionBindingsCompatible(previous.projection, next.projection);
1045
+ }
1046
+ function areContextEngineProjectionBindingsCompatible(previous, next) {
1047
+ if (!next) return previous === void 0;
1048
+ return previous?.schemaVersion === next.schemaVersion && previous.mode === next.mode && previous.epoch === next.epoch && previous.fingerprint === next.fingerprint;
924
1049
  }
925
1050
  function resolveContextEngineCitationsMode(config) {
926
1051
  const rootConfig = isUnknownRecord(config) ? config : void 0;
@@ -1135,4 +1260,4 @@ function resolveReasoningEffort(thinkLevel, modelId) {
1135
1260
  return null;
1136
1261
  }
1137
1262
  //#endregion
1138
- export { resolveCodexContextEngineProjectionReserveTokens as _, buildThreadStartParams as a, normalizeCodexDynamicToolName as b, resolveCodexAppServerModelProvider as c, buildCodexPluginThreadConfig as d, buildCodexPluginThreadConfigInputFingerprint as f, resolveCodexContextEngineProjectionMaxChars as g, projectContextEngineAssemblyForCodex as h, buildThreadResumeParams as i, resolveReasoningEffort as l, shouldBuildCodexPluginThreadConfig as m, buildCodexRuntimeThreadConfig as n, buildTurnStartParams as o, mergeCodexThreadConfigs as p, buildDeveloperInstructions as r, codexDynamicToolsFingerprint as s, areCodexDynamicToolFingerprintsCompatible as t, startOrResumeThread as u, createCodexDynamicToolBridge as v, filterCodexDynamicTools as y };
1263
+ export { normalizeCodexDynamicToolName as S, projectContextEngineAssemblyForCodex as _, buildThreadResumeParams as a, createCodexDynamicToolBridge as b, codexDynamicToolsFingerprint as c, resolveReasoningEffort as d, startOrResumeThread as f, shouldBuildCodexPluginThreadConfig as g, mergeCodexThreadConfigs as h, buildDeveloperInstructions as i, isContextEngineBindingCompatible as l, buildCodexPluginThreadConfigInputFingerprint as m, buildCodexRuntimeThreadConfig as n, buildThreadStartParams as o, buildCodexPluginThreadConfig as p, buildContextEngineBinding as r, buildTurnStartParams as s, areCodexDynamicToolFingerprintsCompatible as t, resolveCodexAppServerModelProvider as u, resolveCodexContextEngineProjectionMaxChars as v, filterCodexDynamicTools as x, resolveCodexContextEngineProjectionReserveTokens as y };
@@ -1,6 +1,6 @@
1
1
  import { t as isJsonObject } from "./protocol-C9UWI98H.js";
2
- import { r as formatCodexDisplayText } from "./command-formatters-DRJaVHhN.js";
3
- import { callGatewayTool, embeddedAgentLog, formatApprovalDisplayPath } from "openclaw/plugin-sdk/agent-harness-runtime";
2
+ import { r as formatCodexDisplayText } from "./command-formatters-BRW7_Nu7.js";
3
+ import { callGatewayTool, embeddedAgentLog, formatApprovalDisplayPath, runBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
4
4
  //#region extensions/codex/src/app-server/plugin-approval-roundtrip.ts
5
5
  const DEFAULT_CODEX_APPROVAL_TIMEOUT_MS = 12e4;
6
6
  const MAX_PLUGIN_APPROVAL_TITLE_LENGTH = 80;
@@ -84,6 +84,25 @@ async function handleCodexAppServerApprovalRequest(params) {
84
84
  paramsForRun: params.paramsForRun
85
85
  });
86
86
  try {
87
+ const policyOutcome = await runOpenClawToolPolicyForApprovalRequest({
88
+ method: params.method,
89
+ requestParams,
90
+ paramsForRun: params.paramsForRun,
91
+ context,
92
+ signal: params.signal
93
+ });
94
+ if (policyOutcome?.blocked) {
95
+ emitApprovalEvent(params.paramsForRun, {
96
+ phase: "resolved",
97
+ kind: context.kind,
98
+ status: "denied",
99
+ title: context.title,
100
+ ...context.eventDetails,
101
+ ...approvalEventScope(params.method, "denied"),
102
+ message: policyOutcome.reason
103
+ });
104
+ return buildApprovalResponse(params.method, context.requestParams, "denied");
105
+ }
87
106
  const requestResult = await requestPluginApproval({
88
107
  paramsForRun: params.paramsForRun,
89
108
  title: context.title,
@@ -198,6 +217,79 @@ function buildApprovalContext(params) {
198
217
  }
199
218
  };
200
219
  }
220
+ async function runOpenClawToolPolicyForApprovalRequest(params) {
221
+ const policyRequest = buildOpenClawToolPolicyRequest(params.method, params.requestParams);
222
+ if (!policyRequest) return;
223
+ const cwd = readString$1(params.requestParams, "cwd") ?? params.paramsForRun.workspaceDir;
224
+ const outcome = await runBeforeToolCallHook({
225
+ toolName: policyRequest.toolName,
226
+ params: policyRequest.params,
227
+ ...params.context.itemId ? { toolCallId: params.context.itemId } : {},
228
+ approvalMode: "report",
229
+ signal: params.signal,
230
+ ctx: {
231
+ ...params.paramsForRun.agentId ? { agentId: params.paramsForRun.agentId } : {},
232
+ ...params.paramsForRun.config ? { config: params.paramsForRun.config } : {},
233
+ ...cwd ? { cwd } : {},
234
+ ...params.paramsForRun.sessionKey ? { sessionKey: params.paramsForRun.sessionKey } : {},
235
+ ...params.paramsForRun.sessionId ? { sessionId: params.paramsForRun.sessionId } : {},
236
+ ...params.paramsForRun.runId ? { runId: params.paramsForRun.runId } : {},
237
+ ...params.paramsForRun.messageChannel || params.paramsForRun.messageProvider ? { channelId: params.paramsForRun.messageChannel ?? params.paramsForRun.messageProvider } : {}
238
+ }
239
+ });
240
+ if (outcome.blocked) return {
241
+ blocked: true,
242
+ reason: outcome.reason
243
+ };
244
+ if ("params" in outcome && toolPolicyParamsWereRewritten(policyRequest.params, outcome.params)) return {
245
+ blocked: true,
246
+ reason: "OpenClaw tool policy rewrote Codex app-server approval params; refusing original request."
247
+ };
248
+ }
249
+ function buildOpenClawToolPolicyRequest(method, requestParams) {
250
+ if (method === "item/commandExecution/requestApproval") {
251
+ const command = readPolicyCommand(requestParams);
252
+ return {
253
+ toolName: "bash",
254
+ params: {
255
+ ...command ? { command } : {},
256
+ ...readString$1(requestParams, "cwd") ? { cwd: readString$1(requestParams, "cwd") } : {},
257
+ approval: requestParams ?? {}
258
+ }
259
+ };
260
+ }
261
+ if (method === "item/fileChange/requestApproval") return {
262
+ toolName: "apply_patch",
263
+ params: requestParams ?? {}
264
+ };
265
+ if (method === "item/permissions/requestApproval") return {
266
+ toolName: "codex_permission_approval",
267
+ params: requestParams ?? {}
268
+ };
269
+ }
270
+ function toolPolicyParamsWereRewritten(original, candidate) {
271
+ if (candidate === original) return false;
272
+ const originalText = stableJsonText(original);
273
+ const candidateText = stableJsonText(candidate);
274
+ return !candidateText || candidateText !== originalText;
275
+ }
276
+ function stableJsonText(value) {
277
+ if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") return JSON.stringify(value);
278
+ if (Array.isArray(value)) {
279
+ const items = value.map((item) => stableJsonText(item));
280
+ return items.every((item) => item !== void 0) ? `[${items.join(",")}]` : void 0;
281
+ }
282
+ if (isPlainRecord(value)) {
283
+ const entries = Object.entries(value).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, item]) => {
284
+ const text = stableJsonText(item);
285
+ return text === void 0 ? void 0 : `${JSON.stringify(key)}:${text}`;
286
+ });
287
+ return entries.every((entry) => entry !== void 0) ? `{${entries.join(",")}}` : void 0;
288
+ }
289
+ }
290
+ function isPlainRecord(value) {
291
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
292
+ }
201
293
  function commandApprovalDecision(requestParams, outcome) {
202
294
  if (outcome === "cancelled") return commandRejectionDecision(requestParams, "cancel");
203
295
  if (outcome === "denied" || outcome === "unavailable") return commandRejectionDecision(requestParams, "decline");
@@ -452,13 +544,21 @@ function readDisplayCommandPreview(record) {
452
544
  if (actionCommand) return actionCommand;
453
545
  return readCommandPreview(record);
454
546
  }
455
- function readCommandActionsPreview(record) {
547
+ function readPolicyCommand(record) {
548
+ const command = record?.command;
549
+ if (typeof command === "string") return command;
550
+ if (Array.isArray(command) && command.every((part) => typeof part === "string")) return command.join(" ");
551
+ const actionCommands = readCommandActions(record);
552
+ if (actionCommands.length > 0) return actionCommands.join(" && ");
553
+ }
554
+ function readCommandActions(record) {
456
555
  const actions = record?.commandActions;
457
- if (!Array.isArray(actions)) return;
556
+ if (!Array.isArray(actions)) return [];
557
+ return actions.map((action) => isJsonObject(action) ? readString$1(action, "command") : void 0).filter((command) => Boolean(command));
558
+ }
559
+ function readCommandActionsPreview(record) {
458
560
  let source;
459
- for (const action of actions) {
460
- const command = isJsonObject(action) ? readString$1(action, "command") : void 0;
461
- if (!command) continue;
561
+ for (const command of readCommandActions(record)) {
462
562
  source = appendPreviewPart(source, command, " && ");
463
563
  if (source.clipped) break;
464
564
  }
@@ -333,7 +333,7 @@
333
333
  },
334
334
  "appServer.turnCompletionIdleTimeoutMs": {
335
335
  "label": "Turn Completion Idle Timeout",
336
- "help": "Maximum quiet time after a turn-scoped Codex app-server request before OpenClaw interrupts the turn while waiting for turn/completed.",
336
+ "help": "Maximum quiet time after Codex accepts a turn or after a turn-scoped app-server request before OpenClaw interrupts the turn while waiting for turn/completed.",
337
337
  "advanced": true
338
338
  },
339
339
  "appServer.approvalPolicy": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/codex",
3
- "version": "2026.5.14-beta.2",
3
+ "version": "2026.5.16-beta.2",
4
4
  "description": "OpenClaw Codex harness and model provider plugin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,10 +27,10 @@
27
27
  "minHostVersion": ">=2026.5.1-beta.1"
28
28
  },
29
29
  "compat": {
30
- "pluginApi": ">=2026.5.14-beta.2"
30
+ "pluginApi": ">=2026.5.16-beta.2"
31
31
  },
32
32
  "build": {
33
- "openclawVersion": "2026.5.14-beta.2"
33
+ "openclawVersion": "2026.5.16-beta.2"
34
34
  },
35
35
  "release": {
36
36
  "publishToClawHub": true,
@@ -45,7 +45,7 @@
45
45
  "openclaw.plugin.json"
46
46
  ],
47
47
  "peerDependencies": {
48
- "openclaw": ">=2026.5.14-beta.2"
48
+ "openclaw": ">=2026.5.16-beta.2"
49
49
  },
50
50
  "peerDependenciesMeta": {
51
51
  "openclaw": {