@openclaw/codex 2026.7.2-beta.4 → 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.
- package/dist/{app-server-policy-BO3jYBkv.js → app-server-policy-BSaO2JIT.js} +1 -1
- package/dist/{attempt-notifications-DdmnBMUp.js → attempt-notifications-AP-a-Q5k.js} +1 -1
- package/dist/{bounded-turn-CaQL96kg.js → bounded-turn-D2ZAgZVz.js} +54 -24
- package/dist/{capabilities-CLICvTxf.js → capabilities-BFDTVYr4.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-DgADqnHa.js → command-formatters-C336eRVS.js} +2 -2
- package/dist/{command-handlers-l_lVPNlB.js → command-handlers-DAHUSry9.js} +1233 -1222
- package/dist/{compact-CC5KhBzX.js → compact-D_uvHurS.js} +8 -8
- package/dist/{computer-use-Ip1-QGa-.js → computer-use-CYEc8U3w.js} +123 -115
- package/dist/{conversation-control-sNPsbTCP.js → conversation-control-xsIeXbo4.js} +6 -6
- package/dist/doctor-contract-api.js +24 -86
- package/dist/{dynamic-tools-CQI3UwqY.js → dynamic-tools-D2gYkSBO.js} +482 -91
- package/dist/effective-mcp-catalog-Bbd98Inw.js +114 -0
- package/dist/{event-projector-usage-D6tE7_qD.js → event-projector-usage-Xp4AlR2k.js} +20 -3
- package/dist/harness.js +19 -14
- package/dist/index.js +292 -328
- package/dist/media-understanding-provider.js +6 -1
- package/dist/{models-BNeMlHgg.js → models-BBMKU4jA.js} +2 -2
- package/dist/{notification-correlation-BGLixv5_.js → notification-correlation-CU6_AnOb.js} +3 -3
- package/dist/{plugin-app-cache-key-CvzvmBRz.js → plugin-app-cache-key-DztPafOA.js} +135 -42
- package/dist/{rate-limits-D0IJT-a6.js → rate-limits-CU-gVCCS.js} +1 -1
- package/dist/{request-BTccUTD3.js → request-qKh331yu.js} +3 -3
- package/dist/{run-attempt--858NXDl.js → run-attempt-CY9WlDLc.js} +1060 -402
- package/dist/{runtime-artifact-C2ITXdhM.js → runtime-artifact-CmtG_t1L.js} +90 -24
- package/dist/{sandbox-guard-D1Wky__S.js → sandbox-guard-NuhpXmPB.js} +4 -0
- package/dist/{session-binding-ZSMX1omP.js → session-binding-BXpo9ymA.js} +1006 -891
- package/dist/{session-catalog-DsKaezgR.js → session-catalog-DyOgR4WH.js} +289 -56
- package/dist/{session-cli-CYJTfRLG.js → session-cli-2PZaFLRh.js} +2 -2
- package/dist/{session-upstream-marker-D7XlI9us.js → session-upstream-marker-B6U7tLw5.js} +1 -1
- package/dist/{settled-turn-finalizer-DHltNgtF.js → settled-turn-finalizer-CXY2Z9dT.js} +19 -6
- package/dist/{shared-client-wmgNFNYp.js → shared-client-DTbvH-XV.js} +1993 -1720
- package/dist/{side-question-BfFZCsJ-.js → side-question-_ulBk1AL.js} +12 -10
- package/dist/{thread-lifecycle-cqrOlJkq.js → thread-lifecycle-DF53ogiA.js} +980 -346
- package/dist/{transcript-mirror-2p7kl6e4.js → transcript-mirror-DzsdNCf5.js} +80 -41
- package/dist/{upstream-session-fork-vPjwkT1i.js → upstream-session-fork-Dy4Xvuoj.js} +3 -3
- package/dist/{usage-DM_I3mPT.js → usage-CQ6GhD5-.js} +3 -3
- package/dist/{web-search-provider.runtime-Bx6HAc_k.js → web-search-provider.runtime-CCFhg2z5.js} +3 -3
- package/package.json +6 -8
- package/npm-shrinkwrap.json +0 -202
- package/dist/{auth-binding-C1czuHPA.js → auth-binding-B4FfbcCg.js} +1 -1
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { D as isForcedPrivateQaCodexRuntime, E as filterCodexDynamicToolsWithOpenClawShell, O as isSystemAgentOnlyCodexDynamicToolAllowlist, T as filterCodexDynamicTools, ct as
|
|
4
|
-
import { S as readCodexTurn } from "./transcript-mirror-
|
|
5
|
-
import { r as formatCodexDisplayText } from "./command-formatters-
|
|
6
|
-
import { a as resolveCodexNodeExecToolOverrides, i as resolveCodexNativeExecutionPolicy } from "./sandbox-guard-
|
|
7
|
-
import { n as readCodexNotificationThreadId, r as readCodexNotificationTurnId } from "./notification-correlation-
|
|
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
|
-
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
10
|
-
import { createHash } from "node:crypto";
|
|
11
|
-
import { resolveAgentDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
12
|
-
import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
|
|
13
|
-
import { asOptionalRecord, isRecord, normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
14
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";
|
|
11
|
+
import { createHash } from "node:crypto";
|
|
12
|
+
import { resolveAgentDir as resolveAgentDir$1 } from "openclaw/plugin-sdk/agent-runtime";
|
|
13
|
+
import { isRecord, normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
14
|
+
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
15
15
|
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
16
16
|
import { emitTrustedDiagnosticEvent, hasPendingInternalDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
17
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";
|
|
18
21
|
import { isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
|
|
19
22
|
import { normalizeOpenAIToolSchemas } from "openclaw/plugin-sdk/provider-tools";
|
|
20
23
|
//#region extensions/codex/src/app-server/event-projector-items.ts
|
|
@@ -109,7 +112,7 @@ function shouldSynthesizeToolProgressForItem(item) {
|
|
|
109
112
|
}
|
|
110
113
|
}
|
|
111
114
|
function shouldRecordNativeToolTranscript(item) {
|
|
112
|
-
return shouldSynthesizeToolProgressForItem(item)
|
|
115
|
+
return shouldSynthesizeToolProgressForItem(item);
|
|
113
116
|
}
|
|
114
117
|
function isMutatingNativeToolItem(item) {
|
|
115
118
|
if (item.type === "commandExecution") return true;
|
|
@@ -129,6 +132,18 @@ function shouldClearTerminalPresentationForNativeItem(item) {
|
|
|
129
132
|
}
|
|
130
133
|
//#endregion
|
|
131
134
|
//#region extensions/codex/src/app-server/dynamic-tool-response-state.ts
|
|
135
|
+
/** Retains the host-owned app preview without adding it to Codex's response payload. */
|
|
136
|
+
function withDynamicToolTranscriptDetails(response, details) {
|
|
137
|
+
if (!details || typeof details !== "object" || Array.isArray(details)) return response;
|
|
138
|
+
const mcpAppPreview = details.mcpAppPreview;
|
|
139
|
+
if (!mcpAppPreview || typeof mcpAppPreview !== "object" || Array.isArray(mcpAppPreview)) return response;
|
|
140
|
+
Object.defineProperty(response, "transcriptDetails", {
|
|
141
|
+
configurable: true,
|
|
142
|
+
enumerable: false,
|
|
143
|
+
value: { mcpAppPreview }
|
|
144
|
+
});
|
|
145
|
+
return response;
|
|
146
|
+
}
|
|
132
147
|
function withDynamicToolTerminalResolution(response, terminalResolution) {
|
|
133
148
|
if (terminalResolution) {
|
|
134
149
|
Object.defineProperties(response, {
|
|
@@ -444,13 +459,16 @@ function toCodexDynamicToolProtocolResponse(response) {
|
|
|
444
459
|
}
|
|
445
460
|
/** Adds async-started progress details when a tool result continues out of band. */
|
|
446
461
|
function toCodexDynamicToolProgressResponse(response, protocolResponse) {
|
|
447
|
-
|
|
462
|
+
const transcriptDetails = response.transcriptDetails;
|
|
463
|
+
if (response.asyncStarted !== true && transcriptDetails === void 0) return protocolResponse;
|
|
448
464
|
return {
|
|
449
465
|
...protocolResponse,
|
|
450
|
-
details: {
|
|
466
|
+
...transcriptDetails ? { details: transcriptDetails } : {},
|
|
467
|
+
...response.asyncStarted === true ? { details: {
|
|
468
|
+
...transcriptDetails,
|
|
451
469
|
async: true,
|
|
452
470
|
status: "started"
|
|
453
|
-
}
|
|
471
|
+
} } : {}
|
|
454
472
|
};
|
|
455
473
|
}
|
|
456
474
|
/** Decides whether a terminal dynamic tool response can release the Codex turn. */
|
|
@@ -590,6 +608,19 @@ const CODEX_NATIVE_HOOK_RELAY_COMMAND_MAX_PARENT_MARGIN_MS = 1e3;
|
|
|
590
608
|
const CODEX_NATIVE_HOOK_RELAY_DEFAULT_TIMEOUT_SEC = 10;
|
|
591
609
|
const CODEX_NATIVE_HOOK_RELAY_UNREGISTER_GRACE_MS = 1e4;
|
|
592
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
|
+
};
|
|
593
624
|
/** Defers relay unregister so late native hook subprocesses can still resolve. */
|
|
594
625
|
function scheduleCodexNativeHookRelayUnregister(params) {
|
|
595
626
|
let pending;
|
|
@@ -648,6 +679,7 @@ function createCodexNativeHookRelay(params) {
|
|
|
648
679
|
runId: params.runId,
|
|
649
680
|
...params.channelId ? { channelId: params.channelId } : {},
|
|
650
681
|
...params.requester ? { requester: params.requester } : {},
|
|
682
|
+
...params.approvalContext ? { approvalContext: params.approvalContext } : {},
|
|
651
683
|
allowedEvents: params.events,
|
|
652
684
|
preToolUseLoopDetection: params.loopDetectionPreToolUseRelay,
|
|
653
685
|
ttlMs: resolveCodexNativeHookRelayTtlMs({
|
|
@@ -716,18 +748,23 @@ function buildCodexNativeHookRelayConfig(params) {
|
|
|
716
748
|
}
|
|
717
749
|
const timeout = normalizeHookTimeoutSec(params.hookTimeoutSec);
|
|
718
750
|
const command = params.relay.commandForEvent(event, { timeoutMs: resolveCodexNativeHookRelayCommandTimeoutMs(timeout) });
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
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
|
+
}];
|
|
726
762
|
const state = {
|
|
727
763
|
enabled: true,
|
|
728
764
|
trusted_hash: codexCommandHookTrustedHash({
|
|
729
765
|
event,
|
|
730
766
|
command,
|
|
767
|
+
matcher,
|
|
731
768
|
timeout,
|
|
732
769
|
statusMessage: "OpenClaw native hook relay"
|
|
733
770
|
})
|
|
@@ -755,9 +792,26 @@ function resolveCodexNativeHookRelayCommandTimeoutMs(hookTimeoutSec) {
|
|
|
755
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)));
|
|
756
793
|
return Math.max(1, parentTimeoutMs - parentMarginMs);
|
|
757
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
|
+
}
|
|
758
811
|
function codexCommandHookTrustedHash(params) {
|
|
759
812
|
const identity = {
|
|
760
813
|
event_name: CODEX_HOOK_KEY_LABEL_BY_NATIVE_EVENT[params.event],
|
|
814
|
+
...params.matcher ? { matcher: params.matcher } : {},
|
|
761
815
|
hooks: [{
|
|
762
816
|
async: false,
|
|
763
817
|
command: params.command,
|
|
@@ -970,6 +1024,322 @@ var CodexNativeToolLifecycleProjector = class {
|
|
|
970
1024
|
}
|
|
971
1025
|
};
|
|
972
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
|
|
973
1343
|
//#region extensions/codex/src/app-server/dynamic-tool-build-state.ts
|
|
974
1344
|
/** Mutable dependency seam shared by dynamic-tool construction and its behavioral tests. */
|
|
975
1345
|
const dynamicToolBuildState = {};
|
|
@@ -1178,9 +1548,11 @@ async function buildDynamicTools(input) {
|
|
|
1178
1548
|
}
|
|
1179
1549
|
const toolBuildStages = createCodexDynamicToolBuildStageTracker({ enabled: input.profilerEnabled });
|
|
1180
1550
|
const modelHasVision = params.model.input?.includes("image") ?? false;
|
|
1181
|
-
const agentDir = params.agentDir ?? resolveAgentDir(params.config ?? {}, input.sessionAgentId);
|
|
1182
|
-
const
|
|
1183
|
-
|
|
1551
|
+
const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, input.sessionAgentId);
|
|
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;
|
|
1184
1556
|
toolBuildStages.mark("load-agent-harness-tools");
|
|
1185
1557
|
const sessionKeys = resolveOpenClawCodingToolsSessionKeys(params, input.sandboxSessionKey);
|
|
1186
1558
|
const nativeExecutionPolicy = resolveCodexNativeExecutionPolicyForDynamicTools(input);
|
|
@@ -1214,6 +1586,7 @@ async function buildDynamicTools(input) {
|
|
|
1214
1586
|
senderIsOwner: params.senderIsOwner,
|
|
1215
1587
|
inputProvenance: params.inputProvenance,
|
|
1216
1588
|
trustedInternalHandoff: params.trustedInternalHandoff,
|
|
1589
|
+
scheduledToolPolicy: params.scheduledToolPolicy,
|
|
1217
1590
|
allowGatewaySubagentBinding: params.allowGatewaySubagentBinding || isForcedPrivateQaCodexRuntime(),
|
|
1218
1591
|
...sessionKeys,
|
|
1219
1592
|
sessionId: params.sessionId,
|
|
@@ -1290,7 +1663,8 @@ async function buildDynamicTools(input) {
|
|
|
1290
1663
|
});
|
|
1291
1664
|
toolBuildStages.mark("vision-filtering");
|
|
1292
1665
|
const webSearchPresent = visionFilteredTools.some((tool) => tool.name === "web_search");
|
|
1293
|
-
const
|
|
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({
|
|
1294
1668
|
config: params.config,
|
|
1295
1669
|
modelProvider: params.model.provider,
|
|
1296
1670
|
modelId: params.modelId,
|
|
@@ -1308,10 +1682,13 @@ async function buildDynamicTools(input) {
|
|
|
1308
1682
|
senderUsername: params.senderUsername,
|
|
1309
1683
|
senderE164: params.senderE164,
|
|
1310
1684
|
inputProvenance: params.inputProvenance,
|
|
1311
|
-
trustedInternalHandoff: params.trustedInternalHandoff
|
|
1312
|
-
|
|
1685
|
+
trustedInternalHandoff: params.trustedInternalHandoff,
|
|
1686
|
+
scheduledToolPolicy: params.scheduledToolPolicy
|
|
1687
|
+
}) : {
|
|
1688
|
+
allowed: false,
|
|
1689
|
+
persistentAllowed: false
|
|
1690
|
+
};
|
|
1313
1691
|
const transientWebSearchRestriction = !webSearchPolicy.allowed && webSearchPolicy.persistentAllowed || isCodexMemoryFlushRun(params);
|
|
1314
|
-
const persistentCodexWebSearchSurface = params.config?.tools?.web?.search?.enabled !== false && !(input.pluginConfig.codexDynamicToolsExclude ?? []).some((name) => normalizeCodexDynamicToolName(name) === "web_search");
|
|
1315
1692
|
input.onPersistentWebSearchPolicyResolved?.(webSearchPresent || persistentCodexWebSearchSurface && transientWebSearchRestriction && webSearchPolicy.persistentAllowed);
|
|
1316
1693
|
const filteredTools = filterCodexDynamicToolsForAllowlist(visionFilteredTools, includeForcedCodexDynamicToolAllow(params.toolsAllow, messagePolicyParams));
|
|
1317
1694
|
toolBuildStages.mark("allowlist-filter");
|
|
@@ -1424,27 +1801,6 @@ function resolveCodexAppServerExecutionCwd(params) {
|
|
|
1424
1801
|
remoteWorkspaceRoot: params.remoteWorkspaceRoot
|
|
1425
1802
|
});
|
|
1426
1803
|
}
|
|
1427
|
-
/** Projects a local OpenClaw workspace cwd into the remote Codex app-server workspace root. */
|
|
1428
|
-
function mapCodexAppServerRemoteWorkspacePath(params) {
|
|
1429
|
-
if (!params.remoteWorkspaceRoot) return params.value;
|
|
1430
|
-
const localRoot = normalizeRemoteWorkspaceMatchPath(params.localWorkspaceRoot);
|
|
1431
|
-
const remoteRoot = normalizeRemoteWorkspaceMatchPath(params.remoteWorkspaceRoot);
|
|
1432
|
-
const normalizedValue = normalizeRemoteWorkspaceMatchPath(params.value);
|
|
1433
|
-
if (!localRoot || !remoteRoot) throw new Error("Codex remoteWorkspaceRoot requires non-empty workspace roots.");
|
|
1434
|
-
if (normalizedValue === localRoot) return remoteRoot;
|
|
1435
|
-
const prefix = `${localRoot}/`;
|
|
1436
|
-
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.`);
|
|
1437
|
-
return joinRemoteWorkspacePath(remoteRoot, normalizedValue.slice(prefix.length));
|
|
1438
|
-
}
|
|
1439
|
-
function normalizeRemoteWorkspaceMatchPath(value) {
|
|
1440
|
-
return trimTrailingPathSeparator(value.replace(/\\/gu, "/"));
|
|
1441
|
-
}
|
|
1442
|
-
function trimTrailingPathSeparator(value) {
|
|
1443
|
-
return value.length > 1 ? value.replace(/[\\/]+$/u, "") : value;
|
|
1444
|
-
}
|
|
1445
|
-
function joinRemoteWorkspacePath(remoteRoot, suffix) {
|
|
1446
|
-
return remoteRoot === "/" ? `/${suffix}` : `${remoteRoot}/${suffix}`;
|
|
1447
|
-
}
|
|
1448
1804
|
/** Converts OpenClaw sandbox networking into Codex's external-sandbox policy shape. */
|
|
1449
1805
|
function resolveCodexExternalSandboxPolicyForOpenClawSandbox(sandbox) {
|
|
1450
1806
|
return {
|
|
@@ -1586,7 +1942,26 @@ function settleCodexSourceReplyFinality(owner, turnSucceeded) {
|
|
|
1586
1942
|
return turnSucceeded && intents.some((intent) => intent.record.sourceReplyFinal === true);
|
|
1587
1943
|
}
|
|
1588
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
|
|
1589
1959
|
//#region extensions/codex/src/app-server/provider-capabilities.ts
|
|
1960
|
+
function resolveOverriddenProviderWebSearchSupport(modelProviderOverride) {
|
|
1961
|
+
const provider = modelProviderOverride?.trim().toLowerCase();
|
|
1962
|
+
if (!provider) return;
|
|
1963
|
+
return provider === "openai" ? "supported" : "unsupported";
|
|
1964
|
+
}
|
|
1590
1965
|
async function readConfiguredProviderWebSearchSupport(params) {
|
|
1591
1966
|
return (await params.client.request("modelProvider/capabilities/read", {}, {
|
|
1592
1967
|
timeoutMs: params.timeoutMs,
|
|
@@ -1594,9 +1969,8 @@ async function readConfiguredProviderWebSearchSupport(params) {
|
|
|
1594
1969
|
})).webSearch ? "supported" : "unsupported";
|
|
1595
1970
|
}
|
|
1596
1971
|
async function resolveCodexProviderWebSearchSupportForClient(params) {
|
|
1597
|
-
const
|
|
1598
|
-
if (
|
|
1599
|
-
if (modelProviderOverride) return "unsupported";
|
|
1972
|
+
const overrideSupport = resolveOverriddenProviderWebSearchSupport(params.modelProviderOverride);
|
|
1973
|
+
if (overrideSupport) return overrideSupport;
|
|
1600
1974
|
try {
|
|
1601
1975
|
return await readConfiguredProviderWebSearchSupport(params);
|
|
1602
1976
|
} catch {
|
|
@@ -1604,6 +1978,8 @@ async function resolveCodexProviderWebSearchSupportForClient(params) {
|
|
|
1604
1978
|
}
|
|
1605
1979
|
}
|
|
1606
1980
|
async function resolveCodexProviderWebSearchSupport(params) {
|
|
1981
|
+
const overrideSupport = resolveOverriddenProviderWebSearchSupport(params.modelProviderOverride);
|
|
1982
|
+
if (overrideSupport) return overrideSupport;
|
|
1607
1983
|
let client;
|
|
1608
1984
|
try {
|
|
1609
1985
|
client = await params.clientFactory({
|
|
@@ -2383,6 +2759,7 @@ const PERMISSION_VALUE_MAX_LENGTH = 48;
|
|
|
2383
2759
|
const COMMAND_PREVIEW_WITH_DETAILS_MAX_LENGTH = 80;
|
|
2384
2760
|
const APPROVAL_PREVIEW_SCAN_MAX_LENGTH = 4096;
|
|
2385
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"]);
|
|
2386
2763
|
const ANSI_OSC_SEQUENCE_RE = new RegExp(String.raw`(?:\u001b]|\u009d)[^\u001b\u009c\u0007]*(?:\u0007|\u001b\\|\u009c)`, "g");
|
|
2387
2764
|
const ANSI_CONTROL_SEQUENCE_RE = new RegExp(String.raw`(?:\u001b\[[0-?]*[ -/]*[@-~]|\u009b[0-?]*[ -/]*[@-~]|\u001b[@-Z\\-_])`, "g");
|
|
2388
2765
|
const CONTROL_CHARACTER_RE = new RegExp(String.raw`[\u0000-\u001f\u007f-\u009f]+`, "g");
|
|
@@ -2395,7 +2772,6 @@ const DANGLING_TERMINAL_SEQUENCE_SUFFIX_RE = new RegExp(String.raw`(?:\u001b\][^
|
|
|
2395
2772
|
async function handleCodexAppServerApprovalRequest(params) {
|
|
2396
2773
|
const requestParams = isJsonObject(params.requestParams) ? params.requestParams : void 0;
|
|
2397
2774
|
if (!matchesCurrentTurn(requestParams, params.threadId, params.turnId)) return;
|
|
2398
|
-
if (!isSupportedAppServerApprovalMethod(params.method)) return unsupportedApprovalResponse();
|
|
2399
2775
|
const context = buildApprovalContext({
|
|
2400
2776
|
method: params.method,
|
|
2401
2777
|
requestParams,
|
|
@@ -2436,7 +2812,20 @@ async function handleCodexAppServerApprovalRequest(params) {
|
|
|
2436
2812
|
});
|
|
2437
2813
|
return buildApprovalResponse(params.method, context.requestParams, policyOutcome.outcome);
|
|
2438
2814
|
}
|
|
2439
|
-
|
|
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) {
|
|
2440
2829
|
emitApprovalEvent(params.paramsForRun, {
|
|
2441
2830
|
phase: "resolved",
|
|
2442
2831
|
kind: context.kind,
|
|
@@ -2598,7 +2987,7 @@ async function runOpenClawToolPolicyForApprovalRequest(params) {
|
|
|
2598
2987
|
...nativeRelayOutcome.failureDisposition ? { failureDisposition: nativeRelayOutcome.failureDisposition } : {}
|
|
2599
2988
|
};
|
|
2600
2989
|
if (nativeRelayOutcome?.outcome === "approved-once" || nativeRelayOutcome?.outcome === "approved-session") return { outcome: nativeRelayOutcome.outcome };
|
|
2601
|
-
if (nativeRelayOutcome?.handled) return { outcome: "
|
|
2990
|
+
if (nativeRelayOutcome?.handled) return { outcome: "allowed" };
|
|
2602
2991
|
const hookChannelId = buildAgentHookContextChannelFields({
|
|
2603
2992
|
sessionKey: params.paramsForRun.sessionKey,
|
|
2604
2993
|
messageChannel: params.paramsForRun.messageChannel,
|
|
@@ -2606,6 +2995,7 @@ async function runOpenClawToolPolicyForApprovalRequest(params) {
|
|
|
2606
2995
|
currentChannelId: params.paramsForRun.currentChannelId,
|
|
2607
2996
|
messageTo: params.paramsForRun.messageTo
|
|
2608
2997
|
}).channelId;
|
|
2998
|
+
const requester = buildCodexHookRequester(params.paramsForRun);
|
|
2609
2999
|
const outcome = await runBeforeToolCallHook({
|
|
2610
3000
|
toolName: policyRequest.toolName,
|
|
2611
3001
|
params: policyRequest.params,
|
|
@@ -2620,7 +3010,14 @@ async function runOpenClawToolPolicyForApprovalRequest(params) {
|
|
|
2620
3010
|
...params.paramsForRun.sessionKey ? { sessionKey: params.paramsForRun.sessionKey } : {},
|
|
2621
3011
|
...params.paramsForRun.sessionId ? { sessionId: params.paramsForRun.sessionId } : {},
|
|
2622
3012
|
...params.paramsForRun.runId ? { runId: params.paramsForRun.runId } : {},
|
|
2623
|
-
...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
|
|
2624
3021
|
}
|
|
2625
3022
|
});
|
|
2626
3023
|
if (outcome.blocked) return {
|
|
@@ -2633,6 +3030,7 @@ async function runOpenClawToolPolicyForApprovalRequest(params) {
|
|
|
2633
3030
|
reason: "OpenClaw tool policy rewrote Codex app-server approval params; refusing original request."
|
|
2634
3031
|
};
|
|
2635
3032
|
if (outcome.approvalResolution) return { outcome: "approved-once" };
|
|
3033
|
+
return { outcome: "allowed" };
|
|
2636
3034
|
}
|
|
2637
3035
|
async function runNativeRelayToolPolicyForApprovalRequest(params) {
|
|
2638
3036
|
if (params.method !== "item/commandExecution/requestApproval" || !params.nativeHookRelay?.allowedEvents.includes("pre_tool_use")) return;
|
|
@@ -3046,9 +3444,6 @@ function approvalKindForMethod(method) {
|
|
|
3046
3444
|
if (method.includes("fileChange") || method.includes("Patch") || method.includes("permissions")) return "plugin";
|
|
3047
3445
|
return "unknown";
|
|
3048
3446
|
}
|
|
3049
|
-
function isSupportedAppServerApprovalMethod(method) {
|
|
3050
|
-
return method === "item/commandExecution/requestApproval" || method === "item/fileChange/requestApproval" || method === "item/permissions/requestApproval";
|
|
3051
|
-
}
|
|
3052
3447
|
function emitApprovalEvent(params, data) {
|
|
3053
3448
|
params.onAgentEvent?.({
|
|
3054
3449
|
stream: "approval",
|
|
@@ -3152,25 +3547,6 @@ function formatErrorMessage$1(error) {
|
|
|
3152
3547
|
return error instanceof Error ? error.message : String(error);
|
|
3153
3548
|
}
|
|
3154
3549
|
//#endregion
|
|
3155
|
-
//#region extensions/codex/src/app-server/agent-context-limits.ts
|
|
3156
|
-
/** Resolves an agent override before falling back to the configured default. */
|
|
3157
|
-
function resolveAgentContextLimitValue(params) {
|
|
3158
|
-
const agents = asOptionalRecord(params.config?.agents);
|
|
3159
|
-
const defaultValue = readPositiveInteger(asOptionalRecord(asOptionalRecord(agents?.defaults)?.contextLimits)?.[params.key]);
|
|
3160
|
-
if (!params.agentId) return defaultValue;
|
|
3161
|
-
const list = agents?.list;
|
|
3162
|
-
if (!Array.isArray(list)) return defaultValue;
|
|
3163
|
-
const normalizedAgentId = normalizeAgentId(params.agentId);
|
|
3164
|
-
return readPositiveInteger(asOptionalRecord(asOptionalRecord(list.find((entry) => {
|
|
3165
|
-
const entryId = asOptionalRecord(entry)?.id;
|
|
3166
|
-
return typeof entryId === "string" && normalizeAgentId(entryId) === normalizedAgentId;
|
|
3167
|
-
}))?.contextLimits)?.[params.key]) ?? defaultValue;
|
|
3168
|
-
}
|
|
3169
|
-
function readPositiveInteger(value) {
|
|
3170
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return;
|
|
3171
|
-
return Math.floor(value);
|
|
3172
|
-
}
|
|
3173
|
-
//#endregion
|
|
3174
3550
|
//#region extensions/codex/src/app-server/dynamic-tools.ts
|
|
3175
3551
|
/**
|
|
3176
3552
|
* Bridges OpenClaw runtime tools into Codex app-server dynamic tool specs and
|
|
@@ -3319,6 +3695,13 @@ const EXPLICIT_MESSAGE_REPLY_KEYS = [
|
|
|
3319
3695
|
"replyToIdFull"
|
|
3320
3696
|
];
|
|
3321
3697
|
const DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS = 16e3;
|
|
3698
|
+
const LARGE_CONTEXT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS = 32e3;
|
|
3699
|
+
const XL_CONTEXT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS = 64e3;
|
|
3700
|
+
function resolveCodexDynamicToolResultMaxChars(contextWindowTokens) {
|
|
3701
|
+
if (typeof contextWindowTokens !== "number" || !Number.isFinite(contextWindowTokens) || contextWindowTokens <= 0) return DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS;
|
|
3702
|
+
const tokens = Math.floor(contextWindowTokens);
|
|
3703
|
+
return Math.min(tokens >= 2e5 ? XL_CONTEXT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS : tokens >= 1e5 ? LARGE_CONTEXT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS : DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS, Math.max(1, Math.floor(tokens * .3) * 4));
|
|
3704
|
+
}
|
|
3322
3705
|
function computerFrameImageIdentity(content) {
|
|
3323
3706
|
if (!Array.isArray(content)) return;
|
|
3324
3707
|
const images = content.filter((block) => block.type === "image");
|
|
@@ -3337,7 +3720,7 @@ function invalidateComputerFrame(contextEpoch) {
|
|
|
3337
3720
|
*/
|
|
3338
3721
|
function createCodexDynamicToolBridge(params) {
|
|
3339
3722
|
const toolResultHookContext = toToolResultHookContext(params.hookContext);
|
|
3340
|
-
const toolResultMaxChars = resolveCodexDynamicToolResultMaxChars(params.hookContext);
|
|
3723
|
+
const toolResultMaxChars = resolveCodexDynamicToolResultMaxChars(params.hookContext?.contextWindowTokens);
|
|
3341
3724
|
const availableProjection = projectCodexDynamicTools(params.tools);
|
|
3342
3725
|
const registeredProjection = params.registeredTools ? projectCodexDynamicTools(params.registeredTools) : availableProjection;
|
|
3343
3726
|
const wrappedAvailableProjection = wrapProjectedCodexDynamicTools(availableProjection.tools, params.hookContext);
|
|
@@ -3376,6 +3759,7 @@ function createCodexDynamicToolBridge(params) {
|
|
|
3376
3759
|
const legacyExtensionRunner = createCodexAppServerToolResultExtensionRunner(toolResultHookContext);
|
|
3377
3760
|
const executionSnapshotStates = /* @__PURE__ */ new Map();
|
|
3378
3761
|
const directToolNames = /* @__PURE__ */ new Set([...ALWAYS_DIRECT_DYNAMIC_TOOL_NAMES, ...params.directToolNames ?? []]);
|
|
3762
|
+
let readRemoteWorkspaceFile;
|
|
3379
3763
|
return {
|
|
3380
3764
|
availableSpecs: createCodexDynamicToolSpecs({
|
|
3381
3765
|
entries: availableTools,
|
|
@@ -3387,7 +3771,11 @@ function createCodexDynamicToolBridge(params) {
|
|
|
3387
3771
|
loading: params.loading ?? "searchable",
|
|
3388
3772
|
directToolNames
|
|
3389
3773
|
}),
|
|
3774
|
+
resultContentSourceForTool: (toolName) => toolMap.get(toolName)?.tool.resultContentSource,
|
|
3390
3775
|
telemetry,
|
|
3776
|
+
setRemoteWorkspaceFileReader: (reader) => {
|
|
3777
|
+
readRemoteWorkspaceFile = reader;
|
|
3778
|
+
},
|
|
3391
3779
|
consumeToolExecutionSnapshot: (toolCallId) => {
|
|
3392
3780
|
const state = executionSnapshotStates.get(toolCallId);
|
|
3393
3781
|
executionSnapshotStates.delete(toolCallId);
|
|
@@ -3438,7 +3826,15 @@ function createCodexDynamicToolBridge(params) {
|
|
|
3438
3826
|
};
|
|
3439
3827
|
};
|
|
3440
3828
|
try {
|
|
3441
|
-
const
|
|
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;
|
|
3442
3838
|
const telemetryArgs = isRecord(preparedArgs) ? preparedArgs : args;
|
|
3443
3839
|
executedArgs = structuredClone(telemetryArgs);
|
|
3444
3840
|
const messagingContext = {
|
|
@@ -3516,6 +3912,7 @@ function createCodexDynamicToolBridge(params) {
|
|
|
3516
3912
|
contentItems,
|
|
3517
3913
|
success: !resultIsError
|
|
3518
3914
|
}, terminalType);
|
|
3915
|
+
withDynamicToolTranscriptDetails(response, result.details);
|
|
3519
3916
|
withDiagnosticFailureDisposition(response, resultFailureKind);
|
|
3520
3917
|
const blocksSourceReplyTermination = hasExplicitNonSourceMessageRoute(executedArgs, params.hookContext, confirmedMessagingTarget);
|
|
3521
3918
|
const deliveredSourceReply = isDeliveredMessageToolOnlySourceReplyResult({
|
|
@@ -3669,7 +4066,8 @@ function createCodexDynamicToolSpecs(params) {
|
|
|
3669
4066
|
const specs = [];
|
|
3670
4067
|
const namespaceTools = [];
|
|
3671
4068
|
const directOnlyNamespaceTools = [];
|
|
3672
|
-
|
|
4069
|
+
const entries = params.loading === "direct" ? params.entries : params.entries.toSorted((left, right) => left.name.localeCompare(right.name));
|
|
4070
|
+
for (const entry of entries) {
|
|
3673
4071
|
const functionSpec = createCodexDynamicToolFunctionSpec({ entry });
|
|
3674
4072
|
if (entry.name === "openclaw" && params.directToolNames.has(entry.name)) {
|
|
3675
4073
|
specs.push(functionSpec);
|
|
@@ -3856,13 +4254,6 @@ function toToolResultHookContext(ctx) {
|
|
|
3856
4254
|
...channelId && { channelId }
|
|
3857
4255
|
};
|
|
3858
4256
|
}
|
|
3859
|
-
function resolveCodexDynamicToolResultMaxChars(ctx) {
|
|
3860
|
-
return resolveAgentContextLimitValue({
|
|
3861
|
-
config: ctx?.config,
|
|
3862
|
-
agentId: ctx?.agentId,
|
|
3863
|
-
key: "toolResultMaxChars"
|
|
3864
|
-
}) ?? DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS;
|
|
3865
|
-
}
|
|
3866
4257
|
function composeAbortSignals(...signals) {
|
|
3867
4258
|
const activeSignals = signals.filter((signal) => Boolean(signal));
|
|
3868
4259
|
if (activeSignals.length === 0) return new AbortController().signal;
|
|
@@ -4126,4 +4517,4 @@ function isCronAddAction(args) {
|
|
|
4126
4517
|
return typeof action === "string" && action.trim().toLowerCase() === "add";
|
|
4127
4518
|
}
|
|
4128
4519
|
//#endregion
|
|
4129
|
-
export {
|
|
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 };
|