@openclaw/codex 2026.5.27-beta.1 → 2026.5.28-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{client-BVK_jmHW.js → client-TfDda-h3.js} +1 -1
- package/dist/{client-factory-fW4Hh9q_.js → client-factory-BPBvbguy.js} +2 -2
- package/dist/{command-handlers-YXjMla3v.js → command-handlers-B8MXR7fh.js} +11 -11
- package/dist/{compact-DIXx9K0Q.js → compact-Dyz0rQLl.js} +10 -8
- package/dist/{computer-use-CakwWGCR.js → computer-use-BRIifWhE.js} +2 -2
- package/dist/{config-0-UN67Qg.js → config-BW7NPdAQ.js} +10 -3
- package/dist/{conversation-binding-CWaG0k5A.js → conversation-binding-D8OO0S9R.js} +7 -7
- package/dist/harness.js +5 -5
- package/dist/index.js +13 -12
- package/dist/media-understanding-provider.js +6 -6
- package/dist/{models-_XwpqjR8.js → models-Dnasi6LR.js} +1 -1
- package/dist/{vision-tools-DqpLmF5H.js → native-hook-relay-DYOYE3qb.js} +691 -14
- package/dist/{notification-correlation-YINts3PA.js → notification-correlation-BVB6XFQM.js} +44 -3
- package/dist/provider.js +2 -2
- package/dist/{request-Dtg0vQrE.js → request-Cj95iOk6.js} +3 -3
- package/dist/{run-attempt-BIbGYJog.js → run-attempt-D9i99EqV.js} +8098 -7879
- package/dist/{session-binding-4fRldGaa.js → session-binding-DuJisBZB.js} +1 -1
- package/dist/{shared-client-8kIrP817.js → shared-client-DICbgRn5.js} +21 -3
- package/dist/{side-question-v4nixmAs.js → side-question-280VWjeH.js} +7 -8
- package/dist/{thread-lifecycle-DZAfY4d6.js → thread-lifecycle-1u5ogKG_.js} +4 -4
- package/npm-shrinkwrap.json +96 -1771
- package/package.json +4 -5
- package/dist/dynamic-tools-BSZIYzfP.js +0 -560
- package/dist/test-api.js +0 -51
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { l as isJsonObject } from "./client-
|
|
2
|
-
import {
|
|
1
|
+
import { l as isJsonObject } from "./client-TfDda-h3.js";
|
|
2
|
+
import { S as invalidInlineImageText, w as sanitizeInlineImageDataUrl } from "./thread-lifecycle-1u5ogKG_.js";
|
|
3
|
+
import { s as formatCodexDisplayText } from "./notification-correlation-BVB6XFQM.js";
|
|
3
4
|
import { createHash } from "node:crypto";
|
|
4
|
-
import { normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
|
-
import { buildAgentHookContextChannelFields, callGatewayTool, embeddedAgentLog, formatApprovalDisplayPath, hasNativeHookRelayInvocation, invokeNativeHookRelay, runBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
5
|
+
import { asOptionalRecord, isRecord, normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
|
+
import { HEARTBEAT_RESPONSE_TOOL_NAME, buildAgentHookContextChannelFields, callGatewayTool, createAgentToolResultMiddlewareRunner, createCodexAppServerToolResultExtensionRunner, embeddedAgentLog, extractToolResultMediaArtifact, filterToolResultMediaUrls, formatApprovalDisplayPath, hasNativeHookRelayInvocation, invokeNativeHookRelay, isMessagingTool, isMessagingToolSendAction, isToolWrappedWithBeforeToolCallHook, normalizeHeartbeatToolResponse, projectRuntimeToolInputSchema, registerNativeHookRelay, resolveNativeHookRelayDeferredToolApproval, runAgentHarnessAfterToolCallHook, runBeforeToolCallHook, setBeforeToolCallDiagnosticsEnabled, wrapToolWithBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
6
7
|
import { emitTrustedDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
8
|
+
import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
|
|
7
9
|
//#region extensions/codex/src/app-server/plugin-approval-roundtrip.ts
|
|
8
10
|
const DEFAULT_CODEX_APPROVAL_TIMEOUT_MS = 12e4;
|
|
9
11
|
const MAX_PLUGIN_APPROVAL_TITLE_LENGTH = 80;
|
|
@@ -107,6 +109,18 @@ async function handleCodexAppServerApprovalRequest(params) {
|
|
|
107
109
|
});
|
|
108
110
|
return buildApprovalResponse(params.method, context.requestParams, "denied");
|
|
109
111
|
}
|
|
112
|
+
if (policyOutcome?.outcome === "approved-once" || policyOutcome?.outcome === "approved-session") {
|
|
113
|
+
emitApprovalEvent(params.paramsForRun, {
|
|
114
|
+
phase: "resolved",
|
|
115
|
+
kind: context.kind,
|
|
116
|
+
status: "approved",
|
|
117
|
+
title: context.title,
|
|
118
|
+
...context.eventDetails,
|
|
119
|
+
...approvalEventScope(params.method, policyOutcome.outcome),
|
|
120
|
+
message: approvalResolutionMessage(policyOutcome.outcome)
|
|
121
|
+
});
|
|
122
|
+
return buildApprovalResponse(params.method, context.requestParams, policyOutcome.outcome);
|
|
123
|
+
}
|
|
110
124
|
if (params.autoApprove === true) {
|
|
111
125
|
emitApprovalEvent(params.paramsForRun, {
|
|
112
126
|
phase: "resolved",
|
|
@@ -243,12 +257,14 @@ async function runOpenClawToolPolicyForApprovalRequest(params) {
|
|
|
243
257
|
context: params.context,
|
|
244
258
|
policyRequest,
|
|
245
259
|
nativeHookRelay: params.nativeHookRelay,
|
|
246
|
-
cwd
|
|
260
|
+
cwd,
|
|
261
|
+
signal: params.signal
|
|
247
262
|
});
|
|
248
263
|
if (nativeRelayOutcome?.blocked) return {
|
|
249
264
|
outcome: "denied",
|
|
250
265
|
reason: nativeRelayOutcome.reason
|
|
251
266
|
};
|
|
267
|
+
if (nativeRelayOutcome?.outcome === "approved-once" || nativeRelayOutcome?.outcome === "approved-session") return { outcome: nativeRelayOutcome.outcome };
|
|
252
268
|
if (nativeRelayOutcome?.handled) return { outcome: "no-decision" };
|
|
253
269
|
const hookChannelId = buildAgentHookContextChannelFields({
|
|
254
270
|
sessionKey: params.paramsForRun.sessionKey,
|
|
@@ -261,7 +277,7 @@ async function runOpenClawToolPolicyForApprovalRequest(params) {
|
|
|
261
277
|
toolName: policyRequest.toolName,
|
|
262
278
|
params: policyRequest.params,
|
|
263
279
|
...params.context.itemId ? { toolCallId: params.context.itemId } : {},
|
|
264
|
-
approvalMode: "
|
|
280
|
+
approvalMode: "request",
|
|
265
281
|
signal: params.signal,
|
|
266
282
|
ctx: {
|
|
267
283
|
...params.paramsForRun.agentId ? { agentId: params.paramsForRun.agentId } : {},
|
|
@@ -281,6 +297,7 @@ async function runOpenClawToolPolicyForApprovalRequest(params) {
|
|
|
281
297
|
outcome: "denied",
|
|
282
298
|
reason: "OpenClaw tool policy rewrote Codex app-server approval params; refusing original request."
|
|
283
299
|
};
|
|
300
|
+
if (outcome.approvalResolution) return { outcome: "approved-once" };
|
|
284
301
|
}
|
|
285
302
|
async function runNativeRelayToolPolicyForApprovalRequest(params) {
|
|
286
303
|
if (params.method !== "item/commandExecution/requestApproval" || !params.nativeHookRelay?.allowedEvents.includes("pre_tool_use")) return;
|
|
@@ -295,7 +312,23 @@ async function runNativeRelayToolPolicyForApprovalRequest(params) {
|
|
|
295
312
|
relayId: params.nativeHookRelay.relayId,
|
|
296
313
|
event: "pre_tool_use",
|
|
297
314
|
toolUseId: params.context.itemId
|
|
298
|
-
}))
|
|
315
|
+
})) {
|
|
316
|
+
const approvalOutcome = await resolveNativeHookRelayDeferredToolApproval({
|
|
317
|
+
relayId: params.nativeHookRelay.relayId,
|
|
318
|
+
toolUseId: params.context.itemId,
|
|
319
|
+
signal: params.signal
|
|
320
|
+
});
|
|
321
|
+
if (approvalOutcome?.outcome === "denied") return {
|
|
322
|
+
handled: true,
|
|
323
|
+
blocked: true,
|
|
324
|
+
reason: approvalOutcome.reason
|
|
325
|
+
};
|
|
326
|
+
if (approvalOutcome?.outcome === "approved-once") return {
|
|
327
|
+
handled: true,
|
|
328
|
+
outcome: approvalOutcome.outcome
|
|
329
|
+
};
|
|
330
|
+
return { handled: true };
|
|
331
|
+
}
|
|
299
332
|
try {
|
|
300
333
|
const decision = readNativeRelayPreToolUseDecision(await invokeNativeHookRelay({
|
|
301
334
|
provider: "codex",
|
|
@@ -310,6 +343,20 @@ async function runNativeRelayToolPolicyForApprovalRequest(params) {
|
|
|
310
343
|
blocked: true,
|
|
311
344
|
reason: decision.reason
|
|
312
345
|
};
|
|
346
|
+
const approvalOutcome = await resolveNativeHookRelayDeferredToolApproval({
|
|
347
|
+
relayId: params.nativeHookRelay.relayId,
|
|
348
|
+
toolUseId: params.context.itemId,
|
|
349
|
+
signal: params.signal
|
|
350
|
+
});
|
|
351
|
+
if (approvalOutcome?.outcome === "denied") return {
|
|
352
|
+
handled: true,
|
|
353
|
+
blocked: true,
|
|
354
|
+
reason: approvalOutcome.reason
|
|
355
|
+
};
|
|
356
|
+
if (approvalOutcome?.outcome === "approved-once") return {
|
|
357
|
+
handled: true,
|
|
358
|
+
outcome: approvalOutcome.outcome
|
|
359
|
+
};
|
|
313
360
|
return { handled: true };
|
|
314
361
|
} catch (error) {
|
|
315
362
|
return {
|
|
@@ -758,6 +805,50 @@ function formatErrorMessage$1(error) {
|
|
|
758
805
|
return error instanceof Error ? error.message : String(error);
|
|
759
806
|
}
|
|
760
807
|
//#endregion
|
|
808
|
+
//#region extensions/codex/src/app-server/dynamic-tool-profile.ts
|
|
809
|
+
const CODEX_APP_SERVER_OWNED_DYNAMIC_TOOL_EXCLUDES = [
|
|
810
|
+
"read",
|
|
811
|
+
"write",
|
|
812
|
+
"edit",
|
|
813
|
+
"apply_patch",
|
|
814
|
+
"exec",
|
|
815
|
+
"process",
|
|
816
|
+
"update_plan",
|
|
817
|
+
"tool_call",
|
|
818
|
+
"tool_describe",
|
|
819
|
+
"tool_search",
|
|
820
|
+
"tool_search_code"
|
|
821
|
+
];
|
|
822
|
+
const DYNAMIC_TOOL_NAME_ALIASES = {
|
|
823
|
+
bash: "exec",
|
|
824
|
+
"apply-patch": "apply_patch"
|
|
825
|
+
};
|
|
826
|
+
function normalizeCodexDynamicToolName(name) {
|
|
827
|
+
const normalized = name.trim().toLowerCase();
|
|
828
|
+
return DYNAMIC_TOOL_NAME_ALIASES[normalized] ?? normalized;
|
|
829
|
+
}
|
|
830
|
+
function isForcedPrivateQaCodexRuntime(env = process.env) {
|
|
831
|
+
return env.OPENCLAW_BUILD_PRIVATE_QA === "1" && env.OPENCLAW_QA_FORCE_RUNTIME?.trim().toLowerCase() === "codex";
|
|
832
|
+
}
|
|
833
|
+
function resolveCodexDynamicToolsLoading(config, env = process.env) {
|
|
834
|
+
return isForcedPrivateQaCodexRuntime(env) ? "direct" : config.codexDynamicToolsLoading ?? "searchable";
|
|
835
|
+
}
|
|
836
|
+
function filterCodexDynamicTools(tools, config, env = process.env) {
|
|
837
|
+
const excludes = /* @__PURE__ */ new Set();
|
|
838
|
+
if (!isForcedPrivateQaCodexRuntime(env)) for (const name of CODEX_APP_SERVER_OWNED_DYNAMIC_TOOL_EXCLUDES) excludes.add(name);
|
|
839
|
+
for (const name of config.codexDynamicToolsExclude ?? []) {
|
|
840
|
+
const trimmed = normalizeCodexDynamicToolName(name);
|
|
841
|
+
if (trimmed) excludes.add(trimmed);
|
|
842
|
+
}
|
|
843
|
+
return excludes.size === 0 ? tools : tools.filter((tool) => !excludes.has(normalizeCodexDynamicToolName(tool.name)));
|
|
844
|
+
}
|
|
845
|
+
//#endregion
|
|
846
|
+
//#region extensions/codex/src/app-server/vision-tools.ts
|
|
847
|
+
function filterToolsForVisionInputs(tools, params) {
|
|
848
|
+
if (!params.modelHasVision || !params.hasInboundImages) return tools;
|
|
849
|
+
return tools.filter((tool) => tool.name !== "image");
|
|
850
|
+
}
|
|
851
|
+
//#endregion
|
|
761
852
|
//#region extensions/codex/src/app-server/dynamic-tool-diagnostics.ts
|
|
762
853
|
function emitDynamicToolStartedDiagnostic(params) {
|
|
763
854
|
emitTrustedDiagnosticEvent({
|
|
@@ -811,6 +902,522 @@ function emitDynamicToolTerminalDiagnostic(params) {
|
|
|
811
902
|
emitDynamicToolErrorDiagnostic(params);
|
|
812
903
|
}
|
|
813
904
|
//#endregion
|
|
905
|
+
//#region extensions/codex/src/app-server/dynamic-tools.ts
|
|
906
|
+
const CODEX_OPENCLAW_DYNAMIC_TOOL_NAMESPACE = "openclaw";
|
|
907
|
+
const ALWAYS_DIRECT_DYNAMIC_TOOL_NAMES = new Set(["sessions_yield"]);
|
|
908
|
+
const DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS = 16e3;
|
|
909
|
+
function createCodexDynamicToolBridge(params) {
|
|
910
|
+
const toolResultHookContext = toToolResultHookContext(params.hookContext);
|
|
911
|
+
const toolResultMaxChars = resolveCodexDynamicToolResultMaxChars(params.hookContext);
|
|
912
|
+
const availableProjection = projectCodexDynamicTools(params.tools);
|
|
913
|
+
const registeredProjection = params.registeredTools ? projectCodexDynamicTools(params.registeredTools) : availableProjection;
|
|
914
|
+
const availableTools = availableProjection.tools.map(({ tool, inputSchema }) => {
|
|
915
|
+
if (isToolWrappedWithBeforeToolCallHook(tool)) {
|
|
916
|
+
setBeforeToolCallDiagnosticsEnabled(tool, false);
|
|
917
|
+
return {
|
|
918
|
+
tool,
|
|
919
|
+
inputSchema
|
|
920
|
+
};
|
|
921
|
+
}
|
|
922
|
+
return {
|
|
923
|
+
tool: wrapToolWithBeforeToolCallHook(tool, params.hookContext, { emitDiagnostics: false }),
|
|
924
|
+
inputSchema
|
|
925
|
+
};
|
|
926
|
+
});
|
|
927
|
+
const toolMap = new Map(availableTools.map(({ tool }) => [tool.name, tool]));
|
|
928
|
+
const registeredTools = registeredProjection.tools.map(({ tool }) => tool);
|
|
929
|
+
const registeredToolNames = new Set(registeredTools.map((tool) => tool.name));
|
|
930
|
+
const quarantinedTools = dedupeQuarantinedDynamicTools([...availableProjection.quarantinedTools, ...registeredProjection.quarantinedTools]);
|
|
931
|
+
warnQuarantinedDynamicTools(quarantinedTools);
|
|
932
|
+
emitQuarantinedDynamicToolDiagnostics(quarantinedTools, params.hookContext);
|
|
933
|
+
const telemetry = {
|
|
934
|
+
didSendViaMessagingTool: false,
|
|
935
|
+
messagingToolSentTexts: [],
|
|
936
|
+
messagingToolSentMediaUrls: [],
|
|
937
|
+
messagingToolSentTargets: [],
|
|
938
|
+
messagingToolSourceReplyPayloads: [],
|
|
939
|
+
toolMediaUrls: [],
|
|
940
|
+
toolAudioAsVoice: false,
|
|
941
|
+
quarantinedTools
|
|
942
|
+
};
|
|
943
|
+
const middlewareRunner = createAgentToolResultMiddlewareRunner({
|
|
944
|
+
runtime: "codex",
|
|
945
|
+
...toolResultHookContext
|
|
946
|
+
});
|
|
947
|
+
const legacyExtensionRunner = createCodexAppServerToolResultExtensionRunner(toolResultHookContext);
|
|
948
|
+
const directToolNames = new Set([...ALWAYS_DIRECT_DYNAMIC_TOOL_NAMES, ...params.directToolNames ?? []]);
|
|
949
|
+
return {
|
|
950
|
+
availableSpecs: availableTools.map(({ tool, inputSchema }) => createCodexDynamicToolSpec({
|
|
951
|
+
tool,
|
|
952
|
+
inputSchema,
|
|
953
|
+
loading: params.loading ?? "searchable",
|
|
954
|
+
directToolNames
|
|
955
|
+
})),
|
|
956
|
+
specs: registeredProjection.tools.map(({ tool, inputSchema }) => createCodexDynamicToolSpec({
|
|
957
|
+
tool,
|
|
958
|
+
inputSchema,
|
|
959
|
+
loading: params.loading ?? "searchable",
|
|
960
|
+
directToolNames
|
|
961
|
+
})),
|
|
962
|
+
telemetry,
|
|
963
|
+
handleToolCall: async (call, options) => {
|
|
964
|
+
const tool = toolMap.get(call.tool);
|
|
965
|
+
if (!tool) {
|
|
966
|
+
if (registeredToolNames.has(call.tool)) return {
|
|
967
|
+
contentItems: [{
|
|
968
|
+
type: "inputText",
|
|
969
|
+
text: `OpenClaw tool is not available for this turn: ${call.tool}`
|
|
970
|
+
}],
|
|
971
|
+
success: false
|
|
972
|
+
};
|
|
973
|
+
return {
|
|
974
|
+
contentItems: [{
|
|
975
|
+
type: "inputText",
|
|
976
|
+
text: `Unknown OpenClaw tool: ${call.tool}`
|
|
977
|
+
}],
|
|
978
|
+
success: false
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
const args = jsonObjectToRecord(call.arguments);
|
|
982
|
+
const startedAt = Date.now();
|
|
983
|
+
const signal = composeAbortSignals(params.signal, options?.signal);
|
|
984
|
+
let didStartExecution = false;
|
|
985
|
+
try {
|
|
986
|
+
const preparedArgs = tool.prepareArguments ? tool.prepareArguments(args) : args;
|
|
987
|
+
didStartExecution = true;
|
|
988
|
+
const rawResult = await tool.execute(call.callId, preparedArgs, signal);
|
|
989
|
+
const rawIsError = isToolResultError(rawResult);
|
|
990
|
+
const middlewareResult = await middlewareRunner.applyToolResultMiddleware({
|
|
991
|
+
threadId: call.threadId,
|
|
992
|
+
turnId: call.turnId,
|
|
993
|
+
toolCallId: call.callId,
|
|
994
|
+
toolName: tool.name,
|
|
995
|
+
args,
|
|
996
|
+
isError: rawIsError,
|
|
997
|
+
result: rawResult
|
|
998
|
+
});
|
|
999
|
+
const result = await legacyExtensionRunner.applyToolResultExtensions({
|
|
1000
|
+
threadId: call.threadId,
|
|
1001
|
+
turnId: call.turnId,
|
|
1002
|
+
toolCallId: call.callId,
|
|
1003
|
+
toolName: tool.name,
|
|
1004
|
+
args,
|
|
1005
|
+
result: middlewareResult
|
|
1006
|
+
});
|
|
1007
|
+
const resultIsError = rawIsError || isToolResultError(result);
|
|
1008
|
+
collectToolTelemetry({
|
|
1009
|
+
toolName: tool.name,
|
|
1010
|
+
args,
|
|
1011
|
+
result,
|
|
1012
|
+
mediaTrustResult: rawResult,
|
|
1013
|
+
telemetry,
|
|
1014
|
+
isError: resultIsError
|
|
1015
|
+
});
|
|
1016
|
+
runAgentHarnessAfterToolCallHook({
|
|
1017
|
+
toolName: tool.name,
|
|
1018
|
+
toolCallId: call.callId,
|
|
1019
|
+
runId: toolResultHookContext.runId,
|
|
1020
|
+
agentId: toolResultHookContext.agentId,
|
|
1021
|
+
sessionId: toolResultHookContext.sessionId,
|
|
1022
|
+
sessionKey: toolResultHookContext.sessionKey,
|
|
1023
|
+
channelId: toolResultHookContext.channelId,
|
|
1024
|
+
startArgs: args,
|
|
1025
|
+
result,
|
|
1026
|
+
startedAt
|
|
1027
|
+
});
|
|
1028
|
+
const terminalType = inferToolResultDiagnosticTerminalType(result, resultIsError);
|
|
1029
|
+
const response = withDiagnosticTerminalType({
|
|
1030
|
+
contentItems: convertToolContents(result.content, toolResultMaxChars),
|
|
1031
|
+
success: !resultIsError
|
|
1032
|
+
}, terminalType);
|
|
1033
|
+
withDynamicToolTermination(response, rawResult.terminate === true || result.terminate === true || isToolResultYield(rawResult) || isToolResultYield(result));
|
|
1034
|
+
withDynamicToolAsyncStarted(response, isAsyncStartedToolResult(rawResult) || isAsyncStartedToolResult(result));
|
|
1035
|
+
return withSideEffectEvidence(response, terminalType !== "blocked");
|
|
1036
|
+
} catch (error) {
|
|
1037
|
+
collectToolTelemetry({
|
|
1038
|
+
toolName: tool.name,
|
|
1039
|
+
args,
|
|
1040
|
+
result: void 0,
|
|
1041
|
+
telemetry,
|
|
1042
|
+
isError: true
|
|
1043
|
+
});
|
|
1044
|
+
runAgentHarnessAfterToolCallHook({
|
|
1045
|
+
toolName: tool.name,
|
|
1046
|
+
toolCallId: call.callId,
|
|
1047
|
+
runId: toolResultHookContext.runId,
|
|
1048
|
+
agentId: toolResultHookContext.agentId,
|
|
1049
|
+
sessionId: toolResultHookContext.sessionId,
|
|
1050
|
+
sessionKey: toolResultHookContext.sessionKey,
|
|
1051
|
+
channelId: toolResultHookContext.channelId,
|
|
1052
|
+
startArgs: args,
|
|
1053
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1054
|
+
startedAt
|
|
1055
|
+
});
|
|
1056
|
+
return withSideEffectEvidence(withDiagnosticTerminalType({
|
|
1057
|
+
contentItems: [{
|
|
1058
|
+
type: "inputText",
|
|
1059
|
+
text: error instanceof Error ? error.message : String(error)
|
|
1060
|
+
}],
|
|
1061
|
+
success: false
|
|
1062
|
+
}, "error"), didStartExecution);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
function createCodexDynamicToolSpec(params) {
|
|
1068
|
+
const base = {
|
|
1069
|
+
name: params.tool.name,
|
|
1070
|
+
description: params.tool.description,
|
|
1071
|
+
inputSchema: params.inputSchema
|
|
1072
|
+
};
|
|
1073
|
+
if (params.loading === "direct" || params.directToolNames.has(params.tool.name)) return base;
|
|
1074
|
+
return {
|
|
1075
|
+
...base,
|
|
1076
|
+
namespace: CODEX_OPENCLAW_DYNAMIC_TOOL_NAMESPACE,
|
|
1077
|
+
deferLoading: true
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
function projectCodexDynamicTools(tools) {
|
|
1081
|
+
const projectedTools = [];
|
|
1082
|
+
const quarantinedTools = [];
|
|
1083
|
+
for (const tool of tools) {
|
|
1084
|
+
const projection = projectRuntimeToolInputSchema(tool.parameters, `${tool.name}.inputSchema`);
|
|
1085
|
+
if (projection.violations.length > 0) {
|
|
1086
|
+
quarantinedTools.push({
|
|
1087
|
+
tool: tool.name,
|
|
1088
|
+
violations: projection.violations
|
|
1089
|
+
});
|
|
1090
|
+
continue;
|
|
1091
|
+
}
|
|
1092
|
+
projectedTools.push({
|
|
1093
|
+
tool,
|
|
1094
|
+
inputSchema: projection.schema
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
return {
|
|
1098
|
+
tools: projectedTools,
|
|
1099
|
+
quarantinedTools
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1102
|
+
function warnQuarantinedDynamicTools(tools) {
|
|
1103
|
+
if (tools.length === 0) return;
|
|
1104
|
+
const unique = /* @__PURE__ */ new Map();
|
|
1105
|
+
for (const tool of tools) unique.set(tool.tool, tool.violations);
|
|
1106
|
+
embeddedAgentLog.warn(`codex app-server quarantined ${unique.size} dynamic ${unique.size === 1 ? "tool" : "tools"} with unsupported input schemas: ${[...unique.keys()].join(", ")}`, { tools: [...unique.entries()].map(([tool, violations]) => ({
|
|
1107
|
+
tool,
|
|
1108
|
+
violations
|
|
1109
|
+
})) });
|
|
1110
|
+
}
|
|
1111
|
+
function emitQuarantinedDynamicToolDiagnostics(tools, ctx) {
|
|
1112
|
+
for (const tool of tools) emitTrustedDiagnosticEvent({
|
|
1113
|
+
type: "tool.execution.blocked",
|
|
1114
|
+
runId: ctx?.runId,
|
|
1115
|
+
sessionId: ctx?.sessionId,
|
|
1116
|
+
sessionKey: ctx?.sessionKey,
|
|
1117
|
+
toolName: tool.tool,
|
|
1118
|
+
deniedReason: "unsupported_tool_schema",
|
|
1119
|
+
reason: tool.violations.join(", ")
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
function dedupeQuarantinedDynamicTools(tools) {
|
|
1123
|
+
return [...new Map(tools.map((tool) => [tool.tool, {
|
|
1124
|
+
tool: tool.tool,
|
|
1125
|
+
violations: tool.violations
|
|
1126
|
+
}])).values()];
|
|
1127
|
+
}
|
|
1128
|
+
function toToolResultHookContext(ctx) {
|
|
1129
|
+
const { agentId, sessionId, sessionKey, runId, channelId } = ctx ?? {};
|
|
1130
|
+
return {
|
|
1131
|
+
...agentId && { agentId },
|
|
1132
|
+
...sessionId && { sessionId },
|
|
1133
|
+
...sessionKey && { sessionKey },
|
|
1134
|
+
...runId && { runId },
|
|
1135
|
+
...channelId && { channelId }
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
function resolveCodexDynamicToolResultMaxChars(ctx) {
|
|
1139
|
+
return resolveAgentContextLimitValue({
|
|
1140
|
+
config: ctx?.config,
|
|
1141
|
+
agentId: ctx?.agentId,
|
|
1142
|
+
key: "toolResultMaxChars"
|
|
1143
|
+
}) ?? DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS;
|
|
1144
|
+
}
|
|
1145
|
+
function resolveAgentContextLimitValue(params) {
|
|
1146
|
+
const agents = asOptionalRecord(params.config?.agents);
|
|
1147
|
+
const defaultValue = readPositiveInteger(asOptionalRecord(asOptionalRecord(agents?.defaults)?.contextLimits)?.[params.key]);
|
|
1148
|
+
if (!params.agentId) return defaultValue;
|
|
1149
|
+
const list = agents?.list;
|
|
1150
|
+
if (!Array.isArray(list)) return defaultValue;
|
|
1151
|
+
const normalizedAgentId = normalizeAgentId(params.agentId);
|
|
1152
|
+
return readPositiveInteger(asOptionalRecord(asOptionalRecord(list.find((entry) => {
|
|
1153
|
+
const entryId = asOptionalRecord(entry)?.id;
|
|
1154
|
+
return typeof entryId === "string" && normalizeAgentId(entryId) === normalizedAgentId;
|
|
1155
|
+
}))?.contextLimits)?.[params.key]) ?? defaultValue;
|
|
1156
|
+
}
|
|
1157
|
+
function composeAbortSignals(...signals) {
|
|
1158
|
+
const activeSignals = signals.filter((signal) => Boolean(signal));
|
|
1159
|
+
if (activeSignals.length === 0) return new AbortController().signal;
|
|
1160
|
+
if (activeSignals.length === 1) return activeSignals[0];
|
|
1161
|
+
return AbortSignal.any(activeSignals);
|
|
1162
|
+
}
|
|
1163
|
+
function collectToolTelemetry(params) {
|
|
1164
|
+
if (params.isError) return;
|
|
1165
|
+
if (!params.isError && params.toolName === "cron" && isCronAddAction(params.args)) params.telemetry.successfulCronAdds = (params.telemetry.successfulCronAdds ?? 0) + 1;
|
|
1166
|
+
if (!params.isError && params.toolName === HEARTBEAT_RESPONSE_TOOL_NAME) {
|
|
1167
|
+
const response = normalizeHeartbeatToolResponse(params.result?.details);
|
|
1168
|
+
if (response) params.telemetry.heartbeatToolResponse = response;
|
|
1169
|
+
}
|
|
1170
|
+
if (!params.isError && params.result) {
|
|
1171
|
+
const media = extractToolResultMediaArtifact(params.result);
|
|
1172
|
+
if (media) {
|
|
1173
|
+
const mediaUrls = filterToolResultMediaUrls(params.toolName, media.mediaUrls, params.mediaTrustResult ?? params.result);
|
|
1174
|
+
const seen = new Set(params.telemetry.toolMediaUrls);
|
|
1175
|
+
for (const mediaUrl of mediaUrls) if (!seen.has(mediaUrl)) {
|
|
1176
|
+
seen.add(mediaUrl);
|
|
1177
|
+
params.telemetry.toolMediaUrls.push(mediaUrl);
|
|
1178
|
+
}
|
|
1179
|
+
if (media.audioAsVoice) params.telemetry.toolAudioAsVoice = true;
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
if (!isMessagingTool(params.toolName) || !isMessagingToolSendAction(params.toolName, params.args)) return;
|
|
1183
|
+
params.telemetry.didSendViaMessagingTool = true;
|
|
1184
|
+
const sourceReplyPayload = extractInternalSourceReplyPayload(params.result?.details);
|
|
1185
|
+
if (sourceReplyPayload) {
|
|
1186
|
+
params.telemetry.messagingToolSourceReplyPayloads.push(sourceReplyPayload);
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1189
|
+
const text = readFirstString$1(params.args, [
|
|
1190
|
+
"text",
|
|
1191
|
+
"message",
|
|
1192
|
+
"body",
|
|
1193
|
+
"content"
|
|
1194
|
+
]);
|
|
1195
|
+
if (text) params.telemetry.messagingToolSentTexts.push(text);
|
|
1196
|
+
const mediaUrls = collectMediaUrls(params.args);
|
|
1197
|
+
params.telemetry.messagingToolSentMediaUrls.push(...mediaUrls);
|
|
1198
|
+
params.telemetry.messagingToolSentTargets.push({
|
|
1199
|
+
tool: params.toolName,
|
|
1200
|
+
provider: readFirstString$1(params.args, ["provider", "channel"]) ?? params.toolName,
|
|
1201
|
+
accountId: readFirstString$1(params.args, ["accountId", "account_id"]),
|
|
1202
|
+
to: readFirstString$1(params.args, [
|
|
1203
|
+
"to",
|
|
1204
|
+
"target",
|
|
1205
|
+
"recipient"
|
|
1206
|
+
]),
|
|
1207
|
+
threadId: readFirstString$1(params.args, [
|
|
1208
|
+
"threadId",
|
|
1209
|
+
"thread_id",
|
|
1210
|
+
"messageThreadId"
|
|
1211
|
+
]),
|
|
1212
|
+
...text ? { text } : {},
|
|
1213
|
+
...mediaUrls.length > 0 ? { mediaUrls } : {}
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
function extractInternalSourceReplyPayload(details) {
|
|
1217
|
+
if (!isRecord(details) || details.sourceReplySink !== "internal-ui") return;
|
|
1218
|
+
const rawPayload = details.sourceReply;
|
|
1219
|
+
if (!isRecord(rawPayload)) return;
|
|
1220
|
+
const text = readFirstString$1(rawPayload, ["text", "message"]);
|
|
1221
|
+
const mediaUrls = collectMediaUrls(rawPayload);
|
|
1222
|
+
const mediaUrl = typeof rawPayload.mediaUrl === "string" && rawPayload.mediaUrl.trim() ? rawPayload.mediaUrl.trim() : mediaUrls[0];
|
|
1223
|
+
const payload = {
|
|
1224
|
+
...text ? { text } : {},
|
|
1225
|
+
...mediaUrl ? { mediaUrl } : {},
|
|
1226
|
+
...mediaUrls.length > 0 ? { mediaUrls } : {},
|
|
1227
|
+
...rawPayload.audioAsVoice === true ? { audioAsVoice: true } : {},
|
|
1228
|
+
...isRecord(rawPayload.presentation) ? { presentation: rawPayload.presentation } : {},
|
|
1229
|
+
...isRecord(rawPayload.interactive) ? { interactive: rawPayload.interactive } : {},
|
|
1230
|
+
...isRecord(rawPayload.channelData) ? { channelData: rawPayload.channelData } : {},
|
|
1231
|
+
...typeof details.idempotencyKey === "string" && details.idempotencyKey.trim() ? { idempotencyKey: details.idempotencyKey.trim() } : {}
|
|
1232
|
+
};
|
|
1233
|
+
return text || mediaUrls.length > 0 || payload.presentation || payload.interactive ? payload : void 0;
|
|
1234
|
+
}
|
|
1235
|
+
function readPositiveInteger(value) {
|
|
1236
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return;
|
|
1237
|
+
return Math.floor(value);
|
|
1238
|
+
}
|
|
1239
|
+
function isToolResultError(result) {
|
|
1240
|
+
const details = result.details;
|
|
1241
|
+
if (!isRecord(details)) return false;
|
|
1242
|
+
if (details.timedOut === true) return true;
|
|
1243
|
+
if (typeof details.exitCode === "number" && details.exitCode !== 0) return true;
|
|
1244
|
+
if (typeof details.status !== "string") return false;
|
|
1245
|
+
const status = details.status.trim().toLowerCase();
|
|
1246
|
+
return status !== "" && status !== "0" && status !== "ok" && status !== "success" && status !== "completed" && status !== "recorded" && status !== "pending" && status !== "started" && status !== "running" && status !== "yielded";
|
|
1247
|
+
}
|
|
1248
|
+
function isToolResultYield(result) {
|
|
1249
|
+
const details = result.details;
|
|
1250
|
+
if (!isRecord(details) || typeof details.status !== "string") return false;
|
|
1251
|
+
return details.status.trim().toLowerCase() === "yielded";
|
|
1252
|
+
}
|
|
1253
|
+
function isAsyncStartedToolResult(result) {
|
|
1254
|
+
const details = result.details;
|
|
1255
|
+
return isRecord(details) && details.async === true && details.status === "started";
|
|
1256
|
+
}
|
|
1257
|
+
function inferToolResultDiagnosticTerminalType(result, isError) {
|
|
1258
|
+
const details = result.details;
|
|
1259
|
+
if (isRecord(details) && typeof details.status === "string") {
|
|
1260
|
+
if (details.status.trim().toLowerCase() === "blocked") return "blocked";
|
|
1261
|
+
}
|
|
1262
|
+
return isError ? "error" : "completed";
|
|
1263
|
+
}
|
|
1264
|
+
function withDiagnosticTerminalType(response, terminalType) {
|
|
1265
|
+
Object.defineProperty(response, "diagnosticTerminalType", {
|
|
1266
|
+
configurable: true,
|
|
1267
|
+
enumerable: false,
|
|
1268
|
+
value: terminalType
|
|
1269
|
+
});
|
|
1270
|
+
return response;
|
|
1271
|
+
}
|
|
1272
|
+
function withSideEffectEvidence(response, sideEffectEvidence) {
|
|
1273
|
+
if (!sideEffectEvidence) return response;
|
|
1274
|
+
Object.defineProperty(response, "sideEffectEvidence", {
|
|
1275
|
+
configurable: true,
|
|
1276
|
+
enumerable: false,
|
|
1277
|
+
value: true
|
|
1278
|
+
});
|
|
1279
|
+
return response;
|
|
1280
|
+
}
|
|
1281
|
+
function withDynamicToolTermination(response, terminate) {
|
|
1282
|
+
if (!terminate) return response;
|
|
1283
|
+
Object.defineProperty(response, "terminate", {
|
|
1284
|
+
configurable: true,
|
|
1285
|
+
enumerable: false,
|
|
1286
|
+
value: true
|
|
1287
|
+
});
|
|
1288
|
+
return response;
|
|
1289
|
+
}
|
|
1290
|
+
function withDynamicToolAsyncStarted(response, asyncStarted) {
|
|
1291
|
+
if (!asyncStarted) return response;
|
|
1292
|
+
Object.defineProperty(response, "asyncStarted", {
|
|
1293
|
+
configurable: true,
|
|
1294
|
+
enumerable: false,
|
|
1295
|
+
value: true
|
|
1296
|
+
});
|
|
1297
|
+
return response;
|
|
1298
|
+
}
|
|
1299
|
+
function normalizeToolResultMaxChars(maxChars) {
|
|
1300
|
+
return typeof maxChars === "number" && Number.isFinite(maxChars) && maxChars > 0 ? Math.floor(maxChars) : DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS;
|
|
1301
|
+
}
|
|
1302
|
+
function convertToolContents(content, toolResultMaxChars = DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS) {
|
|
1303
|
+
const maxChars = normalizeToolResultMaxChars(toolResultMaxChars);
|
|
1304
|
+
const totalTextChars = content.reduce((total, item) => total + (item.type === "text" ? item.text.length : 0), 0);
|
|
1305
|
+
if (totalTextChars <= maxChars) return content.flatMap(convertToolContent);
|
|
1306
|
+
const noticeText = `...(OpenClaw truncated dynamic tool result: original ${totalTextChars} chars, showing ${maxChars}; rerun with narrower args.)`;
|
|
1307
|
+
const notice = `\n${noticeText}`;
|
|
1308
|
+
let remainingTextBudget = Math.max(0, maxChars - notice.length);
|
|
1309
|
+
let appendedNotice = false;
|
|
1310
|
+
const output = [];
|
|
1311
|
+
for (const item of content) {
|
|
1312
|
+
if (item.type !== "text") {
|
|
1313
|
+
output.push(...convertToolContent(item));
|
|
1314
|
+
continue;
|
|
1315
|
+
}
|
|
1316
|
+
if (appendedNotice) continue;
|
|
1317
|
+
if (notice.length >= maxChars) {
|
|
1318
|
+
output.push({
|
|
1319
|
+
type: "inputText",
|
|
1320
|
+
text: noticeText.slice(0, maxChars)
|
|
1321
|
+
});
|
|
1322
|
+
appendedNotice = true;
|
|
1323
|
+
continue;
|
|
1324
|
+
}
|
|
1325
|
+
const sliceLength = Math.min(item.text.length, remainingTextBudget);
|
|
1326
|
+
remainingTextBudget -= sliceLength;
|
|
1327
|
+
const shouldAppendNotice = remainingTextBudget <= 0;
|
|
1328
|
+
const text = item.text.slice(0, sliceLength);
|
|
1329
|
+
if (shouldAppendNotice) {
|
|
1330
|
+
output.push({
|
|
1331
|
+
type: "inputText",
|
|
1332
|
+
text: `${text.trimEnd()}${notice}`.slice(0, maxChars)
|
|
1333
|
+
});
|
|
1334
|
+
appendedNotice = true;
|
|
1335
|
+
} else if (text.length > 0) output.push({
|
|
1336
|
+
type: "inputText",
|
|
1337
|
+
text
|
|
1338
|
+
});
|
|
1339
|
+
}
|
|
1340
|
+
if (!appendedNotice) output.push({
|
|
1341
|
+
type: "inputText",
|
|
1342
|
+
text: noticeText.slice(0, maxChars)
|
|
1343
|
+
});
|
|
1344
|
+
return output;
|
|
1345
|
+
}
|
|
1346
|
+
function convertToolContent(content) {
|
|
1347
|
+
if (content.type === "text") return [{
|
|
1348
|
+
type: "inputText",
|
|
1349
|
+
text: content.text
|
|
1350
|
+
}];
|
|
1351
|
+
const imageUrl = sanitizeInlineImageDataUrl(`data:${content.mimeType};base64,${content.data}`);
|
|
1352
|
+
if (!imageUrl) return [{
|
|
1353
|
+
type: "inputText",
|
|
1354
|
+
text: invalidInlineImageText("codex dynamic tool")
|
|
1355
|
+
}];
|
|
1356
|
+
return [{
|
|
1357
|
+
type: "inputImage",
|
|
1358
|
+
imageUrl
|
|
1359
|
+
}];
|
|
1360
|
+
}
|
|
1361
|
+
function jsonObjectToRecord(value) {
|
|
1362
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
1363
|
+
return value;
|
|
1364
|
+
}
|
|
1365
|
+
function readFirstString$1(record, keys) {
|
|
1366
|
+
for (const key of keys) {
|
|
1367
|
+
const value = record[key];
|
|
1368
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
1369
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
function collectMediaUrls(record) {
|
|
1373
|
+
const urls = [];
|
|
1374
|
+
const pushMediaUrl = (value) => {
|
|
1375
|
+
if (typeof value === "string" && value.trim()) urls.push(value.trim());
|
|
1376
|
+
};
|
|
1377
|
+
const pushAttachment = (value) => {
|
|
1378
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
1379
|
+
const attachment = value;
|
|
1380
|
+
for (const key of [
|
|
1381
|
+
"media",
|
|
1382
|
+
"mediaUrl",
|
|
1383
|
+
"path",
|
|
1384
|
+
"filePath",
|
|
1385
|
+
"fileUrl",
|
|
1386
|
+
"url"
|
|
1387
|
+
]) pushMediaUrl(attachment[key]);
|
|
1388
|
+
};
|
|
1389
|
+
for (const key of [
|
|
1390
|
+
"media",
|
|
1391
|
+
"mediaUrl",
|
|
1392
|
+
"media_url",
|
|
1393
|
+
"path",
|
|
1394
|
+
"filePath",
|
|
1395
|
+
"fileUrl",
|
|
1396
|
+
"imageUrl",
|
|
1397
|
+
"image_url"
|
|
1398
|
+
]) {
|
|
1399
|
+
const value = record[key];
|
|
1400
|
+
pushMediaUrl(value);
|
|
1401
|
+
}
|
|
1402
|
+
for (const key of [
|
|
1403
|
+
"mediaUrls",
|
|
1404
|
+
"media_urls",
|
|
1405
|
+
"imageUrls",
|
|
1406
|
+
"image_urls"
|
|
1407
|
+
]) {
|
|
1408
|
+
const value = record[key];
|
|
1409
|
+
if (!Array.isArray(value)) continue;
|
|
1410
|
+
for (const entry of value) pushMediaUrl(entry);
|
|
1411
|
+
}
|
|
1412
|
+
const attachments = record.attachments;
|
|
1413
|
+
if (Array.isArray(attachments)) for (const attachment of attachments) pushAttachment(attachment);
|
|
1414
|
+
return urls;
|
|
1415
|
+
}
|
|
1416
|
+
function isCronAddAction(args) {
|
|
1417
|
+
const action = args.action;
|
|
1418
|
+
return typeof action === "string" && action.trim().toLowerCase() === "add";
|
|
1419
|
+
}
|
|
1420
|
+
//#endregion
|
|
814
1421
|
//#region extensions/codex/src/app-server/elicitation-bridge.ts
|
|
815
1422
|
const MCP_TOOL_APPROVAL_KIND = "mcp_tool_call";
|
|
816
1423
|
const MCP_TOOL_APPROVAL_KIND_KEY = "codex_approval_kind";
|
|
@@ -1326,6 +1933,82 @@ const CODEX_NATIVE_HOOK_RELAY_EVENTS = [
|
|
|
1326
1933
|
"permission_request",
|
|
1327
1934
|
"before_agent_finalize"
|
|
1328
1935
|
];
|
|
1936
|
+
const CODEX_NATIVE_HOOK_RELAY_EVENTS_WITH_APP_SERVER_APPROVALS = CODEX_NATIVE_HOOK_RELAY_EVENTS.filter((event) => event !== "permission_request");
|
|
1937
|
+
const CODEX_NATIVE_HOOK_RELAY_MIN_TTL_MS = 30 * 6e4;
|
|
1938
|
+
const CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS = 5 * 6e4;
|
|
1939
|
+
const CODEX_NATIVE_HOOK_RELAY_UNREGISTER_GRACE_MS = 1e4;
|
|
1940
|
+
const CODEX_NATIVE_HOOK_RELAY_UNREGISTER_EXTRA_GRACE_MS = 5e3;
|
|
1941
|
+
const pendingCodexNativeHookRelayUnregisters = /* @__PURE__ */ new Set();
|
|
1942
|
+
function scheduleCodexNativeHookRelayUnregister(params) {
|
|
1943
|
+
let pending;
|
|
1944
|
+
const unregister = () => {
|
|
1945
|
+
if (!pending) return;
|
|
1946
|
+
const current = pending;
|
|
1947
|
+
pending = void 0;
|
|
1948
|
+
if (!pendingCodexNativeHookRelayUnregisters.delete(current)) return;
|
|
1949
|
+
params.relay.unregister();
|
|
1950
|
+
};
|
|
1951
|
+
const timeout = setTimeout(unregister, resolveCodexNativeHookRelayUnregisterGraceMs(params.hookTimeoutSec));
|
|
1952
|
+
pending = {
|
|
1953
|
+
timeout,
|
|
1954
|
+
unregister
|
|
1955
|
+
};
|
|
1956
|
+
pendingCodexNativeHookRelayUnregisters.add(pending);
|
|
1957
|
+
timeout.unref();
|
|
1958
|
+
}
|
|
1959
|
+
function resolveCodexNativeHookRelayUnregisterGraceMs(hookTimeoutSec) {
|
|
1960
|
+
const hookTimeoutMs = typeof hookTimeoutSec === "number" && Number.isFinite(hookTimeoutSec) && hookTimeoutSec > 0 ? Math.ceil(hookTimeoutSec) * 1e3 : 0;
|
|
1961
|
+
return Math.max(CODEX_NATIVE_HOOK_RELAY_UNREGISTER_GRACE_MS, hookTimeoutMs + CODEX_NATIVE_HOOK_RELAY_UNREGISTER_EXTRA_GRACE_MS);
|
|
1962
|
+
}
|
|
1963
|
+
function createCodexNativeHookRelay(params) {
|
|
1964
|
+
if (params.options?.enabled === false) return;
|
|
1965
|
+
return registerNativeHookRelay({
|
|
1966
|
+
provider: "codex",
|
|
1967
|
+
relayId: buildCodexNativeHookRelayId({
|
|
1968
|
+
agentId: params.agentId,
|
|
1969
|
+
sessionId: params.sessionId,
|
|
1970
|
+
sessionKey: params.sessionKey
|
|
1971
|
+
}),
|
|
1972
|
+
...params.generation ? { generation: params.generation } : {},
|
|
1973
|
+
...params.generationMismatchGraceMs ? { generationMismatchGraceMs: params.generationMismatchGraceMs } : {},
|
|
1974
|
+
...params.agentId ? { agentId: params.agentId } : {},
|
|
1975
|
+
sessionId: params.sessionId,
|
|
1976
|
+
...params.sessionKey ? { sessionKey: params.sessionKey } : {},
|
|
1977
|
+
...params.config ? { config: params.config } : {},
|
|
1978
|
+
runId: params.runId,
|
|
1979
|
+
...params.channelId ? { channelId: params.channelId } : {},
|
|
1980
|
+
allowedEvents: params.events,
|
|
1981
|
+
ttlMs: resolveCodexNativeHookRelayTtlMs({
|
|
1982
|
+
explicitTtlMs: params.options?.ttlMs,
|
|
1983
|
+
attemptTimeoutMs: params.attemptTimeoutMs,
|
|
1984
|
+
startupTimeoutMs: params.startupTimeoutMs,
|
|
1985
|
+
turnStartTimeoutMs: params.turnStartTimeoutMs
|
|
1986
|
+
}),
|
|
1987
|
+
signal: params.signal,
|
|
1988
|
+
command: {
|
|
1989
|
+
nice: 10,
|
|
1990
|
+
timeoutMs: params.options?.gatewayTimeoutMs
|
|
1991
|
+
}
|
|
1992
|
+
});
|
|
1993
|
+
}
|
|
1994
|
+
function resolveCodexNativeHookRelayEvents(params) {
|
|
1995
|
+
if (params.configuredEvents?.length) return params.configuredEvents;
|
|
1996
|
+
return params.appServer.approvalPolicy === "never" ? CODEX_NATIVE_HOOK_RELAY_EVENTS : CODEX_NATIVE_HOOK_RELAY_EVENTS_WITH_APP_SERVER_APPROVALS;
|
|
1997
|
+
}
|
|
1998
|
+
function resolveCodexNativeHookRelayTtlMs(params) {
|
|
1999
|
+
if (params.explicitTtlMs !== void 0) return params.explicitTtlMs;
|
|
2000
|
+
const relayBudgetMs = params.attemptTimeoutMs + params.startupTimeoutMs + params.turnStartTimeoutMs + CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS;
|
|
2001
|
+
return Math.max(CODEX_NATIVE_HOOK_RELAY_MIN_TTL_MS, Math.floor(relayBudgetMs));
|
|
2002
|
+
}
|
|
2003
|
+
function buildCodexNativeHookRelayId(params) {
|
|
2004
|
+
const hash = createHash("sha256");
|
|
2005
|
+
hash.update("openclaw:codex:native-hook-relay:v1");
|
|
2006
|
+
hash.update("\0");
|
|
2007
|
+
hash.update(params.agentId?.trim() || "");
|
|
2008
|
+
hash.update("\0");
|
|
2009
|
+
hash.update(params.sessionKey?.trim() || params.sessionId);
|
|
2010
|
+
return `codex-${hash.digest("hex").slice(0, 40)}`;
|
|
2011
|
+
}
|
|
1329
2012
|
const CODEX_HOOK_EVENT_BY_NATIVE_EVENT = {
|
|
1330
2013
|
pre_tool_use: "PreToolUse",
|
|
1331
2014
|
post_tool_use: "PostToolUse",
|
|
@@ -1408,10 +2091,4 @@ function sortJsonValue(value) {
|
|
|
1408
2091
|
return sorted;
|
|
1409
2092
|
}
|
|
1410
2093
|
//#endregion
|
|
1411
|
-
|
|
1412
|
-
function filterToolsForVisionInputs(tools, params) {
|
|
1413
|
-
if (!params.modelHasVision || !params.hasInboundImages) return tools;
|
|
1414
|
-
return tools.filter((tool) => tool.name !== "image");
|
|
1415
|
-
}
|
|
1416
|
-
//#endregion
|
|
1417
|
-
export { handleCodexAppServerElicitationRequest as a, emitDynamicToolTerminalDiagnostic as c, buildCodexNativeHookRelayDisabledConfig as i, handleCodexAppServerApprovalRequest as l, CODEX_NATIVE_HOOK_RELAY_EVENTS as n, emitDynamicToolErrorDiagnostic as o, buildCodexNativeHookRelayConfig as r, emitDynamicToolStartedDiagnostic as s, filterToolsForVisionInputs as t };
|
|
2094
|
+
export { normalizeCodexDynamicToolName as _, createCodexNativeHookRelay as a, scheduleCodexNativeHookRelayUnregister as c, emitDynamicToolErrorDiagnostic as d, emitDynamicToolStartedDiagnostic as f, isForcedPrivateQaCodexRuntime as g, filterCodexDynamicTools as h, buildCodexNativeHookRelayDisabledConfig as i, handleCodexAppServerElicitationRequest as l, filterToolsForVisionInputs as m, CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS as n, resolveCodexNativeHookRelayEvents as o, emitDynamicToolTerminalDiagnostic as p, buildCodexNativeHookRelayConfig as r, resolveCodexNativeHookRelayTtlMs as s, CODEX_NATIVE_HOOK_RELAY_EVENTS as t, createCodexDynamicToolBridge as u, resolveCodexDynamicToolsLoading as v, handleCodexAppServerApprovalRequest as y };
|