@openclaw/codex 2026.7.2-beta.5 → 2026.7.2-beta.7

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 (42) hide show
  1. package/dist/{app-server-policy-BmDgseo_.js → app-server-policy-BSaO2JIT.js} +1 -1
  2. package/dist/{attempt-notifications-CMR2_fmR.js → attempt-notifications-AP-a-Q5k.js} +1 -1
  3. package/dist/{bounded-turn-FEbUXoYT.js → bounded-turn-D2ZAgZVz.js} +29 -22
  4. package/dist/{capabilities-BHRSI6Cn.js → capabilities-BFDTVYr4.js} +1 -1
  5. package/dist/cli-metadata.js +1 -1
  6. package/dist/{command-formatters-ico4ZFnk.js → command-formatters-C336eRVS.js} +2 -2
  7. package/dist/{command-handlers-CRmnwI2N.js → command-handlers-DAHUSry9.js} +12 -12
  8. package/dist/{compact-dEN49UH6.js → compact-D_uvHurS.js} +5 -5
  9. package/dist/{computer-use-BjGylO-E.js → computer-use-CYEc8U3w.js} +111 -113
  10. package/dist/{conversation-control-DE7d9DOj.js → conversation-control-xsIeXbo4.js} +6 -6
  11. package/dist/doctor-contract-api.js +1 -1
  12. package/dist/{dynamic-tools-LIt9ojep.js → dynamic-tools-D2gYkSBO.js} +438 -51
  13. package/dist/effective-mcp-catalog-Bbd98Inw.js +114 -0
  14. package/dist/{event-projector-usage-tvgb1NCX.js → event-projector-usage-Xp4AlR2k.js} +20 -3
  15. package/dist/harness.js +13 -9
  16. package/dist/index.js +131 -108
  17. package/dist/media-understanding-provider.js +1 -1
  18. package/dist/{models-BA01NEez.js → models-BBMKU4jA.js} +2 -2
  19. package/dist/{notification-correlation-Bj_Ak_jI.js → notification-correlation-CU6_AnOb.js} +3 -3
  20. package/dist/{plugin-app-cache-key-DSXX-rXO.js → plugin-app-cache-key-DztPafOA.js} +132 -39
  21. package/dist/{rate-limits-S_PXs0ul.js → rate-limits-CU-gVCCS.js} +1 -1
  22. package/dist/{request-CXpPennK.js → request-qKh331yu.js} +3 -3
  23. package/dist/{run-attempt-C5GTPJOE.js → run-attempt-CY9WlDLc.js} +677 -199
  24. package/dist/{runtime-artifact-C2ITXdhM.js → runtime-artifact-CmtG_t1L.js} +90 -24
  25. package/dist/{sandbox-guard-D1Wky__S.js → sandbox-guard-NuhpXmPB.js} +4 -0
  26. package/dist/{session-binding-DlVQ-Pxs.js → session-binding-BXpo9ymA.js} +60 -7
  27. package/dist/{session-catalog-CP2oCcEb.js → session-catalog-DyOgR4WH.js} +268 -44
  28. package/dist/{session-cli-CqZ0Fp2a.js → session-cli-2PZaFLRh.js} +1 -1
  29. package/dist/{session-upstream-marker-QE-m5QFG.js → session-upstream-marker-B6U7tLw5.js} +1 -1
  30. package/dist/{settled-turn-finalizer-CA_2QXIE.js → settled-turn-finalizer-CXY2Z9dT.js} +19 -6
  31. package/dist/{shared-client-BVKE40c-.js → shared-client-DTbvH-XV.js} +166 -49
  32. package/dist/{side-question-CO12sHxo.js → side-question-_ulBk1AL.js} +10 -10
  33. package/dist/{thread-lifecycle-DRg_FdzC.js → thread-lifecycle-DF53ogiA.js} +968 -214
  34. package/dist/{protocol-validators-Dm4eXZmt.js → transcript-mirror-DzsdNCf5.js} +589 -2
  35. package/dist/{upstream-session-fork-_Vrz4WJr.js → upstream-session-fork-Dy4Xvuoj.js} +3 -3
  36. package/dist/{usage-UpVbdX5G.js → usage-CQ6GhD5-.js} +3 -3
  37. package/dist/{web-search-provider.runtime-CaQMYDbp.js → web-search-provider.runtime-CCFhg2z5.js} +3 -3
  38. package/package.json +6 -7
  39. package/dist/attempt-client-cleanup-Ia52yRWc.js +0 -127
  40. package/dist/realtime-voice-api-BPcA1uN9.js +0 -494
  41. package/dist/realtime-voice-api.js +0 -2
  42. package/dist/transcript-mirror-uKA-A4tB.js +0 -550
