@openclaw/codex 2026.5.24-beta.2 → 2026.5.26-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{client-1sSy4p3z.js → client-BVK_jmHW.js} +10 -3
- package/dist/{client-factory-Bk6i4FnW.js → client-factory-CaOpX89B.js} +1 -1
- package/dist/{command-handlers-CcTABuem.js → command-handlers-D4C2y46B.js} +10 -23
- package/dist/compact-CRI0BEc_.js +155 -0
- package/dist/{computer-use-Hdq1WgTA.js → computer-use-CDDlIBhY.js} +2 -2
- package/dist/{config-DDMrwfJl.js → config-0-UN67Qg.js} +8 -4
- package/dist/{node-cli-sessions-9CAqnIaA.js → conversation-binding-BnnjOmgs.js} +426 -434
- package/dist/{dynamic-tools-Bq717oJR.js → dynamic-tools-BG9ICyU4.js} +20 -11
- package/dist/harness.js +5 -5
- package/dist/index.js +452 -18
- package/dist/media-understanding-provider.js +8 -6
- package/dist/{models-DtGLkqMP.js → models-ASKu9eOY.js} +4 -4
- package/dist/{notification-correlation-qKY_sgga.js → notification-correlation-YINts3PA.js} +26 -11
- package/dist/{protocol-validators-_gKDcd0x.js → protocol-validators-CSuFMLvY.js} +138 -29
- package/dist/provider.js +3 -3
- package/dist/{request-D93E78SA.js → request-DmBkYLPy.js} +3 -3
- package/dist/{run-attempt-CT1N__qp.js → run-attempt-CFBsGx1T.js} +488 -280
- package/dist/{session-binding-Bw_mfIW2.js → session-binding-UFjjws4k.js} +1 -1
- package/dist/{shared-client-CFCUGEVs.js → shared-client-Fou5nAyt.js} +66 -11
- package/dist/{side-question-CYFMTA1O.js → side-question-fq_T2d_x.js} +17 -12
- package/dist/test-api.js +3 -3
- package/dist/{thread-lifecycle-DGoaguJh.js → thread-lifecycle-BapIT9Qs.js} +113 -28
- package/dist/{vision-tools-DOnxzH2y.js → vision-tools-B30YCKRK.js} +16 -4
- package/npm-shrinkwrap.json +222 -305
- package/package.json +8 -8
- package/dist/compact-DnTgL6UT.js +0 -475
- package/dist/protocol-oeJQu4rs.js +0 -9
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { a as isCodexAppServerConnectionClosedError, i as isCodexAppServerApprovalRequest, r as compareCodexAppServerVersions, s as MIN_CODEX_SANDBOX_EXEC_SERVER_APP_SERVER_VERSION } from "./client-
|
|
5
|
-
import { C as
|
|
6
|
-
import { i as readCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-
|
|
7
|
-
import { n as buildCodexPluginAppCacheKey, r as CODEX_CONTROL_METHODS } from "./request-
|
|
8
|
-
import { g as shouldRefreshCodexRateLimitsForUsageLimitMessage, h as resolveCodexUsageLimitResetAtMs, i as readCodexNotificationTurnId, m as formatCodexUsageLimitErrorMessage, n as isCodexNotificationForTurn, r as readCodexNotificationThreadId, s as formatCodexDisplayText, t as describeCodexNotificationCorrelation } from "./notification-correlation-
|
|
9
|
-
import { c as resolveCodexAppServerAuthAccountCacheKey, d as
|
|
1
|
+
import { t as defaultCodexAppServerClientFactory } from "./client-factory-CaOpX89B.js";
|
|
2
|
+
import { c as readCodexPluginConfig, d as resolveCodexPluginsPolicy, f as shouldAutoApproveCodexAppServerApprovals, i as isCodexAppServerApprovalPolicyAllowedByRequirements, l as resolveCodexAppServerRuntimeOptions, o as isCodexSandboxExecServerEnabled, p as withMcpElicitationsApprovalPolicy, u as resolveCodexComputerUseConfig } from "./config-0-UN67Qg.js";
|
|
3
|
+
import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse } from "./protocol-validators-CSuFMLvY.js";
|
|
4
|
+
import { a as isCodexAppServerConnectionClosedError, i as isCodexAppServerApprovalRequest, l as isJsonObject, r as compareCodexAppServerVersions, s as MIN_CODEX_SANDBOX_EXEC_SERVER_APP_SERVER_VERSION } from "./client-BVK_jmHW.js";
|
|
5
|
+
import { C as defaultCodexAppInventoryCache, D as projectContextEngineAssemblyForCodex, O as resolveCodexContextEngineProjectionMaxChars, T as sanitizeCodexHistoryImagePayloads, _ as buildCodexPluginThreadConfigInputFingerprint, a as buildDeveloperInstructions, c as buildTurnCollaborationMode, d as isContextEngineBindingCompatible, g as buildCodexPluginThreadConfig, h as isCodexAppServerProfilerEnabled, i as buildContextEngineBinding, k as resolveCodexContextEngineProjectionReserveTokens, l as buildTurnStartParams, m as startOrResumeThread, n as areCodexDynamicToolFingerprintsCompatible, u as codexDynamicToolsFingerprint, v as mergeCodexThreadConfigs, y as shouldBuildCodexPluginThreadConfig } from "./thread-lifecycle-BapIT9Qs.js";
|
|
6
|
+
import { i as readCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-UFjjws4k.js";
|
|
7
|
+
import { n as buildCodexPluginAppCacheKey, r as CODEX_CONTROL_METHODS } from "./request-DmBkYLPy.js";
|
|
8
|
+
import { g as shouldRefreshCodexRateLimitsForUsageLimitMessage, h as resolveCodexUsageLimitResetAtMs, i as readCodexNotificationTurnId, m as formatCodexUsageLimitErrorMessage, n as isCodexNotificationForTurn, r as readCodexNotificationThreadId, s as formatCodexDisplayText, t as describeCodexNotificationCorrelation } from "./notification-correlation-YINts3PA.js";
|
|
9
|
+
import { c as resolveCodexAppServerAuthAccountCacheKey, d as resolveCodexAppServerFallbackApiKeyCacheKey, f as resolveCodexAppServerHomeDir, l as resolveCodexAppServerAuthProfileId, s as refreshCodexAppServerAuthTokens, t as clearSharedCodexAppServerClientIfCurrent, u as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-Fou5nAyt.js";
|
|
10
10
|
import { i as resolveCodexNativeExecutionPolicy } from "./sandbox-guard-CTnEWuor.js";
|
|
11
|
-
import { a as resolveCodexDynamicToolsLoading, i as normalizeCodexDynamicToolName, n as filterCodexDynamicTools, r as isForcedPrivateQaCodexRuntime, t as createCodexDynamicToolBridge } from "./dynamic-tools-
|
|
12
|
-
import { t as
|
|
13
|
-
import {
|
|
14
|
-
import { t as ensureCodexComputerUse } from "./computer-use-Hdq1WgTA.js";
|
|
11
|
+
import { a as resolveCodexDynamicToolsLoading, i as normalizeCodexDynamicToolName, n as filterCodexDynamicTools, r as isForcedPrivateQaCodexRuntime, t as createCodexDynamicToolBridge } from "./dynamic-tools-BG9ICyU4.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-B30YCKRK.js";
|
|
13
|
+
import { t as ensureCodexComputerUse } from "./computer-use-CDDlIBhY.js";
|
|
15
14
|
import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-N66I-Rd7.js";
|
|
16
15
|
import { createHash, randomUUID } from "node:crypto";
|
|
17
|
-
import
|
|
18
|
-
import {
|
|
16
|
+
import fsSync from "node:fs";
|
|
17
|
+
import { asBoolean, asFiniteNumber, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
18
|
+
import { CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, TOOL_PROGRESS_OUTPUT_MAX_CHARS, acquireSessionWriteLock, appendSessionTranscriptMessage, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentHarnessAgentEndHook, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildEmbeddedAttemptToolRunContext, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emitSessionTranscriptUpdate, finalizeHarnessContextEngineTurn, formatErrorMessage, formatToolAggregate, formatToolProgressOutput, getBeforeToolCallPolicyDiagnosticState, 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";
|
|
19
19
|
import { spawn } from "node:child_process";
|
|
20
20
|
import { once } from "node:events";
|
|
21
21
|
import { WebSocketServer } from "ws";
|
|
22
22
|
import { redactSensitiveFieldValue, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
|
|
23
23
|
import fs from "node:fs/promises";
|
|
24
24
|
import path, { posix } from "node:path";
|
|
25
|
+
import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, hasPendingInternalDiagnosticEvent, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
25
26
|
import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1 } from "openclaw/plugin-sdk/agent-runtime";
|
|
26
27
|
import { isToolAllowed } from "openclaw/plugin-sdk/sandbox";
|
|
27
28
|
import { appendRegularFile, pathExists } from "openclaw/plugin-sdk/security-runtime";
|
|
28
|
-
import { emitTrustedDiagnosticEvent, hasPendingInternalDiagnosticEvent, onInternalDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
29
29
|
import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "@earendil-works/pi-coding-agent";
|
|
30
30
|
import { createAgentHarnessTaskRuntime, deliverAgentHarnessTaskCompletion, isDurableAgentHarnessCompletionDelivery } from "openclaw/plugin-sdk/agent-harness-task-runtime";
|
|
31
31
|
import { isIP } from "node:net";
|
|
@@ -102,10 +102,6 @@ function inferCodexDynamicToolMeta(call, detailMode) {
|
|
|
102
102
|
//#endregion
|
|
103
103
|
//#region extensions/codex/src/app-server/transcript-mirror.ts
|
|
104
104
|
const MIRROR_IDENTITY_META_KEY = "mirrorIdentity";
|
|
105
|
-
function normalizeOptionalString$1(value) {
|
|
106
|
-
const normalized = value?.trim();
|
|
107
|
-
return normalized ? normalized : void 0;
|
|
108
|
-
}
|
|
109
105
|
function buildSenderLabel(params) {
|
|
110
106
|
const label = params.senderName ?? params.senderUsername ?? params.senderE164 ?? params.senderId;
|
|
111
107
|
if (!label) return;
|
|
@@ -113,17 +109,17 @@ function buildSenderLabel(params) {
|
|
|
113
109
|
return `${label} (${params.senderId})`;
|
|
114
110
|
}
|
|
115
111
|
function buildCodexUserPromptMessage(params) {
|
|
116
|
-
const senderId = normalizeOptionalString
|
|
117
|
-
const senderName = normalizeOptionalString
|
|
118
|
-
const senderUsername = normalizeOptionalString
|
|
119
|
-
const senderE164 = normalizeOptionalString
|
|
112
|
+
const senderId = normalizeOptionalString(params.senderId);
|
|
113
|
+
const senderName = normalizeOptionalString(params.senderName);
|
|
114
|
+
const senderUsername = normalizeOptionalString(params.senderUsername);
|
|
115
|
+
const senderE164 = normalizeOptionalString(params.senderE164);
|
|
120
116
|
const senderLabel = buildSenderLabel({
|
|
121
117
|
senderId,
|
|
122
118
|
senderName,
|
|
123
119
|
senderUsername,
|
|
124
120
|
senderE164
|
|
125
121
|
});
|
|
126
|
-
const sourceChannel = normalizeOptionalString
|
|
122
|
+
const sourceChannel = normalizeOptionalString(params.inputProvenance?.sourceChannel ?? params.messageChannel ?? params.messageProvider);
|
|
127
123
|
return {
|
|
128
124
|
role: "user",
|
|
129
125
|
content: params.prompt,
|
|
@@ -183,12 +179,14 @@ async function mirrorCodexAppServerTranscript(params) {
|
|
|
183
179
|
sessionFile: params.sessionFile,
|
|
184
180
|
...resolveSessionWriteLockOptions(params.config)
|
|
185
181
|
});
|
|
182
|
+
const appendedUpdates = [];
|
|
186
183
|
try {
|
|
187
|
-
const
|
|
184
|
+
const mirrorState = await readTranscriptMirrorState(params.sessionFile);
|
|
185
|
+
let nextMessageSeq = mirrorState.messageCount;
|
|
188
186
|
for (const message of messages) {
|
|
189
187
|
const dedupeIdentity = buildMirrorDedupeIdentity(message);
|
|
190
188
|
const idempotencyKey = params.idempotencyScope ? `${params.idempotencyScope}:${dedupeIdentity}` : void 0;
|
|
191
|
-
if (idempotencyKey &&
|
|
189
|
+
if (idempotencyKey && mirrorState.idempotencyKeys.has(idempotencyKey)) continue;
|
|
192
190
|
const nextMessage = runAgentHarnessBeforeMessageWriteHook({
|
|
193
191
|
message: {
|
|
194
192
|
...message,
|
|
@@ -202,41 +200,57 @@ async function mirrorCodexAppServerTranscript(params) {
|
|
|
202
200
|
...nextMessage,
|
|
203
201
|
idempotencyKey
|
|
204
202
|
} : nextMessage;
|
|
205
|
-
await appendSessionTranscriptMessage({
|
|
203
|
+
const { messageId, message: appendedMessage } = await appendSessionTranscriptMessage({
|
|
206
204
|
transcriptPath: params.sessionFile,
|
|
207
205
|
message: messageToAppend,
|
|
208
206
|
config: params.config
|
|
209
207
|
});
|
|
210
|
-
|
|
208
|
+
nextMessageSeq += 1;
|
|
209
|
+
appendedUpdates.push({
|
|
210
|
+
messageId,
|
|
211
|
+
message: appendedMessage,
|
|
212
|
+
messageSeq: nextMessageSeq
|
|
213
|
+
});
|
|
214
|
+
if (idempotencyKey) mirrorState.idempotencyKeys.add(idempotencyKey);
|
|
211
215
|
}
|
|
212
216
|
} finally {
|
|
213
217
|
await lock.release();
|
|
214
218
|
}
|
|
215
|
-
|
|
219
|
+
for (const update of appendedUpdates) emitSessionTranscriptUpdate({
|
|
216
220
|
sessionFile: params.sessionFile,
|
|
217
|
-
sessionKey: params.sessionKey
|
|
221
|
+
...params.sessionKey ? { sessionKey: params.sessionKey } : {},
|
|
222
|
+
message: update.message,
|
|
223
|
+
messageId: update.messageId,
|
|
224
|
+
messageSeq: update.messageSeq
|
|
218
225
|
});
|
|
219
|
-
else emitSessionTranscriptUpdate(params.sessionFile);
|
|
220
226
|
}
|
|
221
|
-
async function
|
|
222
|
-
const
|
|
227
|
+
async function readTranscriptMirrorState(sessionFile) {
|
|
228
|
+
const idempotencyKeys = /* @__PURE__ */ new Set();
|
|
229
|
+
let messageCount = 0;
|
|
223
230
|
let raw;
|
|
224
231
|
try {
|
|
225
232
|
raw = await fs.readFile(sessionFile, "utf8");
|
|
226
233
|
} catch (error) {
|
|
227
234
|
if (error.code !== "ENOENT") throw error;
|
|
228
|
-
return
|
|
235
|
+
return {
|
|
236
|
+
idempotencyKeys,
|
|
237
|
+
messageCount
|
|
238
|
+
};
|
|
229
239
|
}
|
|
230
240
|
for (const line of raw.split(/\r?\n/)) {
|
|
231
241
|
if (!line.trim()) continue;
|
|
232
242
|
try {
|
|
233
243
|
const parsed = JSON.parse(line);
|
|
234
|
-
if (
|
|
244
|
+
if (parsed.type === "message") messageCount += 1;
|
|
245
|
+
if (typeof parsed.message?.idempotencyKey === "string") idempotencyKeys.add(parsed.message.idempotencyKey);
|
|
235
246
|
} catch {
|
|
236
247
|
continue;
|
|
237
248
|
}
|
|
238
249
|
}
|
|
239
|
-
return
|
|
250
|
+
return {
|
|
251
|
+
idempotencyKeys,
|
|
252
|
+
messageCount
|
|
253
|
+
};
|
|
240
254
|
}
|
|
241
255
|
//#endregion
|
|
242
256
|
//#region extensions/codex/src/app-server/event-projector.ts
|
|
@@ -463,6 +477,12 @@ var CodexAppServerEventProjector = class {
|
|
|
463
477
|
});
|
|
464
478
|
}
|
|
465
479
|
recordDynamicToolResult(params) {
|
|
480
|
+
const existingMeta = this.toolMetas.get(params.callId);
|
|
481
|
+
this.toolMetas.set(params.callId, {
|
|
482
|
+
toolName: params.tool,
|
|
483
|
+
...existingMeta?.meta ? { meta: existingMeta.meta } : {},
|
|
484
|
+
...existingMeta?.asyncStarted === true || params.asyncStarted === true ? { asyncStarted: true } : {}
|
|
485
|
+
});
|
|
466
486
|
this.recordToolTranscriptResult({
|
|
467
487
|
id: params.callId,
|
|
468
488
|
name: params.tool,
|
|
@@ -832,7 +852,7 @@ var CodexAppServerEventProjector = class {
|
|
|
832
852
|
if (savedPath) this.nativeGeneratedMediaUrls.add(savedPath);
|
|
833
853
|
}
|
|
834
854
|
buildToolMediaUrls(toolTelemetry) {
|
|
835
|
-
const mediaUrls = new Set(toolTelemetry.toolMediaUrls
|
|
855
|
+
const mediaUrls = new Set(normalizeStringEntries(toolTelemetry.toolMediaUrls ?? []));
|
|
836
856
|
if ((toolTelemetry.messagingToolSentMediaUrls?.length ?? 0) === 0) for (const mediaUrl of this.nativeGeneratedMediaUrls) mediaUrls.add(mediaUrl);
|
|
837
857
|
return mediaUrls.size > 0 ? [...mediaUrls] : toolTelemetry.toolMediaUrls;
|
|
838
858
|
}
|
|
@@ -1118,9 +1138,11 @@ var CodexAppServerEventProjector = class {
|
|
|
1118
1138
|
const toolName = itemName(item);
|
|
1119
1139
|
if (!toolName) return;
|
|
1120
1140
|
const meta = itemMeta(item, this.toolProgressDetailMode());
|
|
1141
|
+
const existingMeta = this.toolMetas.get(item.id);
|
|
1121
1142
|
this.toolMetas.set(item.id, {
|
|
1122
1143
|
toolName,
|
|
1123
|
-
...meta ? { meta } : {}
|
|
1144
|
+
...meta ? { meta } : {},
|
|
1145
|
+
...existingMeta?.asyncStarted === true ? { asyncStarted: true } : {}
|
|
1124
1146
|
});
|
|
1125
1147
|
if (isSideEffectingNativeToolItem(item)) this.sideEffectingToolItemIds.add(item.id);
|
|
1126
1148
|
else this.sideEffectingToolItemIds.delete(item.id);
|
|
@@ -1364,12 +1386,10 @@ function readNullableString$1(record, key) {
|
|
|
1364
1386
|
return typeof value === "string" ? value : void 0;
|
|
1365
1387
|
}
|
|
1366
1388
|
function readNumber$1(record, key) {
|
|
1367
|
-
|
|
1368
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1389
|
+
return asFiniteNumber(record[key]);
|
|
1369
1390
|
}
|
|
1370
1391
|
function readBoolean$1(record, key) {
|
|
1371
|
-
|
|
1372
|
-
return typeof value === "boolean" ? value : void 0;
|
|
1392
|
+
return asBoolean(record[key]);
|
|
1373
1393
|
}
|
|
1374
1394
|
function readBooleanAlias(record, keys) {
|
|
1375
1395
|
for (const key of keys) {
|
|
@@ -2616,9 +2636,6 @@ function readString$2(record, key) {
|
|
|
2616
2636
|
const value = record?.[key];
|
|
2617
2637
|
return typeof value === "string" ? value : void 0;
|
|
2618
2638
|
}
|
|
2619
|
-
function normalizeOptionalString(value) {
|
|
2620
|
-
return value?.trim() || void 0;
|
|
2621
|
-
}
|
|
2622
2639
|
function readStringArray(value) {
|
|
2623
2640
|
if (!Array.isArray(value)) return [];
|
|
2624
2641
|
return value.filter((entry) => typeof entry === "string" && entry.trim() !== "");
|
|
@@ -2741,8 +2758,7 @@ function readTranscriptParentThreadId(payload) {
|
|
|
2741
2758
|
return readString$2(isJsonObject(subagent?.thread_spawn) ? subagent.thread_spawn : void 0, "parent_thread_id")?.trim();
|
|
2742
2759
|
}
|
|
2743
2760
|
function readNumber(record, key) {
|
|
2744
|
-
|
|
2745
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
2761
|
+
return asFiniteNumber(record[key]);
|
|
2746
2762
|
}
|
|
2747
2763
|
function secondsToMillis(value) {
|
|
2748
2764
|
return value === void 0 ? void 0 : Math.round(value * 1e3);
|
|
@@ -3930,7 +3946,7 @@ const JWT_VALUE_RE = /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]
|
|
|
3930
3946
|
const COOKIE_PAIR_RE = /\b([A-Za-z][A-Za-z0-9_.-]{1,64})=([A-Za-z0-9+/._~%=-]{16,})(?=;|\s|$)/gu;
|
|
3931
3947
|
const TRAJECTORY_RUNTIME_FILE_MAX_BYTES = 50 * 1024 * 1024;
|
|
3932
3948
|
const TRAJECTORY_RUNTIME_EVENT_MAX_BYTES = 256 * 1024;
|
|
3933
|
-
function resolveCodexTrajectoryPointerFlags(constants =
|
|
3949
|
+
function resolveCodexTrajectoryPointerFlags(constants = fsSync.constants) {
|
|
3934
3950
|
const noFollow = constants.O_NOFOLLOW;
|
|
3935
3951
|
return constants.O_CREAT | constants.O_TRUNC | constants.O_WRONLY | (typeof noFollow === "number" ? noFollow : 0);
|
|
3936
3952
|
}
|
|
@@ -3964,23 +3980,23 @@ function writeTrajectoryPointerBestEffort(params) {
|
|
|
3964
3980
|
const pointerPath = resolveTrajectoryPointerFilePath(params.sessionFile);
|
|
3965
3981
|
try {
|
|
3966
3982
|
const pointerDir = path.resolve(path.dirname(pointerPath));
|
|
3967
|
-
if (
|
|
3983
|
+
if (fsSync.lstatSync(pointerDir).isSymbolicLink()) return;
|
|
3968
3984
|
try {
|
|
3969
|
-
if (
|
|
3985
|
+
if (fsSync.lstatSync(pointerPath).isSymbolicLink()) return;
|
|
3970
3986
|
} catch (error) {
|
|
3971
3987
|
if (error.code !== "ENOENT") return;
|
|
3972
3988
|
}
|
|
3973
|
-
const fd =
|
|
3989
|
+
const fd = fsSync.openSync(pointerPath, resolveCodexTrajectoryPointerFlags(), 384);
|
|
3974
3990
|
try {
|
|
3975
|
-
|
|
3991
|
+
fsSync.writeFileSync(fd, `${JSON.stringify({
|
|
3976
3992
|
traceSchema: "openclaw-trajectory-pointer",
|
|
3977
3993
|
schemaVersion: 1,
|
|
3978
3994
|
sessionId: params.sessionId,
|
|
3979
3995
|
runtimeFile: params.filePath
|
|
3980
3996
|
}, null, 2)}\n`, "utf8");
|
|
3981
|
-
|
|
3997
|
+
fsSync.fchmodSync(fd, 384);
|
|
3982
3998
|
} finally {
|
|
3983
|
-
|
|
3999
|
+
fsSync.closeSync(fd);
|
|
3984
4000
|
}
|
|
3985
4001
|
} catch {}
|
|
3986
4002
|
}
|
|
@@ -4345,6 +4361,7 @@ const CODEX_BOOTSTRAP_CONTEXT_ORDER = new Map([
|
|
|
4345
4361
|
["memory.md", 60],
|
|
4346
4362
|
["heartbeat.md", 70]
|
|
4347
4363
|
]);
|
|
4364
|
+
const ensuredCodexWorkspaceDirs = /* @__PURE__ */ new Set();
|
|
4348
4365
|
const pendingCodexNativeHookRelayUnregisters = /* @__PURE__ */ new Set();
|
|
4349
4366
|
function scheduleCodexNativeHookRelayUnregister(params) {
|
|
4350
4367
|
let pending;
|
|
@@ -4367,6 +4384,19 @@ function resolveCodexNativeHookRelayUnregisterGraceMs(hookTimeoutSec) {
|
|
|
4367
4384
|
const hookTimeoutMs = typeof hookTimeoutSec === "number" && Number.isFinite(hookTimeoutSec) && hookTimeoutSec > 0 ? Math.ceil(hookTimeoutSec) * 1e3 : 0;
|
|
4368
4385
|
return Math.max(CODEX_NATIVE_HOOK_RELAY_UNREGISTER_GRACE_MS, hookTimeoutMs + CODEX_NATIVE_HOOK_RELAY_UNREGISTER_EXTRA_GRACE_MS);
|
|
4369
4386
|
}
|
|
4387
|
+
async function ensureCodexWorkspaceDirOnce(workspaceDir) {
|
|
4388
|
+
const normalized = path.resolve(workspaceDir);
|
|
4389
|
+
if (ensuredCodexWorkspaceDirs.has(normalized)) {
|
|
4390
|
+
try {
|
|
4391
|
+
if ((await fs.stat(normalized)).isDirectory()) return;
|
|
4392
|
+
} catch (error) {
|
|
4393
|
+
if ((typeof error === "object" && error ? error.code : void 0) !== "ENOENT") throw error;
|
|
4394
|
+
}
|
|
4395
|
+
ensuredCodexWorkspaceDirs.delete(normalized);
|
|
4396
|
+
}
|
|
4397
|
+
await fs.mkdir(normalized, { recursive: true });
|
|
4398
|
+
ensuredCodexWorkspaceDirs.add(normalized);
|
|
4399
|
+
}
|
|
4370
4400
|
function emitCodexAppServerEvent(params, event) {
|
|
4371
4401
|
try {
|
|
4372
4402
|
emitAgentEvent({
|
|
@@ -4549,7 +4579,7 @@ function isCodexAppServerPolicyMode(value) {
|
|
|
4549
4579
|
function isCodexAppServerApprovalPolicy(value) {
|
|
4550
4580
|
return value === "never" || value === "on-request" || value === "on-failure" || value === "untrusted";
|
|
4551
4581
|
}
|
|
4552
|
-
const
|
|
4582
|
+
const CODEX_APP_SERVER_NATIVE_THREAD_FALLBACK_MAX_TOKENS = 3e5;
|
|
4553
4583
|
const CODEX_APP_SERVER_BYTE_UNITS = {
|
|
4554
4584
|
b: 1,
|
|
4555
4585
|
k: 1024,
|
|
@@ -4637,25 +4667,29 @@ async function readCodexSessionRecordForSessionFile(sessionFile) {
|
|
|
4637
4667
|
};
|
|
4638
4668
|
}
|
|
4639
4669
|
}
|
|
4640
|
-
async function
|
|
4670
|
+
async function readCodexAppServerRolloutTokenSnapshot(file) {
|
|
4641
4671
|
let handle;
|
|
4642
4672
|
try {
|
|
4643
4673
|
handle = await fs.open(file, "r");
|
|
4644
4674
|
} catch {
|
|
4645
4675
|
return;
|
|
4646
4676
|
}
|
|
4647
|
-
let
|
|
4677
|
+
let snapshot;
|
|
4648
4678
|
try {
|
|
4649
4679
|
for await (const line of handle.readLines()) {
|
|
4650
|
-
const
|
|
4651
|
-
if (
|
|
4680
|
+
const lineSnapshot = readCodexAppServerRolloutTokenSnapshotLine(line);
|
|
4681
|
+
if (lineSnapshot !== void 0) {
|
|
4682
|
+
snapshot ??= {};
|
|
4683
|
+
if (lineSnapshot.totalTokens !== void 0) snapshot.totalTokens = lineSnapshot.totalTokens;
|
|
4684
|
+
if (lineSnapshot.modelContextWindow !== void 0) snapshot.modelContextWindow = lineSnapshot.modelContextWindow;
|
|
4685
|
+
}
|
|
4652
4686
|
}
|
|
4653
4687
|
} finally {
|
|
4654
4688
|
await handle.close();
|
|
4655
4689
|
}
|
|
4656
|
-
return
|
|
4690
|
+
return snapshot;
|
|
4657
4691
|
}
|
|
4658
|
-
function
|
|
4692
|
+
function readCodexAppServerRolloutTokenSnapshotLine(line) {
|
|
4659
4693
|
if (!line.trim()) return;
|
|
4660
4694
|
try {
|
|
4661
4695
|
const parsed = JSON.parse(line);
|
|
@@ -4664,7 +4698,23 @@ function readCodexAppServerRolloutTokenUsageLine(line) {
|
|
|
4664
4698
|
if (!info) return;
|
|
4665
4699
|
const usage = isJsonObject(info.last_token_usage) ? info.last_token_usage : isJsonObject(info.total_token_usage) ? info.total_token_usage : void 0;
|
|
4666
4700
|
const value = usage?.total_tokens ?? usage?.totalTokens;
|
|
4667
|
-
|
|
4701
|
+
const totalTokens = typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
4702
|
+
const windowValue = info.model_context_window ?? info.modelContextWindow;
|
|
4703
|
+
const modelContextWindow = typeof windowValue === "number" && Number.isFinite(windowValue) && windowValue > 0 ? Math.floor(windowValue) : void 0;
|
|
4704
|
+
const snapshot = {};
|
|
4705
|
+
if (totalTokens !== void 0) snapshot.totalTokens = totalTokens;
|
|
4706
|
+
if (modelContextWindow !== void 0) snapshot.modelContextWindow = modelContextWindow;
|
|
4707
|
+
return snapshot.totalTokens !== void 0 || snapshot.modelContextWindow !== void 0 ? snapshot : void 0;
|
|
4708
|
+
} catch {
|
|
4709
|
+
return;
|
|
4710
|
+
}
|
|
4711
|
+
}
|
|
4712
|
+
function resolveCodexAppServerNativeThreadTokenFuse(modelContextWindow) {
|
|
4713
|
+
return modelContextWindow ?? CODEX_APP_SERVER_NATIVE_THREAD_FALLBACK_MAX_TOKENS;
|
|
4714
|
+
}
|
|
4715
|
+
function utf8JsonByteLength(value) {
|
|
4716
|
+
try {
|
|
4717
|
+
return Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
4668
4718
|
} catch {
|
|
4669
4719
|
return;
|
|
4670
4720
|
}
|
|
@@ -4674,10 +4724,22 @@ function maxFiniteNumber(values) {
|
|
|
4674
4724
|
if (nums.length === 0) return;
|
|
4675
4725
|
return Math.max(...nums);
|
|
4676
4726
|
}
|
|
4727
|
+
function hasContextEngineThreadBootstrapProjection(binding) {
|
|
4728
|
+
return binding.contextEngine?.projection?.mode === "thread_bootstrap";
|
|
4729
|
+
}
|
|
4677
4730
|
async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
4678
4731
|
const binding = params.binding;
|
|
4679
4732
|
if (!binding?.threadId) return binding;
|
|
4680
4733
|
if (params.config?.agents?.defaults?.compaction?.truncateAfterCompaction !== true) return binding;
|
|
4734
|
+
if (params.contextEngineActive === true && hasContextEngineThreadBootstrapProjection(binding)) {
|
|
4735
|
+
embeddedAgentLog.debug("codex app-server deferring native transcript size guard for context-engine thread bootstrap", {
|
|
4736
|
+
threadId: binding.threadId,
|
|
4737
|
+
engineId: binding.contextEngine?.engineId,
|
|
4738
|
+
epoch: binding.contextEngine?.projection?.epoch,
|
|
4739
|
+
fingerprint: binding.contextEngine?.projection?.fingerprint
|
|
4740
|
+
});
|
|
4741
|
+
return binding;
|
|
4742
|
+
}
|
|
4681
4743
|
const sessionRecord = await readCodexSessionRecordForSessionFile(params.sessionFile);
|
|
4682
4744
|
const maxBytes = parseCodexAppServerByteLimit(params.config?.agents?.defaults?.compaction?.maxActiveTranscriptBytes);
|
|
4683
4745
|
const rolloutFiles = await listCodexAppServerRolloutFilesForThread(params.agentDir, binding.threadId, params.codexHome);
|
|
@@ -4696,16 +4758,20 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
4696
4758
|
return;
|
|
4697
4759
|
}
|
|
4698
4760
|
}
|
|
4699
|
-
const
|
|
4761
|
+
const nativeTokenSnapshots = await Promise.all(rolloutFiles.map(async (file) => readCodexAppServerRolloutTokenSnapshot(file.path)));
|
|
4762
|
+
const nativeTokens = maxFiniteNumber(nativeTokenSnapshots.map((snapshot) => snapshot?.totalTokens));
|
|
4763
|
+
const nativeModelContextWindow = maxFiniteNumber(nativeTokenSnapshots.map((snapshot) => snapshot?.modelContextWindow));
|
|
4764
|
+
const maxTokens = resolveCodexAppServerNativeThreadTokenFuse(nativeModelContextWindow);
|
|
4700
4765
|
const sessionTokens = sessionRecord?.totalTokensFresh !== false && typeof sessionRecord?.totalTokens === "number" && Number.isFinite(sessionRecord.totalTokens) ? sessionRecord.totalTokens : void 0;
|
|
4701
4766
|
const tokenCount = maxFiniteNumber([sessionTokens, nativeTokens]);
|
|
4702
|
-
if (tokenCount !== void 0 && tokenCount >=
|
|
4767
|
+
if (tokenCount !== void 0 && tokenCount >= maxTokens) {
|
|
4703
4768
|
embeddedAgentLog.warn("codex app-server native transcript exceeded active token limit; starting a fresh thread", {
|
|
4704
4769
|
threadId: binding.threadId,
|
|
4705
|
-
maxTokens
|
|
4770
|
+
maxTokens,
|
|
4706
4771
|
sessionKey: sessionRecord?.sessionKey,
|
|
4707
4772
|
sessionTokens,
|
|
4708
|
-
nativeTokens
|
|
4773
|
+
nativeTokens,
|
|
4774
|
+
nativeModelContextWindow
|
|
4709
4775
|
});
|
|
4710
4776
|
await clearCodexAppServerBinding(params.sessionFile);
|
|
4711
4777
|
return;
|
|
@@ -4724,12 +4790,24 @@ async function runCodexAgentEndHook(params, hookParams) {
|
|
|
4724
4790
|
}
|
|
4725
4791
|
async function runCodexAppServerAttempt(params, options = {}) {
|
|
4726
4792
|
const attemptStartedAt = Date.now();
|
|
4793
|
+
const profilerEnabled = isCodexAppServerProfilerEnabled(params.config);
|
|
4794
|
+
const codexModelCallTrace = freezeDiagnosticTraceContext(createDiagnosticTraceContextFromActiveScope());
|
|
4795
|
+
const codexModelContentCapture = resolveDiagnosticModelContentCapturePolicy(params.config);
|
|
4796
|
+
const codexModelCallId = `${params.runId}:codex-model:1`;
|
|
4797
|
+
let codexModelCallStartedAt = attemptStartedAt;
|
|
4798
|
+
let codexModelCallStarted = false;
|
|
4799
|
+
let codexModelCallTerminalEmitted = false;
|
|
4800
|
+
let codexModelCallRequestPayloadBytes;
|
|
4801
|
+
const preDynamicStartupStages = createCodexDynamicToolBuildStageTracker({ enabled: profilerEnabled });
|
|
4727
4802
|
const attemptClientFactory = options.clientFactory ?? defaultCodexAppServerClientFactory;
|
|
4728
4803
|
const pluginConfig = readCodexPluginConfig(options.pluginConfig);
|
|
4729
4804
|
const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig });
|
|
4730
4805
|
const configuredAppServer = resolveCodexAppServerRuntimeOptions({ pluginConfig });
|
|
4806
|
+
const beforeToolCallPolicy = getBeforeToolCallPolicyDiagnosticState();
|
|
4807
|
+
preDynamicStartupStages.mark("config");
|
|
4731
4808
|
const resolvedWorkspace = resolveUserPath(params.workspaceDir);
|
|
4732
|
-
await
|
|
4809
|
+
await ensureCodexWorkspaceDirOnce(resolvedWorkspace);
|
|
4810
|
+
preDynamicStartupStages.mark("workspace");
|
|
4733
4811
|
const sandboxSessionKey = params.sandboxSessionKey?.trim() || params.sessionKey?.trim() || params.sessionId;
|
|
4734
4812
|
const contextSessionKey = params.sessionKey?.trim() || sandboxSessionKey;
|
|
4735
4813
|
const sandbox = await resolveSandboxContext({
|
|
@@ -4737,20 +4815,30 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
4737
4815
|
sessionKey: sandboxSessionKey,
|
|
4738
4816
|
workspaceDir: resolvedWorkspace
|
|
4739
4817
|
});
|
|
4818
|
+
preDynamicStartupStages.mark("sandbox");
|
|
4740
4819
|
const effectiveWorkspace = sandbox?.enabled ? sandbox.workspaceAccess === "rw" ? resolvedWorkspace : sandbox.workspaceDir : resolvedWorkspace;
|
|
4741
|
-
await
|
|
4820
|
+
await ensureCodexWorkspaceDirOnce(effectiveWorkspace);
|
|
4821
|
+
preDynamicStartupStages.mark("effective-workspace");
|
|
4742
4822
|
const appServer = resolveCodexAppServerForOpenClawToolPolicy({
|
|
4743
4823
|
appServer: configuredAppServer,
|
|
4744
4824
|
pluginConfig,
|
|
4745
4825
|
env: process.env,
|
|
4746
|
-
shouldPromote:
|
|
4826
|
+
shouldPromote: beforeToolCallPolicy.hasBeforeToolCallHook || beforeToolCallPolicy.trustedToolPolicies.length > 0,
|
|
4747
4827
|
canUseUntrustedApprovalPolicy: configuredAppServer.start.transport !== "stdio" || isCodexAppServerApprovalPolicyAllowedByRequirements("untrusted")
|
|
4748
4828
|
});
|
|
4829
|
+
if (configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted") embeddedAgentLog.info("codex app-server approval policy promoted for OpenClaw tool policy", {
|
|
4830
|
+
from: "never",
|
|
4831
|
+
to: "untrusted",
|
|
4832
|
+
beforeToolCallHook: beforeToolCallPolicy.hasBeforeToolCallHook,
|
|
4833
|
+
trustedToolPolicies: beforeToolCallPolicy.trustedToolPolicies
|
|
4834
|
+
});
|
|
4835
|
+
preDynamicStartupStages.mark("app-server-policy");
|
|
4749
4836
|
let pluginAppServer = appServer;
|
|
4750
4837
|
const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
|
|
4751
4838
|
configuredEvents: options.nativeHookRelay?.events,
|
|
4752
4839
|
appServer
|
|
4753
4840
|
});
|
|
4841
|
+
preDynamicStartupStages.mark("native-hook-relay");
|
|
4754
4842
|
const runAbortController = new AbortController();
|
|
4755
4843
|
const abortFromUpstream = () => {
|
|
4756
4844
|
runAbortController.abort(params.abortSignal?.reason ?? "upstream_abort");
|
|
@@ -4763,15 +4851,19 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
4763
4851
|
agentId: params.agentId
|
|
4764
4852
|
});
|
|
4765
4853
|
const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId);
|
|
4854
|
+
preDynamicStartupStages.mark("session-agent");
|
|
4766
4855
|
let startupBinding = await readCodexAppServerBinding(params.sessionFile);
|
|
4856
|
+
preDynamicStartupStages.mark("read-binding");
|
|
4767
4857
|
const startupBindingAuthProfileId = startupBinding?.authProfileId;
|
|
4768
4858
|
startupBinding = await rotateOversizedCodexAppServerStartupBinding({
|
|
4769
4859
|
binding: startupBinding,
|
|
4770
4860
|
sessionFile: params.sessionFile,
|
|
4771
4861
|
agentDir,
|
|
4772
4862
|
codexHome: appServer.start.env?.CODEX_HOME,
|
|
4773
|
-
config: params.config
|
|
4863
|
+
config: params.config,
|
|
4864
|
+
contextEngineActive: isActiveHarnessContextEngine(params.contextEngine)
|
|
4774
4865
|
});
|
|
4866
|
+
preDynamicStartupStages.mark("rotate-binding");
|
|
4775
4867
|
const startupAuthProfileCandidate = params.runtimePlan?.auth.forwardedAuthProfileId ?? params.authProfileId ?? startupBinding?.authProfileId ?? startupBindingAuthProfileId;
|
|
4776
4868
|
const startupAuthProfileId = params.authProfileStore ? resolveCodexAppServerAuthProfileId({
|
|
4777
4869
|
authProfileId: startupAuthProfileCandidate,
|
|
@@ -4782,6 +4874,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
4782
4874
|
agentDir,
|
|
4783
4875
|
config: params.config
|
|
4784
4876
|
});
|
|
4877
|
+
preDynamicStartupStages.mark("auth-profile");
|
|
4785
4878
|
const runtimeParams = {
|
|
4786
4879
|
...params,
|
|
4787
4880
|
sessionKey: contextSessionKey,
|
|
@@ -4794,22 +4887,20 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
4794
4887
|
sessionId: activeSessionId,
|
|
4795
4888
|
sessionFile: activeSessionFile
|
|
4796
4889
|
});
|
|
4797
|
-
const adoptContextEngineCompactionTranscript = (compactResult) => {
|
|
4798
|
-
if (compactResult.result?.sessionId) activeSessionId = compactResult.result.sessionId;
|
|
4799
|
-
if (compactResult.result?.sessionFile) activeSessionFile = compactResult.result.sessionFile;
|
|
4800
|
-
};
|
|
4801
4890
|
const startupAuthAccountCacheKey = await resolveCodexAppServerAuthAccountCacheKey({
|
|
4802
4891
|
authProfileId: startupAuthProfileId,
|
|
4803
4892
|
authProfileStore: params.authProfileStore,
|
|
4804
4893
|
agentDir,
|
|
4805
4894
|
config: params.config
|
|
4806
4895
|
});
|
|
4807
|
-
const startupEnvApiKeyCacheKey = startupAuthProfileId ? void 0 :
|
|
4896
|
+
const startupEnvApiKeyCacheKey = startupAuthProfileId ? void 0 : resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions: appServer.start });
|
|
4897
|
+
preDynamicStartupStages.mark("auth-cache");
|
|
4808
4898
|
const nodeExecBlocksNativeExecution = isCodexNativeExecutionBlockedByNodeExecHost(params, {
|
|
4809
4899
|
agentId: sessionAgentId,
|
|
4810
4900
|
runtimeSessionKey: sandboxSessionKey,
|
|
4811
4901
|
sandbox
|
|
4812
4902
|
});
|
|
4903
|
+
preDynamicStartupStages.mark("native-exec-policy");
|
|
4813
4904
|
const bundleMcpThreadConfig = await loadCodexBundleMcpThreadConfig({
|
|
4814
4905
|
workspaceDir: effectiveWorkspace,
|
|
4815
4906
|
cfg: params.config,
|
|
@@ -4817,12 +4908,14 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
4817
4908
|
disableTools: params.disableTools,
|
|
4818
4909
|
toolsAllow: nodeExecBlocksNativeExecution ? [] : params.toolsAllow
|
|
4819
4910
|
});
|
|
4911
|
+
preDynamicStartupStages.mark("bundle-mcp");
|
|
4820
4912
|
const sandboxExecServerEnabled = isCodexSandboxExecServerEnabled(pluginConfig);
|
|
4821
4913
|
const nativeToolSurfaceEnabled = shouldEnableCodexAppServerNativeToolSurface(params, sandbox, {
|
|
4822
4914
|
agentId: sessionAgentId,
|
|
4823
4915
|
runtimeSessionKey: sandboxSessionKey,
|
|
4824
4916
|
sandboxExecServerEnabled
|
|
4825
4917
|
});
|
|
4918
|
+
preDynamicStartupStages.mark("native-tool-surface");
|
|
4826
4919
|
for (const diagnostic of bundleMcpThreadConfig.diagnostics) embeddedAgentLog.warn(`bundle-mcp: ${diagnostic.pluginId}: ${diagnostic.message}`);
|
|
4827
4920
|
const activeContextEngine = isActiveHarnessContextEngine(params.contextEngine) ? params.contextEngine : void 0;
|
|
4828
4921
|
if (activeContextEngine) assertContextEngineHostSupport({
|
|
@@ -4831,22 +4924,36 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
4831
4924
|
host: CODEX_APP_SERVER_CONTEXT_ENGINE_HOST
|
|
4832
4925
|
});
|
|
4833
4926
|
const hookChannelId = resolveCodexAppServerHookChannelId(params, sandboxSessionKey);
|
|
4927
|
+
preDynamicStartupStages.mark("context-engine-support");
|
|
4928
|
+
const preDynamicSummary = preDynamicStartupStages.snapshot();
|
|
4929
|
+
if (shouldWarnCodexDynamicToolBuildStageSummary(preDynamicSummary)) embeddedAgentLog.warn(`codex app-server pre-dynamic startup timings runId=${params.runId} sessionId=${params.sessionId} totalMs=${preDynamicSummary.totalMs} stages=${formatCodexDynamicToolBuildStageSummary(preDynamicSummary)}`, {
|
|
4930
|
+
runId: params.runId,
|
|
4931
|
+
sessionId: params.sessionId,
|
|
4932
|
+
totalMs: preDynamicSummary.totalMs,
|
|
4933
|
+
stages: preDynamicSummary.stages,
|
|
4934
|
+
hasStartupBinding: Boolean(startupBinding?.threadId),
|
|
4935
|
+
startupAuthProfileId: startupAuthProfileId ?? null,
|
|
4936
|
+
bundleMcpDiagnosticCount: bundleMcpThreadConfig.diagnostics.length,
|
|
4937
|
+
nativeToolSurfaceEnabled
|
|
4938
|
+
});
|
|
4834
4939
|
let yieldDetected = false;
|
|
4940
|
+
const tools = await buildDynamicTools({
|
|
4941
|
+
params,
|
|
4942
|
+
resolvedWorkspace,
|
|
4943
|
+
effectiveWorkspace,
|
|
4944
|
+
sandboxSessionKey,
|
|
4945
|
+
sandbox,
|
|
4946
|
+
nativeToolSurfaceEnabled,
|
|
4947
|
+
runAbortController,
|
|
4948
|
+
sessionAgentId,
|
|
4949
|
+
pluginConfig,
|
|
4950
|
+
profilerEnabled,
|
|
4951
|
+
onYieldDetected: () => {
|
|
4952
|
+
yieldDetected = true;
|
|
4953
|
+
}
|
|
4954
|
+
});
|
|
4835
4955
|
const toolBridge = createCodexDynamicToolBridge({
|
|
4836
|
-
tools
|
|
4837
|
-
params,
|
|
4838
|
-
resolvedWorkspace,
|
|
4839
|
-
effectiveWorkspace,
|
|
4840
|
-
sandboxSessionKey,
|
|
4841
|
-
sandbox,
|
|
4842
|
-
nativeToolSurfaceEnabled,
|
|
4843
|
-
runAbortController,
|
|
4844
|
-
sessionAgentId,
|
|
4845
|
-
pluginConfig,
|
|
4846
|
-
onYieldDetected: () => {
|
|
4847
|
-
yieldDetected = true;
|
|
4848
|
-
}
|
|
4849
|
-
}),
|
|
4956
|
+
tools,
|
|
4850
4957
|
registeredTools: await buildDynamicTools({
|
|
4851
4958
|
params,
|
|
4852
4959
|
resolvedWorkspace,
|
|
@@ -4857,6 +4964,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
4857
4964
|
runAbortController,
|
|
4858
4965
|
sessionAgentId,
|
|
4859
4966
|
pluginConfig,
|
|
4967
|
+
profilerEnabled,
|
|
4860
4968
|
forceHeartbeatTool: true,
|
|
4861
4969
|
ignoreRuntimePlan: true,
|
|
4862
4970
|
onYieldDetected: () => {
|
|
@@ -4902,65 +5010,6 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
4902
5010
|
contextEnginePluginId: activeContextEnginePluginId,
|
|
4903
5011
|
tokenBudget: params.contextTokenBudget
|
|
4904
5012
|
});
|
|
4905
|
-
const forceContextEngineCompactionForCodexOverflow = async (error, options = {}) => {
|
|
4906
|
-
if (!activeContextEngine?.info.ownsCompaction) return false;
|
|
4907
|
-
embeddedAgentLog.warn("codex app-server context-engine prompt overflowed; forcing context-engine compaction", {
|
|
4908
|
-
sessionId: activeSessionId,
|
|
4909
|
-
sessionKey: contextSessionKey,
|
|
4910
|
-
...options.threadId ? { threadId: options.threadId } : {},
|
|
4911
|
-
engineId: activeContextEngine.info.id,
|
|
4912
|
-
tokenBudget: params.contextTokenBudget,
|
|
4913
|
-
error: formatErrorMessage(error)
|
|
4914
|
-
});
|
|
4915
|
-
try {
|
|
4916
|
-
const runtimeContext = buildActiveContextEngineRuntimeContext();
|
|
4917
|
-
const overflowTokenCount = params.contextTokenBudget ?? params.contextWindowInfo?.tokens;
|
|
4918
|
-
const compactResult = await compactContextEngineWithSafetyTimeout(activeContextEngine, {
|
|
4919
|
-
sessionId: activeSessionId,
|
|
4920
|
-
sessionKey: contextSessionKey,
|
|
4921
|
-
sessionFile: activeSessionFile,
|
|
4922
|
-
tokenBudget: params.contextTokenBudget,
|
|
4923
|
-
force: true,
|
|
4924
|
-
...overflowTokenCount ? { currentTokenCount: overflowTokenCount } : {},
|
|
4925
|
-
compactionTarget: "threshold",
|
|
4926
|
-
runtimeContext: overflowTokenCount ? {
|
|
4927
|
-
...runtimeContext,
|
|
4928
|
-
currentTokenCount: overflowTokenCount
|
|
4929
|
-
} : runtimeContext
|
|
4930
|
-
}, resolveCompactionTimeoutMs(params.config), runAbortController.signal);
|
|
4931
|
-
embeddedAgentLog.info("codex app-server context-engine forced compaction result", {
|
|
4932
|
-
sessionId: activeSessionId,
|
|
4933
|
-
sessionKey: contextSessionKey,
|
|
4934
|
-
engineId: activeContextEngine.info.id,
|
|
4935
|
-
ok: compactResult.ok,
|
|
4936
|
-
compacted: compactResult.compacted,
|
|
4937
|
-
reason: compactResult.reason,
|
|
4938
|
-
tokensBefore: compactResult.result?.tokensBefore,
|
|
4939
|
-
tokensAfter: compactResult.result?.tokensAfter
|
|
4940
|
-
});
|
|
4941
|
-
if (!compactResult.ok || !compactResult.compacted) return false;
|
|
4942
|
-
adoptContextEngineCompactionTranscript(compactResult);
|
|
4943
|
-
const maintenanceRuntimeContext = buildActiveContextEngineRuntimeContext();
|
|
4944
|
-
await runHarnessContextEngineMaintenance({
|
|
4945
|
-
contextEngine: activeContextEngine,
|
|
4946
|
-
sessionId: activeSessionId,
|
|
4947
|
-
sessionKey: contextSessionKey,
|
|
4948
|
-
sessionFile: activeSessionFile,
|
|
4949
|
-
reason: "compaction",
|
|
4950
|
-
runtimeContext: maintenanceRuntimeContext,
|
|
4951
|
-
config: params.config
|
|
4952
|
-
});
|
|
4953
|
-
return true;
|
|
4954
|
-
} catch (compactErr) {
|
|
4955
|
-
embeddedAgentLog.warn("codex app-server context-engine forced compaction failed", {
|
|
4956
|
-
sessionId: params.sessionId,
|
|
4957
|
-
sessionKey: contextSessionKey,
|
|
4958
|
-
engineId: activeContextEngine.info.id,
|
|
4959
|
-
error: formatErrorMessage(compactErr)
|
|
4960
|
-
});
|
|
4961
|
-
return false;
|
|
4962
|
-
}
|
|
4963
|
-
};
|
|
4964
5013
|
if (activeContextEngine) {
|
|
4965
5014
|
await bootstrapHarnessContextEngine({
|
|
4966
5015
|
hadSessionFile,
|
|
@@ -4992,12 +5041,6 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
4992
5041
|
let developerInstructions = baseDeveloperInstructions;
|
|
4993
5042
|
let prePromptMessageCount = historyMessages.length;
|
|
4994
5043
|
let contextEngineProjection;
|
|
4995
|
-
const resetCodexPromptInputs = () => {
|
|
4996
|
-
promptText = params.prompt;
|
|
4997
|
-
developerInstructions = baseDeveloperInstructions;
|
|
4998
|
-
prePromptMessageCount = historyMessages.length;
|
|
4999
|
-
contextEngineProjection = void 0;
|
|
5000
|
-
};
|
|
5001
5044
|
const applyActiveContextEngineProjection = async (decisionStartupBinding) => {
|
|
5002
5045
|
if (!activeContextEngine) return;
|
|
5003
5046
|
const assembled = await assembleHarnessContextEngine({
|
|
@@ -5082,78 +5125,11 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
5082
5125
|
let promptBuild = await buildPromptFromCurrentInputs();
|
|
5083
5126
|
const decorateCodexTurnPromptText = (prompt) => prependCodexOpenClawPromptContext(prompt, openClawPromptContext);
|
|
5084
5127
|
let codexTurnPromptText = decorateCodexTurnPromptText(promptBuild.prompt);
|
|
5085
|
-
const refreshCodexTurnPromptText = () => {
|
|
5086
|
-
codexTurnPromptText = decorateCodexTurnPromptText(promptBuild.prompt);
|
|
5087
|
-
};
|
|
5088
5128
|
const buildCodexTurnCollaborationDeveloperInstructions = () => buildTurnCollaborationMode(params, {
|
|
5089
5129
|
turnScopedDeveloperInstructions: workspaceBootstrapContext.turnScopedDeveloperInstructions,
|
|
5090
5130
|
heartbeatCollaborationInstructions: workspaceBootstrapContext.heartbeatCollaborationInstructions
|
|
5091
5131
|
}).settings.developer_instructions ?? void 0;
|
|
5092
5132
|
const buildRenderedCodexDeveloperInstructions = () => joinPresentSections(promptBuild.developerInstructions, buildCodexTurnCollaborationDeveloperInstructions());
|
|
5093
|
-
const rebuildPromptAfterContextEngineCompaction = async () => {
|
|
5094
|
-
historyMessages = await readMirroredSessionHistoryMessages(activeSessionFile) ?? historyMessages;
|
|
5095
|
-
resetCodexPromptInputs();
|
|
5096
|
-
try {
|
|
5097
|
-
await applyActiveContextEngineProjection(void 0);
|
|
5098
|
-
} catch (assembleErr) {
|
|
5099
|
-
embeddedAgentLog.warn("context engine assemble failed after forced compaction; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
|
|
5100
|
-
}
|
|
5101
|
-
promptBuild = await buildPromptFromCurrentInputs();
|
|
5102
|
-
refreshCodexTurnPromptText();
|
|
5103
|
-
};
|
|
5104
|
-
const buildCodexProviderBoundaryPrecheck = () => {
|
|
5105
|
-
const contextTokenBudget = typeof params.contextTokenBudget === "number" && Number.isFinite(params.contextTokenBudget) ? Math.floor(params.contextTokenBudget) : typeof params.contextWindowInfo?.tokens === "number" && Number.isFinite(params.contextWindowInfo.tokens) ? Math.floor(params.contextWindowInfo.tokens) : void 0;
|
|
5106
|
-
if (!contextTokenBudget || contextTokenBudget <= 0) return;
|
|
5107
|
-
const reserveTokens = resolveCodexContextEngineProjectionReserveTokens({ config: params.config }) ?? 2e4;
|
|
5108
|
-
const renderedDeveloperInstructions = buildRenderedCodexDeveloperInstructions();
|
|
5109
|
-
const renderedChars = codexTurnPromptText.length + renderedDeveloperInstructions.length;
|
|
5110
|
-
return shouldPreemptivelyCompactBeforePrompt({
|
|
5111
|
-
messages: historyMessages,
|
|
5112
|
-
systemPrompt: renderedDeveloperInstructions,
|
|
5113
|
-
prompt: codexTurnPromptText,
|
|
5114
|
-
contextTokenBudget,
|
|
5115
|
-
reserveTokens,
|
|
5116
|
-
llmBoundaryTokenPressure: {
|
|
5117
|
-
estimatedPromptTokens: estimateRenderedLlmBoundaryTokenPressure({
|
|
5118
|
-
systemPrompt: renderedDeveloperInstructions,
|
|
5119
|
-
prompt: codexTurnPromptText
|
|
5120
|
-
}),
|
|
5121
|
-
source: "codex_app_server_rendered_prompt",
|
|
5122
|
-
renderedChars
|
|
5123
|
-
}
|
|
5124
|
-
});
|
|
5125
|
-
};
|
|
5126
|
-
const maybeCompactContextEngineForProviderBoundaryPrecheck = async () => {
|
|
5127
|
-
if (!activeContextEngine?.info.ownsCompaction || !contextEngineProjection) return;
|
|
5128
|
-
const precheck = buildCodexProviderBoundaryPrecheck();
|
|
5129
|
-
if (!precheck) return;
|
|
5130
|
-
embeddedAgentLog.debug(formatPrePromptPrecheckLog({
|
|
5131
|
-
result: precheck,
|
|
5132
|
-
provider: params.provider,
|
|
5133
|
-
modelId: params.modelId,
|
|
5134
|
-
messageCount: historyMessages.length,
|
|
5135
|
-
contextTokenBudget: typeof params.contextTokenBudget === "number" ? params.contextTokenBudget : params.contextWindowInfo?.tokens ?? 0,
|
|
5136
|
-
reserveTokens: resolveCodexContextEngineProjectionReserveTokens({ config: params.config }) ?? 2e4,
|
|
5137
|
-
...contextSessionKey ? { sessionKey: contextSessionKey } : {},
|
|
5138
|
-
...activeSessionId ? { sessionId: activeSessionId } : {},
|
|
5139
|
-
...activeSessionFile ? { sessionFile: activeSessionFile } : {}
|
|
5140
|
-
}));
|
|
5141
|
-
if (precheck.route === "fits") return;
|
|
5142
|
-
if (!await forceContextEngineCompactionForCodexOverflow(PREEMPTIVE_OVERFLOW_ERROR_TEXT)) throw new Error(PREEMPTIVE_OVERFLOW_ERROR_TEXT);
|
|
5143
|
-
await rebuildPromptAfterContextEngineCompaction();
|
|
5144
|
-
const afterCompactionPrecheck = buildCodexProviderBoundaryPrecheck();
|
|
5145
|
-
if (!afterCompactionPrecheck || afterCompactionPrecheck.route === "fits") return;
|
|
5146
|
-
embeddedAgentLog.warn("codex app-server provider-boundary precheck still overflowed after compaction", {
|
|
5147
|
-
sessionId: activeSessionId,
|
|
5148
|
-
sessionKey: contextSessionKey,
|
|
5149
|
-
route: afterCompactionPrecheck.route,
|
|
5150
|
-
estimatedPromptTokens: afterCompactionPrecheck.estimatedPromptTokens,
|
|
5151
|
-
promptBudgetBeforeReserve: afterCompactionPrecheck.promptBudgetBeforeReserve,
|
|
5152
|
-
overflowTokens: afterCompactionPrecheck.overflowTokens
|
|
5153
|
-
});
|
|
5154
|
-
throw new Error(PREEMPTIVE_OVERFLOW_ERROR_TEXT);
|
|
5155
|
-
};
|
|
5156
|
-
await maybeCompactContextEngineForProviderBoundaryPrecheck();
|
|
5157
5133
|
const systemPromptReport = buildCodexSystemPromptReport({
|
|
5158
5134
|
attempt: params,
|
|
5159
5135
|
sessionKey: contextSessionKey,
|
|
@@ -5916,7 +5892,9 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
5916
5892
|
...turnId ? { turnId } : {}
|
|
5917
5893
|
});
|
|
5918
5894
|
embeddedAgentLog.debug("codex app-server raw notification received", correlation);
|
|
5919
|
-
if (notification.method === "turn/completed" && correlation.matchesActiveTurn === false) embeddedAgentLog.warn("codex app-server turn/completed did not match active turn", correlation);
|
|
5895
|
+
if (notification.method === "turn/completed" && correlation.matchesActiveTurn === false) if (correlation.matchesActiveThread) embeddedAgentLog.warn("codex app-server turn/completed did not match active turn", correlation);
|
|
5896
|
+
else embeddedAgentLog.debug("codex app-server turn/completed ignored for other subscribed thread", correlation);
|
|
5897
|
+
if (isCodexNotificationOutsideActiveRun(correlation)) return Promise.resolve();
|
|
5920
5898
|
if (!projector || !turnId) {
|
|
5921
5899
|
userInputBridge?.handleNotification(notification);
|
|
5922
5900
|
pendingNotifications.push(notification);
|
|
@@ -5990,6 +5968,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
5990
5968
|
threadId: thread.threadId,
|
|
5991
5969
|
turnId,
|
|
5992
5970
|
nativeHookRelay,
|
|
5971
|
+
autoApprove: shouldAutoApproveCodexAppServerApprovals(appServer),
|
|
5993
5972
|
signal: runAbortController.signal
|
|
5994
5973
|
});
|
|
5995
5974
|
}
|
|
@@ -6083,22 +6062,26 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
6083
6062
|
projector?.recordDynamicToolResult({
|
|
6084
6063
|
callId: call.callId,
|
|
6085
6064
|
tool: call.tool,
|
|
6065
|
+
asyncStarted: response.asyncStarted === true,
|
|
6086
6066
|
success: protocolResponse.success,
|
|
6087
6067
|
terminalType: response.diagnosticTerminalType ?? (protocolResponse.success ? "completed" : "error"),
|
|
6088
6068
|
sideEffectEvidence: response.sideEffectEvidence === true,
|
|
6089
6069
|
contentItems: protocolResponse.contentItems
|
|
6090
6070
|
});
|
|
6091
|
-
if (shouldEmitDynamicToolProgress)
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6071
|
+
if (shouldEmitDynamicToolProgress) {
|
|
6072
|
+
const progressResponse = toCodexDynamicToolProgressResponse(response, protocolResponse);
|
|
6073
|
+
emitCodexAppServerEvent(params, {
|
|
6074
|
+
stream: "tool",
|
|
6075
|
+
data: {
|
|
6076
|
+
phase: "result",
|
|
6077
|
+
name: call.tool,
|
|
6078
|
+
toolCallId: call.callId,
|
|
6079
|
+
...toolMeta ? { meta: toolMeta } : {},
|
|
6080
|
+
isError: !protocolResponse.success,
|
|
6081
|
+
result: sanitizeCodexToolResponse(progressResponse)
|
|
6082
|
+
}
|
|
6083
|
+
});
|
|
6084
|
+
}
|
|
6102
6085
|
if (!terminalDiagnosticObserved && !hasPendingDynamicToolTerminalDiagnostic({
|
|
6103
6086
|
call,
|
|
6104
6087
|
runId: params.runId,
|
|
@@ -6161,27 +6144,99 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
6161
6144
|
systemPrompt: buildRenderedCodexDeveloperInstructions(),
|
|
6162
6145
|
prompt: codexTurnPromptText,
|
|
6163
6146
|
historyMessages,
|
|
6164
|
-
imagesCount: params.images?.length ?? 0
|
|
6147
|
+
imagesCount: params.images?.length ?? 0,
|
|
6148
|
+
tools
|
|
6165
6149
|
});
|
|
6166
6150
|
const buildTurnStartFailureMessages = () => [...historyMessages, buildCodexUserPromptMessage({
|
|
6167
6151
|
...params,
|
|
6168
6152
|
prompt: codexTurnPromptText
|
|
6169
6153
|
})];
|
|
6154
|
+
const codexModelCallBaseFields = {
|
|
6155
|
+
runId: params.runId,
|
|
6156
|
+
callId: codexModelCallId,
|
|
6157
|
+
...params.sessionKey ? { sessionKey: params.sessionKey } : {},
|
|
6158
|
+
sessionId: params.sessionId,
|
|
6159
|
+
provider: params.provider,
|
|
6160
|
+
model: params.modelId,
|
|
6161
|
+
api: params.model.api,
|
|
6162
|
+
transport: appServer.start.transport,
|
|
6163
|
+
...hookContextWindowFields,
|
|
6164
|
+
trace: codexModelCallTrace
|
|
6165
|
+
};
|
|
6166
|
+
const codexDiagnosticToolDefinitions = codexModelContentCapture.toolDefinitions ? buildCodexDiagnosticToolDefinitions(tools) : void 0;
|
|
6167
|
+
const codexModelContentPrivateData = (modelContent) => modelContent && Object.keys(modelContent).length > 0 ? { modelContent } : void 0;
|
|
6168
|
+
const buildCodexModelCallDiagnosticContent = () => {
|
|
6169
|
+
const modelContent = {
|
|
6170
|
+
...codexModelContentCapture.inputMessages ? { inputMessages: buildTurnStartFailureMessages() } : {},
|
|
6171
|
+
...codexModelContentCapture.systemPrompt ? { systemPrompt: buildRenderedCodexDeveloperInstructions() } : {},
|
|
6172
|
+
...codexDiagnosticToolDefinitions ? { toolDefinitions: codexDiagnosticToolDefinitions } : {}
|
|
6173
|
+
};
|
|
6174
|
+
return Object.keys(modelContent).length > 0 ? modelContent : void 0;
|
|
6175
|
+
};
|
|
6176
|
+
const emitCodexModelCallStarted = () => {
|
|
6177
|
+
codexModelCallStartedAt = Date.now();
|
|
6178
|
+
codexModelCallStarted = true;
|
|
6179
|
+
emitTrustedDiagnosticEventWithPrivateData({
|
|
6180
|
+
type: "model.call.started",
|
|
6181
|
+
...codexModelCallBaseFields
|
|
6182
|
+
}, codexModelContentPrivateData(buildCodexModelCallDiagnosticContent()));
|
|
6183
|
+
};
|
|
6184
|
+
const emitCodexModelCallCompleted = (result) => {
|
|
6185
|
+
if (!codexModelCallStarted || codexModelCallTerminalEmitted) return;
|
|
6186
|
+
codexModelCallTerminalEmitted = true;
|
|
6187
|
+
emitTrustedDiagnosticEventWithPrivateData({
|
|
6188
|
+
type: "model.call.completed",
|
|
6189
|
+
...codexModelCallBaseFields,
|
|
6190
|
+
durationMs: Math.max(0, Date.now() - codexModelCallStartedAt),
|
|
6191
|
+
...codexModelCallRequestPayloadBytes !== void 0 ? { requestPayloadBytes: codexModelCallRequestPayloadBytes } : {}
|
|
6192
|
+
}, codexModelContentPrivateData({
|
|
6193
|
+
...buildCodexModelCallDiagnosticContent(),
|
|
6194
|
+
...codexModelContentCapture.outputMessages ? { outputMessages: result.lastAssistant ? [result.lastAssistant] : result.assistantTexts } : {}
|
|
6195
|
+
}));
|
|
6196
|
+
};
|
|
6197
|
+
const emitCodexModelCallError = (error, fields = {}) => {
|
|
6198
|
+
if (!codexModelCallStarted || codexModelCallTerminalEmitted) return;
|
|
6199
|
+
codexModelCallTerminalEmitted = true;
|
|
6200
|
+
emitTrustedDiagnosticEventWithPrivateData({
|
|
6201
|
+
type: "model.call.error",
|
|
6202
|
+
...codexModelCallBaseFields,
|
|
6203
|
+
durationMs: Math.max(0, Date.now() - codexModelCallStartedAt),
|
|
6204
|
+
errorCategory: fields.failureKind ?? "error",
|
|
6205
|
+
...fields.failureKind ? { failureKind: fields.failureKind } : {},
|
|
6206
|
+
...codexModelCallRequestPayloadBytes !== void 0 ? { requestPayloadBytes: codexModelCallRequestPayloadBytes } : {}
|
|
6207
|
+
}, codexModelContentPrivateData({
|
|
6208
|
+
...buildCodexModelCallDiagnosticContent(),
|
|
6209
|
+
...codexModelContentCapture.outputMessages ? { outputMessages: [] } : {}
|
|
6210
|
+
}));
|
|
6211
|
+
embeddedAgentLog.debug("codex app-server model call diagnostic ended with error", { error: formatErrorMessage(error) });
|
|
6212
|
+
};
|
|
6213
|
+
const classifyCodexModelCallFailureKind = (error) => {
|
|
6214
|
+
if (timedOut || turnCompletionIdleTimedOut) return "timeout";
|
|
6215
|
+
const errorMessage = error ? formatErrorMessage(error).toLowerCase() : "";
|
|
6216
|
+
if (errorMessage.includes("timed out") || errorMessage.includes("timeout")) return "timeout";
|
|
6217
|
+
if (runAbortController.signal.aborted && !clientClosedAbort) return String(runAbortController.signal.reason ?? "").toLowerCase().includes("timeout") ? "timeout" : "aborted";
|
|
6218
|
+
return errorMessage.includes("aborted") ? "aborted" : void 0;
|
|
6219
|
+
};
|
|
6170
6220
|
let turn;
|
|
6171
|
-
const startCodexTurn = async () =>
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6221
|
+
const startCodexTurn = async () => {
|
|
6222
|
+
const turnStartParams = buildTurnStartParams(params, {
|
|
6223
|
+
threadId: thread.threadId,
|
|
6224
|
+
cwd: codexExecutionCwd,
|
|
6225
|
+
appServer: pluginAppServer,
|
|
6226
|
+
promptText: codexTurnPromptText,
|
|
6227
|
+
sandboxPolicy: codexSandboxPolicy,
|
|
6228
|
+
environmentSelection: codexEnvironmentSelection,
|
|
6229
|
+
turnScopedDeveloperInstructions: workspaceBootstrapContext.turnScopedDeveloperInstructions,
|
|
6230
|
+
heartbeatCollaborationInstructions: workspaceBootstrapContext.heartbeatCollaborationInstructions
|
|
6231
|
+
});
|
|
6232
|
+
codexModelCallRequestPayloadBytes = utf8JsonByteLength(turnStartParams);
|
|
6233
|
+
return assertCodexTurnStartResponse(await client.request("turn/start", turnStartParams, {
|
|
6234
|
+
timeoutMs: params.timeoutMs,
|
|
6235
|
+
signal: runAbortController.signal
|
|
6236
|
+
}));
|
|
6237
|
+
};
|
|
6184
6238
|
try {
|
|
6239
|
+
emitCodexModelCallStarted();
|
|
6185
6240
|
runAgentHarnessLlmInputHook({
|
|
6186
6241
|
event: buildLlmInputEvent(),
|
|
6187
6242
|
ctx: hookContext
|
|
@@ -6207,10 +6262,8 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
6207
6262
|
});
|
|
6208
6263
|
try {
|
|
6209
6264
|
const preRetrySessionFile = activeSessionFile;
|
|
6210
|
-
const compactedForRetry = await forceContextEngineCompactionForCodexOverflow(turnStartError, { threadId: thread.threadId });
|
|
6211
6265
|
await clearCodexAppServerBinding(preRetrySessionFile);
|
|
6212
6266
|
if (activeSessionFile !== preRetrySessionFile) await clearCodexAppServerBinding(activeSessionFile);
|
|
6213
|
-
if (compactedForRetry) await rebuildPromptAfterContextEngineCompaction();
|
|
6214
6267
|
thread = await restartContextEngineCodexThread();
|
|
6215
6268
|
emitCodexAppServerEvent(params, {
|
|
6216
6269
|
stream: "codex_app_server.lifecycle",
|
|
@@ -6270,6 +6323,8 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
6270
6323
|
},
|
|
6271
6324
|
ctx: hookContext
|
|
6272
6325
|
});
|
|
6326
|
+
const turnStartFailureKind = classifyCodexModelCallFailureKind(turnStartError);
|
|
6327
|
+
emitCodexModelCallError(turnStartErrorMessage, turnStartFailureKind ? { failureKind: turnStartFailureKind } : {});
|
|
6273
6328
|
await runCodexAgentEndHook(params, {
|
|
6274
6329
|
event: {
|
|
6275
6330
|
messages: buildTurnStartFailureMessages(),
|
|
@@ -6303,12 +6358,12 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
6303
6358
|
authProfileId: startupAuthProfileId,
|
|
6304
6359
|
rateLimits: usageLimitError.rateLimitsForProfile
|
|
6305
6360
|
});
|
|
6306
|
-
return buildCodexTurnStartFailureResult({
|
|
6361
|
+
return { ...buildCodexTurnStartFailureResult({
|
|
6307
6362
|
params,
|
|
6308
6363
|
message: usageLimitError.message,
|
|
6309
6364
|
messagesSnapshot: buildTurnStartFailureMessages(),
|
|
6310
6365
|
systemPromptReport
|
|
6311
|
-
});
|
|
6366
|
+
}) };
|
|
6312
6367
|
}
|
|
6313
6368
|
throw turnStartError;
|
|
6314
6369
|
}
|
|
@@ -6380,24 +6435,26 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
6380
6435
|
queueMessage: async (text, options) => activeSteeringQueue.queue(text, options),
|
|
6381
6436
|
isStreaming: () => !completed,
|
|
6382
6437
|
isCompacting: () => projector?.isCompacting() ?? false,
|
|
6438
|
+
sourceReplyDeliveryMode: params.sourceReplyDeliveryMode,
|
|
6383
6439
|
cancel: () => runAbortController.abort("cancelled"),
|
|
6384
6440
|
abort: () => runAbortController.abort("aborted")
|
|
6385
6441
|
};
|
|
6386
6442
|
setActiveEmbeddedRun(params.sessionId, handle, params.sessionKey);
|
|
6443
|
+
mirrorPromptAtTurnStartBestEffort({
|
|
6444
|
+
params,
|
|
6445
|
+
agentId: sessionAgentId,
|
|
6446
|
+
sessionKey: sandboxSessionKey,
|
|
6447
|
+
threadId: thread.threadId,
|
|
6448
|
+
turnId: activeTurnId
|
|
6449
|
+
});
|
|
6387
6450
|
turnAttemptIdleWatchArmed = true;
|
|
6388
6451
|
turnTerminalIdleWatchArmed = true;
|
|
6389
6452
|
touchTurnCompletionActivity("turn:start", { attemptProgress: true });
|
|
6390
6453
|
const abortListener = () => {
|
|
6391
|
-
const shouldRetireClient = timedOut;
|
|
6392
6454
|
interruptCodexTurnBestEffort(client, {
|
|
6393
6455
|
threadId: thread.threadId,
|
|
6394
6456
|
turnId: activeTurnId,
|
|
6395
|
-
timeoutMs:
|
|
6396
|
-
});
|
|
6397
|
-
if (shouldRetireClient) retireCodexAppServerClientAfterTimedOutTurn(client, {
|
|
6398
|
-
threadId: thread.threadId,
|
|
6399
|
-
turnId: activeTurnId,
|
|
6400
|
-
reason: String(runAbortController.signal.reason ?? "timeout")
|
|
6457
|
+
timeoutMs: timedOut ? CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS : void 0
|
|
6401
6458
|
});
|
|
6402
6459
|
resolveCompletion?.();
|
|
6403
6460
|
};
|
|
@@ -6432,6 +6489,10 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
6432
6489
|
result,
|
|
6433
6490
|
turnCompletionIdleTimedOut
|
|
6434
6491
|
});
|
|
6492
|
+
const modelCallFailureKind = classifyCodexModelCallFailureKind(finalPromptError) ?? (finalAborted ? "aborted" : void 0);
|
|
6493
|
+
if (modelCallFailureKind) emitCodexModelCallError(finalPromptError ?? "codex app-server attempt interrupted", { failureKind: modelCallFailureKind });
|
|
6494
|
+
else if (finalPromptError) emitCodexModelCallError(finalPromptError);
|
|
6495
|
+
else emitCodexModelCallCompleted(result);
|
|
6435
6496
|
recordCodexTrajectoryCompletion(trajectoryRecorder, {
|
|
6436
6497
|
attempt: params,
|
|
6437
6498
|
result,
|
|
@@ -6542,6 +6603,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
6542
6603
|
systemPromptReport
|
|
6543
6604
|
};
|
|
6544
6605
|
} finally {
|
|
6606
|
+
emitCodexModelCallError("codex app-server run completed without model-call terminal event");
|
|
6545
6607
|
emitLifecycleTerminal({
|
|
6546
6608
|
phase: "error",
|
|
6547
6609
|
error: "codex app-server run completed without lifecycle terminal event"
|
|
@@ -6717,6 +6779,16 @@ function toCodexDynamicToolProtocolResponse(response) {
|
|
|
6717
6779
|
success: response.success
|
|
6718
6780
|
};
|
|
6719
6781
|
}
|
|
6782
|
+
function toCodexDynamicToolProgressResponse(response, protocolResponse) {
|
|
6783
|
+
if (response.asyncStarted !== true) return protocolResponse;
|
|
6784
|
+
return {
|
|
6785
|
+
...protocolResponse,
|
|
6786
|
+
details: {
|
|
6787
|
+
async: true,
|
|
6788
|
+
status: "started"
|
|
6789
|
+
}
|
|
6790
|
+
};
|
|
6791
|
+
}
|
|
6720
6792
|
function shouldReleaseTurnAfterTerminalDynamicTool(state) {
|
|
6721
6793
|
return !state.completed && !state.aborted && state.responseSuccess && !state.currentTurnHadNonTerminalDynamicToolResult && state.activeAppServerTurnRequests === 0 && state.activeTurnItemIdsCount === 0 && state.pendingOpenClawDynamicToolCompletionIdsCount === 0;
|
|
6722
6794
|
}
|
|
@@ -6797,7 +6869,10 @@ function createCodexNativeHookRelay(params) {
|
|
|
6797
6869
|
turnStartTimeoutMs: params.turnStartTimeoutMs
|
|
6798
6870
|
}),
|
|
6799
6871
|
signal: params.signal,
|
|
6800
|
-
command: {
|
|
6872
|
+
command: {
|
|
6873
|
+
nice: 10,
|
|
6874
|
+
timeoutMs: params.options?.gatewayTimeoutMs
|
|
6875
|
+
}
|
|
6801
6876
|
});
|
|
6802
6877
|
}
|
|
6803
6878
|
function resolveCodexNativeHookRelayEvents(params) {
|
|
@@ -6865,19 +6940,6 @@ async function unsubscribeCodexThreadBestEffort(client, params) {
|
|
|
6865
6940
|
});
|
|
6866
6941
|
}
|
|
6867
6942
|
}
|
|
6868
|
-
function retireCodexAppServerClientAfterTimedOutTurn(client, params) {
|
|
6869
|
-
const clearedSharedClient = clearSharedCodexAppServerClientIfCurrent(client);
|
|
6870
|
-
if (!clearedSharedClient) {
|
|
6871
|
-
const close = client.close;
|
|
6872
|
-
if (typeof close === "function") close.call(client);
|
|
6873
|
-
}
|
|
6874
|
-
embeddedAgentLog.warn("codex app-server client retired after timed-out turn", {
|
|
6875
|
-
threadId: params.threadId,
|
|
6876
|
-
turnId: params.turnId,
|
|
6877
|
-
reason: params.reason,
|
|
6878
|
-
clearedSharedClient
|
|
6879
|
-
});
|
|
6880
|
-
}
|
|
6881
6943
|
function resolveOpenClawCodingToolsSessionKeys(params, sandboxSessionKey) {
|
|
6882
6944
|
return {
|
|
6883
6945
|
sessionKey: sandboxSessionKey,
|
|
@@ -6893,12 +6955,54 @@ function resolveCodexAppServerHookChannelId(params, sandboxSessionKey) {
|
|
|
6893
6955
|
messageTo: params.messageTo
|
|
6894
6956
|
}).channelId;
|
|
6895
6957
|
}
|
|
6958
|
+
const CODEX_DYNAMIC_TOOL_BUILD_WARN_TOTAL_MS = 1e3;
|
|
6959
|
+
const CODEX_DYNAMIC_TOOL_BUILD_WARN_STAGE_MS = 500;
|
|
6960
|
+
function createCodexDynamicToolBuildStageTracker(options = {}) {
|
|
6961
|
+
if (!options.enabled) return {
|
|
6962
|
+
mark() {},
|
|
6963
|
+
snapshot() {
|
|
6964
|
+
return {
|
|
6965
|
+
totalMs: 0,
|
|
6966
|
+
stages: []
|
|
6967
|
+
};
|
|
6968
|
+
}
|
|
6969
|
+
};
|
|
6970
|
+
const startedAt = Date.now();
|
|
6971
|
+
let previousAt = startedAt;
|
|
6972
|
+
const stages = [];
|
|
6973
|
+
const toMs = (value) => Math.max(0, Math.round(value));
|
|
6974
|
+
return {
|
|
6975
|
+
mark(name) {
|
|
6976
|
+
const currentAt = Date.now();
|
|
6977
|
+
stages.push({
|
|
6978
|
+
name,
|
|
6979
|
+
durationMs: toMs(currentAt - previousAt),
|
|
6980
|
+
elapsedMs: toMs(currentAt - startedAt)
|
|
6981
|
+
});
|
|
6982
|
+
previousAt = currentAt;
|
|
6983
|
+
},
|
|
6984
|
+
snapshot() {
|
|
6985
|
+
return {
|
|
6986
|
+
totalMs: toMs(Date.now() - startedAt),
|
|
6987
|
+
stages: stages.slice()
|
|
6988
|
+
};
|
|
6989
|
+
}
|
|
6990
|
+
};
|
|
6991
|
+
}
|
|
6992
|
+
function shouldWarnCodexDynamicToolBuildStageSummary(summary) {
|
|
6993
|
+
return summary.totalMs >= CODEX_DYNAMIC_TOOL_BUILD_WARN_TOTAL_MS || summary.stages.some((stage) => stage.durationMs >= CODEX_DYNAMIC_TOOL_BUILD_WARN_STAGE_MS);
|
|
6994
|
+
}
|
|
6995
|
+
function formatCodexDynamicToolBuildStageSummary(summary) {
|
|
6996
|
+
return summary.stages.length > 0 ? summary.stages.map((stage) => `${stage.name}:${stage.durationMs}ms@${stage.elapsedMs}ms`).join(",") : "none";
|
|
6997
|
+
}
|
|
6896
6998
|
async function buildDynamicTools(input) {
|
|
6897
6999
|
const { params } = input;
|
|
6898
7000
|
if (params.disableTools || !supportsModelTools(params.model)) return [];
|
|
7001
|
+
const toolBuildStages = createCodexDynamicToolBuildStageTracker({ enabled: input.profilerEnabled });
|
|
6899
7002
|
const modelHasVision = params.model.input?.includes("image") ?? false;
|
|
6900
7003
|
const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, input.sessionAgentId);
|
|
6901
7004
|
const createOpenClawCodingTools = (await import("openclaw/plugin-sdk/agent-harness")).createOpenClawCodingTools;
|
|
7005
|
+
toolBuildStages.mark("load-agent-harness-tools");
|
|
6902
7006
|
const sessionKeys = resolveOpenClawCodingToolsSessionKeys(params, input.sandboxSessionKey);
|
|
6903
7007
|
const allTools = createOpenClawCodingTools({
|
|
6904
7008
|
agentId: input.sessionAgentId,
|
|
@@ -6963,13 +7067,22 @@ async function buildDynamicTools(input) {
|
|
|
6963
7067
|
message
|
|
6964
7068
|
}
|
|
6965
7069
|
});
|
|
7070
|
+
},
|
|
7071
|
+
recordToolPrepStage: (name) => {
|
|
7072
|
+
toolBuildStages.mark(name);
|
|
6966
7073
|
}
|
|
6967
7074
|
});
|
|
6968
|
-
|
|
7075
|
+
toolBuildStages.mark("create-openclaw-coding-tools");
|
|
7076
|
+
const codexFilteredTools = addNodeShellDynamicToolsIfNeeded(addSandboxShellDynamicToolsIfAvailable(isCodexMemoryFlushRun(params) ? filterCodexMemoryFlushDynamicTools(allTools) : filterCodexDynamicTools(allTools, input.pluginConfig), allTools, input), allTools, input);
|
|
7077
|
+
toolBuildStages.mark("codex-filtering");
|
|
7078
|
+
const visionFilteredTools = filterToolsForVisionInputs(codexFilteredTools, {
|
|
6969
7079
|
modelHasVision,
|
|
6970
7080
|
hasInboundImages: (params.images?.length ?? 0) > 0
|
|
6971
|
-
})
|
|
6972
|
-
|
|
7081
|
+
});
|
|
7082
|
+
toolBuildStages.mark("vision-filtering");
|
|
7083
|
+
const filteredTools = filterCodexDynamicToolsForAllowlist(visionFilteredTools, includeForcedCodexDynamicToolAllow(params.toolsAllow, params));
|
|
7084
|
+
toolBuildStages.mark("allowlist-filter");
|
|
7085
|
+
const normalizedTools = normalizeAgentRuntimeTools({
|
|
6973
7086
|
runtimePlan: input.ignoreRuntimePlan ? void 0 : params.runtimePlan,
|
|
6974
7087
|
tools: filteredTools,
|
|
6975
7088
|
provider: params.provider,
|
|
@@ -6980,6 +7093,27 @@ async function buildDynamicTools(input) {
|
|
|
6980
7093
|
modelApi: params.model.api,
|
|
6981
7094
|
model: params.model
|
|
6982
7095
|
});
|
|
7096
|
+
toolBuildStages.mark("runtime-normalization");
|
|
7097
|
+
const summary = toolBuildStages.snapshot();
|
|
7098
|
+
if (shouldWarnCodexDynamicToolBuildStageSummary(summary)) {
|
|
7099
|
+
const phase = input.forceHeartbeatTool ? "registered-tools" : "runtime-tools";
|
|
7100
|
+
embeddedAgentLog.warn(`codex app-server dynamic tool build timings runId=${params.runId} sessionId=${params.sessionId} phase=${phase} totalMs=${summary.totalMs} stages=${formatCodexDynamicToolBuildStageSummary(summary)}`, {
|
|
7101
|
+
runId: params.runId,
|
|
7102
|
+
sessionId: params.sessionId,
|
|
7103
|
+
phase,
|
|
7104
|
+
totalMs: summary.totalMs,
|
|
7105
|
+
stages: summary.stages,
|
|
7106
|
+
allToolCount: allTools.length,
|
|
7107
|
+
codexFilteredToolCount: codexFilteredTools.length,
|
|
7108
|
+
visionFilteredToolCount: visionFilteredTools.length,
|
|
7109
|
+
filteredToolCount: filteredTools.length,
|
|
7110
|
+
normalizedToolCount: normalizedTools.length,
|
|
7111
|
+
forceHeartbeatTool: input.forceHeartbeatTool === true,
|
|
7112
|
+
ignoreRuntimePlan: input.ignoreRuntimePlan === true,
|
|
7113
|
+
nativeToolSurfaceEnabled: input.nativeToolSurfaceEnabled === true
|
|
7114
|
+
});
|
|
7115
|
+
}
|
|
7116
|
+
return normalizedTools;
|
|
6983
7117
|
}
|
|
6984
7118
|
function includeForcedCodexDynamicToolAllow(toolsAllow, params) {
|
|
6985
7119
|
if (toolsAllow === void 0 || hasWildcardCodexToolsAllow(toolsAllow)) return toolsAllow;
|
|
@@ -7149,11 +7283,33 @@ function shouldProjectMirroredHistoryForCodexStart(params) {
|
|
|
7149
7283
|
if (!params.historyMessages.some((message) => message.role === "user")) return false;
|
|
7150
7284
|
if (params.forceProject) return true;
|
|
7151
7285
|
if (!params.startupBinding?.threadId) return true;
|
|
7286
|
+
if (hasUserVisibleHistoryAfterCodexBinding({
|
|
7287
|
+
startupBinding: params.startupBinding,
|
|
7288
|
+
historyMessages: params.historyMessages
|
|
7289
|
+
})) return true;
|
|
7152
7290
|
return !areCodexDynamicToolFingerprintsCompatible({
|
|
7153
7291
|
previous: params.startupBinding.dynamicToolsFingerprint,
|
|
7154
7292
|
next: params.dynamicToolsFingerprint
|
|
7155
7293
|
});
|
|
7156
7294
|
}
|
|
7295
|
+
function hasUserVisibleHistoryAfterCodexBinding(params) {
|
|
7296
|
+
const bindingUpdatedAt = Date.parse(params.startupBinding.updatedAt);
|
|
7297
|
+
if (!Number.isFinite(bindingUpdatedAt)) return false;
|
|
7298
|
+
return params.historyMessages.some((message) => {
|
|
7299
|
+
if (message.role !== "user" && message.role !== "assistant") return false;
|
|
7300
|
+
if (isCodexAppServerMirroredTranscriptMessage(message)) return false;
|
|
7301
|
+
const timestamp = typeof message.timestamp === "number" ? message.timestamp : typeof message.timestamp === "string" ? Date.parse(message.timestamp) : NaN;
|
|
7302
|
+
return Number.isFinite(timestamp) && timestamp > bindingUpdatedAt;
|
|
7303
|
+
});
|
|
7304
|
+
}
|
|
7305
|
+
function isCodexAppServerMirroredTranscriptMessage(message) {
|
|
7306
|
+
const record = message;
|
|
7307
|
+
const idempotencyKey = record.idempotencyKey;
|
|
7308
|
+
if (typeof idempotencyKey === "string" && idempotencyKey.startsWith("codex-app-server:")) return true;
|
|
7309
|
+
const meta = record["__openclaw"];
|
|
7310
|
+
if (!meta || typeof meta !== "object" || Array.isArray(meta)) return false;
|
|
7311
|
+
return typeof meta.mirrorIdentity === "string";
|
|
7312
|
+
}
|
|
7157
7313
|
function readContextEngineThreadBootstrapProjection(projection) {
|
|
7158
7314
|
if (projection?.mode !== "thread_bootstrap") return;
|
|
7159
7315
|
const epoch = projection.epoch?.trim();
|
|
@@ -7471,6 +7627,11 @@ function readRawAssistantTextPreview(item) {
|
|
|
7471
7627
|
function isTurnNotification(value, threadId, turnId) {
|
|
7472
7628
|
return isCodexNotificationForTurn(value, threadId, turnId);
|
|
7473
7629
|
}
|
|
7630
|
+
function isCodexNotificationOutsideActiveRun(correlation) {
|
|
7631
|
+
if (!Boolean(correlation.threadId || correlation.nestedTurnThreadId)) return false;
|
|
7632
|
+
if (!correlation.matchesActiveThread) return true;
|
|
7633
|
+
return Boolean(correlation.turnId || correlation.nestedTurnId) && correlation.matchesActiveTurn === false;
|
|
7634
|
+
}
|
|
7474
7635
|
function isCurrentThreadTurnRequestParams(value, threadId, turnId) {
|
|
7475
7636
|
if (!isJsonObject(value)) return false;
|
|
7476
7637
|
return readString(value, "threadId") === threadId && readString(value, "turnId") === turnId;
|
|
@@ -7528,8 +7689,7 @@ function readString(record, key) {
|
|
|
7528
7689
|
return typeof value === "string" ? value : void 0;
|
|
7529
7690
|
}
|
|
7530
7691
|
function readBoolean(record, key) {
|
|
7531
|
-
|
|
7532
|
-
return typeof value === "boolean" ? value : void 0;
|
|
7692
|
+
return asBoolean(record[key]);
|
|
7533
7693
|
}
|
|
7534
7694
|
async function readMirroredSessionHistoryMessages(sessionFile) {
|
|
7535
7695
|
const messages = await readCodexMirroredSessionHistoryMessages(sessionFile);
|
|
@@ -7596,7 +7756,8 @@ function buildCodexSystemPromptReport(params) {
|
|
|
7596
7756
|
systemPrompt: {
|
|
7597
7757
|
chars: params.developerInstructions.length,
|
|
7598
7758
|
projectContextChars: 0,
|
|
7599
|
-
nonProjectContextChars: params.developerInstructions.length
|
|
7759
|
+
nonProjectContextChars: params.developerInstructions.length,
|
|
7760
|
+
hash: sha256Text(params.developerInstructions)
|
|
7600
7761
|
},
|
|
7601
7762
|
injectedWorkspaceFiles: buildCodexBootstrapInjectionStats({
|
|
7602
7763
|
bootstrapFiles: params.workspaceBootstrapContext.bootstrapFiles,
|
|
@@ -7605,6 +7766,7 @@ function buildCodexSystemPromptReport(params) {
|
|
|
7605
7766
|
}),
|
|
7606
7767
|
skills: {
|
|
7607
7768
|
promptChars: skillsPrompt.length,
|
|
7769
|
+
hash: sha256Text(skillsPrompt),
|
|
7608
7770
|
entries: buildCodexSkillReportEntries(skillsPrompt)
|
|
7609
7771
|
},
|
|
7610
7772
|
tools: {
|
|
@@ -7621,17 +7783,30 @@ function buildCodexSkillReportEntries(skillsPrompt) {
|
|
|
7621
7783
|
blockChars: block.length
|
|
7622
7784
|
})).filter((entry) => entry.blockChars > 0);
|
|
7623
7785
|
}
|
|
7786
|
+
function readCodexDiagnosticToolParameters(tool) {
|
|
7787
|
+
return tool.inputSchema ?? tool.parameters;
|
|
7788
|
+
}
|
|
7789
|
+
function buildCodexDiagnosticToolDefinitions(tools) {
|
|
7790
|
+
return tools.map((tool) => ({
|
|
7791
|
+
name: tool.name,
|
|
7792
|
+
description: tool.description,
|
|
7793
|
+
parameters: readCodexDiagnosticToolParameters(tool)
|
|
7794
|
+
}));
|
|
7795
|
+
}
|
|
7624
7796
|
function buildCodexToolReportEntry(tool) {
|
|
7625
7797
|
const summary = tool.description.trim();
|
|
7626
7798
|
if (tool.deferLoading === true) return {
|
|
7627
7799
|
name: tool.name,
|
|
7628
7800
|
summaryChars: summary.length,
|
|
7801
|
+
summaryHash: sha256Text(summary),
|
|
7629
7802
|
schemaChars: 0,
|
|
7803
|
+
schemaHash: stableJsonHash(null),
|
|
7630
7804
|
propertiesCount: null
|
|
7631
7805
|
};
|
|
7632
7806
|
return {
|
|
7633
7807
|
name: tool.name,
|
|
7634
7808
|
summaryChars: summary.length,
|
|
7809
|
+
summaryHash: sha256Text(summary),
|
|
7635
7810
|
...buildCodexToolSchemaStats(tool.inputSchema)
|
|
7636
7811
|
};
|
|
7637
7812
|
}
|
|
@@ -7646,9 +7821,24 @@ function buildCodexToolSchemaStats(schema) {
|
|
|
7646
7821
|
const properties = isJsonObject(schema) && isJsonObject(schema.properties) ? schema.properties : null;
|
|
7647
7822
|
return {
|
|
7648
7823
|
schemaChars,
|
|
7824
|
+
schemaHash: stableJsonHash(schema),
|
|
7649
7825
|
propertiesCount: properties ? Object.keys(properties).length : null
|
|
7650
7826
|
};
|
|
7651
7827
|
}
|
|
7828
|
+
function sha256Text(value) {
|
|
7829
|
+
return createHash("sha256").update(value).digest("hex");
|
|
7830
|
+
}
|
|
7831
|
+
function normalizeForStableHash(value) {
|
|
7832
|
+
if (Array.isArray(value)) return value.map((entry) => normalizeForStableHash(entry));
|
|
7833
|
+
if (value && typeof value === "object") {
|
|
7834
|
+
const record = value;
|
|
7835
|
+
return Object.fromEntries(Object.keys(record).toSorted((left, right) => left.localeCompare(right)).map((key) => [key, normalizeForStableHash(record[key])]));
|
|
7836
|
+
}
|
|
7837
|
+
return value;
|
|
7838
|
+
}
|
|
7839
|
+
function stableJsonHash(value) {
|
|
7840
|
+
return sha256Text(JSON.stringify(normalizeForStableHash(value)) ?? "null");
|
|
7841
|
+
}
|
|
7652
7842
|
function buildCodexBootstrapInjectionStats(params) {
|
|
7653
7843
|
const injectedIndex = indexCodexContextFileContent(params.injectedFiles);
|
|
7654
7844
|
const developerInstructionIndex = indexCodexContextFileContent(params.developerInstructionFiles ?? []);
|
|
@@ -7822,9 +8012,11 @@ function isMissingCodexBootstrapContextFile(file) {
|
|
|
7822
8012
|
function remapCodexContextFilePath(params) {
|
|
7823
8013
|
const relativePath = path.relative(params.sourceWorkspaceDir, params.file.path);
|
|
7824
8014
|
if (!relativePath || relativePath === ".." || relativePath.startsWith(`..${path.sep}`) || path.isAbsolute(relativePath) || params.sourceWorkspaceDir === params.targetWorkspaceDir) return params.file;
|
|
8015
|
+
const targetUsesPosixSeparators = params.targetWorkspaceDir.includes("/") && !params.targetWorkspaceDir.includes("\\");
|
|
8016
|
+
const normalizedRelativePath = targetUsesPosixSeparators ? relativePath.replaceAll("\\", "/") : relativePath.replaceAll("/", "\\");
|
|
7825
8017
|
return {
|
|
7826
8018
|
...params.file,
|
|
7827
|
-
path: path.join(params.targetWorkspaceDir,
|
|
8019
|
+
path: targetUsesPosixSeparators ? path.posix.join(params.targetWorkspaceDir, normalizedRelativePath) : path.win32.join(params.targetWorkspaceDir, normalizedRelativePath)
|
|
7828
8020
|
};
|
|
7829
8021
|
}
|
|
7830
8022
|
function compareCodexContextFiles(left, right) {
|
|
@@ -7861,6 +8053,21 @@ async function mirrorTranscriptBestEffort(params) {
|
|
|
7861
8053
|
embeddedAgentLog.warn("failed to mirror codex app-server transcript", { error });
|
|
7862
8054
|
}
|
|
7863
8055
|
}
|
|
8056
|
+
async function mirrorPromptAtTurnStartBestEffort(params) {
|
|
8057
|
+
if (params.params.suppressNextUserMessagePersistence) return;
|
|
8058
|
+
try {
|
|
8059
|
+
await mirrorCodexAppServerTranscript({
|
|
8060
|
+
sessionFile: params.params.sessionFile,
|
|
8061
|
+
agentId: params.agentId,
|
|
8062
|
+
sessionKey: params.sessionKey,
|
|
8063
|
+
messages: [attachCodexMirrorIdentity(buildCodexUserPromptMessage(params.params), `${params.turnId}:prompt`)],
|
|
8064
|
+
idempotencyScope: `codex-app-server:${params.threadId}`,
|
|
8065
|
+
config: params.params.config
|
|
8066
|
+
});
|
|
8067
|
+
} catch (error) {
|
|
8068
|
+
embeddedAgentLog.warn("failed to mirror codex app-server prompt at turn start", { error });
|
|
8069
|
+
}
|
|
8070
|
+
}
|
|
7864
8071
|
function isNonEmptyString(value) {
|
|
7865
8072
|
return typeof value === "string" && value.length > 0;
|
|
7866
8073
|
}
|
|
@@ -7907,6 +8114,7 @@ function handleApprovalRequest(params) {
|
|
|
7907
8114
|
threadId: params.threadId,
|
|
7908
8115
|
turnId: params.turnId,
|
|
7909
8116
|
nativeHookRelay: params.nativeHookRelay,
|
|
8117
|
+
autoApprove: params.autoApprove,
|
|
7910
8118
|
signal: params.signal
|
|
7911
8119
|
});
|
|
7912
8120
|
}
|