@openclaw/codex 2026.5.18 → 2026.5.19-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{client-6FkrXfaz.js → client-BCJaLwdZ.js} +1 -1
- package/dist/{client-factory-9L6Ie1dC.js → client-factory-By1f68U_.js} +1 -1
- package/dist/{command-formatters-BRW7_Nu7.js → command-formatters-BpPOTePl.js} +2 -1
- package/dist/{command-handlers-DcoFMn4e.js → command-handlers-CFFYwpt4.js} +78 -7
- package/dist/{compact-UKyG6Pw2.js → compact-BPnB6ZWJ.js} +6 -6
- package/dist/{computer-use-UJ3dxrXF.js → computer-use-BD8UmXB-.js} +2 -2
- package/dist/{config-B5pq6hEz.js → config-B5rU0vP3.js} +2 -0
- package/dist/harness.js +8 -8
- package/dist/index.js +54 -10
- package/dist/media-understanding-provider.js +3 -3
- package/dist/{models-C1zn2RN0.js → models-6ViLQ-HQ.js} +1 -1
- package/dist/{node-cli-sessions-C9rlYMPw.js → node-cli-sessions-douLgfcf.js} +5 -5
- package/dist/{plugin-activation-B49xb7pI.js → plugin-activation-Dtcfb3sk.js} +65 -6
- package/dist/provider.js +2 -2
- package/dist/{request-XPjLayGw.js → request-BLCZjckr.js} +3 -3
- package/dist/{run-attempt-DyLQRA61.js → run-attempt-BqRPAaHk.js} +469 -118
- package/dist/{session-binding-DqApZIgD.js → session-binding-D9ejASYj.js} +1 -1
- package/dist/{shared-client-DlvmoLBJ.js → shared-client-DWgKldR5.js} +2 -2
- package/dist/{side-question-CfRPUq5X.js → side-question-DjyRnjPQ.js} +50 -17
- package/dist/test-api.js +8 -4
- package/dist/{thread-lifecycle-5SBrtWFl.js → thread-lifecycle-C07GnPSH.js} +141 -57
- package/dist/{vision-tools-BX9YuTEK.js → vision-tools-CDoJ4rDN.js} +61 -7
- package/openclaw.plugin.json +9 -0
- package/package.json +4 -4
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { c as resolveCodexAppServerRuntimeOptions, d as withMcpElicitationsApprovalPolicy, i as isCodexAppServerApprovalPolicyAllowedByRequirements, s as readCodexPluginConfig, u as resolveCodexPluginsPolicy } from "./config-
|
|
1
|
+
import { c as resolveCodexAppServerRuntimeOptions, d as withMcpElicitationsApprovalPolicy, i as isCodexAppServerApprovalPolicyAllowedByRequirements, s as readCodexPluginConfig, u as resolveCodexPluginsPolicy } from "./config-B5rU0vP3.js";
|
|
2
2
|
import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse } from "./protocol-validators-BGBspNmF.js";
|
|
3
3
|
import { t as isJsonObject } from "./protocol-C9UWI98H.js";
|
|
4
|
-
import { i as isCodexAppServerConnectionClosedError, r as isCodexAppServerApprovalRequest } from "./client-
|
|
5
|
-
import { n as buildCodexPluginAppCacheKey, r as CODEX_CONTROL_METHODS } from "./request-
|
|
6
|
-
import { d as resolveCodexUsageLimitResetAtMs, f as shouldRefreshCodexRateLimitsForUsageLimitMessage, r as formatCodexDisplayText, u as formatCodexUsageLimitErrorMessage } from "./command-formatters-
|
|
7
|
-
import { c as resolveCodexAppServerAuthAccountCacheKey, d as resolveCodexAppServerEnvApiKeyCacheKey, f as resolveCodexAppServerHomeDir, l as resolveCodexAppServerAuthProfileId, s as refreshCodexAppServerAuthTokens, t as clearSharedCodexAppServerClientIfCurrent, u as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-
|
|
8
|
-
import { i as readCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-
|
|
9
|
-
import { a as defaultCodexAppInventoryCache } from "./plugin-activation-
|
|
10
|
-
import { C as isForcedPrivateQaCodexRuntime, S as filterCodexDynamicTools, T as resolveCodexDynamicToolsLoading, _ as projectContextEngineAssemblyForCodex, b as createCodexDynamicToolBridge, c as codexDynamicToolsFingerprint, f as startOrResumeThread, g as shouldBuildCodexPluginThreadConfig, h as mergeCodexThreadConfigs, i as buildDeveloperInstructions, l as isContextEngineBindingCompatible, m as buildCodexPluginThreadConfigInputFingerprint, p as buildCodexPluginThreadConfig, r as buildContextEngineBinding, s as buildTurnStartParams, t as areCodexDynamicToolFingerprintsCompatible, v as resolveCodexContextEngineProjectionMaxChars, w as normalizeCodexDynamicToolName, x as sanitizeCodexHistoryImagePayloads, y as resolveCodexContextEngineProjectionReserveTokens } from "./thread-lifecycle-
|
|
11
|
-
import { t as defaultCodexAppServerClientFactory } from "./client-factory-
|
|
12
|
-
import { a as handleCodexAppServerElicitationRequest, i as buildCodexNativeHookRelayDisabledConfig, n as CODEX_NATIVE_HOOK_RELAY_EVENTS, o as
|
|
13
|
-
import { t as ensureCodexComputerUse } from "./computer-use-
|
|
4
|
+
import { i as isCodexAppServerConnectionClosedError, r as isCodexAppServerApprovalRequest } from "./client-BCJaLwdZ.js";
|
|
5
|
+
import { n as buildCodexPluginAppCacheKey, r as CODEX_CONTROL_METHODS } from "./request-BLCZjckr.js";
|
|
6
|
+
import { d as resolveCodexUsageLimitResetAtMs, f as shouldRefreshCodexRateLimitsForUsageLimitMessage, r as formatCodexDisplayText, u as formatCodexUsageLimitErrorMessage } from "./command-formatters-BpPOTePl.js";
|
|
7
|
+
import { c as resolveCodexAppServerAuthAccountCacheKey, d as resolveCodexAppServerEnvApiKeyCacheKey, f as resolveCodexAppServerHomeDir, l as resolveCodexAppServerAuthProfileId, s as refreshCodexAppServerAuthTokens, t as clearSharedCodexAppServerClientIfCurrent, u as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-DWgKldR5.js";
|
|
8
|
+
import { i as readCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-D9ejASYj.js";
|
|
9
|
+
import { a as defaultCodexAppInventoryCache } from "./plugin-activation-Dtcfb3sk.js";
|
|
10
|
+
import { C as isForcedPrivateQaCodexRuntime, S as filterCodexDynamicTools, T as resolveCodexDynamicToolsLoading, _ as projectContextEngineAssemblyForCodex, b as createCodexDynamicToolBridge, c as codexDynamicToolsFingerprint, f as startOrResumeThread, g as shouldBuildCodexPluginThreadConfig, h as mergeCodexThreadConfigs, i as buildDeveloperInstructions, l as isContextEngineBindingCompatible, m as buildCodexPluginThreadConfigInputFingerprint, p as buildCodexPluginThreadConfig, r as buildContextEngineBinding, s as buildTurnStartParams, t as areCodexDynamicToolFingerprintsCompatible, v as resolveCodexContextEngineProjectionMaxChars, w as normalizeCodexDynamicToolName, x as sanitizeCodexHistoryImagePayloads, y as resolveCodexContextEngineProjectionReserveTokens } from "./thread-lifecycle-C07GnPSH.js";
|
|
11
|
+
import { t as defaultCodexAppServerClientFactory } from "./client-factory-By1f68U_.js";
|
|
12
|
+
import { a as handleCodexAppServerElicitationRequest, c as emitDynamicToolTerminalDiagnostic, i as buildCodexNativeHookRelayDisabledConfig, l as handleCodexAppServerApprovalRequest, n as CODEX_NATIVE_HOOK_RELAY_EVENTS, o as emitDynamicToolErrorDiagnostic, r as buildCodexNativeHookRelayConfig, s as emitDynamicToolStartedDiagnostic, t as filterToolsForVisionInputs } from "./vision-tools-CDoJ4rDN.js";
|
|
13
|
+
import { t as ensureCodexComputerUse } from "./computer-use-BD8UmXB-.js";
|
|
14
14
|
import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-dvhq-4pi.js";
|
|
15
15
|
import { createHash } from "node:crypto";
|
|
16
16
|
import nodeFs from "node:fs";
|
|
17
|
-
import { TOOL_PROGRESS_OUTPUT_MAX_CHARS, acquireSessionWriteLock, appendSessionTranscriptMessage, assembleHarnessContextEngine, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildEmbeddedAttemptToolRunContext, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emitSessionTranscriptUpdate, finalizeHarnessContextEngineTurn, formatErrorMessage, formatToolAggregate, formatToolProgressOutput, hasBeforeToolCallPolicy, inferToolMetaFromArgs, isActiveHarnessContextEngine, isSubagentSessionKey, loadCodexBundleMcpThreadConfig, normalizeAgentRuntimeTools, normalizeUsage, registerNativeHookRelay, resolveAgentHarnessBeforePromptBuildResult, resolveAttemptSpawnWorkspaceDir, resolveBootstrapContextForRun, resolveContextEngineOwnerPluginId, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, resolveSessionWriteLockOptions, resolveUserPath, runAgentCleanupStep, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessAgentEndHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessBeforeMessageWriteHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
17
|
+
import { TOOL_PROGRESS_OUTPUT_MAX_CHARS, acquireSessionWriteLock, appendSessionTranscriptMessage, assembleHarnessContextEngine, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildEmbeddedAttemptToolRunContext, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, compactContextEngineWithSafetyTimeout, embeddedAgentLog, emitAgentEvent, emitSessionTranscriptUpdate, finalizeHarnessContextEngineTurn, formatErrorMessage, formatToolAggregate, formatToolProgressOutput, hasBeforeToolCallPolicy, hasSandboxBindContainerPathAliases, hasSandboxBindReadonlyHostShadows, inferToolMetaFromArgs, isActiveHarnessContextEngine, isSubagentSessionKey, loadCodexBundleMcpThreadConfig, normalizeAgentRuntimeTools, normalizeUsage, registerNativeHookRelay, resolveAgentHarnessBeforePromptBuildResult, resolveAttemptSpawnWorkspaceDir, resolveBootstrapContextForRun, resolveCompactionTimeoutMs, resolveContextEngineOwnerPluginId, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, resolveSessionWriteLockOptions, resolveUserPath, resolveWritableSandboxBindHostRoots, runAgentCleanupStep, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessAgentEndHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessBeforeMessageWriteHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
18
18
|
import fs from "node:fs/promises";
|
|
19
19
|
import path from "node:path";
|
|
20
20
|
import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1 } from "openclaw/plugin-sdk/agent-runtime";
|
|
21
21
|
import { appendRegularFile, pathExists } from "openclaw/plugin-sdk/security-runtime";
|
|
22
22
|
import { redactSensitiveFieldValue, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
|
|
23
|
-
import { emitTrustedDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
23
|
+
import { emitTrustedDiagnosticEvent, hasPendingInternalDiagnosticEvent, onInternalDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
24
24
|
import { CODEX_NATIVE_SUBAGENT_RUNTIME, CODEX_NATIVE_SUBAGENT_RUN_ID_PREFIX, CODEX_NATIVE_SUBAGENT_TASK_KIND, createRunningTaskRun, finalizeTaskRunByRunId, recordTaskRunProgressByRunId } from "openclaw/plugin-sdk/codex-native-task-runtime";
|
|
25
25
|
import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "@earendil-works/pi-coding-agent";
|
|
26
26
|
//#region extensions/codex/src/app-server/local-runtime-attribution.ts
|
|
@@ -164,9 +164,27 @@ var CodexNativeSubagentTaskMirror = class {
|
|
|
164
164
|
if (!item || readString$3(item, "type") !== "collabAgentToolCall") return;
|
|
165
165
|
if (readString$3(item, "senderThreadId") !== this.params.parentThreadId) return;
|
|
166
166
|
const receiverThreadIds = readStringArray(item.receiverThreadIds);
|
|
167
|
-
|
|
167
|
+
const isSpawnAgentTool = normalizeToolName(readString$3(item, "tool")) === "spawnagent";
|
|
168
|
+
if (isSpawnAgentTool) for (const receiverThreadId of receiverThreadIds) this.createTaskFromCollabSpawnItem(receiverThreadId, item);
|
|
168
169
|
const agentsStates = readAgentsStates(item.agentsStates);
|
|
169
|
-
|
|
170
|
+
const toolCallStatus = normalizeCollabToolCallStatus(readString$3(item, "status"));
|
|
171
|
+
const terminalToolCallThreadIds = /* @__PURE__ */ new Set();
|
|
172
|
+
if (isSpawnAgentTool && isBlockedOrFailedCollabToolCallStatus(toolCallStatus)) {
|
|
173
|
+
for (const threadId of receiverThreadIds) terminalToolCallThreadIds.add(threadId);
|
|
174
|
+
for (const threadId of agentsStates.keys()) terminalToolCallThreadIds.add(threadId);
|
|
175
|
+
}
|
|
176
|
+
const terminalAgentStateThreadIds = /* @__PURE__ */ new Set();
|
|
177
|
+
for (const [threadId, state] of agentsStates) {
|
|
178
|
+
const normalizedStatus = normalizeAgentStateStatus(state.status);
|
|
179
|
+
if (terminalToolCallThreadIds.has(threadId) && isNonTerminalAgentStateStatus(normalizedStatus)) continue;
|
|
180
|
+
this.applyCollabAgentStatus(threadId, normalizedStatus, state.message);
|
|
181
|
+
if (isTerminalAgentStateStatus(normalizedStatus)) terminalAgentStateThreadIds.add(threadId);
|
|
182
|
+
}
|
|
183
|
+
if (isBlockedOrFailedCollabToolCallStatus(toolCallStatus)) for (const threadId of terminalToolCallThreadIds) {
|
|
184
|
+
if (terminalAgentStateThreadIds.has(threadId)) continue;
|
|
185
|
+
const state = agentsStates.get(threadId);
|
|
186
|
+
this.applyCollabAgentStatus(threadId, toolCallStatus, state?.message);
|
|
187
|
+
}
|
|
170
188
|
}
|
|
171
189
|
createTaskFromCollabSpawnItem(threadId, item) {
|
|
172
190
|
const normalizedThreadId = threadId.trim();
|
|
@@ -200,6 +218,7 @@ var CodexNativeSubagentTaskMirror = class {
|
|
|
200
218
|
const normalizedStatus = normalizeAgentStateStatus(status);
|
|
201
219
|
if (!normalizedStatus) return;
|
|
202
220
|
const runId = codexNativeSubagentRunId(threadId);
|
|
221
|
+
if (this.terminalRunIds.has(runId) && isNonTerminalAgentStateStatus(normalizedStatus)) return;
|
|
203
222
|
const eventAt = this.now();
|
|
204
223
|
if (normalizedStatus === "pendingInit" || normalizedStatus === "running") {
|
|
205
224
|
this.runtime.recordTaskRunProgressByRunId({
|
|
@@ -223,6 +242,20 @@ var CodexNativeSubagentTaskMirror = class {
|
|
|
223
242
|
});
|
|
224
243
|
return;
|
|
225
244
|
}
|
|
245
|
+
if (normalizedStatus === "blocked") {
|
|
246
|
+
this.terminalRunIds.add(runId);
|
|
247
|
+
this.runtime.finalizeTaskRunByRunId({
|
|
248
|
+
runId,
|
|
249
|
+
runtime: CODEX_NATIVE_SUBAGENT_RUNTIME,
|
|
250
|
+
status: "succeeded",
|
|
251
|
+
endedAt: eventAt,
|
|
252
|
+
lastEventAt: eventAt,
|
|
253
|
+
progressSummary: trimOptional(message) ?? "Codex native subagent blocked.",
|
|
254
|
+
terminalSummary: trimOptional(message) ?? "Codex native subagent blocked.",
|
|
255
|
+
terminalOutcome: "blocked"
|
|
256
|
+
});
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
226
259
|
this.terminalRunIds.add(runId);
|
|
227
260
|
this.runtime.finalizeTaskRunByRunId({
|
|
228
261
|
runId,
|
|
@@ -293,6 +326,23 @@ function readNullableString$1(value, key) {
|
|
|
293
326
|
function normalizeToolName(value) {
|
|
294
327
|
return value?.replace(/[^a-z0-9]/giu, "").toLowerCase();
|
|
295
328
|
}
|
|
329
|
+
function normalizeCollabToolCallStatus(value) {
|
|
330
|
+
const key = value?.replace(/[^a-z0-9]/giu, "").toLowerCase();
|
|
331
|
+
if (key === "completed" || key === "succeeded" || key === "success") return "completed";
|
|
332
|
+
if (key === "failed" || key === "error" || key === "errored") return "failed";
|
|
333
|
+
if (key === "blocked" || key === "declined") return "blocked";
|
|
334
|
+
if (key === "inprogress" || key === "running") return "running";
|
|
335
|
+
return value?.trim();
|
|
336
|
+
}
|
|
337
|
+
function isBlockedOrFailedCollabToolCallStatus(value) {
|
|
338
|
+
return value === "failed" || value === "blocked";
|
|
339
|
+
}
|
|
340
|
+
function isNonTerminalAgentStateStatus(value) {
|
|
341
|
+
return value === "pendingInit" || value === "running";
|
|
342
|
+
}
|
|
343
|
+
function isTerminalAgentStateStatus(value) {
|
|
344
|
+
return value !== void 0 && !isNonTerminalAgentStateStatus(value);
|
|
345
|
+
}
|
|
296
346
|
function normalizeAgentStateStatus(value) {
|
|
297
347
|
const key = value?.replace(/[^a-z0-9]/giu, "").toLowerCase();
|
|
298
348
|
if (!key) return;
|
|
@@ -301,6 +351,7 @@ function normalizeAgentStateStatus(value) {
|
|
|
301
351
|
if (key === "completed" || key === "succeeded" || key === "success") return "completed";
|
|
302
352
|
if (key === "interrupted" || key === "cancelled" || key === "canceled" || key === "shutdown") return key === "shutdown" ? "shutdown" : "interrupted";
|
|
303
353
|
if (key === "failed" || key === "error" || key === "systemerror") return "failed";
|
|
354
|
+
if (key === "blocked" || key === "declined") return "blocked";
|
|
304
355
|
return value?.trim();
|
|
305
356
|
}
|
|
306
357
|
function secondsToMillis(value) {
|
|
@@ -411,7 +462,7 @@ function buildCodexUserPromptMessage(params) {
|
|
|
411
462
|
*/
|
|
412
463
|
function attachCodexMirrorIdentity(message, identity) {
|
|
413
464
|
const record = message;
|
|
414
|
-
const existing = record
|
|
465
|
+
const existing = record["__openclaw"];
|
|
415
466
|
const baseMeta = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
|
|
416
467
|
return {
|
|
417
468
|
...record,
|
|
@@ -422,7 +473,7 @@ function attachCodexMirrorIdentity(message, identity) {
|
|
|
422
473
|
};
|
|
423
474
|
}
|
|
424
475
|
function readMirrorIdentity(message) {
|
|
425
|
-
const meta = message
|
|
476
|
+
const meta = message["__openclaw"];
|
|
426
477
|
if (!meta || typeof meta !== "object" || Array.isArray(meta)) return;
|
|
427
478
|
const id = meta[MIRROR_IDENTITY_META_KEY];
|
|
428
479
|
return typeof id === "string" && id.length > 0 ? id : void 0;
|
|
@@ -2311,6 +2362,7 @@ function readRequestId(record) {
|
|
|
2311
2362
|
//#region extensions/codex/src/app-server/run-attempt.ts
|
|
2312
2363
|
const CODEX_DYNAMIC_TOOL_TIMEOUT_MS = 3e4;
|
|
2313
2364
|
const CODEX_DYNAMIC_TOOL_MAX_TIMEOUT_MS = 6e5;
|
|
2365
|
+
const CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS = 12e4;
|
|
2314
2366
|
const CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS = 6e4;
|
|
2315
2367
|
const CODEX_APP_SERVER_STARTUP_CONNECTION_CLOSE_MAX_ATTEMPTS = 3;
|
|
2316
2368
|
const CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS = 100;
|
|
@@ -2325,6 +2377,13 @@ const CODEX_NATIVE_HOOK_RELAY_RENEW_INTERVAL_MS = 6e4;
|
|
|
2325
2377
|
const CODEX_STEER_ALL_DEBOUNCE_MS = 500;
|
|
2326
2378
|
const LOG_FIELD_MAX_LENGTH = 160;
|
|
2327
2379
|
const CODEX_NATIVE_PROJECT_DOC_BASENAMES = new Set(["agents.md"]);
|
|
2380
|
+
const CODEX_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES = new Set([
|
|
2381
|
+
"identity.md",
|
|
2382
|
+
"soul.md",
|
|
2383
|
+
"tools.md",
|
|
2384
|
+
"user.md"
|
|
2385
|
+
]);
|
|
2386
|
+
const CODEX_HEARTBEAT_CONTEXT_BASENAME = "heartbeat.md";
|
|
2328
2387
|
const CODEX_NATIVE_HOOK_RELAY_EVENTS_WITH_APP_SERVER_APPROVALS = CODEX_NATIVE_HOOK_RELAY_EVENTS.filter((event) => event !== "permission_request");
|
|
2329
2388
|
const CODEX_BOOTSTRAP_CONTEXT_ORDER = new Map([
|
|
2330
2389
|
["soul.md", 10],
|
|
@@ -2485,9 +2544,11 @@ function toCodexTextInput(text) {
|
|
|
2485
2544
|
function resolveCodexAppServerSandboxPolicyForOpenClawSandbox(appServer, sandbox, cwd) {
|
|
2486
2545
|
if (!sandbox?.enabled || appServer.sandbox === "read-only") return;
|
|
2487
2546
|
const networkAccess = codexNetworkAccessForOpenClawSandbox(sandbox);
|
|
2547
|
+
const writableRoots = new Set([cwd]);
|
|
2548
|
+
if (sandbox.backendId === "docker") for (const root of resolveWritableSandboxBindHostRoots(sandbox.docker.binds)) writableRoots.add(root);
|
|
2488
2549
|
return {
|
|
2489
2550
|
type: "workspaceWrite",
|
|
2490
|
-
writableRoots: [
|
|
2551
|
+
writableRoots: [...writableRoots],
|
|
2491
2552
|
networkAccess,
|
|
2492
2553
|
excludeTmpdirEnvVar: false,
|
|
2493
2554
|
excludeSlashTmp: false
|
|
@@ -2765,7 +2826,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2765
2826
|
disableTools: params.disableTools,
|
|
2766
2827
|
toolsAllow: params.toolsAllow
|
|
2767
2828
|
});
|
|
2768
|
-
const nativeToolSurfaceEnabled = shouldEnableCodexAppServerNativeToolSurface(params);
|
|
2829
|
+
const nativeToolSurfaceEnabled = shouldEnableCodexAppServerNativeToolSurface(params, sandbox);
|
|
2769
2830
|
for (const diagnostic of bundleMcpThreadConfig.diagnostics) embeddedAgentLog.warn(`bundle-mcp: ${diagnostic.pluginId}: ${diagnostic.message}`);
|
|
2770
2831
|
const activeContextEngine = isActiveHarnessContextEngine(params.contextEngine) ? params.contextEngine : void 0;
|
|
2771
2832
|
const hookChannelId = resolveCodexAppServerHookChannelId(params, sandboxSessionKey);
|
|
@@ -2777,6 +2838,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2777
2838
|
effectiveWorkspace,
|
|
2778
2839
|
sandboxSessionKey,
|
|
2779
2840
|
sandbox,
|
|
2841
|
+
nativeToolSurfaceEnabled,
|
|
2780
2842
|
runAbortController,
|
|
2781
2843
|
sessionAgentId,
|
|
2782
2844
|
pluginConfig,
|
|
@@ -2837,7 +2899,6 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2837
2899
|
});
|
|
2838
2900
|
historyMessages = await readMirroredSessionHistoryMessages(activeSessionFile) ?? historyMessages;
|
|
2839
2901
|
}
|
|
2840
|
-
const baseDeveloperInstructions = buildDeveloperInstructions(params);
|
|
2841
2902
|
const workspaceBootstrapContext = await buildCodexWorkspaceBootstrapContext({
|
|
2842
2903
|
params,
|
|
2843
2904
|
resolvedWorkspace,
|
|
@@ -2845,14 +2906,19 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2845
2906
|
sessionKey: sandboxSessionKey,
|
|
2846
2907
|
sessionAgentId
|
|
2847
2908
|
});
|
|
2848
|
-
const
|
|
2909
|
+
const baseDeveloperInstructions = joinPresentSections(buildDeveloperInstructions(params, { dynamicTools: toolBridge.specs }), workspaceBootstrapContext.developerInstructions);
|
|
2910
|
+
const openClawPromptContext = buildCodexOpenClawPromptContext({
|
|
2911
|
+
params,
|
|
2912
|
+
skillsPrompt: params.skillsSnapshot?.prompt,
|
|
2913
|
+
workspacePromptContext: workspaceBootstrapContext.promptContext
|
|
2914
|
+
});
|
|
2849
2915
|
let promptText = params.prompt;
|
|
2850
|
-
let developerInstructions =
|
|
2916
|
+
let developerInstructions = baseDeveloperInstructions;
|
|
2851
2917
|
let prePromptMessageCount = historyMessages.length;
|
|
2852
2918
|
let contextEngineProjection;
|
|
2853
2919
|
const resetCodexPromptInputs = () => {
|
|
2854
2920
|
promptText = params.prompt;
|
|
2855
|
-
developerInstructions =
|
|
2921
|
+
developerInstructions = baseDeveloperInstructions;
|
|
2856
2922
|
prePromptMessageCount = historyMessages.length;
|
|
2857
2923
|
contextEngineProjection = void 0;
|
|
2858
2924
|
};
|
|
@@ -2909,7 +2975,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2909
2975
|
developerInstructionAdditionChars: projection.developerInstructionAddition?.length ?? 0
|
|
2910
2976
|
});
|
|
2911
2977
|
promptText = projectionDecision.project ? projection.promptText : params.prompt;
|
|
2912
|
-
developerInstructions = joinPresentSections(baseDeveloperInstructions,
|
|
2978
|
+
developerInstructions = joinPresentSections(baseDeveloperInstructions, projection.developerInstructionAddition);
|
|
2913
2979
|
prePromptMessageCount = projection.prePromptMessageCount;
|
|
2914
2980
|
};
|
|
2915
2981
|
if (activeContextEngine) try {
|
|
@@ -2937,19 +3003,25 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2937
3003
|
ctx: hookContext
|
|
2938
3004
|
});
|
|
2939
3005
|
let promptBuild = await buildPromptFromCurrentInputs();
|
|
3006
|
+
const decorateCodexTurnPromptText = (prompt) => prependCodexOpenClawPromptContext(prompt, openClawPromptContext);
|
|
3007
|
+
let codexTurnPromptText = decorateCodexTurnPromptText(promptBuild.prompt);
|
|
3008
|
+
const refreshCodexTurnPromptText = () => {
|
|
3009
|
+
codexTurnPromptText = decorateCodexTurnPromptText(promptBuild.prompt);
|
|
3010
|
+
};
|
|
2940
3011
|
const systemPromptReport = buildCodexSystemPromptReport({
|
|
2941
3012
|
attempt: params,
|
|
2942
3013
|
sessionKey: sandboxSessionKey,
|
|
2943
3014
|
workspaceDir: effectiveWorkspace,
|
|
2944
3015
|
developerInstructions: promptBuild.developerInstructions,
|
|
2945
3016
|
workspaceBootstrapContext,
|
|
3017
|
+
skillsPrompt: openClawPromptContext ? params.skillsSnapshot?.prompt ?? "" : "",
|
|
2946
3018
|
tools: toolBridge.specs
|
|
2947
3019
|
});
|
|
2948
3020
|
const trajectoryRecorder = createCodexTrajectoryRecorder({
|
|
2949
3021
|
attempt: params,
|
|
2950
3022
|
cwd: effectiveWorkspace,
|
|
2951
3023
|
developerInstructions: promptBuild.developerInstructions,
|
|
2952
|
-
prompt:
|
|
3024
|
+
prompt: codexTurnPromptText,
|
|
2953
3025
|
tools: toolBridge.specs
|
|
2954
3026
|
});
|
|
2955
3027
|
let client;
|
|
@@ -3002,6 +3074,16 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3002
3074
|
}) : void 0;
|
|
3003
3075
|
const resolvedPluginPolicy = pluginThreadConfigRequired ? resolveCodexPluginsPolicy(pluginThreadConfigPluginConfig) : void 0;
|
|
3004
3076
|
const enabledPluginConfigKeys = resolvedPluginPolicy ? resolvedPluginPolicy.pluginPolicies.filter((plugin) => plugin.enabled).map((plugin) => plugin.configKey).toSorted() : void 0;
|
|
3077
|
+
embeddedAgentLog.info("codex plugin thread config eligibility", buildCodexPluginThreadConfigEligibilityLogData({
|
|
3078
|
+
sessionId: params.sessionId,
|
|
3079
|
+
sessionKey: sandboxSessionKey,
|
|
3080
|
+
pluginThreadConfigRequired,
|
|
3081
|
+
resolvedPluginPolicy,
|
|
3082
|
+
enabledPluginConfigKeys,
|
|
3083
|
+
pluginAppCacheKey,
|
|
3084
|
+
startupAuthProfileId,
|
|
3085
|
+
appServer
|
|
3086
|
+
}));
|
|
3005
3087
|
pluginAppServer = resolvedPluginPolicy?.enabled === true ? {
|
|
3006
3088
|
...appServer,
|
|
3007
3089
|
approvalPolicy: withMcpElicitationsApprovalPolicy(appServer.approvalPolicy)
|
|
@@ -3032,6 +3114,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3032
3114
|
config: threadConfig,
|
|
3033
3115
|
finalConfigPatch: nativeHookRelayConfig,
|
|
3034
3116
|
nativeCodeModeEnabled: nativeToolSurfaceEnabled,
|
|
3117
|
+
nativeCodeModeOnlyEnabled: appServer.codeModeOnly,
|
|
3035
3118
|
userMcpServersEnabled: nativeToolSurfaceEnabled,
|
|
3036
3119
|
mcpServersFingerprint: bundleMcpThreadConfig.fingerprint,
|
|
3037
3120
|
mcpServersFingerprintEvaluated: bundleMcpThreadConfig.evaluated,
|
|
@@ -3110,7 +3193,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3110
3193
|
attempt: params,
|
|
3111
3194
|
cwd: effectiveWorkspace,
|
|
3112
3195
|
developerInstructions: promptBuild.developerInstructions,
|
|
3113
|
-
prompt:
|
|
3196
|
+
prompt: codexTurnPromptText,
|
|
3114
3197
|
tools: toolBridge.specs
|
|
3115
3198
|
});
|
|
3116
3199
|
let projector;
|
|
@@ -3156,7 +3239,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3156
3239
|
let turnAttemptLastProgressDetails;
|
|
3157
3240
|
let nativeHookRelayLastRenewedAt = 0;
|
|
3158
3241
|
let activeAppServerTurnRequests = 0;
|
|
3159
|
-
const
|
|
3242
|
+
const pendingOpenClawDynamicToolCompletionIds = /* @__PURE__ */ new Set();
|
|
3160
3243
|
const activeTurnItemIds = /* @__PURE__ */ new Set();
|
|
3161
3244
|
let turnCrossedToolHandoff = false;
|
|
3162
3245
|
const clearTurnCompletionIdleTimer = () => {
|
|
@@ -3465,7 +3548,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3465
3548
|
};
|
|
3466
3549
|
const isTerminalTurnNotificationForTurn = (notification, notificationTurnId) => {
|
|
3467
3550
|
if (!isTurnNotification(notification.params, thread.threadId, notificationTurnId)) return false;
|
|
3468
|
-
return notification.method === "turn/completed" || isCodexTurnAbortMarkerNotification(notification, {
|
|
3551
|
+
return notification.method === "turn/completed" || isCodexTurnAbortMarkerNotification(notification, { currentPromptTexts: [codexTurnPromptText] });
|
|
3469
3552
|
};
|
|
3470
3553
|
const handleNotification = async (notification) => {
|
|
3471
3554
|
userInputBridge?.handleNotification(notification);
|
|
@@ -3484,7 +3567,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3484
3567
|
}
|
|
3485
3568
|
if (isCurrentTurnNotification) updateActiveTurnItemIds(notification, activeTurnItemIds);
|
|
3486
3569
|
const unblockedAssistantCompletionRelease = isCurrentTurnNotification && turnAssistantCompletionIdleWatchArmed && notification.method === "item/completed" && activeTurnItemIds.size === 0;
|
|
3487
|
-
const trackedDynamicToolCompletion =
|
|
3570
|
+
const trackedDynamicToolCompletion = isPendingOpenClawDynamicToolCompletionNotification(notification, pendingOpenClawDynamicToolCompletionIds);
|
|
3488
3571
|
const rawToolOutputCompletion = isRawToolOutputCompletionNotification(notification);
|
|
3489
3572
|
if (isCurrentTurnNotification && (rawToolOutputCompletion || isNativeToolProgressNotification(notification))) turnCrossedToolHandoff = true;
|
|
3490
3573
|
const assistantCompletionCanRelease = isAssistantCompletionReleaseNotification(notification, turnCrossedToolHandoff);
|
|
@@ -3502,7 +3585,11 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3502
3585
|
else if (isCurrentTurnNotification && rawToolOutputCompletion) armTurnCompletionIdleWatch();
|
|
3503
3586
|
else if (isCurrentTurnNotification && shouldDisarmAssistantCompletionIdleWatch(notification)) disarmTurnAssistantCompletionIdleWatch();
|
|
3504
3587
|
if (turnCompletionIdleWatchArmed && !turnCompletionIdleWatchPinnedByTerminalError && notification.method !== "turn/completed" && isCurrentTurnNotification && !trackedDynamicToolCompletion && !rawToolOutputCompletion && !postToolRawAssistantCompletionNeedsTerminalGuard && !shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem) disarmTurnCompletionIdleWatch();
|
|
3505
|
-
|
|
3588
|
+
if (trackedDynamicToolCompletion) {
|
|
3589
|
+
const itemId = readNotificationItemId(notification);
|
|
3590
|
+
if (itemId) pendingOpenClawDynamicToolCompletionIds.delete(itemId);
|
|
3591
|
+
}
|
|
3592
|
+
const isTurnAbortMarker = isCurrentTurnNotification && isCodexTurnAbortMarkerNotification(notification, { currentPromptTexts: [codexTurnPromptText] });
|
|
3506
3593
|
const isTurnTerminal = isTerminalTurnNotificationForTurn(notification, turnId);
|
|
3507
3594
|
if (isTurnTerminal) terminalTurnNotificationQueued = true;
|
|
3508
3595
|
try {
|
|
@@ -3600,7 +3687,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3600
3687
|
armCompletionWatchOnResponse = true;
|
|
3601
3688
|
markCurrentTurnRequestProgress();
|
|
3602
3689
|
turnCrossedToolHandoff = true;
|
|
3603
|
-
|
|
3690
|
+
pendingOpenClawDynamicToolCompletionIds.add(call.callId);
|
|
3604
3691
|
trajectoryRecorder?.recordEvent("tool.call", {
|
|
3605
3692
|
threadId: call.threadId,
|
|
3606
3693
|
turnId: call.turnId,
|
|
@@ -3618,6 +3705,12 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3618
3705
|
tool: call.tool,
|
|
3619
3706
|
toolCallId: call.callId
|
|
3620
3707
|
});
|
|
3708
|
+
emitDynamicToolStartedDiagnostic({
|
|
3709
|
+
call,
|
|
3710
|
+
runId: params.runId,
|
|
3711
|
+
sessionId: params.sessionId,
|
|
3712
|
+
sessionKey: params.sessionKey
|
|
3713
|
+
});
|
|
3621
3714
|
const toolMeta = inferCodexDynamicToolMeta(call, resolveCodexToolProgressDetailMode(params.toolProgressDetail));
|
|
3622
3715
|
const toolArgs = sanitizeCodexToolArguments(call.arguments);
|
|
3623
3716
|
const shouldEmitDynamicToolProgress = shouldEmitTranscriptToolProgress(call.tool, toolArgs);
|
|
@@ -3635,47 +3728,92 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3635
3728
|
call,
|
|
3636
3729
|
config: params.config
|
|
3637
3730
|
});
|
|
3638
|
-
const
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
timeoutMs: dynamicToolTimeoutMs
|
|
3650
|
-
});
|
|
3731
|
+
const toolStartedAt = Date.now();
|
|
3732
|
+
let terminalDiagnosticObserved = false;
|
|
3733
|
+
const unsubscribeToolDiagnosticObserver = onInternalDiagnosticEvent((event) => {
|
|
3734
|
+
if (isDynamicToolTerminalDiagnosticEvent(event)) {
|
|
3735
|
+
if (isMatchingDynamicToolTerminalDiagnostic({
|
|
3736
|
+
event,
|
|
3737
|
+
call,
|
|
3738
|
+
runId: params.runId,
|
|
3739
|
+
sessionId: params.sessionId,
|
|
3740
|
+
sessionKey: params.sessionKey
|
|
3741
|
+
})) terminalDiagnosticObserved = true;
|
|
3651
3742
|
}
|
|
3652
3743
|
});
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3744
|
+
try {
|
|
3745
|
+
const response = await handleDynamicToolCallWithTimeout({
|
|
3746
|
+
call,
|
|
3747
|
+
toolBridge,
|
|
3748
|
+
signal: runAbortController.signal,
|
|
3749
|
+
timeoutMs: dynamicToolTimeoutMs,
|
|
3750
|
+
onTimeout: () => {
|
|
3751
|
+
trajectoryRecorder?.recordEvent("tool.timeout", {
|
|
3752
|
+
threadId: call.threadId,
|
|
3753
|
+
turnId: call.turnId,
|
|
3754
|
+
toolCallId: call.callId,
|
|
3755
|
+
name: call.tool,
|
|
3756
|
+
timeoutMs: dynamicToolTimeoutMs
|
|
3757
|
+
});
|
|
3758
|
+
}
|
|
3759
|
+
});
|
|
3760
|
+
const protocolResponse = toCodexDynamicToolProtocolResponse(response);
|
|
3761
|
+
trajectoryRecorder?.recordEvent("tool.result", {
|
|
3762
|
+
threadId: call.threadId,
|
|
3763
|
+
turnId: call.turnId,
|
|
3672
3764
|
toolCallId: call.callId,
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
}
|
|
3677
|
-
|
|
3678
|
-
|
|
3765
|
+
name: call.tool,
|
|
3766
|
+
success: protocolResponse.success,
|
|
3767
|
+
contentItems: protocolResponse.contentItems
|
|
3768
|
+
});
|
|
3769
|
+
projector?.recordDynamicToolResult({
|
|
3770
|
+
callId: call.callId,
|
|
3771
|
+
tool: call.tool,
|
|
3772
|
+
success: protocolResponse.success,
|
|
3773
|
+
contentItems: protocolResponse.contentItems
|
|
3774
|
+
});
|
|
3775
|
+
if (shouldEmitDynamicToolProgress) emitCodexAppServerEvent(params, {
|
|
3776
|
+
stream: "tool",
|
|
3777
|
+
data: {
|
|
3778
|
+
phase: "result",
|
|
3779
|
+
name: call.tool,
|
|
3780
|
+
toolCallId: call.callId,
|
|
3781
|
+
...toolMeta ? { meta: toolMeta } : {},
|
|
3782
|
+
isError: !protocolResponse.success,
|
|
3783
|
+
result: sanitizeCodexToolResponse(protocolResponse)
|
|
3784
|
+
}
|
|
3785
|
+
});
|
|
3786
|
+
if (!terminalDiagnosticObserved && !hasPendingDynamicToolTerminalDiagnostic({
|
|
3787
|
+
call,
|
|
3788
|
+
runId: params.runId,
|
|
3789
|
+
sessionId: params.sessionId,
|
|
3790
|
+
sessionKey: params.sessionKey
|
|
3791
|
+
})) emitDynamicToolTerminalDiagnostic({
|
|
3792
|
+
response,
|
|
3793
|
+
call,
|
|
3794
|
+
runId: params.runId,
|
|
3795
|
+
sessionId: params.sessionId,
|
|
3796
|
+
sessionKey: params.sessionKey,
|
|
3797
|
+
durationMs: Math.max(0, Date.now() - toolStartedAt)
|
|
3798
|
+
});
|
|
3799
|
+
return protocolResponse;
|
|
3800
|
+
} catch (error) {
|
|
3801
|
+
if (!terminalDiagnosticObserved && !hasPendingDynamicToolTerminalDiagnostic({
|
|
3802
|
+
call,
|
|
3803
|
+
runId: params.runId,
|
|
3804
|
+
sessionId: params.sessionId,
|
|
3805
|
+
sessionKey: params.sessionKey
|
|
3806
|
+
})) emitDynamicToolErrorDiagnostic({
|
|
3807
|
+
call,
|
|
3808
|
+
runId: params.runId,
|
|
3809
|
+
sessionId: params.sessionId,
|
|
3810
|
+
sessionKey: params.sessionKey,
|
|
3811
|
+
durationMs: Math.max(0, Date.now() - toolStartedAt)
|
|
3812
|
+
});
|
|
3813
|
+
throw error;
|
|
3814
|
+
} finally {
|
|
3815
|
+
unsubscribeToolDiagnosticObserver();
|
|
3816
|
+
}
|
|
3679
3817
|
} finally {
|
|
3680
3818
|
if (requestCountsAsTurnActivity) {
|
|
3681
3819
|
activeAppServerTurnRequests = Math.max(0, activeAppServerTurnRequests - 1);
|
|
@@ -3700,7 +3838,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3700
3838
|
try {
|
|
3701
3839
|
const runtimeContext = buildActiveContextEngineRuntimeContext();
|
|
3702
3840
|
const overflowTokenCount = params.contextTokenBudget ?? params.contextWindowInfo?.tokens;
|
|
3703
|
-
const compactResult = await activeContextEngine
|
|
3841
|
+
const compactResult = await compactContextEngineWithSafetyTimeout(activeContextEngine, {
|
|
3704
3842
|
sessionId: activeSessionId,
|
|
3705
3843
|
sessionKey: sandboxSessionKey,
|
|
3706
3844
|
sessionFile: activeSessionFile,
|
|
@@ -3712,7 +3850,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3712
3850
|
...runtimeContext,
|
|
3713
3851
|
currentTokenCount: overflowTokenCount
|
|
3714
3852
|
} : runtimeContext
|
|
3715
|
-
});
|
|
3853
|
+
}, resolveCompactionTimeoutMs(params.config), runAbortController.signal);
|
|
3716
3854
|
embeddedAgentLog.info("codex app-server context-engine forced compaction result", {
|
|
3717
3855
|
sessionId: activeSessionId,
|
|
3718
3856
|
sessionKey: sandboxSessionKey,
|
|
@@ -3755,6 +3893,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3755
3893
|
embeddedAgentLog.warn("context engine assemble failed after forced compaction; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
|
|
3756
3894
|
}
|
|
3757
3895
|
promptBuild = await buildPromptFromCurrentInputs();
|
|
3896
|
+
refreshCodexTurnPromptText();
|
|
3758
3897
|
};
|
|
3759
3898
|
const buildLlmInputEvent = () => ({
|
|
3760
3899
|
runId: params.runId,
|
|
@@ -3762,21 +3901,22 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3762
3901
|
provider: params.provider,
|
|
3763
3902
|
model: params.modelId,
|
|
3764
3903
|
systemPrompt: promptBuild.developerInstructions,
|
|
3765
|
-
prompt:
|
|
3904
|
+
prompt: codexTurnPromptText,
|
|
3766
3905
|
historyMessages,
|
|
3767
3906
|
imagesCount: params.images?.length ?? 0
|
|
3768
3907
|
});
|
|
3769
3908
|
const buildTurnStartFailureMessages = () => [...historyMessages, buildCodexUserPromptMessage({
|
|
3770
3909
|
...params,
|
|
3771
|
-
prompt:
|
|
3910
|
+
prompt: codexTurnPromptText
|
|
3772
3911
|
})];
|
|
3773
3912
|
let turn;
|
|
3774
3913
|
const startCodexTurn = async () => assertCodexTurnStartResponse(await client.request("turn/start", buildTurnStartParams(params, {
|
|
3775
3914
|
threadId: thread.threadId,
|
|
3776
3915
|
cwd: effectiveWorkspace,
|
|
3777
3916
|
appServer: pluginAppServer,
|
|
3778
|
-
promptText:
|
|
3779
|
-
sandboxPolicy: codexSandboxPolicy
|
|
3917
|
+
promptText: codexTurnPromptText,
|
|
3918
|
+
sandboxPolicy: codexSandboxPolicy,
|
|
3919
|
+
heartbeatCollaborationInstructions: workspaceBootstrapContext.heartbeatCollaborationInstructions
|
|
3780
3920
|
}), {
|
|
3781
3921
|
timeoutMs: params.timeoutMs,
|
|
3782
3922
|
signal: runAbortController.signal
|
|
@@ -3917,7 +4057,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3917
4057
|
trajectoryRecorder?.recordEvent("prompt.submitted", {
|
|
3918
4058
|
threadId: thread.threadId,
|
|
3919
4059
|
turnId: activeTurnId,
|
|
3920
|
-
prompt:
|
|
4060
|
+
prompt: codexTurnPromptText,
|
|
3921
4061
|
imagesCount: params.images?.length ?? 0
|
|
3922
4062
|
});
|
|
3923
4063
|
projector = new CodexAppServerEventProjector(params, thread.threadId, activeTurnId, {
|
|
@@ -4258,14 +4398,48 @@ async function handleDynamicToolCallWithTimeout(params) {
|
|
|
4258
4398
|
}
|
|
4259
4399
|
}
|
|
4260
4400
|
function failedDynamicToolResponse(message) {
|
|
4261
|
-
|
|
4262
|
-
success: false,
|
|
4401
|
+
const response = {
|
|
4263
4402
|
contentItems: [{
|
|
4264
4403
|
type: "inputText",
|
|
4265
4404
|
text: message
|
|
4266
|
-
}]
|
|
4405
|
+
}],
|
|
4406
|
+
success: false
|
|
4407
|
+
};
|
|
4408
|
+
Object.defineProperty(response, "diagnosticTerminalType", {
|
|
4409
|
+
configurable: true,
|
|
4410
|
+
enumerable: false,
|
|
4411
|
+
value: "error"
|
|
4412
|
+
});
|
|
4413
|
+
return response;
|
|
4414
|
+
}
|
|
4415
|
+
function toCodexDynamicToolProtocolResponse(response) {
|
|
4416
|
+
return {
|
|
4417
|
+
contentItems: response.contentItems,
|
|
4418
|
+
success: response.success
|
|
4267
4419
|
};
|
|
4268
4420
|
}
|
|
4421
|
+
function isDynamicToolTerminalDiagnosticEvent(event) {
|
|
4422
|
+
return event.type === "tool.execution.completed" || event.type === "tool.execution.error" || event.type === "tool.execution.blocked";
|
|
4423
|
+
}
|
|
4424
|
+
function isMatchingDynamicToolTerminalDiagnostic(params) {
|
|
4425
|
+
if (params.event.toolCallId !== params.call.callId || params.event.toolName !== params.call.tool) return false;
|
|
4426
|
+
if (params.runId !== void 0) return params.event.runId === params.runId;
|
|
4427
|
+
if (params.sessionId !== void 0) return params.event.sessionId === params.sessionId;
|
|
4428
|
+
if (params.sessionKey !== void 0) return params.event.sessionKey === params.sessionKey;
|
|
4429
|
+
return params.event.runId === void 0 && params.event.sessionId === void 0 && params.event.sessionKey === void 0;
|
|
4430
|
+
}
|
|
4431
|
+
function hasPendingDynamicToolTerminalDiagnostic(params) {
|
|
4432
|
+
return hasPendingInternalDiagnosticEvent((event) => {
|
|
4433
|
+
if (!isDynamicToolTerminalDiagnosticEvent(event)) return false;
|
|
4434
|
+
return isMatchingDynamicToolTerminalDiagnostic({
|
|
4435
|
+
event,
|
|
4436
|
+
call: params.call,
|
|
4437
|
+
runId: params.runId,
|
|
4438
|
+
sessionId: params.sessionId,
|
|
4439
|
+
sessionKey: params.sessionKey
|
|
4440
|
+
});
|
|
4441
|
+
});
|
|
4442
|
+
}
|
|
4269
4443
|
function resolveDynamicToolCallTimeoutMs(params) {
|
|
4270
4444
|
return clampDynamicToolTimeoutMs(readDynamicToolCallTimeoutMs(params.call.arguments) ?? readConfiguredDynamicToolTimeoutMs(params.call.tool, params.config) ?? CODEX_DYNAMIC_TOOL_TIMEOUT_MS);
|
|
4271
4445
|
}
|
|
@@ -4276,8 +4450,8 @@ function readDynamicToolCallTimeoutMs(value) {
|
|
|
4276
4450
|
function readConfiguredDynamicToolTimeoutMs(toolName, config) {
|
|
4277
4451
|
if (toolName === "image_generate") {
|
|
4278
4452
|
const imageGenerationModel = config?.agents?.defaults?.imageGenerationModel;
|
|
4279
|
-
if (!imageGenerationModel || typeof imageGenerationModel !== "object") return;
|
|
4280
|
-
return readPositiveFiniteTimeoutMs(imageGenerationModel.timeoutMs);
|
|
4453
|
+
if (!imageGenerationModel || typeof imageGenerationModel !== "object") return CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS;
|
|
4454
|
+
return readPositiveFiniteTimeoutMs(imageGenerationModel.timeoutMs) ?? CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS;
|
|
4281
4455
|
}
|
|
4282
4456
|
if (toolName === "image") return readTimeoutSecondsAsMs(config?.tools?.media?.image?.timeoutSeconds) ?? CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS;
|
|
4283
4457
|
}
|
|
@@ -4335,6 +4509,28 @@ function buildCodexNativeHookRelayId(params) {
|
|
|
4335
4509
|
hash.update(params.sessionKey?.trim() || params.sessionId);
|
|
4336
4510
|
return `codex-${hash.digest("hex").slice(0, 40)}`;
|
|
4337
4511
|
}
|
|
4512
|
+
function fingerprintCodexLogValue(namespace, value) {
|
|
4513
|
+
const hash = createHash("sha256");
|
|
4514
|
+
hash.update(namespace);
|
|
4515
|
+
hash.update("\0");
|
|
4516
|
+
hash.update(value);
|
|
4517
|
+
return `sha256:${hash.digest("hex").slice(0, 16)}`;
|
|
4518
|
+
}
|
|
4519
|
+
function buildCodexPluginThreadConfigEligibilityLogData(params) {
|
|
4520
|
+
return {
|
|
4521
|
+
sessionId: params.sessionId,
|
|
4522
|
+
sessionKey: params.sessionKey,
|
|
4523
|
+
enabled: params.pluginThreadConfigRequired,
|
|
4524
|
+
policyConfigured: params.resolvedPluginPolicy?.configured === true,
|
|
4525
|
+
policyEnabled: params.resolvedPluginPolicy?.enabled === true,
|
|
4526
|
+
pluginConfigKeys: params.resolvedPluginPolicy?.pluginPolicies.map((plugin) => plugin.configKey).toSorted(),
|
|
4527
|
+
enabledPluginConfigKeys: params.enabledPluginConfigKeys,
|
|
4528
|
+
appCacheKeyFingerprint: fingerprintCodexLogValue("openclaw:codex:plugin-app-cache-key:v1", params.pluginAppCacheKey),
|
|
4529
|
+
authProfileId: params.startupAuthProfileId,
|
|
4530
|
+
appServerTransport: params.appServer.start.transport,
|
|
4531
|
+
appServerCommandSource: params.appServer.start.commandSource
|
|
4532
|
+
};
|
|
4533
|
+
}
|
|
4338
4534
|
function interruptCodexTurnBestEffort(client, params) {
|
|
4339
4535
|
const requestOptions = params.timeoutMs && Number.isFinite(params.timeoutMs) && params.timeoutMs > 0 ? { timeoutMs: params.timeoutMs } : void 0;
|
|
4340
4536
|
const requestParams = {
|
|
@@ -4385,7 +4581,7 @@ async function buildDynamicTools(input) {
|
|
|
4385
4581
|
const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, input.sessionAgentId);
|
|
4386
4582
|
const createOpenClawCodingTools = openClawCodingToolsFactoryForTests ?? (await import("openclaw/plugin-sdk/agent-harness")).createOpenClawCodingTools;
|
|
4387
4583
|
const sessionKeys = resolveOpenClawCodingToolsSessionKeys(params, input.sandboxSessionKey);
|
|
4388
|
-
const
|
|
4584
|
+
const allTools = createOpenClawCodingTools({
|
|
4389
4585
|
agentId: input.sessionAgentId,
|
|
4390
4586
|
...buildEmbeddedAttemptToolRunContext(params),
|
|
4391
4587
|
exec: {
|
|
@@ -4417,8 +4613,9 @@ async function buildDynamicTools(input) {
|
|
|
4417
4613
|
resolvedWorkspace: input.resolvedWorkspace
|
|
4418
4614
|
}),
|
|
4419
4615
|
config: params.config,
|
|
4420
|
-
authProfileStore: params.authProfileStore,
|
|
4616
|
+
authProfileStore: params.toolAuthProfileStore ?? params.authProfileStore,
|
|
4421
4617
|
abortSignal: input.runAbortController.signal,
|
|
4618
|
+
emitBeforeToolCallDiagnostics: false,
|
|
4422
4619
|
modelProvider: params.model.provider,
|
|
4423
4620
|
modelId: params.modelId,
|
|
4424
4621
|
modelCompat: params.model.compat && typeof params.model.compat === "object" ? params.model.compat : void 0,
|
|
@@ -4450,7 +4647,8 @@ async function buildDynamicTools(input) {
|
|
|
4450
4647
|
});
|
|
4451
4648
|
input.runAbortController.abort("sessions_yield");
|
|
4452
4649
|
}
|
|
4453
|
-
})
|
|
4650
|
+
});
|
|
4651
|
+
const filteredTools = filterCodexDynamicToolsForAllowlist(filterToolsForVisionInputs(addSandboxShellDynamicToolsIfAvailable(filterCodexDynamicTools(allTools, input.pluginConfig), allTools, input), {
|
|
4454
4652
|
modelHasVision,
|
|
4455
4653
|
hasInboundImages: (params.images?.length ?? 0) > 0
|
|
4456
4654
|
}), includeForcedMessageToolAllow(params.toolsAllow, params));
|
|
@@ -4471,10 +4669,14 @@ function includeForcedMessageToolAllow(toolsAllow, params) {
|
|
|
4471
4669
|
if (toolsAllow.length === 0) return ["message"];
|
|
4472
4670
|
return new Set(toolsAllow.map((name) => normalizeCodexDynamicToolName(name))).has("message") ? toolsAllow : [...toolsAllow, "message"];
|
|
4473
4671
|
}
|
|
4474
|
-
function shouldEnableCodexAppServerNativeToolSurface(params) {
|
|
4672
|
+
function shouldEnableCodexAppServerNativeToolSurface(params, sandbox) {
|
|
4475
4673
|
const toolsAllow = includeForcedMessageToolAllow(params.toolsAllow, params);
|
|
4476
|
-
if (toolsAllow === void 0) return
|
|
4477
|
-
return hasWildcardCodexToolsAllow(toolsAllow);
|
|
4674
|
+
if (toolsAllow === void 0) return canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox);
|
|
4675
|
+
return hasWildcardCodexToolsAllow(toolsAllow) && canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox);
|
|
4676
|
+
}
|
|
4677
|
+
function canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox) {
|
|
4678
|
+
if (!sandbox?.enabled || sandbox.backendId !== "docker") return true;
|
|
4679
|
+
return !hasSandboxBindContainerPathAliases(sandbox.docker.binds) && !hasSandboxBindReadonlyHostShadows(sandbox.docker.binds);
|
|
4478
4680
|
}
|
|
4479
4681
|
function disableCodexPluginThreadConfig(pluginConfig) {
|
|
4480
4682
|
const config = readCodexPluginConfig(pluginConfig);
|
|
@@ -4486,18 +4688,59 @@ function disableCodexPluginThreadConfig(pluginConfig) {
|
|
|
4486
4688
|
}
|
|
4487
4689
|
};
|
|
4488
4690
|
}
|
|
4691
|
+
function addSandboxShellDynamicToolsIfAvailable(filteredTools, allTools, input) {
|
|
4692
|
+
if (!shouldExposeSandboxExecDynamicTool(input) || isSandboxShellDynamicToolExcluded(input.pluginConfig)) return filteredTools;
|
|
4693
|
+
const execTool = allTools.find((tool) => normalizeCodexDynamicToolName(tool.name) === "exec");
|
|
4694
|
+
const processTool = allTools.find((tool) => normalizeCodexDynamicToolName(tool.name) === "process");
|
|
4695
|
+
if (!execTool || !processTool) return filteredTools;
|
|
4696
|
+
const sandboxExecTool = {
|
|
4697
|
+
...execTool,
|
|
4698
|
+
name: "sandbox_exec",
|
|
4699
|
+
description: "Run a shell command through OpenClaw's configured sandbox backend for this session. Use only when the command must execute in the OpenClaw sandbox backend, such as an SSH-backed sandbox or Docker container-path bind layout that Codex's native shell cannot represent. Use Codex's native shell for normal local workspace commands.",
|
|
4700
|
+
execute: async (toolCallId, args, signal, onUpdate) => {
|
|
4701
|
+
const result = await execTool.execute(toolCallId, args, signal, onUpdate);
|
|
4702
|
+
return {
|
|
4703
|
+
...result,
|
|
4704
|
+
content: result.content.map((item) => item.type === "text" ? Object.assign({}, item, { text: item.text.replace("Use process (list/poll/log/write/send-keys/submit/paste/kill/clear/remove) for follow-up.", "Use sandbox_process (list/poll/log/write/send-keys/submit/paste/kill/clear/remove) for follow-up.") }) : item)
|
|
4705
|
+
};
|
|
4706
|
+
}
|
|
4707
|
+
};
|
|
4708
|
+
const sandboxProcessTool = {
|
|
4709
|
+
...processTool,
|
|
4710
|
+
name: "sandbox_process",
|
|
4711
|
+
description: "Manage sandbox_exec sessions that were started through OpenClaw's configured sandbox backend for this session: list, poll, log, write, send-keys, submit, paste, kill, clear, or remove. Use only for sandbox_exec follow-up; use Codex's native shell session handling for normal native shell commands."
|
|
4712
|
+
};
|
|
4713
|
+
return [
|
|
4714
|
+
...filteredTools,
|
|
4715
|
+
sandboxExecTool,
|
|
4716
|
+
sandboxProcessTool
|
|
4717
|
+
];
|
|
4718
|
+
}
|
|
4719
|
+
function shouldExposeSandboxExecDynamicTool(input) {
|
|
4720
|
+
const backendId = input.sandbox?.enabled ? input.sandbox.backendId.trim().toLowerCase() : "";
|
|
4721
|
+
return Boolean(backendId && (backendId !== "docker" || input.nativeToolSurfaceEnabled === false));
|
|
4722
|
+
}
|
|
4723
|
+
function isSandboxShellDynamicToolExcluded(config) {
|
|
4724
|
+
return (config.codexDynamicToolsExclude ?? []).some((name) => {
|
|
4725
|
+
const normalized = normalizeCodexDynamicToolName(name);
|
|
4726
|
+
return normalized === "exec" || normalized === "sandbox_exec" || normalized === "process" || normalized === "sandbox_process";
|
|
4727
|
+
});
|
|
4728
|
+
}
|
|
4489
4729
|
function filterCodexDynamicToolsForAllowlist(tools, toolsAllow) {
|
|
4490
4730
|
if (!toolsAllow) return tools;
|
|
4491
4731
|
if (toolsAllow.length === 0) return [];
|
|
4492
4732
|
if (hasWildcardCodexToolsAllow(toolsAllow)) return tools;
|
|
4493
4733
|
const allowSet = new Set(toolsAllow.map((name) => normalizeCodexDynamicToolName(name)).filter(Boolean));
|
|
4494
|
-
return tools.filter((tool) =>
|
|
4734
|
+
return tools.filter((tool) => {
|
|
4735
|
+
const normalized = normalizeCodexDynamicToolName(tool.name);
|
|
4736
|
+
return allowSet.has(normalized) || normalized === "sandbox_exec" && allowSet.has("exec") || normalized === "sandbox_process" && (allowSet.has("exec") || allowSet.has("process"));
|
|
4737
|
+
});
|
|
4495
4738
|
}
|
|
4496
4739
|
function hasWildcardCodexToolsAllow(toolsAllow) {
|
|
4497
4740
|
return toolsAllow.some((name) => normalizeCodexDynamicToolName(name) === "*");
|
|
4498
4741
|
}
|
|
4499
4742
|
function shouldForceMessageTool(params) {
|
|
4500
|
-
return params.sourceReplyDeliveryMode === "message_tool_only";
|
|
4743
|
+
return params.disableMessageTool !== true && params.sourceReplyDeliveryMode === "message_tool_only";
|
|
4501
4744
|
}
|
|
4502
4745
|
function shouldProjectMirroredHistoryForCodexStart(params) {
|
|
4503
4746
|
if (!params.historyMessages.some((message) => message.role === "user")) return false;
|
|
@@ -4759,10 +5002,10 @@ function readNotificationItemId(notification) {
|
|
|
4759
5002
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
4760
5003
|
return (item ? readString(item, "id") : void 0) ?? readString(notification.params, "itemId") ?? readString(notification.params, "id");
|
|
4761
5004
|
}
|
|
4762
|
-
function
|
|
5005
|
+
function isPendingOpenClawDynamicToolCompletionNotification(notification, pendingOpenClawDynamicToolCompletionIds) {
|
|
4763
5006
|
if (notification.method !== "item/completed" || !isJsonObject(notification.params)) return false;
|
|
4764
5007
|
const itemId = readNotificationItemId(notification);
|
|
4765
|
-
if (!itemId || !
|
|
5008
|
+
if (!itemId || !pendingOpenClawDynamicToolCompletionIds.has(itemId)) return false;
|
|
4766
5009
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
4767
5010
|
const itemType = item ? readString(item, "type") : void 0;
|
|
4768
5011
|
return itemType === void 0 || itemType === "dynamicToolCall";
|
|
@@ -4840,7 +5083,8 @@ function isCodexTurnAbortMarkerNotification(notification, options = {}) {
|
|
|
4840
5083
|
const role = isJsonObject(item) ? readString(item, "role") : void 0;
|
|
4841
5084
|
if (!isJsonObject(item) || role !== "user" && role !== "developer") return false;
|
|
4842
5085
|
const text = extractRawResponseItemText(item).trim();
|
|
4843
|
-
|
|
5086
|
+
const currentPromptTexts = [options.currentPromptText, ...options.currentPromptTexts ?? []].filter(isNonEmptyString).map((prompt) => prompt.trim());
|
|
5087
|
+
if (role === "user" && currentPromptTexts.includes(text)) return false;
|
|
4844
5088
|
const markerBody = readCodexTurnAbortMarkerBody(text);
|
|
4845
5089
|
return markerBody === CODEX_INTERRUPTED_USER_GUIDANCE || markerBody === CODEX_INTERRUPTED_DEVELOPER_GUIDANCE;
|
|
4846
5090
|
}
|
|
@@ -4889,10 +5133,18 @@ async function buildCodexWorkspaceBootstrapContext(params) {
|
|
|
4889
5133
|
sourceWorkspaceDir: params.resolvedWorkspace,
|
|
4890
5134
|
targetWorkspaceDir: params.effectiveWorkspace
|
|
4891
5135
|
}));
|
|
5136
|
+
const promptContextFiles = selectCodexWorkspacePromptContextFiles(contextFiles);
|
|
5137
|
+
const developerInstructionFiles = shouldInjectCodexOpenClawPromptContext(params.params) ? selectCodexWorkspaceDeveloperInstructionFiles(contextFiles) : [];
|
|
5138
|
+
const heartbeatReferenceFiles = selectCodexWorkspaceHeartbeatReferenceFiles(contextFiles);
|
|
4892
5139
|
return {
|
|
4893
5140
|
...bootstrapContext,
|
|
4894
5141
|
contextFiles,
|
|
4895
|
-
|
|
5142
|
+
promptContextFiles,
|
|
5143
|
+
developerInstructionFiles,
|
|
5144
|
+
heartbeatReferenceFiles,
|
|
5145
|
+
promptContext: renderCodexWorkspaceBootstrapPromptContext(promptContextFiles),
|
|
5146
|
+
developerInstructions: renderCodexWorkspaceDeveloperInstructions(developerInstructionFiles),
|
|
5147
|
+
heartbeatCollaborationInstructions: renderCodexWorkspaceHeartbeatReference(heartbeatReferenceFiles)
|
|
4896
5148
|
};
|
|
4897
5149
|
} catch (error) {
|
|
4898
5150
|
embeddedAgentLog.warn("failed to load codex workspace bootstrap instructions", { error });
|
|
@@ -4905,7 +5157,7 @@ async function buildCodexWorkspaceBootstrapContext(params) {
|
|
|
4905
5157
|
function buildCodexSystemPromptReport(params) {
|
|
4906
5158
|
const toolEntries = params.tools.map(buildCodexToolReportEntry);
|
|
4907
5159
|
const schemaChars = toolEntries.reduce((sum, tool) => sum + tool.schemaChars, 0);
|
|
4908
|
-
const
|
|
5160
|
+
const skillsPrompt = params.skillsPrompt.trim();
|
|
4909
5161
|
const bootstrapMaxChars = readPositiveNumber(params.attempt.config?.agents?.defaults?.bootstrapMaxChars);
|
|
4910
5162
|
const bootstrapTotalMaxChars = readPositiveNumber(params.attempt.config?.agents?.defaults?.bootstrapTotalMaxChars);
|
|
4911
5163
|
return {
|
|
@@ -4920,16 +5172,17 @@ function buildCodexSystemPromptReport(params) {
|
|
|
4920
5172
|
...bootstrapTotalMaxChars ? { bootstrapTotalMaxChars } : {},
|
|
4921
5173
|
systemPrompt: {
|
|
4922
5174
|
chars: params.developerInstructions.length,
|
|
4923
|
-
projectContextChars,
|
|
4924
|
-
nonProjectContextChars:
|
|
5175
|
+
projectContextChars: 0,
|
|
5176
|
+
nonProjectContextChars: params.developerInstructions.length
|
|
4925
5177
|
},
|
|
4926
5178
|
injectedWorkspaceFiles: buildCodexBootstrapInjectionStats({
|
|
4927
5179
|
bootstrapFiles: params.workspaceBootstrapContext.bootstrapFiles,
|
|
4928
|
-
injectedFiles: params.workspaceBootstrapContext.
|
|
5180
|
+
injectedFiles: params.workspaceBootstrapContext.promptContextFiles ?? [],
|
|
5181
|
+
developerInstructionFiles: params.workspaceBootstrapContext.developerInstructionFiles ?? []
|
|
4929
5182
|
}),
|
|
4930
5183
|
skills: {
|
|
4931
|
-
promptChars:
|
|
4932
|
-
entries:
|
|
5184
|
+
promptChars: skillsPrompt.length,
|
|
5185
|
+
entries: buildCodexSkillReportEntries(skillsPrompt)
|
|
4933
5186
|
},
|
|
4934
5187
|
tools: {
|
|
4935
5188
|
listChars: 0,
|
|
@@ -4938,6 +5191,13 @@ function buildCodexSystemPromptReport(params) {
|
|
|
4938
5191
|
}
|
|
4939
5192
|
};
|
|
4940
5193
|
}
|
|
5194
|
+
function buildCodexSkillReportEntries(skillsPrompt) {
|
|
5195
|
+
if (!skillsPrompt) return [];
|
|
5196
|
+
return Array.from(skillsPrompt.matchAll(/<skill>[\s\S]*?<\/skill>/gi)).map((match) => match[0] ?? "").map((block) => ({
|
|
5197
|
+
name: block.match(/<name>\s*([^<]+?)\s*<\/name>/i)?.[1]?.trim() || "(unknown)",
|
|
5198
|
+
blockChars: block.length
|
|
5199
|
+
})).filter((entry) => entry.blockChars > 0);
|
|
5200
|
+
}
|
|
4941
5201
|
function buildCodexToolReportEntry(tool) {
|
|
4942
5202
|
const summary = tool.description.trim();
|
|
4943
5203
|
if (tool.deferLoading === true) return {
|
|
@@ -4967,54 +5227,145 @@ function buildCodexToolSchemaStats(schema) {
|
|
|
4967
5227
|
};
|
|
4968
5228
|
}
|
|
4969
5229
|
function buildCodexBootstrapInjectionStats(params) {
|
|
4970
|
-
const
|
|
4971
|
-
const
|
|
4972
|
-
for (const file of params.injectedFiles) {
|
|
4973
|
-
const pathValue = readNonEmptyString(file.path);
|
|
4974
|
-
if (!pathValue) continue;
|
|
4975
|
-
if (!injectedByPath.has(pathValue)) injectedByPath.set(pathValue, file.content);
|
|
4976
|
-
const baseName = path.posix.basename(pathValue.replaceAll("\\", "/"));
|
|
4977
|
-
if (!injectedByBaseName.has(baseName)) injectedByBaseName.set(baseName, file.content);
|
|
4978
|
-
}
|
|
5230
|
+
const injectedIndex = indexCodexContextFileContent(params.injectedFiles);
|
|
5231
|
+
const developerInstructionIndex = indexCodexContextFileContent(params.developerInstructionFiles ?? []);
|
|
4979
5232
|
return params.bootstrapFiles.map((file) => {
|
|
4980
5233
|
const pathValue = readNonEmptyString(file.path) ?? file.name;
|
|
5234
|
+
const baseName = getCodexContextFileBasename(pathValue || file.name);
|
|
4981
5235
|
const rawChars = file.missing ? 0 : (file.content ?? "").trimEnd().length;
|
|
4982
|
-
const
|
|
5236
|
+
const injected = readCodexIndexedContextFileContent(injectedIndex, pathValue, file.name) ?? readCodexIndexedContextFileContent(developerInstructionIndex, pathValue, file.name);
|
|
5237
|
+
let injectedChars = injected?.length ?? 0;
|
|
5238
|
+
let truncated = !file.missing && injectedChars < rawChars;
|
|
5239
|
+
if (injected === void 0) {
|
|
5240
|
+
if (CODEX_NATIVE_PROJECT_DOC_BASENAMES.has(baseName)) {
|
|
5241
|
+
injectedChars = rawChars;
|
|
5242
|
+
truncated = false;
|
|
5243
|
+
} else if (baseName === CODEX_HEARTBEAT_CONTEXT_BASENAME) {
|
|
5244
|
+
injectedChars = 0;
|
|
5245
|
+
truncated = false;
|
|
5246
|
+
}
|
|
5247
|
+
}
|
|
4983
5248
|
return {
|
|
4984
5249
|
name: file.name,
|
|
4985
5250
|
path: pathValue,
|
|
4986
5251
|
missing: file.missing,
|
|
4987
5252
|
rawChars,
|
|
4988
5253
|
injectedChars,
|
|
4989
|
-
truncated
|
|
5254
|
+
truncated
|
|
4990
5255
|
};
|
|
4991
5256
|
});
|
|
4992
5257
|
}
|
|
5258
|
+
function indexCodexContextFileContent(files) {
|
|
5259
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
5260
|
+
const byBaseName = /* @__PURE__ */ new Map();
|
|
5261
|
+
for (const file of files) {
|
|
5262
|
+
const pathValue = readNonEmptyString(file.path);
|
|
5263
|
+
if (!pathValue) continue;
|
|
5264
|
+
if (!byPath.has(pathValue)) byPath.set(pathValue, file.content);
|
|
5265
|
+
const baseName = getCodexContextFileBasename(pathValue);
|
|
5266
|
+
if (baseName && !byBaseName.has(baseName)) byBaseName.set(baseName, file.content);
|
|
5267
|
+
}
|
|
5268
|
+
return {
|
|
5269
|
+
byPath,
|
|
5270
|
+
byBaseName
|
|
5271
|
+
};
|
|
5272
|
+
}
|
|
5273
|
+
function readCodexIndexedContextFileContent(index, pathValue, fileName) {
|
|
5274
|
+
return index.byPath.get(pathValue) ?? index.byPath.get(fileName) ?? index.byBaseName.get(getCodexContextFileBasename(fileName));
|
|
5275
|
+
}
|
|
4993
5276
|
function readPositiveNumber(value) {
|
|
4994
5277
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : void 0;
|
|
4995
5278
|
}
|
|
4996
5279
|
function readNonEmptyString(value) {
|
|
4997
5280
|
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
4998
5281
|
}
|
|
4999
|
-
function
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5282
|
+
function buildCodexOpenClawPromptContext(params) {
|
|
5283
|
+
if (!shouldInjectCodexOpenClawPromptContext(params.params)) return;
|
|
5284
|
+
const sections = [params.skillsPrompt?.trim() ? [
|
|
5285
|
+
"## OpenClaw Skills",
|
|
5286
|
+
"",
|
|
5287
|
+
params.skillsPrompt.trim()
|
|
5288
|
+
].join("\n") : void 0, params.workspacePromptContext?.trim() ? [
|
|
5289
|
+
"## OpenClaw Workspace Context",
|
|
5290
|
+
"",
|
|
5291
|
+
params.workspacePromptContext.trim()
|
|
5292
|
+
].join("\n") : void 0].filter(isNonEmptyString);
|
|
5293
|
+
if (sections.length === 0) return;
|
|
5294
|
+
return [
|
|
5295
|
+
"OpenClaw runtime context for this turn:",
|
|
5296
|
+
"Treat this OpenClaw-provided context as supporting project/user reference for the current request.",
|
|
5297
|
+
"",
|
|
5298
|
+
...sections
|
|
5299
|
+
].join("\n");
|
|
5300
|
+
}
|
|
5301
|
+
function shouldInjectCodexOpenClawPromptContext(params) {
|
|
5302
|
+
return !(params.bootstrapContextMode === "lightweight" && params.bootstrapContextRunKind === "cron");
|
|
5303
|
+
}
|
|
5304
|
+
function prependCodexOpenClawPromptContext(prompt, context) {
|
|
5305
|
+
if (!context?.trim()) return prompt;
|
|
5306
|
+
const promptSection = prompt.startsWith("OpenClaw assembled context for this turn:") ? prompt : ["Current user request:", prompt].join("\n");
|
|
5307
|
+
return [
|
|
5308
|
+
context.trim(),
|
|
5309
|
+
"",
|
|
5310
|
+
promptSection
|
|
5311
|
+
].join("\n");
|
|
5312
|
+
}
|
|
5313
|
+
function renderCodexWorkspaceBootstrapPromptContext(contextFiles) {
|
|
5314
|
+
const files = selectCodexWorkspacePromptContextFiles(contextFiles);
|
|
5004
5315
|
if (files.length === 0) return;
|
|
5005
|
-
const hasSoulFile = files.some((file) => getCodexContextFileBasename(file.path) === "soul.md");
|
|
5006
5316
|
const lines = [
|
|
5007
|
-
"OpenClaw loaded these user-editable workspace files
|
|
5317
|
+
"OpenClaw loaded these user-editable workspace files for the current turn. Codex loads AGENTS.md natively. SOUL.md, IDENTITY.md, TOOLS.md, and USER.md are provided separately as Codex developer instructions. HEARTBEAT.md is handled by heartbeat collaboration-mode guidance. Those files are not repeated here.",
|
|
5008
5318
|
"",
|
|
5009
5319
|
"# Project Context",
|
|
5010
5320
|
"",
|
|
5011
5321
|
"The following project context files have been loaded:"
|
|
5012
5322
|
];
|
|
5013
|
-
if (hasSoulFile) lines.push("SOUL.md: persona/tone. Follow it unless higher-priority instructions override.");
|
|
5014
5323
|
lines.push("");
|
|
5015
5324
|
for (const file of files) lines.push(`## ${file.path}`, "", file.content, "");
|
|
5016
5325
|
return lines.join("\n").trim();
|
|
5017
5326
|
}
|
|
5327
|
+
function selectCodexWorkspacePromptContextFiles(contextFiles) {
|
|
5328
|
+
return contextFiles.filter((file) => {
|
|
5329
|
+
const baseName = getCodexContextFileBasename(file.path);
|
|
5330
|
+
return baseName && !CODEX_NATIVE_PROJECT_DOC_BASENAMES.has(baseName) && !CODEX_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES.has(baseName) && baseName !== CODEX_HEARTBEAT_CONTEXT_BASENAME && !isMissingCodexBootstrapContextFile(file);
|
|
5331
|
+
}).toSorted(compareCodexContextFiles);
|
|
5332
|
+
}
|
|
5333
|
+
function selectCodexWorkspaceDeveloperInstructionFiles(contextFiles) {
|
|
5334
|
+
return contextFiles.filter((file) => {
|
|
5335
|
+
const baseName = getCodexContextFileBasename(file.path);
|
|
5336
|
+
return baseName && CODEX_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES.has(baseName) && !isMissingCodexBootstrapContextFile(file) && file.content.trim().length > 0;
|
|
5337
|
+
}).toSorted(compareCodexContextFiles);
|
|
5338
|
+
}
|
|
5339
|
+
function renderCodexWorkspaceDeveloperInstructions(files) {
|
|
5340
|
+
if (files.length === 0) return;
|
|
5341
|
+
const lines = [
|
|
5342
|
+
"## OpenClaw Agent Soul",
|
|
5343
|
+
"",
|
|
5344
|
+
"OpenClaw loaded these workspace instruction files from the active agent workspace. They define who you are, how you work, what tools are available, and the human you work alongside. Internalize and follow them accordingly.",
|
|
5345
|
+
""
|
|
5346
|
+
];
|
|
5347
|
+
for (const file of files) lines.push(`### ${file.path}`, "", file.content, "");
|
|
5348
|
+
return lines.join("\n").trim();
|
|
5349
|
+
}
|
|
5350
|
+
function selectCodexWorkspaceHeartbeatReferenceFiles(contextFiles) {
|
|
5351
|
+
return contextFiles.filter((file) => {
|
|
5352
|
+
return getCodexContextFileBasename(file.path) === CODEX_HEARTBEAT_CONTEXT_BASENAME && !isMissingCodexBootstrapContextFile(file) && file.content.trim().length > 0;
|
|
5353
|
+
}).toSorted(compareCodexContextFiles);
|
|
5354
|
+
}
|
|
5355
|
+
function renderCodexWorkspaceHeartbeatReference(files) {
|
|
5356
|
+
if (files.length === 0) return;
|
|
5357
|
+
const lines = [
|
|
5358
|
+
"## OpenClaw Heartbeat Workspace",
|
|
5359
|
+
"",
|
|
5360
|
+
"HEARTBEAT.md exists in the active agent workspace. Read it before proceeding with this heartbeat, then decide what action is appropriate.",
|
|
5361
|
+
""
|
|
5362
|
+
];
|
|
5363
|
+
for (const file of files) lines.push(`- ${file.path}`);
|
|
5364
|
+
return lines.join("\n").trim();
|
|
5365
|
+
}
|
|
5366
|
+
function isMissingCodexBootstrapContextFile(file) {
|
|
5367
|
+
return file.content.trimStart().startsWith("[MISSING] Expected at:");
|
|
5368
|
+
}
|
|
5018
5369
|
function remapCodexContextFilePath(params) {
|
|
5019
5370
|
const relativePath = path.relative(params.sourceWorkspaceDir, params.file.path);
|
|
5020
5371
|
if (!relativePath || relativePath === ".." || relativePath.startsWith(`..${path.sep}`) || path.isAbsolute(relativePath) || params.sourceWorkspaceDir === params.targetWorkspaceDir) return params.file;
|