@@ -1,10 +1,11 @@
1
- import { V as isJsonObject, l as releaseLeasedSharedCodexAppServerClient, q as resolveCodexGatewayTimeoutWithGraceMs, z as CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE } from "./shared-client-BVKE40c-.js";
2
- import { T as readCodexPluginConfig } from "./session-binding-DlVQ-Pxs.js";
3
- import { D as isForcedPrivateQaCodexRuntime, E as filterCodexDynamicToolsWithOpenClawShell, O as isSystemAgentOnlyCodexDynamicToolAllowlist, T as filterCodexDynamicTools, et as readItem, h as resolveCodexWebSearchPlan, i as invalidInlineImageText, k as normalizeCodexDynamicToolName, o as sanitizeInlineImageDataUrl, st as readString$2, tt as readItemString } from "./thread-lifecycle-DRg_FdzC.js";
4
- import { l as readCodexTurn } from "./protocol-validators-Dm4eXZmt.js";
5
- import { r as formatCodexDisplayText } from "./command-formatters-ico4ZFnk.js";
6
- import { a as resolveCodexNodeExecToolOverrides, i as resolveCodexNativeExecutionPolicy } from "./sandbox-guard-D1Wky__S.js";
7
- import { n as readCodexNotificationThreadId, r as readCodexNotificationTurnId } from "./notification-correlation-Bj_Ak_jI.js";
1
+ import { H as CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE, W as isJsonObject, X as resolveCodexGatewayTimeoutWithGraceMs, l as releaseLeasedSharedCodexAppServerClient } from "./shared-client-DTbvH-XV.js";
2
+ import { O as readCodexPluginConfig } from "./session-binding-BXpo9ymA.js";
3
+ import { D as isForcedPrivateQaCodexRuntime, E as filterCodexDynamicToolsWithOpenClawShell, O as isSystemAgentOnlyCodexDynamicToolAllowlist, T as filterCodexDynamicTools, ct as readString$2, g as resolveCodexWebSearchPlan, i as invalidInlineImageText, k as normalizeCodexDynamicToolName, nt as readItemString, o as sanitizeInlineImageDataUrl, tt as readItem } from "./thread-lifecycle-DF53ogiA.js";
4
+ import { S as readCodexTurn } from "./transcript-mirror-DzsdNCf5.js";
5
+ import { r as formatCodexDisplayText } from "./command-formatters-C336eRVS.js";
6
+ import { a as resolveCodexNodeExecToolOverrides, i as resolveCodexNativeExecutionPolicy } from "./sandbox-guard-NuhpXmPB.js";
7
+ import { n as readCodexNotificationThreadId, r as readCodexNotificationTurnId } from "./notification-correlation-CU6_AnOb.js";
8
+ import path from "node:path";
8
9
  import { addTimerTimeoutGraceMs, asDateTimestampMs, finiteSecondsToTimerSafeMilliseconds, parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
9
10
  import { HEARTBEAT_RESPONSE_TOOL_NAME, buildAgentHookContextChannelFields, buildEmbeddedAttemptToolRunContext, callGatewayTool, consumeAdjustedParamsForToolCall, consumePreExecutionBlockedToolCall, createAgentToolResultMiddlewareRunner, createCodexAppServerToolResultExtensionRunner, embeddedAgentLog, extractMessagingToolSend, extractMessagingToolSendResult, extractToolResultMediaArtifact, filterProviderNormalizableTools, filterToolResultMediaUrls, finalizeToolTerminalPresentation, formatApprovalDisplayPath, formatToolExecutionErrorMessage, getBeforeToolCallFailureDisposition, getChannelAgentToolMeta, getPluginToolMeta, hasNativeHookRelayInvocation, invokeNativeHookRelay, isDeliveredMessageToolOnlySourceReplyResult, isDeliveredMessagingToolResult, isHostScopedAgentToolActive, isMessagingTool, isMessagingToolSendAction, isReplaySafeToolCall, isSubagentSessionKey, isToolResultError, isToolWrappedWithBeforeToolCallHook, normalizeAgentRuntimeTools, normalizeHeartbeatToolResponse, projectRuntimeToolInputSchema, registerNativeHookRelay, resolveAttemptSpawnWorkspaceDir, resolveModelAuthMode, resolveNativeHookRelayDeferredToolApproval, resolveToolExecutionErrorKind, resolveToolResultFailureKind, runAgentHarnessAfterToolCallHook, runBeforeToolCallHook, sanitizeToolResult, setBeforeToolCallDiagnosticsEnabled, supportsModelTools, wrapToolWithBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
10
11
  import { createHash } from "node:crypto";
@@ -14,6 +15,9 @@ import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-util
14
15
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
15
16
  import { emitTrustedDiagnosticEvent, hasPendingInternalDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
16
17
  import { isToolAllowed } from "openclaw/plugin-sdk/sandbox";
18
+ import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
19
+ import { root } from "openclaw/plugin-sdk/file-access-runtime";
20
+ import { getMediaDir } from "openclaw/plugin-sdk/media-runtime";
17
21
  import { isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
18
22
  import { normalizeOpenAIToolSchemas } from "openclaw/plugin-sdk/provider-tools";
19
23
  //#region extensions/codex/src/app-server/event-projector-items.ts
@@ -108,7 +112,7 @@ function shouldSynthesizeToolProgressForItem(item) {
108
112
  }
109
113
  }
110
114
  function shouldRecordNativeToolTranscript(item) {
111
- return shouldSynthesizeToolProgressForItem(item) && item.type !== "webSearch";
115
+ return shouldSynthesizeToolProgressForItem(item);
112
116
  }
113
117
  function isMutatingNativeToolItem(item) {
114
118
  if (item.type === "commandExecution") return true;
@@ -604,6 +608,19 @@ const CODEX_NATIVE_HOOK_RELAY_COMMAND_MAX_PARENT_MARGIN_MS = 1e3;
604
608
  const CODEX_NATIVE_HOOK_RELAY_DEFAULT_TIMEOUT_SEC = 10;
605
609
  const CODEX_NATIVE_HOOK_RELAY_UNREGISTER_GRACE_MS = 1e4;
606
610
  const CODEX_NATIVE_HOOK_RELAY_UNREGISTER_EXTRA_GRACE_MS = 5e3;
611
+ const CODEX_HOOK_MATCHER_NAMES_BY_TOOL_ID = {
612
+ exec: [
613
+ "Bash",
614
+ "exec",
615
+ "exec_command"
616
+ ],
617
+ apply_patch: [
618
+ "apply_patch",
619
+ "Write",
620
+ "Edit"
621
+ ],
622
+ spawn_agent: ["spawn_agent", "Agent"]
623
+ };
607
624
  /** Defers relay unregister so late native hook subprocesses can still resolve. */
608
625
  function scheduleCodexNativeHookRelayUnregister(params) {
609
626
  let pending;
@@ -662,6 +679,7 @@ function createCodexNativeHookRelay(params) {
662
679
  runId: params.runId,
663
680
  ...params.channelId ? { channelId: params.channelId } : {},
664
681
  ...params.requester ? { requester: params.requester } : {},
682
+ ...params.approvalContext ? { approvalContext: params.approvalContext } : {},
665
683
  allowedEvents: params.events,
666
684
  preToolUseLoopDetection: params.loopDetectionPreToolUseRelay,
667
685
  ttlMs: resolveCodexNativeHookRelayTtlMs({
@@ -730,18 +748,23 @@ function buildCodexNativeHookRelayConfig(params) {
730
748
  }
731
749
  const timeout = normalizeHookTimeoutSec(params.hookTimeoutSec);
732
750
  const command = params.relay.commandForEvent(event, { timeoutMs: resolveCodexNativeHookRelayCommandTimeoutMs(timeout) });
733
- config[`hooks.${codexEvent}`] = [{ hooks: [{
734
- type: "command",
735
- command,
736
- timeout,
737
- async: false,
738
- statusMessage: "OpenClaw native hook relay"
739
- }] }];
751
+ const matcher = selectedNoopPreToolUse ? void 0 : buildCodexNativeToolMatcher(params.relay.toolMatcherForEvent(event));
752
+ config[`hooks.${codexEvent}`] = [{
753
+ ...matcher ? { matcher } : {},
754
+ hooks: [{
755
+ type: "command",
756
+ command,
757
+ timeout,
758
+ async: false,
759
+ statusMessage: "OpenClaw native hook relay"
760
+ }]
761
+ }];
740
762
  const state = {
741
763
  enabled: true,
742
764
  trusted_hash: codexCommandHookTrustedHash({
743
765
  event,
744
766
  command,
767
+ matcher,
745
768
  timeout,
746
769
  statusMessage: "OpenClaw native hook relay"
747
770
  })
@@ -769,9 +792,26 @@ function resolveCodexNativeHookRelayCommandTimeoutMs(hookTimeoutSec) {
769
792
  const parentMarginMs = Math.min(CODEX_NATIVE_HOOK_RELAY_COMMAND_MAX_PARENT_MARGIN_MS, Math.max(CODEX_NATIVE_HOOK_RELAY_COMMAND_MIN_PARENT_MARGIN_MS, Math.floor(parentTimeoutMs / 5)));
770
793
  return Math.max(1, parentTimeoutMs - parentMarginMs);
771
794
  }
795
+ function buildCodexNativeToolMatcher(toolNames) {
796
+ if (toolNames === void 0) return;
797
+ if (toolNames.length === 0) throw new TypeError("Codex native hook matcher requires at least one tool name");
798
+ const nativeNames = /* @__PURE__ */ new Set();
799
+ let hasCustomToolName = false;
800
+ for (const toolName of toolNames) {
801
+ const canonicalToolName = toolName.trim();
802
+ if (!canonicalToolName || canonicalToolName === "*") throw new TypeError("Codex native hook matcher requires canonical OpenClaw tool ids");
803
+ const nativeAliases = CODEX_HOOK_MATCHER_NAMES_BY_TOOL_ID[canonicalToolName];
804
+ if (!nativeAliases) hasCustomToolName = true;
805
+ for (const nativeName of nativeAliases ?? [canonicalToolName]) nativeNames.add(nativeName);
806
+ }
807
+ const sortedNames = Array.from(nativeNames).toSorted();
808
+ if (!hasCustomToolName && sortedNames.every((toolName) => /^[A-Za-z0-9_]+$/.test(toolName))) return sortedNames.join("|");
809
+ return `(?i)^(?:${sortedNames.map((toolName) => toolName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})$`;
810
+ }
772
811
  function codexCommandHookTrustedHash(params) {
773
812
  const identity = {
774
813
  event_name: CODEX_HOOK_KEY_LABEL_BY_NATIVE_EVENT[params.event],
814
+ ...params.matcher ? { matcher: params.matcher } : {},
775
815
  hooks: [{
776
816
  async: false,
777
817
  command: params.command,
@@ -984,6 +1024,322 @@ var CodexNativeToolLifecycleProjector = class {
984
1024
  }
985
1025
  };
986
1026
  //#endregion
1027
+ //#region extensions/codex/src/app-server/remote-workspace-path.ts
1028
+ /** Projects a gateway workspace path into the remote Codex execution workspace. */
1029
+ function mapCodexAppServerRemoteWorkspacePath(params) {
1030
+ if (!params.remoteWorkspaceRoot) return params.value;
1031
+ const localRoot = normalizeWorkspaceMatchPath(params.localWorkspaceRoot);
1032
+ const remoteRoot = normalizeWorkspaceMatchPath(params.remoteWorkspaceRoot);
1033
+ const normalizedValue = normalizeWorkspaceMatchPath(params.value);
1034
+ if (!localRoot || !remoteRoot) throw new Error("Codex remoteWorkspaceRoot requires non-empty workspace roots.");
1035
+ if (normalizedValue === localRoot) return remoteRoot;
1036
+ const prefix = `${localRoot}/`;
1037
+ if (!normalizedValue.startsWith(prefix)) throw new Error(`Codex remoteWorkspaceRoot is configured but cwd ${params.value} is outside OpenClaw workspace root ${params.localWorkspaceRoot}; refusing to send a gateway-local cwd to the remote Codex app-server.`);
1038
+ return joinRemoteWorkspacePath(remoteRoot, normalizedValue.slice(prefix.length));
1039
+ }
1040
+ /** Maps a remote workspace artifact back into the corresponding gateway workspace. */
1041
+ function mapCodexAppServerLocalWorkspacePath(params) {
1042
+ if (!params.remoteWorkspaceRoot) return params.value;
1043
+ const localRoot = normalizeWorkspaceMatchPath(params.localWorkspaceRoot);
1044
+ const remoteRoot = normalizeWorkspaceMatchPath(params.remoteWorkspaceRoot);
1045
+ if (!localRoot || !remoteRoot) throw new Error("Codex remoteWorkspaceRoot requires non-empty workspace roots.");
1046
+ const normalizedValue = normalizeWorkspaceMatchPath(params.value);
1047
+ if (!normalizedValue || isCodexPassThroughMediaSource(normalizedValue)) return params.value;
1048
+ const usesWindowsPaths = /^[a-z]:\//iu.test(remoteRoot) || remoteRoot.startsWith("//");
1049
+ const matchValue = usesWindowsPaths ? normalizedValue.toLowerCase() : normalizedValue;
1050
+ const matchRoot = usesWindowsPaths ? remoteRoot.toLowerCase() : remoteRoot;
1051
+ if (matchValue === matchRoot) return params.localWorkspaceRoot;
1052
+ const prefix = matchRoot.endsWith("/") ? matchRoot : `${matchRoot}/`;
1053
+ const isRemoteWorkspacePath = matchValue.startsWith(prefix);
1054
+ if (!isRemoteWorkspacePath && isAbsoluteWorkspacePath(normalizedValue)) throw new Error(`Codex remote workspace artifact ${params.value} is outside ${params.remoteWorkspaceRoot}.`);
1055
+ const suffixSegments = (isRemoteWorkspacePath ? normalizedValue.slice(prefix.length) : normalizedValue).split("/");
1056
+ if (suffixSegments.some((segment) => segment === "..")) throw new Error(`Codex remote workspace artifact ${params.value} must stay inside ${params.remoteWorkspaceRoot}.`);
1057
+ return path.join(params.localWorkspaceRoot, ...suffixSegments.filter((segment) => segment !== "."));
1058
+ }
1059
+ function normalizeWorkspaceMatchPath(value) {
1060
+ const normalized = value.replace(/\\/gu, "/");
1061
+ if (/^[a-z]:\/$/iu.test(normalized)) return normalized;
1062
+ return normalized.length > 1 ? normalized.replace(/[\\/]+$/u, "") : normalized;
1063
+ }
1064
+ /** Keeps remote URLs and opaque managed media references out of workspace path mapping. */
1065
+ function isCodexPassThroughMediaSource(value) {
1066
+ return /^(?:https?|mxc|buffer|media):\/\//iu.test(value) || /^data:/iu.test(value);
1067
+ }
1068
+ function isAbsoluteWorkspacePath(value) {
1069
+ return value.startsWith("/") || /^[a-z]:\//iu.test(value) || /^[a-z][a-z0-9+.-]*:/iu.test(value);
1070
+ }
1071
+ function joinRemoteWorkspacePath(remoteRoot, suffix) {
1072
+ return remoteRoot.endsWith("/") ? `${remoteRoot}${suffix}` : `${remoteRoot}/${suffix}`;
1073
+ }
1074
+ //#endregion
1075
+ //#region extensions/codex/src/app-server/remote-workspace-media.ts
1076
+ const REMOTE_WORKSPACE_MEDIA_TIMEOUT_MS = 6e4;
1077
+ const REMOTE_WORKSPACE_MEDIA_MAX_BYTES = 64 * 1024 * 1024;
1078
+ const REMOTE_WORKSPACE_MEDIA_MAX_ATTACHMENTS = 16;
1079
+ const CODEX_REMOTE_MEDIA_CHUNK_BYTES = 512 * 1024;
1080
+ const CODEX_REMOTE_COMMAND_DEFAULT_OUTPUT_BYTES = 1024 * 1024;
1081
+ const CODEX_BOUNDED_REMOTE_FILE_READER = [
1082
+ "try{",
1083
+ "const fs=require(\"node:fs\");",
1084
+ "const path=require(\"node:path\");",
1085
+ "const file=process.argv[1];",
1086
+ "const max=Number(process.argv[2]);",
1087
+ "const offset=Number(process.argv[3]);",
1088
+ "const chunk=Number(process.argv[4]);",
1089
+ "const workspace=process.argv[5];",
1090
+ "if(!Number.isSafeInteger(max)||max<0)throw Error(\"invalid media byte limit\");",
1091
+ "if(!Number.isSafeInteger(offset)||offset<0||!Number.isSafeInteger(chunk)||chunk<=0)throw Error(\"invalid media chunk\");",
1092
+ "if(fs.lstatSync(file).isSymbolicLink())throw Error(\"symbolic links are not allowed\");",
1093
+ "const noFollow=fs.constants.O_NOFOLLOW??0;",
1094
+ "const fd=fs.openSync(file,fs.constants.O_RDONLY|noFollow);",
1095
+ "try{",
1096
+ "const before=fs.fstatSync(fd);",
1097
+ "if(!before.isFile())throw Error(\"not a regular file\");",
1098
+ "if(workspace){",
1099
+ "const descriptor=process.platform===\"linux\"?fs.realpathSync(`/proc/self/fd/${fd}`):fs.realpathSync(file);",
1100
+ "const relative=path.relative(fs.realpathSync(workspace),descriptor);",
1101
+ "if(!relative||relative===\"..\"||relative.startsWith(`..${path.sep}`)||path.isAbsolute(relative))throw Error(\"file escapes remote workspace\");",
1102
+ "const verified=fs.statSync(descriptor);",
1103
+ "if(verified.dev!==before.dev||verified.ino!==before.ino)throw Error(\"file changed while being opened\");",
1104
+ "}",
1105
+ "if(before.size>max)throw Error(`file exceeds limit of ${max} bytes`);",
1106
+ "if(offset>before.size)throw Error(\"file changed while being read\");",
1107
+ "const expected=Math.min(chunk,before.size-offset);",
1108
+ "const buffer=Buffer.allocUnsafe(expected);",
1109
+ "let total=0;",
1110
+ "while(total<buffer.length){",
1111
+ "const count=fs.readSync(fd,buffer,total,buffer.length-total,offset+total);",
1112
+ "if(count===0)break;total+=count;",
1113
+ "}",
1114
+ "if(total!==expected)throw Error(\"file changed while being read\");",
1115
+ "const after=fs.fstatSync(fd);",
1116
+ "const revision=stat=>[stat.dev,stat.ino,stat.size,stat.mtimeMs,stat.ctimeMs].join(\":\");",
1117
+ "if(!after.isFile()||revision(after)!==revision(before))throw Error(\"file changed while being read\");",
1118
+ "process.stdout.write(JSON.stringify({dataBase64:buffer.toString(\"base64\"),size:before.size,revision:revision(before)}));",
1119
+ "}finally{fs.closeSync(fd)}",
1120
+ "}catch(error){process.stderr.write(error instanceof Error?error.message:String(error));process.exitCode=1}"
1121
+ ].join("");
1122
+ const MESSAGE_MEDIA_KEYS = [
1123
+ "media",
1124
+ "mediaUrl",
1125
+ "media_url",
1126
+ "path",
1127
+ "filePath",
1128
+ "fileUrl",
1129
+ "imageUrl",
1130
+ "image_url"
1131
+ ];
1132
+ const MESSAGE_MEDIA_ARRAY_KEYS = [
1133
+ "mediaUrls",
1134
+ "media_urls",
1135
+ "imageUrls",
1136
+ "image_urls"
1137
+ ];
1138
+ const ATTACHMENT_MEDIA_KEYS = [
1139
+ "media",
1140
+ "mediaUrl",
1141
+ "path",
1142
+ "filePath",
1143
+ "fileUrl",
1144
+ "url"
1145
+ ];
1146
+ /** Reads actual remote bytes with a cap enforced by Codex before transport. */
1147
+ async function readBoundedCodexRemoteWorkspaceFile(params) {
1148
+ if (!Number.isSafeInteger(params.maxBytes) || params.maxBytes < 0) throw new Error("Codex remote workspace upload requires a valid media byte limit.");
1149
+ params.signal?.throwIfAborted();
1150
+ const chunks = [];
1151
+ let offset = 0;
1152
+ let expectedSize;
1153
+ let expectedRevision;
1154
+ const startedAt = Date.now();
1155
+ do {
1156
+ params.signal?.throwIfAborted();
1157
+ const timeoutMs = params.timeoutMs === void 0 ? void 0 : params.timeoutMs - (Date.now() - startedAt);
1158
+ if (timeoutMs !== void 0 && timeoutMs <= 0) throw new Error("Codex remote workspace file transfer timed out.");
1159
+ let response;
1160
+ try {
1161
+ response = await params.client.request("command/exec", {
1162
+ command: [
1163
+ "node",
1164
+ "-e",
1165
+ CODEX_BOUNDED_REMOTE_FILE_READER,
1166
+ "--",
1167
+ params.path,
1168
+ String(params.maxBytes),
1169
+ String(offset),
1170
+ String(CODEX_REMOTE_MEDIA_CHUNK_BYTES),
1171
+ ...params.workspaceRoot ? [params.workspaceRoot] : []
1172
+ ],
1173
+ env: {
1174
+ NODE_OPTIONS: null,
1175
+ NODE_PATH: null
1176
+ },
1177
+ ...timeoutMs === void 0 ? {} : { timeoutMs }
1178
+ }, {
1179
+ signal: params.signal,
1180
+ timeoutMs
1181
+ });
1182
+ } catch (error) {
1183
+ if (error instanceof Error && /failed to spawn|executable.*not found|\bENOENT\b/iu.test(error.message)) throw new Error("Codex remote workspace file transfer requires Node.js on the remote app-server host.", { cause: error });
1184
+ throw error;
1185
+ }
1186
+ if (!response || response.exitCode !== 0) {
1187
+ const detail = typeof response?.stderr === "string" ? response.stderr.trim() : "";
1188
+ throw new Error(`Codex remote workspace artifact could not be read: ${params.path}${detail ? `: ${detail}` : ""}`);
1189
+ }
1190
+ if (typeof response.stdout !== "string" || response.stdout.length > CODEX_REMOTE_COMMAND_DEFAULT_OUTPUT_BYTES) throw new Error("Codex remote workspace artifact exceeded the native command output cap.");
1191
+ let payload;
1192
+ try {
1193
+ payload = JSON.parse(response.stdout);
1194
+ } catch {
1195
+ throw new Error("Codex remote workspace artifact returned invalid chunk data.");
1196
+ }
1197
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) throw new Error("Codex remote workspace artifact returned invalid chunk data.");
1198
+ const chunk = payload;
1199
+ if (typeof chunk.dataBase64 !== "string" || !Number.isSafeInteger(chunk.size) || chunk.size < 0 || chunk.size > params.maxBytes || typeof chunk.revision !== "string" || !chunk.revision) throw new Error("Codex remote workspace artifact returned invalid or oversized chunk data.");
1200
+ if (expectedSize === void 0) {
1201
+ expectedSize = chunk.size;
1202
+ expectedRevision = chunk.revision;
1203
+ }
1204
+ if (chunk.size !== expectedSize || chunk.revision !== expectedRevision) throw new Error("Codex remote workspace artifact changed during chunked transfer.");
1205
+ const remainingBytes = expectedSize - offset;
1206
+ const expectedChunkBytes = Math.min(CODEX_REMOTE_MEDIA_CHUNK_BYTES, remainingBytes);
1207
+ if (chunk.dataBase64.length > Math.ceil(expectedChunkBytes / 3) * 4) throw new Error("Codex remote workspace artifact returned oversized chunk data.");
1208
+ const buffer = Buffer.from(chunk.dataBase64, "base64");
1209
+ if (buffer.byteLength !== expectedChunkBytes || buffer.toString("base64") !== chunk.dataBase64) throw new Error("Codex remote workspace artifact returned invalid chunk data.");
1210
+ chunks.push(buffer);
1211
+ offset += buffer.byteLength;
1212
+ } while (offset < (expectedSize ?? 0));
1213
+ return { dataBase64: Buffer.concat(chunks, offset).toString("base64") };
1214
+ }
1215
+ /** Stages authoritative bounded remote bytes into immutable Gateway-owned media. */
1216
+ async function prepareCodexRemoteWorkspaceMessageMedia(params) {
1217
+ const { localWorkspaceRoot, remoteWorkspaceRoot } = params;
1218
+ if (!localWorkspaceRoot || !remoteWorkspaceRoot) return params.args;
1219
+ const remotePathsByLocalPath = /* @__PURE__ */ new Map();
1220
+ const gatewayManagedPaths = /* @__PURE__ */ new Set();
1221
+ const gatewayMediaRoot = getMediaDir();
1222
+ let attachmentEntries = 0;
1223
+ const mapMediaPath = (value) => {
1224
+ if (typeof value !== "string") return value;
1225
+ if (isGatewayManagedMediaPath(value, gatewayMediaRoot)) {
1226
+ attachmentEntries += 1;
1227
+ gatewayManagedPaths.add(value);
1228
+ return value;
1229
+ }
1230
+ const mapped = mapCodexAppServerLocalWorkspacePath({
1231
+ value,
1232
+ localWorkspaceRoot,
1233
+ remoteWorkspaceRoot
1234
+ });
1235
+ if (value.trim() && !isCodexPassThroughMediaSource(value)) {
1236
+ attachmentEntries += 1;
1237
+ remotePathsByLocalPath.set(mapped, mapCodexAppServerRemoteWorkspacePath({
1238
+ value: mapped,
1239
+ localWorkspaceRoot,
1240
+ remoteWorkspaceRoot
1241
+ }));
1242
+ }
1243
+ return mapped;
1244
+ };
1245
+ let mappedArgs = params.args;
1246
+ const setMappedValue = (key, value) => {
1247
+ if (value === params.args[key]) return;
1248
+ if (mappedArgs === params.args) mappedArgs = { ...params.args };
1249
+ mappedArgs[key] = value;
1250
+ };
1251
+ for (const key of MESSAGE_MEDIA_KEYS) setMappedValue(key, mapMediaPath(params.args[key]));
1252
+ for (const key of MESSAGE_MEDIA_ARRAY_KEYS) {
1253
+ const value = params.args[key];
1254
+ if (Array.isArray(value)) {
1255
+ const mapped = value.map(mapMediaPath);
1256
+ if (mapped.some((entry, index) => entry !== value[index])) setMappedValue(key, mapped);
1257
+ }
1258
+ }
1259
+ if (Array.isArray(params.args.attachments)) {
1260
+ const attachments = params.args.attachments;
1261
+ const mapped = attachments.map((attachment) => {
1262
+ if (!attachment || typeof attachment !== "object" || Array.isArray(attachment)) return attachment;
1263
+ const record = attachment;
1264
+ let mappedAttachment = record;
1265
+ for (const key of ATTACHMENT_MEDIA_KEYS) {
1266
+ const value = mapMediaPath(record[key]);
1267
+ if (value !== record[key]) {
1268
+ if (mappedAttachment === record) mappedAttachment = { ...record };
1269
+ mappedAttachment[key] = value;
1270
+ }
1271
+ }
1272
+ return mappedAttachment;
1273
+ });
1274
+ if (mapped.some((attachment, index) => attachment !== attachments[index])) setMappedValue("attachments", mapped);
1275
+ }
1276
+ if (attachmentEntries > REMOTE_WORKSPACE_MEDIA_MAX_ATTACHMENTS) throw new Error(`Codex remote workspace upload exceeds the ${REMOTE_WORKSPACE_MEDIA_MAX_ATTACHMENTS}-attachment limit.`);
1277
+ for (const managedPath of gatewayManagedPaths) await assertGatewayManagedMediaPath(managedPath, gatewayMediaRoot);
1278
+ if (remotePathsByLocalPath.size === 0) return mappedArgs;
1279
+ const readRemoteFile = params.readRemoteFile;
1280
+ if (!readRemoteFile) throw new Error("Codex remote workspace file transfer requires an active app-server client.");
1281
+ const maxBytes = params.maxBytes ?? REMOTE_WORKSPACE_MEDIA_MAX_BYTES;
1282
+ const timeoutMs = params.timeoutMs ?? REMOTE_WORKSPACE_MEDIA_TIMEOUT_MS;
1283
+ const deadline = Date.now() + timeoutMs;
1284
+ const stagedPaths = /* @__PURE__ */ new Map();
1285
+ let totalBytes = 0;
1286
+ for (const [localPath, remotePath] of remotePathsByLocalPath) {
1287
+ params.signal?.throwIfAborted();
1288
+ const remainingBytes = maxBytes - totalBytes;
1289
+ const remainingMs = deadline - Date.now();
1290
+ if (remainingMs <= 0) throw new Error("Codex remote workspace attachment batch timed out.");
1291
+ const response = await readRemoteFile({
1292
+ path: remotePath,
1293
+ maxBytes: remainingBytes,
1294
+ workspaceRoot: remoteWorkspaceRoot,
1295
+ signal: params.signal,
1296
+ timeoutMs: remainingMs
1297
+ });
1298
+ if (!response || typeof response.dataBase64 !== "string") throw new Error(`Codex remote workspace artifact returned no file data: ${remotePath}`);
1299
+ if (response.dataBase64.length > Math.ceil(remainingBytes / 3) * 4) throw new Error(`Codex remote workspace artifact exceeds the limit of ${remainingBytes} bytes.`);
1300
+ const remoteBuffer = Buffer.from(response.dataBase64, "base64");
1301
+ if (remoteBuffer.byteLength > remainingBytes || remoteBuffer.toString("base64") !== response.dataBase64) throw new Error(`Codex remote workspace artifact returned invalid or oversized file data: ${remotePath}`);
1302
+ totalBytes += remoteBuffer.byteLength;
1303
+ const saved = await saveMediaBuffer(remoteBuffer, void 0, "outbound", maxBytes, path.basename(remotePath));
1304
+ stagedPaths.set(localPath, saved.path);
1305
+ }
1306
+ return mapMessageMediaValues(mappedArgs, (value) => stagedPaths.get(value) ?? value);
1307
+ }
1308
+ function isGatewayManagedMediaPath(value, mediaRoot) {
1309
+ if (!path.isAbsolute(value)) return false;
1310
+ const relativePath = path.relative(mediaRoot, value);
1311
+ return Boolean(relativePath && relativePath !== ".." && !relativePath.startsWith(`..${path.sep}`) && !path.isAbsolute(relativePath));
1312
+ }
1313
+ async function assertGatewayManagedMediaPath(value, mediaRoot) {
1314
+ const opened = await (await root(mediaRoot, { symlinks: "reject" })).open(path.relative(mediaRoot, value), { symlinks: "reject" });
1315
+ try {
1316
+ if (!(await opened.handle.stat()).isFile()) throw new Error(`Codex Gateway-managed media is not a regular file: ${value}`);
1317
+ } finally {
1318
+ await opened[Symbol.asyncDispose]();
1319
+ }
1320
+ }
1321
+ function mapMessageMediaValues(args, mapValue) {
1322
+ const mapped = { ...args };
1323
+ for (const key of MESSAGE_MEDIA_KEYS) {
1324
+ const value = mapped[key];
1325
+ if (typeof value === "string") mapped[key] = mapValue(value);
1326
+ }
1327
+ for (const key of MESSAGE_MEDIA_ARRAY_KEYS) {
1328
+ const value = mapped[key];
1329
+ if (Array.isArray(value)) mapped[key] = value.map((entry) => typeof entry === "string" ? mapValue(entry) : entry);
1330
+ }
1331
+ if (Array.isArray(mapped.attachments)) mapped.attachments = mapped.attachments.map((attachment) => {
1332
+ if (!attachment || typeof attachment !== "object" || Array.isArray(attachment)) return attachment;
1333
+ const record = { ...attachment };
1334
+ for (const key of ATTACHMENT_MEDIA_KEYS) {
1335
+ const value = record[key];
1336
+ if (typeof value === "string") record[key] = mapValue(value);
1337
+ }
1338
+ return record;
1339
+ });
1340
+ return mapped;
1341
+ }
1342
+ //#endregion
987
1343
  //#region extensions/codex/src/app-server/dynamic-tool-build-state.ts
988
1344
  /** Mutable dependency seam shared by dynamic-tool construction and its behavioral tests. */
989
1345
  const dynamicToolBuildState = {};
@@ -1193,8 +1549,10 @@ async function buildDynamicTools(input) {
1193
1549
  const toolBuildStages = createCodexDynamicToolBuildStageTracker({ enabled: input.profilerEnabled });
1194
1550
  const modelHasVision = params.model.input?.includes("image") ?? false;
1195
1551
  const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, input.sessionAgentId);
1196
- const { createOpenClawCodingTools: defaultCreateOpenClawCodingTools, resolveWebSearchToolPolicy } = await import("openclaw/plugin-sdk/agent-harness");
1197
- const createOpenClawCodingTools = dynamicToolBuildState.openClawCodingToolsFactory ?? defaultCreateOpenClawCodingTools;
1552
+ const injectedOpenClawCodingToolsFactory = dynamicToolBuildState.openClawCodingToolsFactory;
1553
+ let agentHarnessModule;
1554
+ const loadAgentHarnessModule = async () => agentHarnessModule ??= await import("openclaw/plugin-sdk/agent-harness");
1555
+ const createOpenClawCodingTools = injectedOpenClawCodingToolsFactory ?? (await loadAgentHarnessModule()).createOpenClawCodingTools;
1198
1556
  toolBuildStages.mark("load-agent-harness-tools");
1199
1557
  const sessionKeys = resolveOpenClawCodingToolsSessionKeys(params, input.sandboxSessionKey);
1200
1558
  const nativeExecutionPolicy = resolveCodexNativeExecutionPolicyForDynamicTools(input);
@@ -1305,7 +1663,8 @@ async function buildDynamicTools(input) {
1305
1663
  });
1306
1664
  toolBuildStages.mark("vision-filtering");
1307
1665
  const webSearchPresent = visionFilteredTools.some((tool) => tool.name === "web_search");
1308
- const webSearchPolicy = resolveWebSearchToolPolicy({
1666
+ const persistentCodexWebSearchSurface = params.config?.tools?.web?.search?.enabled !== false && !(input.pluginConfig.codexDynamicToolsExclude ?? []).some((name) => normalizeCodexDynamicToolName(name) === "web_search");
1667
+ const webSearchPolicy = webSearchPresent || persistentCodexWebSearchSurface ? (await loadAgentHarnessModule()).resolveWebSearchToolPolicy({
1309
1668
  config: params.config,
1310
1669
  modelProvider: params.model.provider,
1311
1670
  modelId: params.modelId,
@@ -1325,9 +1684,11 @@ async function buildDynamicTools(input) {
1325
1684
  inputProvenance: params.inputProvenance,
1326
1685
  trustedInternalHandoff: params.trustedInternalHandoff,
1327
1686
  scheduledToolPolicy: params.scheduledToolPolicy
1328
- });
1687
+ }) : {
1688
+ allowed: false,
1689
+ persistentAllowed: false
1690
+ };
1329
1691
  const transientWebSearchRestriction = !webSearchPolicy.allowed && webSearchPolicy.persistentAllowed || isCodexMemoryFlushRun(params);
1330
- const persistentCodexWebSearchSurface = params.config?.tools?.web?.search?.enabled !== false && !(input.pluginConfig.codexDynamicToolsExclude ?? []).some((name) => normalizeCodexDynamicToolName(name) === "web_search");
1331
1692
  input.onPersistentWebSearchPolicyResolved?.(webSearchPresent || persistentCodexWebSearchSurface && transientWebSearchRestriction && webSearchPolicy.persistentAllowed);
1332
1693
  const filteredTools = filterCodexDynamicToolsForAllowlist(visionFilteredTools, includeForcedCodexDynamicToolAllow(params.toolsAllow, messagePolicyParams));
1333
1694
  toolBuildStages.mark("allowlist-filter");
@@ -1440,27 +1801,6 @@ function resolveCodexAppServerExecutionCwd(params) {
1440
1801
  remoteWorkspaceRoot: params.remoteWorkspaceRoot
1441
1802
  });
1442
1803
  }
1443
- /** Projects a local OpenClaw workspace cwd into the remote Codex app-server workspace root. */
1444
- function mapCodexAppServerRemoteWorkspacePath(params) {
1445
- if (!params.remoteWorkspaceRoot) return params.value;
1446
- const localRoot = normalizeRemoteWorkspaceMatchPath(params.localWorkspaceRoot);
1447
- const remoteRoot = normalizeRemoteWorkspaceMatchPath(params.remoteWorkspaceRoot);
1448
- const normalizedValue = normalizeRemoteWorkspaceMatchPath(params.value);
1449
- if (!localRoot || !remoteRoot) throw new Error("Codex remoteWorkspaceRoot requires non-empty workspace roots.");
1450
- if (normalizedValue === localRoot) return remoteRoot;
1451
- const prefix = `${localRoot}/`;
1452
- if (!normalizedValue.startsWith(prefix)) throw new Error(`Codex remoteWorkspaceRoot is configured but cwd ${params.value} is outside OpenClaw workspace root ${params.localWorkspaceRoot}; refusing to send a gateway-local cwd to the remote Codex app-server.`);
1453
- return joinRemoteWorkspacePath(remoteRoot, normalizedValue.slice(prefix.length));
1454
- }
1455
- function normalizeRemoteWorkspaceMatchPath(value) {
1456
- return trimTrailingPathSeparator(value.replace(/\\/gu, "/"));
1457
- }
1458
- function trimTrailingPathSeparator(value) {
1459
- return value.length > 1 ? value.replace(/[\\/]+$/u, "") : value;
1460
- }
1461
- function joinRemoteWorkspacePath(remoteRoot, suffix) {
1462
- return remoteRoot === "/" ? `/${suffix}` : `${remoteRoot}/${suffix}`;
1463
- }
1464
1804
  /** Converts OpenClaw sandbox networking into Codex's external-sandbox policy shape. */
1465
1805
  function resolveCodexExternalSandboxPolicyForOpenClawSandbox(sandbox) {
1466
1806
  return {
@@ -1602,6 +1942,20 @@ function settleCodexSourceReplyFinality(owner, turnSucceeded) {
1602
1942
  return turnSucceeded && intents.some((intent) => intent.record.sourceReplyFinal === true);
1603
1943
  }
1604
1944
  //#endregion
1945
+ //#region extensions/codex/src/app-server/hook-requester.ts
1946
+ /** Rebuilds the host-proven requester identity shared by native and bridged tool hooks. */
1947
+ function buildCodexHookRequester(params) {
1948
+ const channel = params.messageChannel ?? params.messageProvider;
1949
+ const requester = {
1950
+ ...channel ? { channel } : {},
1951
+ ...params.agentAccountId ? { accountId: params.agentAccountId } : {},
1952
+ ...params.senderId ? { senderId: params.senderId } : {},
1953
+ ...params.senderIsOwner !== void 0 ? { senderIsOwner: params.senderIsOwner } : {},
1954
+ ...params.memberRoleIds?.length ? { roleIds: [...params.memberRoleIds] } : {}
1955
+ };
1956
+ return Object.keys(requester).length > 0 ? requester : void 0;
1957
+ }
1958
+ //#endregion
1605
1959
  //#region extensions/codex/src/app-server/provider-capabilities.ts
1606
1960
  function resolveOverriddenProviderWebSearchSupport(modelProviderOverride) {
1607
1961
  const provider = modelProviderOverride?.trim().toLowerCase();
@@ -2405,6 +2759,7 @@ const PERMISSION_VALUE_MAX_LENGTH = 48;
2405
2759
  const COMMAND_PREVIEW_WITH_DETAILS_MAX_LENGTH = 80;
2406
2760
  const APPROVAL_PREVIEW_SCAN_MAX_LENGTH = 4096;
2407
2761
  const APPROVAL_PREVIEW_OMITTED = "[preview truncated or unsafe content omitted]";
2762
+ const CONCRETE_TOOL_AUTO_APPROVAL_METHODS = /* @__PURE__ */ new Set(["item/commandExecution/requestApproval", "item/fileChange/requestApproval"]);
2408
2763
  const ANSI_OSC_SEQUENCE_RE = new RegExp(String.raw`(?:\u001b]|\u009d)[^\u001b\u009c\u0007]*(?:\u0007|\u001b\\|\u009c)`, "g");
2409
2764
  const ANSI_CONTROL_SEQUENCE_RE = new RegExp(String.raw`(?:\u001b\[[0-?]*[ -/]*[@-~]|\u009b[0-?]*[ -/]*[@-~]|\u001b[@-Z\\-_])`, "g");
2410
2765
  const CONTROL_CHARACTER_RE = new RegExp(String.raw`[\u0000-\u001f\u007f-\u009f]+`, "g");
@@ -2417,7 +2772,6 @@ const DANGLING_TERMINAL_SEQUENCE_SUFFIX_RE = new RegExp(String.raw`(?:\u001b\][^
2417
2772
  async function handleCodexAppServerApprovalRequest(params) {
2418
2773
  const requestParams = isJsonObject(params.requestParams) ? params.requestParams : void 0;
2419
2774
  if (!matchesCurrentTurn(requestParams, params.threadId, params.turnId)) return;
2420
- if (!isSupportedAppServerApprovalMethod(params.method)) return unsupportedApprovalResponse();
2421
2775
  const context = buildApprovalContext({
2422
2776
  method: params.method,
2423
2777
  requestParams,
@@ -2458,7 +2812,20 @@ async function handleCodexAppServerApprovalRequest(params) {
2458
2812
  });
2459
2813
  return buildApprovalResponse(params.method, context.requestParams, policyOutcome.outcome);
2460
2814
  }
2461
- if (params.autoApprove === true) {
2815
+ const canAutoApproveConcreteToolCall = CONCRETE_TOOL_AUTO_APPROVAL_METHODS.has(params.method);
2816
+ if (canAutoApproveConcreteToolCall && params.autoApproveOpenClawToolPolicy === true && policyOutcome?.outcome === "allowed") {
2817
+ emitApprovalEvent(params.paramsForRun, {
2818
+ phase: "resolved",
2819
+ kind: context.kind,
2820
+ status: "approved",
2821
+ title: context.title,
2822
+ ...context.eventDetails,
2823
+ ...approvalEventScope(params.method, "approved-once"),
2824
+ message: "Codex app-server approval accepted by OpenClaw tool policy."
2825
+ });
2826
+ return buildApprovalResponse(params.method, context.requestParams, "approved-once");
2827
+ }
2828
+ if (canAutoApproveConcreteToolCall && params.autoApprove === true) {
2462
2829
  emitApprovalEvent(params.paramsForRun, {
2463
2830
  phase: "resolved",
2464
2831
  kind: context.kind,
@@ -2620,7 +2987,7 @@ async function runOpenClawToolPolicyForApprovalRequest(params) {
2620
2987
  ...nativeRelayOutcome.failureDisposition ? { failureDisposition: nativeRelayOutcome.failureDisposition } : {}
2621
2988
  };
2622
2989
  if (nativeRelayOutcome?.outcome === "approved-once" || nativeRelayOutcome?.outcome === "approved-session") return { outcome: nativeRelayOutcome.outcome };
2623
- if (nativeRelayOutcome?.handled) return { outcome: "no-decision" };
2990
+ if (nativeRelayOutcome?.handled) return { outcome: "allowed" };
2624
2991
  const hookChannelId = buildAgentHookContextChannelFields({
2625
2992
  sessionKey: params.paramsForRun.sessionKey,
2626
2993
  messageChannel: params.paramsForRun.messageChannel,
@@ -2628,6 +2995,7 @@ async function runOpenClawToolPolicyForApprovalRequest(params) {
2628
2995
  currentChannelId: params.paramsForRun.currentChannelId,
2629
2996
  messageTo: params.paramsForRun.messageTo
2630
2997
  }).channelId;
2998
+ const requester = buildCodexHookRequester(params.paramsForRun);
2631
2999
  const outcome = await runBeforeToolCallHook({
2632
3000
  toolName: policyRequest.toolName,
2633
3001
  params: policyRequest.params,
@@ -2642,7 +3010,14 @@ async function runOpenClawToolPolicyForApprovalRequest(params) {
2642
3010
  ...params.paramsForRun.sessionKey ? { sessionKey: params.paramsForRun.sessionKey } : {},
2643
3011
  ...params.paramsForRun.sessionId ? { sessionId: params.paramsForRun.sessionId } : {},
2644
3012
  ...params.paramsForRun.runId ? { runId: params.paramsForRun.runId } : {},
2645
- ...hookChannelId ? { channelId: hookChannelId } : {}
3013
+ ...hookChannelId ? { channelId: hookChannelId } : {},
3014
+ ...requester ? { requester } : {},
3015
+ trigger: params.paramsForRun.trigger,
3016
+ approvalReviewerDeviceId: params.paramsForRun.approvalReviewerDeviceId,
3017
+ turnSourceChannel: params.paramsForRun.messageChannel ?? params.paramsForRun.messageProvider,
3018
+ turnSourceTo: params.paramsForRun.currentMessagingTarget ?? params.paramsForRun.currentChannelId,
3019
+ turnSourceAccountId: params.paramsForRun.agentAccountId,
3020
+ turnSourceThreadId: params.paramsForRun.currentThreadTs
2646
3021
  }
2647
3022
  });
2648
3023
  if (outcome.blocked) return {
@@ -2655,6 +3030,7 @@ async function runOpenClawToolPolicyForApprovalRequest(params) {
2655
3030
  reason: "OpenClaw tool policy rewrote Codex app-server approval params; refusing original request."
2656
3031
  };
2657
3032
  if (outcome.approvalResolution) return { outcome: "approved-once" };
3033
+ return { outcome: "allowed" };
2658
3034
  }
2659
3035
  async function runNativeRelayToolPolicyForApprovalRequest(params) {
2660
3036
  if (params.method !== "item/commandExecution/requestApproval" || !params.nativeHookRelay?.allowedEvents.includes("pre_tool_use")) return;
@@ -3068,9 +3444,6 @@ function approvalKindForMethod(method) {
3068
3444
  if (method.includes("fileChange") || method.includes("Patch") || method.includes("permissions")) return "plugin";
3069
3445
  return "unknown";
3070
3446
  }
3071
- function isSupportedAppServerApprovalMethod(method) {
3072
- return method === "item/commandExecution/requestApproval" || method === "item/fileChange/requestApproval" || method === "item/permissions/requestApproval";
3073
- }
3074
3447
  function emitApprovalEvent(params, data) {
3075
3448
  params.onAgentEvent?.({
3076
3449
  stream: "approval",
@@ -3386,6 +3759,7 @@ function createCodexDynamicToolBridge(params) {
3386
3759
  const legacyExtensionRunner = createCodexAppServerToolResultExtensionRunner(toolResultHookContext);
3387
3760
  const executionSnapshotStates = /* @__PURE__ */ new Map();
3388
3761
  const directToolNames = /* @__PURE__ */ new Set([...ALWAYS_DIRECT_DYNAMIC_TOOL_NAMES, ...params.directToolNames ?? []]);
3762
+ let readRemoteWorkspaceFile;
3389
3763
  return {
3390
3764
  availableSpecs: createCodexDynamicToolSpecs({
3391
3765
  entries: availableTools,
@@ -3397,7 +3771,11 @@ function createCodexDynamicToolBridge(params) {
3397
3771
  loading: params.loading ?? "searchable",
3398
3772
  directToolNames
3399
3773
  }),
3774
+ resultContentSourceForTool: (toolName) => toolMap.get(toolName)?.tool.resultContentSource,
3400
3775
  telemetry,
3776
+ setRemoteWorkspaceFileReader: (reader) => {
3777
+ readRemoteWorkspaceFile = reader;
3778
+ },
3401
3779
  consumeToolExecutionSnapshot: (toolCallId) => {
3402
3780
  const state = executionSnapshotStates.get(toolCallId);
3403
3781
  executionSnapshotStates.delete(toolCallId);
@@ -3448,7 +3826,15 @@ function createCodexDynamicToolBridge(params) {
3448
3826
  };
3449
3827
  };
3450
3828
  try {
3451
- const preparedArgs = tool.prepareArguments ? tool.prepareArguments(args) : args;
3829
+ const toolArgs = tool.prepareArguments ? tool.prepareArguments(args) : args;
3830
+ const preparedArgs = toolName === "message" && isRecord(toolArgs) ? await prepareCodexRemoteWorkspaceMessageMedia({
3831
+ args: toolArgs,
3832
+ localWorkspaceRoot: params.hookContext?.workspaceDir,
3833
+ remoteWorkspaceRoot: params.hookContext?.remoteWorkspaceRoot,
3834
+ readRemoteFile: readRemoteWorkspaceFile,
3835
+ timeoutMs: params.hookContext?.remoteWorkspaceRequestTimeoutMs,
3836
+ signal
3837
+ }) : toolArgs;
3452
3838
  const telemetryArgs = isRecord(preparedArgs) ? preparedArgs : args;
3453
3839
  executedArgs = structuredClone(telemetryArgs);
3454
3840
  const messagingContext = {
@@ -3680,7 +4066,8 @@ function createCodexDynamicToolSpecs(params) {
3680
4066
  const specs = [];
3681
4067
  const namespaceTools = [];
3682
4068
  const directOnlyNamespaceTools = [];
3683
- for (const entry of params.entries) {
4069
+ const entries = params.loading === "direct" ? params.entries : params.entries.toSorted((left, right) => left.name.localeCompare(right.name));
4070
+ for (const entry of entries) {
3684
4071
  const functionSpec = createCodexDynamicToolFunctionSpec({ entry });
3685
4072
  if (entry.name === "openclaw" && params.directToolNames.has(entry.name)) {
3686
4073
  specs.push(functionSpec);
@@ -4130,4 +4517,4 @@ function isCronAddAction(args) {
4130
4517
  return typeof action === "string" && action.trim().toLowerCase() === "add";
4131
4518
  }
4132
4519
  //#endregion
4133
- export { shouldSynthesizeToolProgressForItem as $, resolveCodexNativeHookRelayEvents as A, shouldReleaseTurnAfterTerminalDynamicTool as B, CodexNativeToolLifecycleProjector as C, buildCodexNativeHookRelayDisabledConfig as D, buildCodexNativeHookRelayConfig as E, isDynamicToolTerminalDiagnosticEvent as F, isNonSuccessItemStatus as G, toCodexDynamicToolProtocolResponse as H, isMatchingDynamicToolTerminalDiagnostic as I, itemName as J, isSideEffectingNativeToolItem as K, resolveDynamicToolCallTimeoutMs as L, scheduleCodexNativeHookRelayUnregister as M, handleDynamicToolCallWithTimeout as N, createCodexNativeHookRelay as O, hasPendingDynamicToolTerminalDiagnostic as P, shouldRecordNativeToolTranscript as Q, resolveTerminalDynamicToolBatchAction as R, filterToolsForVisionInputs as S, CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS as T, resolveCodexToolAbortTerminalReason as U, toCodexDynamicToolProgressResponse as V, isMutatingNativeToolItem as W, itemTitle as X, itemStatus as Y, shouldClearTerminalPresentationForNativeItem as Z, resolveCodexMessageToolProvider as _, emitDynamicToolStartedDiagnostic as a, shouldRequireCodexSandboxExecServerEnvironment as b, resolveCodexProviderWebSearchSupportForClient as c, createCodexDynamicToolBuildStageTracker as d, unknownItemStatus as et, disableCodexPluginThreadConfig as f, resolveCodexExternalSandboxPolicyForOpenClawSandbox as g, resolveCodexAppServerHookChannelId as h, emitDynamicToolErrorDiagnostic as i, resolveCodexNativeHookRelayTtlMs as j, emitCodexNativePreToolUseFailureDiagnostic as k, settleCodexSourceReplyFinality as l, resolveCodexAppServerExecutionCwd as m, handleCodexAppServerApprovalRequest as n, emitDynamicToolTerminalDiagnostic as o, formatCodexDynamicToolBuildStageSummary as p, itemKind as q, handleCodexAppServerElicitationRequest as r, resolveCodexProviderWebSearchSupport as s, createCodexDynamicToolBridge as t, buildDynamicTools as u, resolveCodexSandboxEnvironmentSelection as v, CODEX_NATIVE_HOOK_RELAY_EVENTS as w, shouldWarnCodexDynamicToolBuildStageSummary as x, shouldEnableCodexAppServerNativeToolSurface as y, shouldBlockTerminalReleaseForNonTerminalDynamicToolResult as z };
4520
+ export { shouldClearTerminalPresentationForNativeItem as $, createCodexNativeHookRelay as A, resolveTerminalDynamicToolBatchAction as B, filterToolsForVisionInputs as C, CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS as D, CODEX_NATIVE_HOOK_RELAY_EVENTS as E, handleDynamicToolCallWithTimeout as F, resolveCodexToolAbortTerminalReason as G, shouldReleaseTurnAfterTerminalDynamicTool as H, hasPendingDynamicToolTerminalDiagnostic as I, isSideEffectingNativeToolItem as J, isMutatingNativeToolItem as K, isDynamicToolTerminalDiagnosticEvent as L, resolveCodexNativeHookRelayEvents as M, resolveCodexNativeHookRelayTtlMs as N, buildCodexNativeHookRelayConfig as O, scheduleCodexNativeHookRelayUnregister as P, itemTitle as Q, isMatchingDynamicToolTerminalDiagnostic as R, shouldWarnCodexDynamicToolBuildStageSummary as S, CodexNativeToolLifecycleProjector as T, toCodexDynamicToolProgressResponse as U, shouldBlockTerminalReleaseForNonTerminalDynamicToolResult as V, toCodexDynamicToolProtocolResponse as W, itemName as X, itemKind as Y, itemStatus as Z, resolveCodexExternalSandboxPolicyForOpenClawSandbox as _, emitDynamicToolStartedDiagnostic as a, shouldEnableCodexAppServerNativeToolSurface as b, resolveCodexProviderWebSearchSupportForClient as c, buildDynamicTools as d, shouldRecordNativeToolTranscript as et, createCodexDynamicToolBuildStageTracker as f, resolveCodexAppServerHookChannelId as g, resolveCodexAppServerExecutionCwd as h, emitDynamicToolErrorDiagnostic as i, emitCodexNativePreToolUseFailureDiagnostic as j, buildCodexNativeHookRelayDisabledConfig as k, buildCodexHookRequester as l, formatCodexDynamicToolBuildStageSummary as m, handleCodexAppServerApprovalRequest as n, unknownItemStatus as nt, emitDynamicToolTerminalDiagnostic as o, disableCodexPluginThreadConfig as p, isNonSuccessItemStatus as q, handleCodexAppServerElicitationRequest as r, resolveCodexProviderWebSearchSupport as s, createCodexDynamicToolBridge as t, shouldSynthesizeToolProgressForItem as tt, settleCodexSourceReplyFinality as u, resolveCodexMessageToolProvider as v, readBoundedCodexRemoteWorkspaceFile as w, shouldRequireCodexSandboxExecServerEnvironment as x, resolveCodexSandboxEnvironmentSelection as y, resolveDynamicToolCallTimeoutMs as z };