@openclaw/codex 2026.5.20 → 2026.5.22
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-Ab4Fw77C.js → client-D3SUwPFl.js} +14 -8
- package/dist/{client-factory-BbesECdh.js → client-factory-DdrIY1lw.js} +1 -1
- package/dist/{command-handlers-Gceg_rBZ.js → command-handlers-DsB0GYd2.js} +64 -7
- package/dist/{compact-BaSDurdH.js → compact-BwQn7jKq.js} +186 -40
- package/dist/{computer-use-B4iTog6z.js → computer-use-BMMwWwno.js} +2 -2
- package/dist/{config-DqIp6oTk.js → config-DDMrwfJl.js} +21 -2
- package/dist/dynamic-tools-DA42no4X.js +497 -0
- package/dist/harness.js +15 -5
- package/dist/index.js +10 -9
- package/dist/media-understanding-provider.js +6 -3
- package/dist/{models-C8MdOXGD.js → models-B_uo1pf5.js} +1 -1
- package/dist/{node-cli-sessions-T1olB1SH.js → node-cli-sessions-yVCifOyG.js} +23 -9
- package/dist/{command-formatters-BVBnEgyA.js → notification-correlation-qKY_sgga.js} +66 -15
- package/dist/provider.js +3 -3
- package/dist/{request-BePR77QD.js → request-NklFaHM4.js} +12 -3
- package/dist/{run-attempt-CRHVB240.js → run-attempt-DzlLXP5Y.js} +3750 -1409
- package/dist/sandbox-guard-CTnEWuor.js +233 -0
- package/dist/{session-binding-DEiYHgJ_.js → session-binding-Bw_mfIW2.js} +4 -2
- package/dist/{shared-client-DCxJx5QU.js → shared-client-C_RbGxW8.js} +2 -2
- package/dist/{side-question-DlJAUYst.js → side-question-DzP1wClA.js} +20 -15
- package/dist/test-api.js +3 -2
- package/dist/{thread-lifecycle-Cgi62SSl.js → thread-lifecycle-4Ul7RoW4.js} +606 -589
- package/dist/{vision-tools-B2wt6ecs.js → vision-tools-DOnxzH2y.js} +7 -3
- package/npm-shrinkwrap.json +1934 -0
- package/openclaw.plugin.json +29 -0
- package/package.json +8 -6
- package/dist/plugin-activation-BkQkPLOY.js +0 -452
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
import { C as sanitizeInlineImageDataUrl, x as invalidInlineImageText } from "./thread-lifecycle-4Ul7RoW4.js";
|
|
2
|
+
import { HEARTBEAT_RESPONSE_TOOL_NAME, createAgentToolResultMiddlewareRunner, createCodexAppServerToolResultExtensionRunner, extractToolResultMediaArtifact, filterToolResultMediaUrls, isMessagingTool, isMessagingToolSendAction, isToolWrappedWithBeforeToolCallHook, normalizeHeartbeatToolResponse, runAgentHarnessAfterToolCallHook, setBeforeToolCallDiagnosticsEnabled, wrapToolWithBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
3
|
+
import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
|
|
4
|
+
//#region extensions/codex/src/app-server/dynamic-tool-profile.ts
|
|
5
|
+
const CODEX_APP_SERVER_OWNED_DYNAMIC_TOOL_EXCLUDES = [
|
|
6
|
+
"read",
|
|
7
|
+
"write",
|
|
8
|
+
"edit",
|
|
9
|
+
"apply_patch",
|
|
10
|
+
"exec",
|
|
11
|
+
"process",
|
|
12
|
+
"update_plan",
|
|
13
|
+
"tool_call",
|
|
14
|
+
"tool_describe",
|
|
15
|
+
"tool_search",
|
|
16
|
+
"tool_search_code"
|
|
17
|
+
];
|
|
18
|
+
const DYNAMIC_TOOL_NAME_ALIASES = {
|
|
19
|
+
bash: "exec",
|
|
20
|
+
"apply-patch": "apply_patch"
|
|
21
|
+
};
|
|
22
|
+
function normalizeCodexDynamicToolName(name) {
|
|
23
|
+
const normalized = name.trim().toLowerCase();
|
|
24
|
+
return DYNAMIC_TOOL_NAME_ALIASES[normalized] ?? normalized;
|
|
25
|
+
}
|
|
26
|
+
function isForcedPrivateQaCodexRuntime(env = process.env) {
|
|
27
|
+
return env.OPENCLAW_BUILD_PRIVATE_QA === "1" && env.OPENCLAW_QA_FORCE_RUNTIME?.trim().toLowerCase() === "codex";
|
|
28
|
+
}
|
|
29
|
+
function resolveCodexDynamicToolsLoading(config, env = process.env) {
|
|
30
|
+
return isForcedPrivateQaCodexRuntime(env) ? "direct" : config.codexDynamicToolsLoading ?? "searchable";
|
|
31
|
+
}
|
|
32
|
+
function filterCodexDynamicTools(tools, config, env = process.env) {
|
|
33
|
+
const excludes = /* @__PURE__ */ new Set();
|
|
34
|
+
if (!isForcedPrivateQaCodexRuntime(env)) for (const name of CODEX_APP_SERVER_OWNED_DYNAMIC_TOOL_EXCLUDES) excludes.add(name);
|
|
35
|
+
for (const name of config.codexDynamicToolsExclude ?? []) {
|
|
36
|
+
const trimmed = normalizeCodexDynamicToolName(name);
|
|
37
|
+
if (trimmed) excludes.add(trimmed);
|
|
38
|
+
}
|
|
39
|
+
return excludes.size === 0 ? tools : tools.filter((tool) => !excludes.has(normalizeCodexDynamicToolName(tool.name)));
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region extensions/codex/src/app-server/dynamic-tools.ts
|
|
43
|
+
const CODEX_OPENCLAW_DYNAMIC_TOOL_NAMESPACE = "openclaw";
|
|
44
|
+
const ALWAYS_DIRECT_DYNAMIC_TOOL_NAMES = new Set(["sessions_yield"]);
|
|
45
|
+
const DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS = 16e3;
|
|
46
|
+
function createCodexDynamicToolBridge(params) {
|
|
47
|
+
const toolResultHookContext = toToolResultHookContext(params.hookContext);
|
|
48
|
+
const toolResultMaxChars = resolveCodexDynamicToolResultMaxChars(params.hookContext);
|
|
49
|
+
const tools = params.tools.map((tool) => {
|
|
50
|
+
if (isToolWrappedWithBeforeToolCallHook(tool)) {
|
|
51
|
+
setBeforeToolCallDiagnosticsEnabled(tool, false);
|
|
52
|
+
return tool;
|
|
53
|
+
}
|
|
54
|
+
return wrapToolWithBeforeToolCallHook(tool, params.hookContext, { emitDiagnostics: false });
|
|
55
|
+
});
|
|
56
|
+
const toolMap = new Map(tools.map((tool) => [tool.name, tool]));
|
|
57
|
+
const registeredTools = params.registeredTools ?? tools;
|
|
58
|
+
const registeredToolNames = new Set(registeredTools.map((tool) => tool.name));
|
|
59
|
+
const telemetry = {
|
|
60
|
+
didSendViaMessagingTool: false,
|
|
61
|
+
messagingToolSentTexts: [],
|
|
62
|
+
messagingToolSentMediaUrls: [],
|
|
63
|
+
messagingToolSentTargets: [],
|
|
64
|
+
messagingToolSourceReplyPayloads: [],
|
|
65
|
+
toolMediaUrls: [],
|
|
66
|
+
toolAudioAsVoice: false
|
|
67
|
+
};
|
|
68
|
+
const middlewareRunner = createAgentToolResultMiddlewareRunner({
|
|
69
|
+
runtime: "codex",
|
|
70
|
+
...toolResultHookContext
|
|
71
|
+
});
|
|
72
|
+
const legacyExtensionRunner = createCodexAppServerToolResultExtensionRunner(toolResultHookContext);
|
|
73
|
+
const directToolNames = new Set([...ALWAYS_DIRECT_DYNAMIC_TOOL_NAMES, ...params.directToolNames ?? []]);
|
|
74
|
+
return {
|
|
75
|
+
availableSpecs: tools.map((tool) => createCodexDynamicToolSpec({
|
|
76
|
+
tool,
|
|
77
|
+
loading: params.loading ?? "searchable",
|
|
78
|
+
directToolNames
|
|
79
|
+
})),
|
|
80
|
+
specs: registeredTools.map((tool) => createCodexDynamicToolSpec({
|
|
81
|
+
tool,
|
|
82
|
+
loading: params.loading ?? "searchable",
|
|
83
|
+
directToolNames
|
|
84
|
+
})),
|
|
85
|
+
telemetry,
|
|
86
|
+
handleToolCall: async (call, options) => {
|
|
87
|
+
const tool = toolMap.get(call.tool);
|
|
88
|
+
if (!tool) {
|
|
89
|
+
if (registeredToolNames.has(call.tool)) return {
|
|
90
|
+
contentItems: [{
|
|
91
|
+
type: "inputText",
|
|
92
|
+
text: `OpenClaw tool is not available for this turn: ${call.tool}`
|
|
93
|
+
}],
|
|
94
|
+
success: false
|
|
95
|
+
};
|
|
96
|
+
return {
|
|
97
|
+
contentItems: [{
|
|
98
|
+
type: "inputText",
|
|
99
|
+
text: `Unknown OpenClaw tool: ${call.tool}`
|
|
100
|
+
}],
|
|
101
|
+
success: false
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const args = jsonObjectToRecord(call.arguments);
|
|
105
|
+
const startedAt = Date.now();
|
|
106
|
+
const signal = composeAbortSignals(params.signal, options?.signal);
|
|
107
|
+
let didStartExecution = false;
|
|
108
|
+
try {
|
|
109
|
+
const preparedArgs = tool.prepareArguments ? tool.prepareArguments(args) : args;
|
|
110
|
+
didStartExecution = true;
|
|
111
|
+
const rawResult = await tool.execute(call.callId, preparedArgs, signal);
|
|
112
|
+
const rawIsError = isToolResultError(rawResult);
|
|
113
|
+
const middlewareResult = await middlewareRunner.applyToolResultMiddleware({
|
|
114
|
+
threadId: call.threadId,
|
|
115
|
+
turnId: call.turnId,
|
|
116
|
+
toolCallId: call.callId,
|
|
117
|
+
toolName: tool.name,
|
|
118
|
+
args,
|
|
119
|
+
isError: rawIsError,
|
|
120
|
+
result: rawResult
|
|
121
|
+
});
|
|
122
|
+
const result = await legacyExtensionRunner.applyToolResultExtensions({
|
|
123
|
+
threadId: call.threadId,
|
|
124
|
+
turnId: call.turnId,
|
|
125
|
+
toolCallId: call.callId,
|
|
126
|
+
toolName: tool.name,
|
|
127
|
+
args,
|
|
128
|
+
result: middlewareResult
|
|
129
|
+
});
|
|
130
|
+
const resultIsError = rawIsError || isToolResultError(result);
|
|
131
|
+
collectToolTelemetry({
|
|
132
|
+
toolName: tool.name,
|
|
133
|
+
args,
|
|
134
|
+
result,
|
|
135
|
+
mediaTrustResult: rawResult,
|
|
136
|
+
telemetry,
|
|
137
|
+
isError: resultIsError
|
|
138
|
+
});
|
|
139
|
+
runAgentHarnessAfterToolCallHook({
|
|
140
|
+
toolName: tool.name,
|
|
141
|
+
toolCallId: call.callId,
|
|
142
|
+
runId: toolResultHookContext.runId,
|
|
143
|
+
agentId: toolResultHookContext.agentId,
|
|
144
|
+
sessionId: toolResultHookContext.sessionId,
|
|
145
|
+
sessionKey: toolResultHookContext.sessionKey,
|
|
146
|
+
channelId: toolResultHookContext.channelId,
|
|
147
|
+
startArgs: args,
|
|
148
|
+
result,
|
|
149
|
+
startedAt
|
|
150
|
+
});
|
|
151
|
+
const terminalType = inferToolResultDiagnosticTerminalType(result, resultIsError);
|
|
152
|
+
const response = withDiagnosticTerminalType({
|
|
153
|
+
contentItems: convertToolContents(result.content, toolResultMaxChars),
|
|
154
|
+
success: !resultIsError
|
|
155
|
+
}, terminalType);
|
|
156
|
+
withDynamicToolTermination(response, rawResult.terminate === true || result.terminate === true || isToolResultYield(rawResult) || isToolResultYield(result));
|
|
157
|
+
return withSideEffectEvidence(response, terminalType !== "blocked");
|
|
158
|
+
} catch (error) {
|
|
159
|
+
collectToolTelemetry({
|
|
160
|
+
toolName: tool.name,
|
|
161
|
+
args,
|
|
162
|
+
result: void 0,
|
|
163
|
+
telemetry,
|
|
164
|
+
isError: true
|
|
165
|
+
});
|
|
166
|
+
runAgentHarnessAfterToolCallHook({
|
|
167
|
+
toolName: tool.name,
|
|
168
|
+
toolCallId: call.callId,
|
|
169
|
+
runId: toolResultHookContext.runId,
|
|
170
|
+
agentId: toolResultHookContext.agentId,
|
|
171
|
+
sessionId: toolResultHookContext.sessionId,
|
|
172
|
+
sessionKey: toolResultHookContext.sessionKey,
|
|
173
|
+
channelId: toolResultHookContext.channelId,
|
|
174
|
+
startArgs: args,
|
|
175
|
+
error: error instanceof Error ? error.message : String(error),
|
|
176
|
+
startedAt
|
|
177
|
+
});
|
|
178
|
+
return withSideEffectEvidence(withDiagnosticTerminalType({
|
|
179
|
+
contentItems: [{
|
|
180
|
+
type: "inputText",
|
|
181
|
+
text: error instanceof Error ? error.message : String(error)
|
|
182
|
+
}],
|
|
183
|
+
success: false
|
|
184
|
+
}, "error"), didStartExecution);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function createCodexDynamicToolSpec(params) {
|
|
190
|
+
const base = {
|
|
191
|
+
name: params.tool.name,
|
|
192
|
+
description: params.tool.description,
|
|
193
|
+
inputSchema: toJsonValue(params.tool.parameters)
|
|
194
|
+
};
|
|
195
|
+
if (params.loading === "direct" || params.directToolNames.has(params.tool.name)) return base;
|
|
196
|
+
return {
|
|
197
|
+
...base,
|
|
198
|
+
namespace: CODEX_OPENCLAW_DYNAMIC_TOOL_NAMESPACE,
|
|
199
|
+
deferLoading: true
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function toToolResultHookContext(ctx) {
|
|
203
|
+
const { agentId, sessionId, sessionKey, runId, channelId } = ctx ?? {};
|
|
204
|
+
return {
|
|
205
|
+
...agentId && { agentId },
|
|
206
|
+
...sessionId && { sessionId },
|
|
207
|
+
...sessionKey && { sessionKey },
|
|
208
|
+
...runId && { runId },
|
|
209
|
+
...channelId && { channelId }
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function resolveCodexDynamicToolResultMaxChars(ctx) {
|
|
213
|
+
return resolveAgentContextLimitValue({
|
|
214
|
+
config: ctx?.config,
|
|
215
|
+
agentId: ctx?.agentId,
|
|
216
|
+
key: "toolResultMaxChars"
|
|
217
|
+
}) ?? DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS;
|
|
218
|
+
}
|
|
219
|
+
function resolveAgentContextLimitValue(params) {
|
|
220
|
+
const agents = readRecord(params.config?.agents);
|
|
221
|
+
const defaultValue = readPositiveInteger(readRecord(readRecord(agents?.defaults)?.contextLimits)?.[params.key]);
|
|
222
|
+
if (!params.agentId) return defaultValue;
|
|
223
|
+
const list = agents?.list;
|
|
224
|
+
if (!Array.isArray(list)) return defaultValue;
|
|
225
|
+
const normalizedAgentId = normalizeAgentId(params.agentId);
|
|
226
|
+
return readPositiveInteger(readRecord(readRecord(list.find((entry) => {
|
|
227
|
+
const entryId = readRecord(entry)?.id;
|
|
228
|
+
return typeof entryId === "string" && normalizeAgentId(entryId) === normalizedAgentId;
|
|
229
|
+
}))?.contextLimits)?.[params.key]) ?? defaultValue;
|
|
230
|
+
}
|
|
231
|
+
function composeAbortSignals(...signals) {
|
|
232
|
+
const activeSignals = signals.filter((signal) => Boolean(signal));
|
|
233
|
+
if (activeSignals.length === 0) return new AbortController().signal;
|
|
234
|
+
if (activeSignals.length === 1) return activeSignals[0];
|
|
235
|
+
return AbortSignal.any(activeSignals);
|
|
236
|
+
}
|
|
237
|
+
function collectToolTelemetry(params) {
|
|
238
|
+
if (params.isError) return;
|
|
239
|
+
if (!params.isError && params.toolName === "cron" && isCronAddAction(params.args)) params.telemetry.successfulCronAdds = (params.telemetry.successfulCronAdds ?? 0) + 1;
|
|
240
|
+
if (!params.isError && params.toolName === HEARTBEAT_RESPONSE_TOOL_NAME) {
|
|
241
|
+
const response = normalizeHeartbeatToolResponse(params.result?.details);
|
|
242
|
+
if (response) params.telemetry.heartbeatToolResponse = response;
|
|
243
|
+
}
|
|
244
|
+
if (!params.isError && params.result) {
|
|
245
|
+
const media = extractToolResultMediaArtifact(params.result);
|
|
246
|
+
if (media) {
|
|
247
|
+
const mediaUrls = filterToolResultMediaUrls(params.toolName, media.mediaUrls, params.mediaTrustResult ?? params.result);
|
|
248
|
+
const seen = new Set(params.telemetry.toolMediaUrls);
|
|
249
|
+
for (const mediaUrl of mediaUrls) if (!seen.has(mediaUrl)) {
|
|
250
|
+
seen.add(mediaUrl);
|
|
251
|
+
params.telemetry.toolMediaUrls.push(mediaUrl);
|
|
252
|
+
}
|
|
253
|
+
if (media.audioAsVoice) params.telemetry.toolAudioAsVoice = true;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (!isMessagingTool(params.toolName) || !isMessagingToolSendAction(params.toolName, params.args)) return;
|
|
257
|
+
params.telemetry.didSendViaMessagingTool = true;
|
|
258
|
+
const sourceReplyPayload = extractInternalSourceReplyPayload(params.result?.details);
|
|
259
|
+
if (sourceReplyPayload) {
|
|
260
|
+
params.telemetry.messagingToolSourceReplyPayloads.push(sourceReplyPayload);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const text = readFirstString(params.args, [
|
|
264
|
+
"text",
|
|
265
|
+
"message",
|
|
266
|
+
"body",
|
|
267
|
+
"content"
|
|
268
|
+
]);
|
|
269
|
+
if (text) params.telemetry.messagingToolSentTexts.push(text);
|
|
270
|
+
const mediaUrls = collectMediaUrls(params.args);
|
|
271
|
+
params.telemetry.messagingToolSentMediaUrls.push(...mediaUrls);
|
|
272
|
+
params.telemetry.messagingToolSentTargets.push({
|
|
273
|
+
tool: params.toolName,
|
|
274
|
+
provider: readFirstString(params.args, ["provider", "channel"]) ?? params.toolName,
|
|
275
|
+
accountId: readFirstString(params.args, ["accountId", "account_id"]),
|
|
276
|
+
to: readFirstString(params.args, [
|
|
277
|
+
"to",
|
|
278
|
+
"target",
|
|
279
|
+
"recipient"
|
|
280
|
+
]),
|
|
281
|
+
threadId: readFirstString(params.args, [
|
|
282
|
+
"threadId",
|
|
283
|
+
"thread_id",
|
|
284
|
+
"messageThreadId"
|
|
285
|
+
]),
|
|
286
|
+
...text ? { text } : {},
|
|
287
|
+
...mediaUrls.length > 0 ? { mediaUrls } : {}
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
function extractInternalSourceReplyPayload(details) {
|
|
291
|
+
if (!isRecord(details) || details.sourceReplySink !== "internal-ui") return;
|
|
292
|
+
const rawPayload = details.sourceReply;
|
|
293
|
+
if (!isRecord(rawPayload)) return;
|
|
294
|
+
const text = readFirstString(rawPayload, ["text", "message"]);
|
|
295
|
+
const mediaUrls = collectMediaUrls(rawPayload);
|
|
296
|
+
const mediaUrl = typeof rawPayload.mediaUrl === "string" && rawPayload.mediaUrl.trim() ? rawPayload.mediaUrl.trim() : mediaUrls[0];
|
|
297
|
+
const payload = {
|
|
298
|
+
...text ? { text } : {},
|
|
299
|
+
...mediaUrl ? { mediaUrl } : {},
|
|
300
|
+
...mediaUrls.length > 0 ? { mediaUrls } : {},
|
|
301
|
+
...rawPayload.audioAsVoice === true ? { audioAsVoice: true } : {},
|
|
302
|
+
...isRecord(rawPayload.presentation) ? { presentation: rawPayload.presentation } : {},
|
|
303
|
+
...isRecord(rawPayload.interactive) ? { interactive: rawPayload.interactive } : {},
|
|
304
|
+
...isRecord(rawPayload.channelData) ? { channelData: rawPayload.channelData } : {},
|
|
305
|
+
...typeof details.idempotencyKey === "string" && details.idempotencyKey.trim() ? { idempotencyKey: details.idempotencyKey.trim() } : {}
|
|
306
|
+
};
|
|
307
|
+
return text || mediaUrls.length > 0 || payload.presentation || payload.interactive ? payload : void 0;
|
|
308
|
+
}
|
|
309
|
+
function isRecord(value) {
|
|
310
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
311
|
+
}
|
|
312
|
+
function readRecord(value) {
|
|
313
|
+
return isRecord(value) ? value : void 0;
|
|
314
|
+
}
|
|
315
|
+
function readPositiveInteger(value) {
|
|
316
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return;
|
|
317
|
+
return Math.floor(value);
|
|
318
|
+
}
|
|
319
|
+
function isToolResultError(result) {
|
|
320
|
+
const details = result.details;
|
|
321
|
+
if (!isRecord(details)) return false;
|
|
322
|
+
if (details.timedOut === true) return true;
|
|
323
|
+
if (typeof details.exitCode === "number" && details.exitCode !== 0) return true;
|
|
324
|
+
if (typeof details.status !== "string") return false;
|
|
325
|
+
const status = details.status.trim().toLowerCase();
|
|
326
|
+
return status !== "" && status !== "0" && status !== "ok" && status !== "success" && status !== "completed" && status !== "recorded" && status !== "pending" && status !== "started" && status !== "running" && status !== "yielded";
|
|
327
|
+
}
|
|
328
|
+
function isToolResultYield(result) {
|
|
329
|
+
const details = result.details;
|
|
330
|
+
if (!isRecord(details) || typeof details.status !== "string") return false;
|
|
331
|
+
return details.status.trim().toLowerCase() === "yielded";
|
|
332
|
+
}
|
|
333
|
+
function inferToolResultDiagnosticTerminalType(result, isError) {
|
|
334
|
+
const details = result.details;
|
|
335
|
+
if (isRecord(details) && typeof details.status === "string") {
|
|
336
|
+
if (details.status.trim().toLowerCase() === "blocked") return "blocked";
|
|
337
|
+
}
|
|
338
|
+
return isError ? "error" : "completed";
|
|
339
|
+
}
|
|
340
|
+
function withDiagnosticTerminalType(response, terminalType) {
|
|
341
|
+
Object.defineProperty(response, "diagnosticTerminalType", {
|
|
342
|
+
configurable: true,
|
|
343
|
+
enumerable: false,
|
|
344
|
+
value: terminalType
|
|
345
|
+
});
|
|
346
|
+
return response;
|
|
347
|
+
}
|
|
348
|
+
function withSideEffectEvidence(response, sideEffectEvidence) {
|
|
349
|
+
if (!sideEffectEvidence) return response;
|
|
350
|
+
Object.defineProperty(response, "sideEffectEvidence", {
|
|
351
|
+
configurable: true,
|
|
352
|
+
enumerable: false,
|
|
353
|
+
value: true
|
|
354
|
+
});
|
|
355
|
+
return response;
|
|
356
|
+
}
|
|
357
|
+
function withDynamicToolTermination(response, terminate) {
|
|
358
|
+
if (!terminate) return response;
|
|
359
|
+
Object.defineProperty(response, "terminate", {
|
|
360
|
+
configurable: true,
|
|
361
|
+
enumerable: false,
|
|
362
|
+
value: true
|
|
363
|
+
});
|
|
364
|
+
return response;
|
|
365
|
+
}
|
|
366
|
+
function normalizeToolResultMaxChars(maxChars) {
|
|
367
|
+
return typeof maxChars === "number" && Number.isFinite(maxChars) && maxChars > 0 ? Math.floor(maxChars) : DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS;
|
|
368
|
+
}
|
|
369
|
+
function convertToolContents(content, toolResultMaxChars = DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS) {
|
|
370
|
+
const maxChars = normalizeToolResultMaxChars(toolResultMaxChars);
|
|
371
|
+
const totalTextChars = content.reduce((total, item) => total + (item.type === "text" ? item.text.length : 0), 0);
|
|
372
|
+
if (totalTextChars <= maxChars) return content.flatMap(convertToolContent);
|
|
373
|
+
const noticeText = `...(OpenClaw truncated dynamic tool result: original ${totalTextChars} chars, showing ${maxChars}; rerun with narrower args.)`;
|
|
374
|
+
const notice = `\n${noticeText}`;
|
|
375
|
+
let remainingTextBudget = Math.max(0, maxChars - notice.length);
|
|
376
|
+
let appendedNotice = false;
|
|
377
|
+
const output = [];
|
|
378
|
+
for (const item of content) {
|
|
379
|
+
if (item.type !== "text") {
|
|
380
|
+
output.push(...convertToolContent(item));
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
if (appendedNotice) continue;
|
|
384
|
+
if (notice.length >= maxChars) {
|
|
385
|
+
output.push({
|
|
386
|
+
type: "inputText",
|
|
387
|
+
text: noticeText.slice(0, maxChars)
|
|
388
|
+
});
|
|
389
|
+
appendedNotice = true;
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
const sliceLength = Math.min(item.text.length, remainingTextBudget);
|
|
393
|
+
remainingTextBudget -= sliceLength;
|
|
394
|
+
const shouldAppendNotice = remainingTextBudget <= 0;
|
|
395
|
+
const text = item.text.slice(0, sliceLength);
|
|
396
|
+
if (shouldAppendNotice) {
|
|
397
|
+
output.push({
|
|
398
|
+
type: "inputText",
|
|
399
|
+
text: `${text.trimEnd()}${notice}`.slice(0, maxChars)
|
|
400
|
+
});
|
|
401
|
+
appendedNotice = true;
|
|
402
|
+
} else if (text.length > 0) output.push({
|
|
403
|
+
type: "inputText",
|
|
404
|
+
text
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
if (!appendedNotice) output.push({
|
|
408
|
+
type: "inputText",
|
|
409
|
+
text: noticeText.slice(0, maxChars)
|
|
410
|
+
});
|
|
411
|
+
return output;
|
|
412
|
+
}
|
|
413
|
+
function convertToolContent(content) {
|
|
414
|
+
if (content.type === "text") return [{
|
|
415
|
+
type: "inputText",
|
|
416
|
+
text: content.text
|
|
417
|
+
}];
|
|
418
|
+
const imageUrl = sanitizeInlineImageDataUrl(`data:${content.mimeType};base64,${content.data}`);
|
|
419
|
+
if (!imageUrl) return [{
|
|
420
|
+
type: "inputText",
|
|
421
|
+
text: invalidInlineImageText("codex dynamic tool")
|
|
422
|
+
}];
|
|
423
|
+
return [{
|
|
424
|
+
type: "inputImage",
|
|
425
|
+
imageUrl
|
|
426
|
+
}];
|
|
427
|
+
}
|
|
428
|
+
function toJsonValue(value) {
|
|
429
|
+
try {
|
|
430
|
+
const text = JSON.stringify(value);
|
|
431
|
+
if (!text) return {};
|
|
432
|
+
return JSON.parse(text);
|
|
433
|
+
} catch {
|
|
434
|
+
return {};
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
function jsonObjectToRecord(value) {
|
|
438
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
439
|
+
return value;
|
|
440
|
+
}
|
|
441
|
+
function readFirstString(record, keys) {
|
|
442
|
+
for (const key of keys) {
|
|
443
|
+
const value = record[key];
|
|
444
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
445
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
function collectMediaUrls(record) {
|
|
449
|
+
const urls = [];
|
|
450
|
+
const pushMediaUrl = (value) => {
|
|
451
|
+
if (typeof value === "string" && value.trim()) urls.push(value.trim());
|
|
452
|
+
};
|
|
453
|
+
const pushAttachment = (value) => {
|
|
454
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
455
|
+
const attachment = value;
|
|
456
|
+
for (const key of [
|
|
457
|
+
"media",
|
|
458
|
+
"mediaUrl",
|
|
459
|
+
"path",
|
|
460
|
+
"filePath",
|
|
461
|
+
"fileUrl",
|
|
462
|
+
"url"
|
|
463
|
+
]) pushMediaUrl(attachment[key]);
|
|
464
|
+
};
|
|
465
|
+
for (const key of [
|
|
466
|
+
"media",
|
|
467
|
+
"mediaUrl",
|
|
468
|
+
"media_url",
|
|
469
|
+
"path",
|
|
470
|
+
"filePath",
|
|
471
|
+
"fileUrl",
|
|
472
|
+
"imageUrl",
|
|
473
|
+
"image_url"
|
|
474
|
+
]) {
|
|
475
|
+
const value = record[key];
|
|
476
|
+
pushMediaUrl(value);
|
|
477
|
+
}
|
|
478
|
+
for (const key of [
|
|
479
|
+
"mediaUrls",
|
|
480
|
+
"media_urls",
|
|
481
|
+
"imageUrls",
|
|
482
|
+
"image_urls"
|
|
483
|
+
]) {
|
|
484
|
+
const value = record[key];
|
|
485
|
+
if (!Array.isArray(value)) continue;
|
|
486
|
+
for (const entry of value) pushMediaUrl(entry);
|
|
487
|
+
}
|
|
488
|
+
const attachments = record.attachments;
|
|
489
|
+
if (Array.isArray(attachments)) for (const attachment of attachments) pushAttachment(attachment);
|
|
490
|
+
return urls;
|
|
491
|
+
}
|
|
492
|
+
function isCronAddAction(args) {
|
|
493
|
+
const action = args.action;
|
|
494
|
+
return typeof action === "string" && action.trim().toLowerCase() === "add";
|
|
495
|
+
}
|
|
496
|
+
//#endregion
|
|
497
|
+
export { resolveCodexDynamicToolsLoading as a, normalizeCodexDynamicToolName as i, filterCodexDynamicTools as n, isForcedPrivateQaCodexRuntime as r, createCodexDynamicToolBridge as t };
|
package/dist/harness.js
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
//#region extensions/codex/harness.ts
|
|
2
2
|
const DEFAULT_CODEX_HARNESS_PROVIDER_IDS = new Set(["codex"]);
|
|
3
|
+
const CODEX_APP_SERVER_CONTEXT_ENGINE_HOST_CAPABILITIES = [
|
|
4
|
+
"bootstrap",
|
|
5
|
+
"assemble-before-prompt",
|
|
6
|
+
"after-turn",
|
|
7
|
+
"maintain",
|
|
8
|
+
"compact",
|
|
9
|
+
"runtime-llm-complete",
|
|
10
|
+
"thread-bootstrap-projection"
|
|
11
|
+
];
|
|
3
12
|
function createCodexAppServerAgentHarness(options) {
|
|
4
13
|
const providerIds = new Set([...options?.providerIds ?? DEFAULT_CODEX_HARNESS_PROVIDER_IDS].map((id) => id.trim().toLowerCase()));
|
|
5
14
|
return {
|
|
6
15
|
id: options?.id ?? "codex",
|
|
7
16
|
label: options?.label ?? "Codex agent harness",
|
|
17
|
+
contextEngineHostCapabilities: CODEX_APP_SERVER_CONTEXT_ENGINE_HOST_CAPABILITIES,
|
|
8
18
|
deliveryDefaults: { sourceVisibleReplies: "message_tool" },
|
|
9
19
|
supports: (ctx) => {
|
|
10
20
|
const provider = ctx.provider.trim().toLowerCase();
|
|
@@ -18,31 +28,31 @@ function createCodexAppServerAgentHarness(options) {
|
|
|
18
28
|
};
|
|
19
29
|
},
|
|
20
30
|
runAttempt: async (params) => {
|
|
21
|
-
const { runCodexAppServerAttempt } = await import("./run-attempt-
|
|
31
|
+
const { runCodexAppServerAttempt } = await import("./run-attempt-DzlLXP5Y.js");
|
|
22
32
|
return runCodexAppServerAttempt(params, {
|
|
23
33
|
pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
|
|
24
34
|
nativeHookRelay: { enabled: true }
|
|
25
35
|
});
|
|
26
36
|
},
|
|
27
37
|
runSideQuestion: async (params) => {
|
|
28
|
-
const { runCodexAppServerSideQuestion } = await import("./side-question-
|
|
38
|
+
const { runCodexAppServerSideQuestion } = await import("./side-question-DzP1wClA.js");
|
|
29
39
|
return runCodexAppServerSideQuestion(params, {
|
|
30
40
|
pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
|
|
31
41
|
nativeHookRelay: { enabled: true }
|
|
32
42
|
});
|
|
33
43
|
},
|
|
34
44
|
compact: async (params) => {
|
|
35
|
-
const { maybeCompactCodexAppServerSession } = await import("./compact-
|
|
45
|
+
const { maybeCompactCodexAppServerSession } = await import("./compact-BwQn7jKq.js");
|
|
36
46
|
return maybeCompactCodexAppServerSession(params, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
|
|
37
47
|
},
|
|
38
48
|
reset: async (params) => {
|
|
39
49
|
if (params.sessionFile) {
|
|
40
|
-
const { clearCodexAppServerBinding } = await import("./session-binding-
|
|
50
|
+
const { clearCodexAppServerBinding } = await import("./session-binding-Bw_mfIW2.js").then((n) => n.a);
|
|
41
51
|
await clearCodexAppServerBinding(params.sessionFile);
|
|
42
52
|
}
|
|
43
53
|
},
|
|
44
54
|
dispose: async () => {
|
|
45
|
-
const { clearSharedCodexAppServerClientAndWait } = await import("./shared-client-
|
|
55
|
+
const { clearSharedCodexAppServerClientAndWait } = await import("./shared-client-C_RbGxW8.js").then((n) => n.a);
|
|
46
56
|
await clearSharedCodexAppServerClientAndWait();
|
|
47
57
|
}
|
|
48
58
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { createCodexAppServerAgentHarness } from "./harness.js";
|
|
2
|
-
import { c as
|
|
3
|
-
import { buildCodexMediaUnderstandingProvider } from "./media-understanding-provider.js";
|
|
2
|
+
import { c as readCodexPluginConfig, l as resolveCodexAppServerRuntimeOptions, t as CODEX_PLUGINS_MARKETPLACE_NAME } from "./config-DDMrwfJl.js";
|
|
4
3
|
import { buildCodexProvider } from "./provider.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
4
|
+
import { _ as ensureCodexPluginActivation, b as defaultCodexAppInventoryCache, v as pluginReadParams } from "./thread-lifecycle-4Ul7RoW4.js";
|
|
5
|
+
import { buildCodexMediaUnderstandingProvider } from "./media-understanding-provider.js";
|
|
6
|
+
import { i as describeControlFailure, n as buildCodexPluginAppCacheKey, t as requestCodexAppServerJson } from "./request-NklFaHM4.js";
|
|
7
|
+
import { s as formatCodexDisplayText } from "./notification-correlation-qKY_sgga.js";
|
|
8
|
+
import { c as resolveCodexAppServerAuthAccountCacheKey, d as resolveCodexAppServerEnvApiKeyCacheKey, i as getSharedCodexAppServerClient, n as clearSharedCodexAppServerClientIfCurrentAndWait, u as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-C_RbGxW8.js";
|
|
9
|
+
import { a as resolveCodexCliSessionForBindingOnNode, c as handleCodexConversationInboundClaim, i as listCodexCliSessionsOnNode, n as createCodexCliSessionNodeInvokePolicies, o as resumeCodexCliSessionOnNode, s as handleCodexConversationBindingResolved, t as createCodexCliSessionNodeHostCommands } from "./node-cli-sessions-yVCifOyG.js";
|
|
10
10
|
import { mutateConfigFile } from "openclaw/plugin-sdk/config-mutation";
|
|
11
11
|
import { resolveLivePluginConfigObject } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
12
12
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
@@ -25,7 +25,7 @@ function createCodexCommand(options) {
|
|
|
25
25
|
description: "Inspect and control the Codex app-server harness",
|
|
26
26
|
ownership: "reserved",
|
|
27
27
|
agentPromptGuidance: [{
|
|
28
|
-
text: "Native Codex app-server plugin is available (`/codex ...`). For Codex bind/control/thread/resume/steer/stop requests, prefer `/codex bind`, `/codex threads`, `/codex resume`, `/codex steer`, and `/codex stop` over ACP.",
|
|
28
|
+
text: "Native Codex app-server plugin is available (`/codex ...`). For Codex bind/control/thread/resume/steer/stop requests, prefer `/codex bind`, `/codex threads`, `/codex resume`, `/codex steer`, and `/codex stop` over ACP. When OpenClaw sandboxing is active, native Codex execution modes are unavailable; use normal Codex harness turns.",
|
|
29
29
|
surfaces: ["pi_main"]
|
|
30
30
|
}, {
|
|
31
31
|
text: "Use ACP for Codex only when the user explicitly asks for ACP/acpx or wants to test the ACP path.",
|
|
@@ -45,7 +45,7 @@ async function handleCodexCommand(ctx, options = {}) {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
async function loadDefaultCodexSubcommandHandler() {
|
|
48
|
-
const { handleCodexSubcommand } = await import("./command-handlers-
|
|
48
|
+
const { handleCodexSubcommand } = await import("./command-handlers-DsB0GYd2.js");
|
|
49
49
|
return handleCodexSubcommand;
|
|
50
50
|
}
|
|
51
51
|
//#endregion
|
|
@@ -1158,6 +1158,7 @@ var codex_default = definePluginEntry({
|
|
|
1158
1158
|
}
|
|
1159
1159
|
}));
|
|
1160
1160
|
api.on("inbound_claim", (event, ctx) => handleCodexConversationInboundClaim(event, ctx, {
|
|
1161
|
+
config: api.runtime.config?.current?.(),
|
|
1161
1162
|
pluginConfig: resolveCurrentPluginConfig(),
|
|
1162
1163
|
resumeCodexCliSessionOnNode: (params) => resumeCodexCliSessionOnNode({
|
|
1163
1164
|
runtime: api.runtime,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { CODEX_PROVIDER_ID, FALLBACK_CODEX_MODELS } from "./provider-catalog.js";
|
|
2
|
-
import {
|
|
2
|
+
import { l as resolveCodexAppServerRuntimeOptions } from "./config-DDMrwfJl.js";
|
|
3
3
|
import { i as assertCodexTurnStartResponse, l as readCodexTurnCompletedNotification, o as readCodexErrorNotification, r as assertCodexThreadStartResponse } from "./protocol-validators-_gKDcd0x.js";
|
|
4
|
-
import { i as readModelListResult } from "./models-
|
|
4
|
+
import { i as readModelListResult } from "./models-B_uo1pf5.js";
|
|
5
5
|
import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
|
|
6
|
+
import { n as buildCodexRuntimeThreadConfig } from "./thread-lifecycle-4Ul7RoW4.js";
|
|
6
7
|
import { validateJsonSchemaValue } from "openclaw/plugin-sdk/json-schema-runtime";
|
|
7
8
|
//#region extensions/codex/media-understanding-provider.ts
|
|
8
9
|
const DEFAULT_CODEX_IMAGE_MODEL = FALLBACK_CODEX_MODELS.find((model) => model.inputModalities.includes("image"))?.id ?? FALLBACK_CODEX_MODELS[0]?.id;
|
|
@@ -62,7 +63,7 @@ async function runBoundedCodexVisionTurn(params) {
|
|
|
62
63
|
const appServer = resolveCodexAppServerRuntimeOptions({ pluginConfig: params.options.pluginConfig });
|
|
63
64
|
const timeoutMs = Math.max(100, params.timeoutMs);
|
|
64
65
|
const ownsClient = !params.options.clientFactory;
|
|
65
|
-
const client = params.options.clientFactory ? await params.options.clientFactory(appServer.start, params.profile) : await import("./shared-client-
|
|
66
|
+
const client = params.options.clientFactory ? await params.options.clientFactory(appServer.start, params.profile) : await import("./shared-client-C_RbGxW8.js").then((n) => n.a).then(({ createIsolatedCodexAppServerClient }) => createIsolatedCodexAppServerClient({
|
|
66
67
|
startOptions: appServer.start,
|
|
67
68
|
timeoutMs,
|
|
68
69
|
authProfileId: params.profile
|
|
@@ -86,6 +87,8 @@ async function runBoundedCodexVisionTurn(params) {
|
|
|
86
87
|
sandbox: "read-only",
|
|
87
88
|
serviceName: "OpenClaw",
|
|
88
89
|
developerInstructions: params.developerInstructions,
|
|
90
|
+
config: buildCodexRuntimeThreadConfig(void 0, { nativeCodeModeEnabled: false }),
|
|
91
|
+
environments: [],
|
|
89
92
|
dynamicTools: [],
|
|
90
93
|
experimentalRawEvents: true,
|
|
91
94
|
persistExtendedHistory: false,
|
|
@@ -39,7 +39,7 @@ async function listAllCodexAppServerModels(options = {}) {
|
|
|
39
39
|
async function withCodexAppServerModelClient(options, run) {
|
|
40
40
|
const timeoutMs = options.timeoutMs ?? 2500;
|
|
41
41
|
const useSharedClient = options.sharedClient !== false;
|
|
42
|
-
const { createIsolatedCodexAppServerClient, getSharedCodexAppServerClient } = await import("./shared-client-
|
|
42
|
+
const { createIsolatedCodexAppServerClient, getSharedCodexAppServerClient } = await import("./shared-client-C_RbGxW8.js").then((n) => n.a);
|
|
43
43
|
const client = useSharedClient ? await getSharedCodexAppServerClient({
|
|
44
44
|
startOptions: options.startOptions,
|
|
45
45
|
timeoutMs,
|