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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,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";
4
+ import { r as isCodexAppServerApprovalRequest } from "./client-CA7amCZ8.js";
5
5
  import { u as formatCodexUsageLimitErrorMessage } from "./command-formatters-BRW7_Nu7.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-BzY-GLGu.js";
9
- import { n as handleCodexAppServerElicitationRequest, r as handleCodexAppServerApprovalRequest, t as filterToolsForVisionInputs } from "./vision-tools-CyhFwJIY.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-BzY-GLGu.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",
@@ -369,7 +370,10 @@ function projectContextEngineAssemblyForCodex(params) {
369
370
  const prompt = params.prompt.trim();
370
371
  const contextMessages = dropDuplicateTrailingPrompt(params.assembledMessages, prompt);
371
372
  const maxRenderedContextChars = normalizeRenderedContextMaxChars(params.maxRenderedContextChars);
372
- const renderedContext = renderMessagesForCodexContext(contextMessages, { maxTextPartChars: resolveTextPartMaxChars(maxRenderedContextChars) });
373
+ const renderedContext = renderMessagesForCodexContext(contextMessages, {
374
+ maxTextPartChars: resolveTextPartMaxChars(maxRenderedContextChars),
375
+ toolPayloadMode: params.toolPayloadMode ?? "elide"
376
+ });
373
377
  const promptText = renderedContext ? [
374
378
  CONTEXT_HEADER,
375
379
  CONTEXT_SAFETY_NOTE,
@@ -440,10 +444,88 @@ function renderMessagePart(part, options) {
440
444
  const type = typeof record.type === "string" ? record.type : void 0;
441
445
  if (type === "text") return typeof record.text === "string" ? truncateText(record.text.trim(), options.maxTextPartChars) : "";
442
446
  if (type === "image") return "[image omitted]";
443
- if (type === "toolCall" || type === "tool_use") return `tool call${typeof record.name === "string" ? `: ${record.name}` : ""} [input omitted]`;
444
- 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
+ }
445
457
  return `[${type ?? "non-text"} content omitted]`;
446
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
+ }
447
529
  function extractMessageText(message) {
448
530
  if (!hasMessageContent(message)) return "";
449
531
  if (typeof message.content === "string") return message.content;
@@ -708,7 +790,7 @@ const CODEX_CODE_MODE_THREAD_CONFIG = {
708
790
  const CODEX_LIGHTWEIGHT_CONTEXT_THREAD_CONFIG = { project_doc_max_bytes: 0 };
709
791
  async function startOrResumeThread(params) {
710
792
  const dynamicToolsFingerprint = fingerprintDynamicTools(params.dynamicTools);
711
- const contextEngineBinding = buildContextEngineBinding(params.params);
793
+ const contextEngineBinding = buildContextEngineBinding(params.params, params.contextEngineProjection);
712
794
  const userMcpServersConfigPatch = buildCodexUserMcpServersThreadConfigPatch(params.params.config, { agentId: params.agentId ?? params.params.agentId });
713
795
  const userMcpServersFingerprint = fingerprintUserMcpServersConfigPatch(userMcpServersConfigPatch);
714
796
  let binding = await readCodexAppServerBinding(params.params.sessionFile, {
@@ -724,7 +806,13 @@ async function startOrResumeThread(params) {
724
806
  embeddedAgentLog.debug("codex app-server context-engine binding changed; starting a new thread", {
725
807
  threadId: binding.threadId,
726
808
  engineId: contextEngineBinding?.engineId,
727
- 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
728
816
  });
729
817
  await clearCodexAppServerBinding(params.params.sessionFile);
730
818
  binding = void 0;
@@ -820,6 +908,15 @@ async function startOrResumeThread(params) {
820
908
  agentDir: params.params.agentDir,
821
909
  config: params.params.config
822
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
+ });
823
920
  return {
824
921
  ...binding,
825
922
  threadId: response.thread.id,
@@ -859,25 +956,36 @@ async function startOrResumeThread(params) {
859
956
  });
860
957
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
861
958
  const nextMcpServersFingerprint = params.mcpServersFingerprintEvaluated === true ? params.mcpServersFingerprint : void 0;
862
- if (!preserveExistingBinding) await writeCodexAppServerBinding(params.params.sessionFile, {
863
- threadId: response.thread.id,
864
- cwd: params.cwd,
865
- authProfileId: params.params.authProfileId,
866
- model: response.model ?? params.params.modelId,
867
- modelProvider: response.modelProvider ?? modelProvider,
868
- dynamicToolsFingerprint,
869
- userMcpServersFingerprint,
870
- mcpServersFingerprint: nextMcpServersFingerprint,
871
- pluginAppsFingerprint: pluginThreadConfig?.fingerprint,
872
- pluginAppsInputFingerprint: pluginThreadConfig?.inputFingerprint,
873
- pluginAppPolicyContext: pluginThreadConfig?.policyContext,
874
- contextEngine: contextEngineBinding,
875
- createdAt
876
- }, {
877
- authProfileStore: params.params.authProfileStore,
878
- agentDir: params.params.agentDir,
879
- config: params.params.config
880
- });
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
+ }
881
989
  return {
882
990
  schemaVersion: 1,
883
991
  threadId: response.thread.id,
@@ -901,7 +1009,7 @@ async function startOrResumeThread(params) {
901
1009
  }
902
1010
  };
903
1011
  }
904
- function buildContextEngineBinding(params) {
1012
+ function buildContextEngineBinding(params, projection) {
905
1013
  const contextEngine = isActiveHarnessContextEngine(params.contextEngine) ? params.contextEngine : void 0;
906
1014
  const engineId = contextEngine?.info?.id?.trim();
907
1015
  if (!contextEngine || !engineId) return;
@@ -920,11 +1028,24 @@ function buildContextEngineBinding(params) {
920
1028
  contextTokenBudget: params.contextTokenBudget,
921
1029
  reserveTokens: resolveCodexContextEngineProjectionReserveTokens({ config: params.config })
922
1030
  })
923
- })
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
924
1041
  };
925
1042
  }
926
1043
  function isContextEngineBindingCompatible(previous, next) {
927
- 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;
928
1049
  }
929
1050
  function resolveContextEngineCitationsMode(config) {
930
1051
  const rootConfig = isUnknownRecord(config) ? config : void 0;
@@ -1139,4 +1260,4 @@ function resolveReasoningEffort(thinkLevel, modelId) {
1139
1260
  return null;
1140
1261
  }
1141
1262
  //#endregion
1142
- 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
2
  import { r as formatCodexDisplayText } from "./command-formatters-BRW7_Nu7.js";
3
- import { callGatewayTool, embeddedAgentLog, formatApprovalDisplayPath } from "openclaw/plugin-sdk/agent-harness-runtime";
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/codex",
3
- "version": "2026.5.16-beta.1",
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.16-beta.1"
30
+ "pluginApi": ">=2026.5.16-beta.2"
31
31
  },
32
32
  "build": {
33
- "openclawVersion": "2026.5.16-beta.1"
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.16-beta.1"
48
+ "openclaw": ">=2026.5.16-beta.2"
49
49
  },
50
50
  "peerDependenciesMeta": {
51
51
  "openclaw": {