@openclaw/codex 2026.7.2-beta.4 → 2026.7.2-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{app-server-policy-BO3jYBkv.js → app-server-policy-BSaO2JIT.js} +1 -1
- package/dist/{attempt-notifications-DdmnBMUp.js → attempt-notifications-AP-a-Q5k.js} +1 -1
- package/dist/{bounded-turn-CaQL96kg.js → bounded-turn-D2ZAgZVz.js} +54 -24
- package/dist/{capabilities-CLICvTxf.js → capabilities-BFDTVYr4.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-DgADqnHa.js → command-formatters-C336eRVS.js} +2 -2
- package/dist/{command-handlers-l_lVPNlB.js → command-handlers-DAHUSry9.js} +1233 -1222
- package/dist/{compact-CC5KhBzX.js → compact-D_uvHurS.js} +8 -8
- package/dist/{computer-use-Ip1-QGa-.js → computer-use-CYEc8U3w.js} +123 -115
- package/dist/{conversation-control-sNPsbTCP.js → conversation-control-xsIeXbo4.js} +6 -6
- package/dist/doctor-contract-api.js +24 -86
- package/dist/{dynamic-tools-CQI3UwqY.js → dynamic-tools-D2gYkSBO.js} +482 -91
- package/dist/effective-mcp-catalog-Bbd98Inw.js +114 -0
- package/dist/{event-projector-usage-D6tE7_qD.js → event-projector-usage-Xp4AlR2k.js} +20 -3
- package/dist/harness.js +19 -14
- package/dist/index.js +292 -328
- package/dist/media-understanding-provider.js +6 -1
- package/dist/{models-BNeMlHgg.js → models-BBMKU4jA.js} +2 -2
- package/dist/{notification-correlation-BGLixv5_.js → notification-correlation-CU6_AnOb.js} +3 -3
- package/dist/{plugin-app-cache-key-CvzvmBRz.js → plugin-app-cache-key-DztPafOA.js} +135 -42
- package/dist/{rate-limits-D0IJT-a6.js → rate-limits-CU-gVCCS.js} +1 -1
- package/dist/{request-BTccUTD3.js → request-qKh331yu.js} +3 -3
- package/dist/{run-attempt--858NXDl.js → run-attempt-CY9WlDLc.js} +1060 -402
- package/dist/{runtime-artifact-C2ITXdhM.js → runtime-artifact-CmtG_t1L.js} +90 -24
- package/dist/{sandbox-guard-D1Wky__S.js → sandbox-guard-NuhpXmPB.js} +4 -0
- package/dist/{session-binding-ZSMX1omP.js → session-binding-BXpo9ymA.js} +1006 -891
- package/dist/{session-catalog-DsKaezgR.js → session-catalog-DyOgR4WH.js} +289 -56
- package/dist/{session-cli-CYJTfRLG.js → session-cli-2PZaFLRh.js} +2 -2
- package/dist/{session-upstream-marker-D7XlI9us.js → session-upstream-marker-B6U7tLw5.js} +1 -1
- package/dist/{settled-turn-finalizer-DHltNgtF.js → settled-turn-finalizer-CXY2Z9dT.js} +19 -6
- package/dist/{shared-client-wmgNFNYp.js → shared-client-DTbvH-XV.js} +1993 -1720
- package/dist/{side-question-BfFZCsJ-.js → side-question-_ulBk1AL.js} +12 -10
- package/dist/{thread-lifecycle-cqrOlJkq.js → thread-lifecycle-DF53ogiA.js} +980 -346
- package/dist/{transcript-mirror-2p7kl6e4.js → transcript-mirror-DzsdNCf5.js} +80 -41
- package/dist/{upstream-session-fork-vPjwkT1i.js → upstream-session-fork-Dy4Xvuoj.js} +3 -3
- package/dist/{usage-DM_I3mPT.js → usage-CQ6GhD5-.js} +3 -3
- package/dist/{web-search-provider.runtime-Bx6HAc_k.js → web-search-provider.runtime-CCFhg2z5.js} +3 -3
- package/package.json +6 -8
- package/npm-shrinkwrap.json +0 -202
- package/dist/{auth-binding-C1czuHPA.js → auth-binding-B4FfbcCg.js} +1 -1
|
@@ -1,35 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { C as readCodexTurnCompletedNotification, S as readCodexTurn, d as attachCodexMirrorIdentity, f as readMirrorIdentity, i as mirrorPromptAtTurnStartBestEffort, n as createCodexAppServerUserMessagePersistenceNotifier, o as buildCodexUserPromptMessage, s as promptSnapshot, t as codexTranscriptMirrorRuntime, u as serializeCodexMirrorSourceEvidence, v as assertCodexTurnStartResponse, y as readCodexDynamicToolCallParams } from "./transcript-mirror-
|
|
7
|
-
import { i as defaultCodexAppInventoryCache, n as buildCodexAppServerRuntimeFingerprint, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-
|
|
1
|
+
import { $ as resolveCodexTurnAssistantCompletionIdleTimeoutMs, A as retainCodexAppServerLiveThread, D as resolveCodexAppServerClientInstanceId, E as isCodexAppServerRequestTimeoutError, F as resolveCodexAppServerAuthProfileId, I as resolveCodexAppServerAuthProfileIdForAgent, J as CodexAppServerStartupError, K as resolveCodexAppServerHomeDir, L as resolveCodexAppServerFallbackApiKeyCacheKey, M as readRecentCodexRateLimits, N as rememberCodexRateLimitsRead, P as resolveCodexAppServerAuthAccountCacheKey, Q as resolveCodexStartupTimeoutMs, R as resolveCodexAppServerPreparedApiKeyCacheKey, S as isCodexAppServerConnectionClosedError, U as flattenCodexDynamicToolFunctions, W as isJsonObject, Y as isCodexAppServerStartupError, Z as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, a as getLeasedSharedCodexAppServerClient, b as isCodexAppServerApprovalRequest, et as resolveCodexTurnCompletionIdleTimeoutMs, f as retainSharedCodexAppServerClientIfCurrent, j as readCodexRateLimitsRevision, k as ensureCodexAppServerClientRuntime, l as releaseLeasedSharedCodexAppServerClient, n as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, nt as withCodexStartupTimeout, o as getSharedCodexAppServerClient, p as retireSharedCodexAppServerClientIfCurrent, q as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS, s as isCodexAppServerStartSelectionChangedError, t as clearSharedCodexAppServerClientIfCurrent, tt as resolveCodexTurnTerminalIdleTimeoutMs, v as CodexAppServerRpcError, x as isCodexAppServerBrokenPipeError, y as getCodexAppServerClientInstanceId, z as resolveCodexAppServerPreparedAuthHandoff } from "./shared-client-DTbvH-XV.js";
|
|
2
|
+
import { A as resolveOpenClawExecPolicyForCodexAppServer, D as isCodexSandboxExecServerEnabled, E as isCodexAppServerApprovalPolicyAllowedByRequirements, O as readCodexPluginConfig, S as withMcpElicitationsApprovalPolicy, T as resolveCodexModelBackedReviewerPolicyContext, c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, h as resolveCodexAppServerHomeScope, i as createCodexSessionGenerationSupersededError, k as resolveCodexPluginsPolicy, l as resolveCodexRunSessionBindingAuthority, u as scopeCodexRunBindingStore, v as resolveCodexComputerUseConfig, x as shouldAutoApproveCodexAppServerApprovals } from "./session-binding-BXpo9ymA.js";
|
|
3
|
+
import { $ as readCodexErrorNotificationMessage, B as resolveCodexContextEngineProjectionReserveTokens, F as buildContextEngineBinding, G as mergeCodexThreadConfigs, H as buildCodexPluginThreadConfig, I as isContextEngineBindingCompatible, K as shouldBuildCodexPluginThreadConfig, L as fitCodexProjectedContextForTurnStart, M as areCodexDynamicToolFingerprintsCompatible, N as codexDynamicToolsFingerprint, O as isSystemAgentOnlyCodexDynamicToolAllowlist, P as codexLegacyDynamicToolsFingerprint, Q as normalizeNonEmptyString, R as projectContextEngineAssemblyForCodex, T as filterCodexDynamicTools, U as buildCodexPluginThreadConfigInputFingerprint, W as buildCodexPluginThreadConfigTimeoutFallback, X as resolveRecoverableCodexPluginConfigKeys, Z as extractRawAssistantText, _ as buildDeveloperInstructions, _t as unsubscribeCodexThreadBestEffort, a as sanitizeCodexHistoryImagePayloads, at as readNonNegativeInteger, c as isCodexAppServerProfilerEnabled, ct as readString$6, dt as CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS, et as readHookOutputEntries, ft as CodexAppServerUnsafeSubscriptionError, g as resolveCodexWebSearchPlan, gt as retireCodexAppServerClientAfterTimedOutTurn, ht as interruptCodexTurnBestEffort, it as readNonEmptyStringArray, j as resolveCodexDynamicToolsLoadingForRuntime, lt as splitPlanText, n as buildTurnStartParams, nt as readItemString, ot as readNullableString$1, pt as closeCodexStartupClientBestEffort, r as buildCodexUserInput, rt as readNonEmptyString$1, s as startOrResumeThread, st as readNumber, t as buildTurnCollaborationMode, tt as readItem, ut as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS, x as resolveCodexAppServerThreadModelSelection, z as resolveCodexContextEngineProjectionMaxChars } from "./thread-lifecycle-DF53ogiA.js";
|
|
4
|
+
import { S as updateActiveTurnItemIds, _ as readCodexNotificationItem, a as isCodexTurnAbortMarkerNotification, b as shouldDisarmAssistantCompletionIdleWatch, c as isPendingOpenClawDynamicToolCompletionNotification, d as isRawReasoningCompletionNotification, f as isRawToolOutputCompletionNotification, g as isTerminalTurnStatus, h as isRetryableErrorNotification, i as isAssistantCompletionReleaseNotification, l as isRawAssistantProgressNotification, m as isReasoningProgressNotification, n as describeNotificationActivity, o as isFileChangePatchUpdatedNotification, p as isReasoningItemCompletionNotification, r as isAssistantCommentaryCompletionNotification, s as isNativeToolProgressNotification, t as codexExecutionToolName, u as isRawFunctionToolOutputCompletionNotification, v as readNotificationItemId, x as updateActiveCompletionBlockerItemIds, y as readRawResponseToolCallId } from "./attempt-notifications-AP-a-Q5k.js";
|
|
5
|
+
import { r as projectCodexThreadUsageUpdate, t as CodexResponseCompletionProjection } from "./event-projector-usage-Xp4AlR2k.js";
|
|
6
|
+
import { C as readCodexTurnCompletedNotification, S as readCodexTurn, d as attachCodexMirrorIdentity, f as readMirrorIdentity, i as mirrorPromptAtTurnStartBestEffort, n as createCodexAppServerUserMessagePersistenceNotifier, o as buildCodexUserPromptMessage, s as promptSnapshot, t as codexTranscriptMirrorRuntime, u as serializeCodexMirrorSourceEvidence, v as assertCodexTurnStartResponse, y as readCodexDynamicToolCallParams } from "./transcript-mirror-DzsdNCf5.js";
|
|
7
|
+
import { i as defaultCodexAppInventoryCache, n as buildCodexAppServerRuntimeFingerprint, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-DztPafOA.js";
|
|
8
8
|
import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
|
|
9
|
-
import { t as CODEX_CONTROL_METHODS } from "./capabilities-
|
|
10
|
-
import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-
|
|
11
|
-
import { r as formatCodexDisplayText } from "./command-formatters-
|
|
12
|
-
import { n as resolveCodexAppServerForOpenClawToolPolicy, t as resolveCodexAppServerForModelProvider } from "./app-server-policy-
|
|
13
|
-
import { a as resolveCodexBindingAppServerConnection, n as readCodexNotificationThreadId, r as readCodexNotificationTurnId, t as isCodexNotificationForTurn } from "./notification-correlation-
|
|
14
|
-
import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-
|
|
9
|
+
import { t as CODEX_CONTROL_METHODS } from "./capabilities-BFDTVYr4.js";
|
|
10
|
+
import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-CU-gVCCS.js";
|
|
11
|
+
import { r as formatCodexDisplayText } from "./command-formatters-C336eRVS.js";
|
|
12
|
+
import { n as resolveCodexAppServerForOpenClawToolPolicy, t as resolveCodexAppServerForModelProvider } from "./app-server-policy-BSaO2JIT.js";
|
|
13
|
+
import { a as resolveCodexBindingAppServerConnection, n as readCodexNotificationThreadId, r as readCodexNotificationTurnId, t as isCodexNotificationForTurn } from "./notification-correlation-CU6_AnOb.js";
|
|
14
|
+
import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-B4FfbcCg.js";
|
|
15
15
|
import { i as resolveCodexLocalRuntimeAttribution, n as createAssistantMessage, r as createAssistantMirrorMessage, t as createAssistantCommentaryMessage } from "./event-projector-assistant-message-DTgnPPVF.js";
|
|
16
|
-
import { $ as
|
|
17
|
-
import { a as
|
|
16
|
+
import { $ as shouldClearTerminalPresentationForNativeItem, A as createCodexNativeHookRelay, B as resolveTerminalDynamicToolBatchAction, D as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, F as handleDynamicToolCallWithTimeout, G as resolveCodexToolAbortTerminalReason, H as shouldReleaseTurnAfterTerminalDynamicTool, I as hasPendingDynamicToolTerminalDiagnostic, J as isSideEffectingNativeToolItem, K as isMutatingNativeToolItem, L as isDynamicToolTerminalDiagnosticEvent, M as resolveCodexNativeHookRelayEvents, N as resolveCodexNativeHookRelayTtlMs, O as buildCodexNativeHookRelayConfig, P as scheduleCodexNativeHookRelayUnregister, Q as itemTitle, R as isMatchingDynamicToolTerminalDiagnostic, S as shouldWarnCodexDynamicToolBuildStageSummary, T as CodexNativeToolLifecycleProjector, U as toCodexDynamicToolProgressResponse, V as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, W as toCodexDynamicToolProtocolResponse, X as itemName, Y as itemKind, Z as itemStatus, _ as resolveCodexExternalSandboxPolicyForOpenClawSandbox, a as emitDynamicToolStartedDiagnostic, b as shouldEnableCodexAppServerNativeToolSurface, d as buildDynamicTools, et as shouldRecordNativeToolTranscript, f as createCodexDynamicToolBuildStageTracker, g as resolveCodexAppServerHookChannelId, h as resolveCodexAppServerExecutionCwd, i as emitDynamicToolErrorDiagnostic, j as emitCodexNativePreToolUseFailureDiagnostic, k as buildCodexNativeHookRelayDisabledConfig, l as buildCodexHookRequester, m as formatCodexDynamicToolBuildStageSummary, n as handleCodexAppServerApprovalRequest, nt as unknownItemStatus, o as emitDynamicToolTerminalDiagnostic, p as disableCodexPluginThreadConfig, q as isNonSuccessItemStatus, r as handleCodexAppServerElicitationRequest, s as resolveCodexProviderWebSearchSupport, t as createCodexDynamicToolBridge, tt as shouldSynthesizeToolProgressForItem, u as settleCodexSourceReplyFinality, v as resolveCodexMessageToolProvider, w as readBoundedCodexRemoteWorkspaceFile, x as shouldRequireCodexSandboxExecServerEnvironment, y as resolveCodexSandboxEnvironmentSelection, z as resolveDynamicToolCallTimeoutMs } from "./dynamic-tools-D2gYkSBO.js";
|
|
17
|
+
import { a as killStaleComputerUseMcpChildren, i as runCodexComputerUseLiveTest, t as ensureCodexComputerUse } from "./computer-use-CYEc8U3w.js";
|
|
18
18
|
import fs from "node:fs/promises";
|
|
19
19
|
import path, { posix } from "node:path";
|
|
20
20
|
import { asDateTimestampMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
21
|
-
import {
|
|
21
|
+
import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, TOOL_PROGRESS_OUTPUT_MAX_CHARS, agentHarnessAttemptTerminal, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine, buildAgentHarnessUserInputAnswers, buildBootstrapContextForFiles, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, buildWatchedSessionsHarnessContext, callGatewayTool, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, deliverAgentHarnessUserInputPrompt, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, finalizeHarnessContextEngineTurn, formatErrorMessage, formatFastModeAutoProgressText, formatToolAggregate, formatToolProgressOutput, getAgentHarnessHookRunner, getBeforeToolCallPolicyDiagnosticState, inferToolMetaFromArgs, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, prepareHarnessNativeMcpAppPreview, projectAgentHarnessTranscriptMessageForDisplay, resolveAgentDir, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveBootstrapFilesForRun, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveSessionAgentIds, resolveUserPath, runAgentCleanupStep, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessGatewayQuestion, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
22
22
|
import { createHash, randomUUID } from "node:crypto";
|
|
23
|
-
import { markAuthProfileBlockedUntil, resolveAgentDir, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
23
|
+
import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
24
24
|
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
25
25
|
import { asFiniteNumber, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
26
|
-
import {
|
|
26
|
+
import { SsrFBlockedError, isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
27
|
+
import { getSessionEntry, parseSqliteSessionFileMarker, resolveTranscriptSessionKeyBySessionId } from "openclaw/plugin-sdk/session-store-runtime";
|
|
27
28
|
import { spawn } from "node:child_process";
|
|
29
|
+
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
28
30
|
import { once } from "node:events";
|
|
29
31
|
import { isIP } from "node:net";
|
|
30
32
|
import { WebSocketServer } from "ws";
|
|
31
|
-
import {
|
|
32
|
-
import { fileURLToPath } from "node:url";
|
|
33
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
33
34
|
import { redactSensitiveFieldValue, redactSensitiveText, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
|
|
34
35
|
import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
35
36
|
import { readSessionTranscriptEvents } from "openclaw/plugin-sdk/session-transcript-runtime";
|
|
@@ -37,10 +38,11 @@ import { prepareMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
|
|
|
37
38
|
import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
|
|
38
39
|
import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "openclaw/plugin-sdk/agent-sessions";
|
|
39
40
|
import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
|
|
41
|
+
import { resolveGeneratedMediaMaxBytes } from "openclaw/plugin-sdk/media-generation-runtime";
|
|
40
42
|
import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
|
|
43
|
+
import { root } from "openclaw/plugin-sdk/file-access-runtime";
|
|
41
44
|
import { MESSAGE_TOOL_DELIVERY_HINTS } from "openclaw/plugin-sdk/message-tool-delivery-hints";
|
|
42
45
|
import { createAgentHarnessTaskRuntime, deliverAgentHarnessTaskCompletion, isDurableAgentHarnessCompletionDelivery } from "openclaw/plugin-sdk/agent-harness-task-runtime";
|
|
43
|
-
import { SsrFBlockedError, isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
44
46
|
//#region extensions/codex/src/app-server/attempt-steering.ts
|
|
45
47
|
/**
|
|
46
48
|
* Debounced steering queue for forwarding user messages to an active Codex
|
|
@@ -201,6 +203,9 @@ function normalizeCodexSteerDebounceMs(value) {
|
|
|
201
203
|
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : CODEX_STEER_ALL_DEBOUNCE_MS;
|
|
202
204
|
}
|
|
203
205
|
//#endregion
|
|
206
|
+
//#region extensions/codex/src/app-server/attempt-terminal.ts
|
|
207
|
+
const attemptTerminal = agentHarnessAttemptTerminal;
|
|
208
|
+
//#endregion
|
|
204
209
|
//#region extensions/codex/src/app-server/event-projector-assistant.ts
|
|
205
210
|
var CodexAssistantProjection = class {
|
|
206
211
|
constructor(params, emitAgentEvent, matchesToolProgressEcho, nextTranscriptTimestamp) {
|
|
@@ -244,8 +249,8 @@ var CodexAssistantProjection = class {
|
|
|
244
249
|
return this.latestTerminalAssistantCandidateCanReleaseAfterToolHandoff && this.hasLatestTerminalAssistantCandidateText();
|
|
245
250
|
}
|
|
246
251
|
async handleAssistantDelta(params) {
|
|
247
|
-
const itemId = readString$
|
|
248
|
-
const delta = readString$
|
|
252
|
+
const itemId = readString$6(params, "itemId") ?? "assistant";
|
|
253
|
+
const delta = readString$6(params, "delta") ?? "";
|
|
249
254
|
if (!delta) return;
|
|
250
255
|
if (itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
251
256
|
const isCommentary = this.isCommentaryAssistantItem(itemId);
|
|
@@ -327,9 +332,9 @@ var CodexAssistantProjection = class {
|
|
|
327
332
|
}
|
|
328
333
|
}
|
|
329
334
|
handleRawResponseItemCompleted(item, activeItemIds) {
|
|
330
|
-
const role = readString$
|
|
331
|
-
const phase = readString$
|
|
332
|
-
const rawItemId = readString$
|
|
335
|
+
const role = readString$6(item, "role");
|
|
336
|
+
const phase = readString$6(item, "phase");
|
|
337
|
+
const rawItemId = readString$6(item, "id");
|
|
333
338
|
const candidateWasSupersededBeforeRaw = this.latestTerminalAssistantCandidateSuperseded;
|
|
334
339
|
const pendingTerminalAssistantEchoItemId = this.pendingRawTerminalAssistantEchoItemId;
|
|
335
340
|
const isPendingTerminalAssistantEcho = role === "assistant" && phase !== "commentary" && pendingTerminalAssistantEchoItemId !== void 0 && (rawItemId === void 0 || rawItemId === pendingTerminalAssistantEchoItemId);
|
|
@@ -388,7 +393,11 @@ var CodexAssistantProjection = class {
|
|
|
388
393
|
return;
|
|
389
394
|
}
|
|
390
395
|
const turnItems = turn.items ?? [];
|
|
391
|
-
const authoritativeIndex = turnItems.findLastIndex((item) =>
|
|
396
|
+
const authoritativeIndex = turnItems.findLastIndex((item) => {
|
|
397
|
+
if (item.type !== "agentMessage" || typeof item.text !== "string" || item.text.trim().length === 0) return false;
|
|
398
|
+
const phase = readItemString(item, "phase");
|
|
399
|
+
return phase === "final_answer" || phase === void 0;
|
|
400
|
+
});
|
|
392
401
|
const authoritative = authoritativeIndex >= 0 ? turnItems[authoritativeIndex] : void 0;
|
|
393
402
|
if (turnItems.slice(authoritativeIndex + 1).some(shouldClearTerminalPresentationForNativeItem) || authoritative?.id === this.latestTerminalAssistantCandidateItemId && this.latestTerminalAssistantCandidateSuperseded) {
|
|
394
403
|
this.supersedeVisibleAnswerCandidate();
|
|
@@ -652,7 +661,7 @@ function collectDynamicToolContentText(contentItems) {
|
|
|
652
661
|
if (!Array.isArray(contentItems)) return "";
|
|
653
662
|
return contentItems.flatMap((entry) => {
|
|
654
663
|
if (!isJsonObject(entry)) return [];
|
|
655
|
-
const text = readString$
|
|
664
|
+
const text = readString$6(entry, "text");
|
|
656
665
|
return text ? [text] : [];
|
|
657
666
|
}).join("\n");
|
|
658
667
|
}
|
|
@@ -1043,8 +1052,8 @@ var CodexToolProgressProjection = class {
|
|
|
1043
1052
|
if (params.sideEffectEvidence === true) this.sideEffectingDynamicIds.add(params.callId);
|
|
1044
1053
|
}
|
|
1045
1054
|
handleOutputDelta(params, toolName) {
|
|
1046
|
-
const itemId = readString$
|
|
1047
|
-
const delta = readString$
|
|
1055
|
+
const itemId = readString$6(params, "itemId");
|
|
1056
|
+
const delta = readString$6(params, "delta");
|
|
1048
1057
|
if (!itemId || !delta) return;
|
|
1049
1058
|
const storedOutput = this.output.append(itemId, delta);
|
|
1050
1059
|
this.rememberEcho(itemId, {
|
|
@@ -1310,17 +1319,19 @@ async function readCodexMirroredSessionEntries(target) {
|
|
|
1310
1319
|
}
|
|
1311
1320
|
function resolveSqliteMarkerSessionKey(target, marker) {
|
|
1312
1321
|
const explicitSessionKey = target.sessionKey?.trim();
|
|
1313
|
-
if (explicitSessionKey)
|
|
1314
|
-
|
|
1322
|
+
if (explicitSessionKey) {
|
|
1323
|
+
const explicitEntry = getSessionEntry({
|
|
1324
|
+
agentId: marker.agentId,
|
|
1325
|
+
sessionKey: explicitSessionKey,
|
|
1326
|
+
storePath: marker.storePath
|
|
1327
|
+
});
|
|
1328
|
+
if (explicitEntry) return explicitEntry.sessionId === marker.sessionId ? explicitSessionKey : void 0;
|
|
1329
|
+
}
|
|
1330
|
+
return resolveTranscriptSessionKeyBySessionId({
|
|
1315
1331
|
agentId: marker.agentId,
|
|
1316
|
-
|
|
1332
|
+
sessionId: marker.sessionId,
|
|
1317
1333
|
storePath: marker.storePath
|
|
1318
1334
|
});
|
|
1319
|
-
return (entries.find(({ entry }) => {
|
|
1320
|
-
return entry.sessionId === marker.sessionId && entry.sessionFile === target.sessionFile;
|
|
1321
|
-
}) ?? entries.find(({ entry }) => {
|
|
1322
|
-
return entry.sessionId === marker.sessionId;
|
|
1323
|
-
}))?.sessionKey;
|
|
1324
1335
|
}
|
|
1325
1336
|
//#endregion
|
|
1326
1337
|
//#region extensions/codex/src/app-server/event-projector-tool-transcript.ts
|
|
@@ -1339,6 +1350,35 @@ const ZERO_USAGE = {
|
|
|
1339
1350
|
}
|
|
1340
1351
|
};
|
|
1341
1352
|
const MISSING_TOOL_RESULT_ERROR = "OpenClaw recorded a native Codex tool.call without a matching tool.result before the turn completed.";
|
|
1353
|
+
const NATIVE_PATCH_REJECTION_RE = /^\s*patch rejected:\s*writing outside of the project;\s*rejected by user approval settings\s*$/iu;
|
|
1354
|
+
const CODE_MODE_NATIVE_PATCH_SOURCE_RE = /^\s*(?:\/\/[^\r\n]*\r?\n\s*)?(?:const|let)\s+([A-Za-z_$][\w$]*)\s*=\s*await\s+tools\.apply_patch\(\s*("(?:\\[\s\S]|[^"\\])*")\s*\)\s*;?\s*text\(\s*\1\s*\)\s*;?\s*$/u;
|
|
1355
|
+
const CODE_MODE_NATIVE_PATCH_RESULT_RE = /^\s*Script (completed|failed)\s*\r?\nWall time\s+\d+(?:\.\d+)?\s+seconds\s*\r?\nOutput:\s*([\s\S]*?)\s*$/iu;
|
|
1356
|
+
function readCodeModeNativePatchInput(source) {
|
|
1357
|
+
if (typeof source !== "string") return;
|
|
1358
|
+
const match = CODE_MODE_NATIVE_PATCH_SOURCE_RE.exec(source);
|
|
1359
|
+
if (!match?.[2]) return;
|
|
1360
|
+
try {
|
|
1361
|
+
const patch = JSON.parse(match[2]);
|
|
1362
|
+
return typeof patch === "string" && /^\*\*\* Begin Patch\r?\n[\s\S]*\r?\n\*\*\* End Patch(?:\r?\n)?$/u.test(patch) ? patch : void 0;
|
|
1363
|
+
} catch {
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
function readInterceptedNativePatchInput(command) {
|
|
1368
|
+
if (typeof command !== "string") return;
|
|
1369
|
+
const lines = command.replace(/\r\n?/gu, "\n").split("\n");
|
|
1370
|
+
const patchStart = lines.indexOf("*** Begin Patch");
|
|
1371
|
+
const invocation = /^[\t ]*(?:cd[\t ]+(?:'([^'\n]+)'|([A-Za-z0-9_./-]+))[\t ]+&&[\t ]+)?apply_patch[\t ]*<<-?[\t ]*'([^'\n]+)'[\t ]*$/u.exec(lines[0] ?? "");
|
|
1372
|
+
if (!invocation || patchStart !== 1) return;
|
|
1373
|
+
const patchEnd = lines.indexOf("*** End Patch", patchStart + 1);
|
|
1374
|
+
const cwd = invocation[1] ?? invocation[2];
|
|
1375
|
+
const delimiter = invocation[3];
|
|
1376
|
+
if (patchEnd < 0 || lines[patchEnd + 1] !== delimiter || lines.slice(patchEnd + 2).some((line) => line.trim().length > 0)) return;
|
|
1377
|
+
return {
|
|
1378
|
+
input: `${lines.slice(patchStart, patchEnd + 1).join("\n")}\n`,
|
|
1379
|
+
...cwd ? { cwd } : {}
|
|
1380
|
+
};
|
|
1381
|
+
}
|
|
1342
1382
|
var CodexToolTranscriptProjection = class {
|
|
1343
1383
|
constructor(params, threadId, turnId, progress, nextTranscriptTimestamp, options = {}) {
|
|
1344
1384
|
this.params = params;
|
|
@@ -1356,6 +1396,10 @@ var CodexToolTranscriptProjection = class {
|
|
|
1356
1396
|
this.trajectoryNamesById = /* @__PURE__ */ new Map();
|
|
1357
1397
|
this.trajectoryItemsById = /* @__PURE__ */ new Map();
|
|
1358
1398
|
this.afterToolCallObservedItemIds = /* @__PURE__ */ new Set();
|
|
1399
|
+
this.nativeMcpAppResultDetails = /* @__PURE__ */ new Map();
|
|
1400
|
+
this.nativeMcpAppResultDetailsAttempted = /* @__PURE__ */ new Set();
|
|
1401
|
+
this.rawNativeToolOutputByCallId = /* @__PURE__ */ new Map();
|
|
1402
|
+
this.codeModeNativePatchInputsByCallId = /* @__PURE__ */ new Map();
|
|
1359
1403
|
}
|
|
1360
1404
|
get transcriptMessages() {
|
|
1361
1405
|
return this.messages;
|
|
@@ -1367,12 +1411,14 @@ var CodexToolTranscriptProjection = class {
|
|
|
1367
1411
|
arguments: sanitizeCodexToolArguments(params.arguments)
|
|
1368
1412
|
});
|
|
1369
1413
|
}
|
|
1370
|
-
recordDynamicToolResult(params) {
|
|
1414
|
+
recordDynamicToolResult(params, resultContentSource) {
|
|
1371
1415
|
this.recordToolResult({
|
|
1372
1416
|
id: params.callId,
|
|
1373
1417
|
name: params.tool,
|
|
1374
1418
|
text: collectDynamicToolContentText(params.contentItems),
|
|
1375
|
-
isError: !params.success
|
|
1419
|
+
isError: !params.success,
|
|
1420
|
+
details: params.details,
|
|
1421
|
+
...resultContentSource ? { resultContentSource } : {}
|
|
1376
1422
|
});
|
|
1377
1423
|
}
|
|
1378
1424
|
recordNativeToolCall(item) {
|
|
@@ -1384,15 +1430,117 @@ var CodexToolTranscriptProjection = class {
|
|
|
1384
1430
|
arguments: itemToolArgs(item)
|
|
1385
1431
|
});
|
|
1386
1432
|
}
|
|
1387
|
-
recordNativeToolResult(item) {
|
|
1433
|
+
recordNativeToolResult(item, details) {
|
|
1388
1434
|
if (!item || !shouldRecordNativeToolTranscript(item)) return;
|
|
1389
1435
|
const name = itemName(item);
|
|
1390
1436
|
if (name) this.recordToolResult({
|
|
1391
1437
|
id: item.id,
|
|
1392
1438
|
name,
|
|
1393
|
-
text: itemTranscriptResultText(item, this.progress.outputTextByItem),
|
|
1394
|
-
isError: isNonSuccessItemStatus(itemStatus(item))
|
|
1395
|
-
|
|
1439
|
+
text: this.rawNativeToolOutputByCallId.get(item.id) ?? itemTranscriptResultText(item, this.progress.outputTextByItem),
|
|
1440
|
+
isError: isNonSuccessItemStatus(itemStatus(item)),
|
|
1441
|
+
details,
|
|
1442
|
+
...item.type === "webSearch" ? { resultContentSource: "network" } : {}
|
|
1443
|
+
});
|
|
1444
|
+
}
|
|
1445
|
+
recordRawNativeToolItem(item) {
|
|
1446
|
+
const type = typeof item.type === "string" ? item.type : void 0;
|
|
1447
|
+
const callId = typeof item.call_id === "string" ? item.call_id : typeof item.callId === "string" ? item.callId : void 0;
|
|
1448
|
+
if (!callId) return;
|
|
1449
|
+
if ((type === "custom_tool_call" || type === "function_call") && (item.name === "apply_patch" || item.name === "exec_command" || item.name === "exec")) {
|
|
1450
|
+
let args;
|
|
1451
|
+
if (type === "custom_tool_call" && item.name === "apply_patch" && typeof item.input === "string") args = { input: item.input };
|
|
1452
|
+
else if (type === "custom_tool_call" && item.name === "exec") {
|
|
1453
|
+
const input = readCodeModeNativePatchInput(item.input);
|
|
1454
|
+
if (input) this.codeModeNativePatchInputsByCallId.set(callId, input);
|
|
1455
|
+
return;
|
|
1456
|
+
} else if (type === "function_call" && typeof item.arguments === "string") try {
|
|
1457
|
+
const parsed = JSON.parse(item.arguments);
|
|
1458
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
1459
|
+
const parsedArguments = parsed;
|
|
1460
|
+
if (item.name === "apply_patch") args = parsedArguments;
|
|
1461
|
+
else {
|
|
1462
|
+
const patch = readInterceptedNativePatchInput(typeof parsedArguments.cmd === "string" ? parsedArguments.cmd : typeof parsedArguments.command === "string" ? parsedArguments.command : void 0);
|
|
1463
|
+
if (patch) {
|
|
1464
|
+
const workdir = typeof parsedArguments.workdir === "string" ? parsedArguments.workdir : typeof parsedArguments.cwd === "string" ? parsedArguments.cwd : void 0;
|
|
1465
|
+
const cwd = patch.cwd ? workdir && !path.isAbsolute(patch.cwd) ? path.join(workdir, patch.cwd) : patch.cwd : workdir;
|
|
1466
|
+
args = {
|
|
1467
|
+
input: patch.input,
|
|
1468
|
+
...cwd ? { cwd } : {}
|
|
1469
|
+
};
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
} catch {
|
|
1474
|
+
return;
|
|
1475
|
+
}
|
|
1476
|
+
if (args) this.recordToolCall({
|
|
1477
|
+
id: callId,
|
|
1478
|
+
name: "apply_patch",
|
|
1479
|
+
arguments: args
|
|
1480
|
+
});
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1483
|
+
if (type !== "custom_tool_call_output" && type !== "function_call_output" || this.namesById.get(callId) !== "apply_patch" && !this.codeModeNativePatchInputsByCallId.has(callId)) return;
|
|
1484
|
+
const text = typeof item.output === "string" ? item.output : Array.isArray(item.output) ? collectDynamicToolContentText(item.output) : "";
|
|
1485
|
+
if (!text.trim()) return;
|
|
1486
|
+
const codeModePatchInput = this.codeModeNativePatchInputsByCallId.get(callId);
|
|
1487
|
+
if (codeModePatchInput) {
|
|
1488
|
+
this.codeModeNativePatchInputsByCallId.delete(callId);
|
|
1489
|
+
const execution = CODE_MODE_NATIVE_PATCH_RESULT_RE.exec(text);
|
|
1490
|
+
if (execution?.[1]?.toLowerCase() === "completed" && execution[2]?.trim() === "{}") return;
|
|
1491
|
+
if (execution?.[1]?.toLowerCase() === "failed") {
|
|
1492
|
+
const failure = execution[2]?.replace(/^Script error:\s*/iu, "").trim() || text;
|
|
1493
|
+
this.recordToolCall({
|
|
1494
|
+
id: callId,
|
|
1495
|
+
name: "apply_patch",
|
|
1496
|
+
arguments: { input: codeModePatchInput }
|
|
1497
|
+
});
|
|
1498
|
+
this.recordToolResult({
|
|
1499
|
+
id: callId,
|
|
1500
|
+
name: "apply_patch",
|
|
1501
|
+
text: failure,
|
|
1502
|
+
isError: true
|
|
1503
|
+
});
|
|
1504
|
+
}
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
this.rawNativeToolOutputByCallId.set(callId, text);
|
|
1508
|
+
const result = this.messages.find((message) => message.role === "toolResult" && message.toolCallId === callId);
|
|
1509
|
+
if (!result) {
|
|
1510
|
+
if (NATIVE_PATCH_REJECTION_RE.test(text)) this.recordToolResult({
|
|
1511
|
+
id: callId,
|
|
1512
|
+
name: "apply_patch",
|
|
1513
|
+
text,
|
|
1514
|
+
isError: true
|
|
1515
|
+
});
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1518
|
+
result.content = this.createToolResultMessage({
|
|
1519
|
+
id: callId,
|
|
1520
|
+
name: "apply_patch",
|
|
1521
|
+
text,
|
|
1522
|
+
isError: result.isError === true
|
|
1523
|
+
}).content;
|
|
1524
|
+
}
|
|
1525
|
+
async recordNativeToolResultWithDetails(item) {
|
|
1526
|
+
this.recordNativeToolResult(item, await this.prepareNativeMcpAppResultDetails(item));
|
|
1527
|
+
}
|
|
1528
|
+
async prepareNativeMcpAppResultDetails(item) {
|
|
1529
|
+
if (!item || item.type !== "mcpToolCall" || itemStatus(item) === "running") return;
|
|
1530
|
+
if (this.nativeMcpAppResultDetails.has(item.id)) return this.nativeMcpAppResultDetails.get(item.id);
|
|
1531
|
+
if (this.nativeMcpAppResultDetailsAttempted.has(item.id) || !this.options.prepareNativeMcpAppResultDetails) return;
|
|
1532
|
+
this.nativeMcpAppResultDetailsAttempted.add(item.id);
|
|
1533
|
+
try {
|
|
1534
|
+
const details = await this.options.prepareNativeMcpAppResultDetails(item);
|
|
1535
|
+
if (details !== void 0) this.nativeMcpAppResultDetails.set(item.id, details);
|
|
1536
|
+
return details;
|
|
1537
|
+
} catch (error) {
|
|
1538
|
+
embeddedAgentLog.debug("codex native MCP App preview preparation failed", {
|
|
1539
|
+
itemId: item.id,
|
|
1540
|
+
error
|
|
1541
|
+
});
|
|
1542
|
+
return;
|
|
1543
|
+
}
|
|
1396
1544
|
}
|
|
1397
1545
|
recordTrajectoryEvent(params) {
|
|
1398
1546
|
if (params.phase === "start") {
|
|
@@ -1489,10 +1637,11 @@ var CodexToolTranscriptProjection = class {
|
|
|
1489
1637
|
output: text
|
|
1490
1638
|
});
|
|
1491
1639
|
}
|
|
1492
|
-
if (
|
|
1640
|
+
if (params.terminalDisposition === "tool_error") {
|
|
1493
1641
|
this.recordMissingToolError(missingTranscriptIds, missingTrajectoryIds);
|
|
1494
1642
|
return;
|
|
1495
1643
|
}
|
|
1644
|
+
if (params.terminalDisposition === "diagnostic_only") return;
|
|
1496
1645
|
const missingCount = (/* @__PURE__ */ new Set([...missingTranscriptIds, ...missingTrajectoryIds])).size;
|
|
1497
1646
|
return missingCount === 1 ? MISSING_TOOL_RESULT_ERROR : `${MISSING_TOOL_RESULT_ERROR} missingToolResultCount=${missingCount}`;
|
|
1498
1647
|
}
|
|
@@ -1578,6 +1727,8 @@ var CodexToolTranscriptProjection = class {
|
|
|
1578
1727
|
content: text,
|
|
1579
1728
|
text
|
|
1580
1729
|
}],
|
|
1730
|
+
...params.details !== void 0 ? { details: params.details } : {},
|
|
1731
|
+
...params.resultContentSource ? { __openclaw: { resultContentSource: params.resultContentSource } } : {},
|
|
1581
1732
|
timestamp: this.nextTranscriptTimestamp()
|
|
1582
1733
|
};
|
|
1583
1734
|
}
|
|
@@ -1616,14 +1767,14 @@ var CodexEventProjection = class {
|
|
|
1616
1767
|
data: {
|
|
1617
1768
|
method,
|
|
1618
1769
|
phase: method.endsWith("/started") ? "started" : "completed",
|
|
1619
|
-
reviewId: readString$
|
|
1770
|
+
reviewId: readString$6(params, "reviewId"),
|
|
1620
1771
|
targetItemId: readNullableString$1(params, "targetItemId"),
|
|
1621
|
-
decisionSource: readString$
|
|
1622
|
-
status: review ? readString$
|
|
1623
|
-
riskLevel: review ? readString$
|
|
1624
|
-
userAuthorization: review ? readString$
|
|
1772
|
+
decisionSource: readString$6(params, "decisionSource"),
|
|
1773
|
+
status: review ? readString$6(review, "status") : void 0,
|
|
1774
|
+
riskLevel: review ? readString$6(review, "riskLevel") : void 0,
|
|
1775
|
+
userAuthorization: review ? readString$6(review, "userAuthorization") : void 0,
|
|
1625
1776
|
rationale: review ? readNullableString$1(review, "rationale") : void 0,
|
|
1626
|
-
actionType: action ? readString$
|
|
1777
|
+
actionType: action ? readString$6(action, "type") : void 0
|
|
1627
1778
|
}
|
|
1628
1779
|
});
|
|
1629
1780
|
}
|
|
@@ -1632,7 +1783,7 @@ var CodexEventProjection = class {
|
|
|
1632
1783
|
stream: "codex_app_server.guardian",
|
|
1633
1784
|
data: {
|
|
1634
1785
|
phase: "warning",
|
|
1635
|
-
message: readString$
|
|
1786
|
+
message: readString$6(params, "message")
|
|
1636
1787
|
}
|
|
1637
1788
|
});
|
|
1638
1789
|
}
|
|
@@ -1648,14 +1799,14 @@ var CodexEventProjection = class {
|
|
|
1648
1799
|
phase: method === "hook/started" ? "started" : "completed",
|
|
1649
1800
|
threadId: this.threadId,
|
|
1650
1801
|
turnId: hookTurnId === void 0 ? this.turnId : hookTurnId,
|
|
1651
|
-
hookRunId: readString$
|
|
1652
|
-
eventName: readString$
|
|
1653
|
-
handlerType: readString$
|
|
1654
|
-
executionMode: readString$
|
|
1655
|
-
scope: readString$
|
|
1656
|
-
source: readString$
|
|
1657
|
-
sourcePath: readString$
|
|
1658
|
-
status: readString$
|
|
1802
|
+
hookRunId: readString$6(run, "id"),
|
|
1803
|
+
eventName: readString$6(run, "eventName"),
|
|
1804
|
+
handlerType: readString$6(run, "handlerType"),
|
|
1805
|
+
executionMode: readString$6(run, "executionMode"),
|
|
1806
|
+
scope: readString$6(run, "scope"),
|
|
1807
|
+
source: readString$6(run, "source"),
|
|
1808
|
+
sourcePath: readString$6(run, "sourcePath"),
|
|
1809
|
+
status: readString$6(run, "status"),
|
|
1659
1810
|
statusMessage: readNullableString$1(run, "statusMessage"),
|
|
1660
1811
|
...durationMs !== void 0 ? { durationMs } : {},
|
|
1661
1812
|
...entries.length > 0 ? { entries } : {}
|
|
@@ -1736,59 +1887,128 @@ var CodexEventProjection = class {
|
|
|
1736
1887
|
//#endregion
|
|
1737
1888
|
//#region extensions/codex/src/app-server/event-projector-media.ts
|
|
1738
1889
|
const GENERATED_IMAGE_MEDIA_SUBDIR = "tool-image-generation";
|
|
1739
|
-
const BYTES_PER_MB = 1024 * 1024;
|
|
1740
|
-
const DEFAULT_GENERATED_IMAGE_MAX_BYTES = 6 * BYTES_PER_MB;
|
|
1741
1890
|
var CodexGeneratedMediaProjection = class {
|
|
1742
|
-
constructor(config) {
|
|
1891
|
+
constructor(config, remote) {
|
|
1743
1892
|
this.config = config;
|
|
1893
|
+
this.remote = remote;
|
|
1744
1894
|
this.itemIds = /* @__PURE__ */ new Set();
|
|
1745
1895
|
this.urlsByItemId = /* @__PURE__ */ new Map();
|
|
1896
|
+
this.gatewayMaterializedItemIds = /* @__PURE__ */ new Set();
|
|
1897
|
+
this.pendingMaterializationsByItemId = /* @__PURE__ */ new Map();
|
|
1746
1898
|
}
|
|
1747
1899
|
hasGeneratedMedia() {
|
|
1748
1900
|
return this.itemIds.size > 0;
|
|
1749
1901
|
}
|
|
1750
|
-
recordNative(item) {
|
|
1902
|
+
async recordNative(item) {
|
|
1751
1903
|
if (item?.type !== "imageGeneration") return;
|
|
1904
|
+
this.itemIds.add(item.id);
|
|
1905
|
+
const result = readItemString(item, "result");
|
|
1906
|
+
if (result) {
|
|
1907
|
+
await this.recordImage({
|
|
1908
|
+
itemId: item.id,
|
|
1909
|
+
result,
|
|
1910
|
+
revisedPrompt: readItemString(item, "revisedPrompt"),
|
|
1911
|
+
source: "native"
|
|
1912
|
+
});
|
|
1913
|
+
return;
|
|
1914
|
+
}
|
|
1752
1915
|
const savedPath = readItemString(item, "savedPath")?.trim();
|
|
1753
|
-
if (savedPath)
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1916
|
+
if (savedPath) {
|
|
1917
|
+
if (this.remote?.remoteWorkspaceRoot) {
|
|
1918
|
+
if (!this.remote.readFile) {
|
|
1919
|
+
embeddedAgentLog.warn("codex remote image has no app-server file transfer", { itemId: item.id });
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
1922
|
+
try {
|
|
1923
|
+
const response = await this.remote.readFile({
|
|
1924
|
+
path: savedPath,
|
|
1925
|
+
maxBytes: resolveGeneratedMediaMaxBytes(this.config, "image"),
|
|
1926
|
+
signal: this.remote.signal,
|
|
1927
|
+
timeoutMs: this.remote.requestTimeoutMs
|
|
1928
|
+
});
|
|
1929
|
+
if (!response || typeof response.dataBase64 !== "string" || !response.dataBase64) {
|
|
1930
|
+
embeddedAgentLog.warn("codex remote image file returned no inline bytes", { itemId: item.id });
|
|
1931
|
+
return;
|
|
1932
|
+
}
|
|
1933
|
+
await this.recordImage({
|
|
1934
|
+
itemId: item.id,
|
|
1935
|
+
result: response.dataBase64,
|
|
1936
|
+
revisedPrompt: readItemString(item, "revisedPrompt"),
|
|
1937
|
+
source: "native"
|
|
1938
|
+
});
|
|
1939
|
+
} catch (error) {
|
|
1940
|
+
embeddedAgentLog.warn("codex app-server remote image file read failed", {
|
|
1941
|
+
itemId: item.id,
|
|
1942
|
+
error
|
|
1943
|
+
});
|
|
1944
|
+
}
|
|
1945
|
+
return;
|
|
1946
|
+
}
|
|
1947
|
+
this.recordUrl({
|
|
1948
|
+
itemId: item.id,
|
|
1949
|
+
mediaUrl: savedPath
|
|
1950
|
+
});
|
|
1951
|
+
}
|
|
1757
1952
|
}
|
|
1758
1953
|
async recordRaw(item) {
|
|
1759
|
-
if (readString$
|
|
1760
|
-
const result = readString$
|
|
1954
|
+
if (readString$6(item, "type") !== "image_generation_call") return;
|
|
1955
|
+
const result = readString$6(item, "result");
|
|
1761
1956
|
if (!result) return;
|
|
1762
|
-
const itemId = readString$
|
|
1763
|
-
this.
|
|
1764
|
-
|
|
1765
|
-
|
|
1957
|
+
const itemId = readString$6(item, "id") ?? `raw-image-${this.itemIds.size}`;
|
|
1958
|
+
await this.recordImage({
|
|
1959
|
+
itemId,
|
|
1960
|
+
result,
|
|
1961
|
+
revisedPrompt: readString$6(item, "revised_prompt") ?? readString$6(item, "revisedPrompt"),
|
|
1962
|
+
source: "raw"
|
|
1963
|
+
});
|
|
1964
|
+
}
|
|
1965
|
+
async recordImage(params) {
|
|
1966
|
+
this.itemIds.add(params.itemId);
|
|
1967
|
+
if (this.gatewayMaterializedItemIds.has(params.itemId)) return;
|
|
1968
|
+
let pending = this.pendingMaterializationsByItemId.get(params.itemId);
|
|
1969
|
+
while (pending) {
|
|
1970
|
+
await pending;
|
|
1971
|
+
if (this.gatewayMaterializedItemIds.has(params.itemId)) return;
|
|
1972
|
+
pending = this.pendingMaterializationsByItemId.get(params.itemId);
|
|
1973
|
+
}
|
|
1974
|
+
const materialization = this.materializeImage(params);
|
|
1975
|
+
this.pendingMaterializationsByItemId.set(params.itemId, materialization);
|
|
1976
|
+
try {
|
|
1977
|
+
await materialization;
|
|
1978
|
+
} finally {
|
|
1979
|
+
if (this.pendingMaterializationsByItemId.get(params.itemId) === materialization) this.pendingMaterializationsByItemId.delete(params.itemId);
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
async materializeImage(params) {
|
|
1983
|
+
const maxBytes = resolveGeneratedMediaMaxBytes(this.config, "image");
|
|
1984
|
+
const estimatedDecodedBytes = estimateBase64DecodedBytes(params.result);
|
|
1766
1985
|
if (estimatedDecodedBytes !== void 0 && estimatedDecodedBytes > maxBytes) {
|
|
1767
|
-
embeddedAgentLog.warn(
|
|
1768
|
-
itemId,
|
|
1986
|
+
embeddedAgentLog.warn(`codex app-server ${params.source} image generation result exceeds media limit`, {
|
|
1987
|
+
itemId: params.itemId,
|
|
1769
1988
|
estimatedDecodedBytes,
|
|
1770
1989
|
maxBytes
|
|
1771
1990
|
});
|
|
1772
1991
|
return;
|
|
1773
1992
|
}
|
|
1774
1993
|
const asset = generatedImageAssetFromBase64({
|
|
1775
|
-
base64: result,
|
|
1994
|
+
base64: params.result,
|
|
1776
1995
|
index: this.itemIds.size,
|
|
1777
|
-
revisedPrompt:
|
|
1996
|
+
revisedPrompt: params.revisedPrompt,
|
|
1778
1997
|
fileNamePrefix: "codex-image-generation",
|
|
1779
1998
|
sniffMimeType: true
|
|
1780
1999
|
});
|
|
1781
2000
|
if (!asset) return;
|
|
1782
2001
|
try {
|
|
1783
2002
|
const saved = await saveMediaBuffer(asset.buffer, asset.mimeType, GENERATED_IMAGE_MEDIA_SUBDIR, maxBytes, asset.fileName);
|
|
2003
|
+
this.gatewayMaterializedItemIds.add(params.itemId);
|
|
1784
2004
|
this.recordUrl({
|
|
1785
|
-
itemId,
|
|
2005
|
+
itemId: params.itemId,
|
|
1786
2006
|
mediaUrl: saved.path,
|
|
1787
2007
|
replaceExisting: true
|
|
1788
2008
|
});
|
|
1789
2009
|
} catch (error) {
|
|
1790
|
-
embeddedAgentLog.warn(
|
|
1791
|
-
itemId,
|
|
2010
|
+
embeddedAgentLog.warn(`codex app-server ${params.source} image generation result save failed`, {
|
|
2011
|
+
itemId: params.itemId,
|
|
1792
2012
|
error
|
|
1793
2013
|
});
|
|
1794
2014
|
}
|
|
@@ -1831,11 +2051,6 @@ function estimateBase64DecodedBytes(base64) {
|
|
|
1831
2051
|
function isBase64WhitespaceCode(code) {
|
|
1832
2052
|
return code === 32 || code === 9 || code === 10 || code === 13;
|
|
1833
2053
|
}
|
|
1834
|
-
function resolveGeneratedImageMaxBytes(config) {
|
|
1835
|
-
const configured = config?.agents?.defaults?.mediaMaxMb;
|
|
1836
|
-
if (typeof configured === "number" && Number.isFinite(configured) && configured > 0) return Math.floor(configured * BYTES_PER_MB);
|
|
1837
|
-
return DEFAULT_GENERATED_IMAGE_MAX_BYTES;
|
|
1838
|
-
}
|
|
1839
2054
|
//#endregion
|
|
1840
2055
|
//#region extensions/codex/src/app-server/event-projector-reasoning.ts
|
|
1841
2056
|
var CodexReasoningProjection = class {
|
|
@@ -1849,8 +2064,8 @@ var CodexReasoningProjection = class {
|
|
|
1849
2064
|
this.reasoningEnded = false;
|
|
1850
2065
|
}
|
|
1851
2066
|
async handleReasoningDelta(method, params) {
|
|
1852
|
-
const itemId = readString$
|
|
1853
|
-
const delta = readString$
|
|
2067
|
+
const itemId = readString$6(params, "itemId") ?? "reasoning";
|
|
2068
|
+
const delta = readString$6(params, "delta") ?? "";
|
|
1854
2069
|
if (!delta) return;
|
|
1855
2070
|
this.reasoningStarted = true;
|
|
1856
2071
|
if (!this.reasoningItemOrder.has(itemId)) this.reasoningItemOrder.set(itemId, this.reasoningItemOrder.size);
|
|
@@ -1869,8 +2084,8 @@ var CodexReasoningProjection = class {
|
|
|
1869
2084
|
});
|
|
1870
2085
|
}
|
|
1871
2086
|
handlePlanDelta(params) {
|
|
1872
|
-
const itemId = readString$
|
|
1873
|
-
const delta = readString$
|
|
2087
|
+
const itemId = readString$6(params, "itemId") ?? "plan";
|
|
2088
|
+
const delta = readString$6(params, "delta") ?? "";
|
|
1874
2089
|
if (!delta) return;
|
|
1875
2090
|
const text = `${this.planTextByItem.get(itemId) ?? ""}${delta}`;
|
|
1876
2091
|
this.planTextByItem.set(itemId, text);
|
|
@@ -1887,11 +2102,11 @@ var CodexReasoningProjection = class {
|
|
|
1887
2102
|
const plan = Array.isArray(params.plan) ? params.plan.flatMap((entry) => {
|
|
1888
2103
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return [];
|
|
1889
2104
|
const record = entry;
|
|
1890
|
-
const step = readString$
|
|
2105
|
+
const step = readString$6(record, "step");
|
|
1891
2106
|
if (!step) return [];
|
|
1892
2107
|
return [{
|
|
1893
2108
|
step,
|
|
1894
|
-
status: normalizePlanStepStatus(readString$
|
|
2109
|
+
status: normalizePlanStepStatus(readString$6(record, "status"))
|
|
1895
2110
|
}];
|
|
1896
2111
|
}) : void 0;
|
|
1897
2112
|
const planText = [explanation, ...(plan ?? []).map(({ step, status }) => `- [${status}] ${step}`)].filter((part) => Boolean(part)).join("\n");
|
|
@@ -1955,6 +2170,28 @@ function reasoningMethodOrder(method) {
|
|
|
1955
2170
|
}
|
|
1956
2171
|
//#endregion
|
|
1957
2172
|
//#region extensions/codex/src/app-server/event-projector-snapshot.ts
|
|
2173
|
+
function readTurnTaintMetadata(message) {
|
|
2174
|
+
const metadata = message["__openclaw"];
|
|
2175
|
+
return metadata && typeof metadata === "object" && !Array.isArray(metadata) ? metadata : void 0;
|
|
2176
|
+
}
|
|
2177
|
+
function applyStickyTurnTaint(messages) {
|
|
2178
|
+
let tainted = false;
|
|
2179
|
+
return messages.map((message) => {
|
|
2180
|
+
if (message.role === "user") {
|
|
2181
|
+
tainted = false;
|
|
2182
|
+
return message;
|
|
2183
|
+
}
|
|
2184
|
+
const metadata = readTurnTaintMetadata(message);
|
|
2185
|
+
tainted ||= metadata?.turnTainted === true || metadata?.resultContentSource === "network";
|
|
2186
|
+
return message.role === "assistant" && tainted ? {
|
|
2187
|
+
...message,
|
|
2188
|
+
__openclaw: {
|
|
2189
|
+
...metadata,
|
|
2190
|
+
turnTainted: true
|
|
2191
|
+
}
|
|
2192
|
+
} : message;
|
|
2193
|
+
});
|
|
2194
|
+
}
|
|
1958
2195
|
function buildCodexMessagesSnapshot(params) {
|
|
1959
2196
|
const messages = promptSnapshot(params.runParams, params.turnId, params.upstreamUserText);
|
|
1960
2197
|
if (params.reasoningText) messages.push(attachCodexMirrorIdentity(params.createAssistantMirrorMessage("Codex reasoning", params.reasoningText), `${params.turnId}:reasoning`));
|
|
@@ -1962,7 +2199,7 @@ function buildCodexMessagesSnapshot(params) {
|
|
|
1962
2199
|
const visibleWorkMessages = [...params.runParams.config?.ui?.prefs?.chatPersistCommentary === false ? [] : params.commentaryMessages.map(({ itemId, message }) => attachCodexMirrorIdentity(message, `${params.turnId}:commentary:${itemId}`)), ...params.toolMessages].toSorted((left, right) => (asDateTimestampMs(left.timestamp) ?? 0) - (asDateTimestampMs(right.timestamp) ?? 0));
|
|
1963
2200
|
messages.push(...visibleWorkMessages);
|
|
1964
2201
|
if (params.lastAssistant) messages.push(attachCodexMirrorIdentity(params.lastAssistant, `${params.turnId}:assistant`));
|
|
1965
|
-
return messages.map((message) => projectAgentHarnessTranscriptMessageForDisplay({
|
|
2202
|
+
return applyStickyTurnTaint(messages).map((message) => projectAgentHarnessTranscriptMessageForDisplay({
|
|
1966
2203
|
hidden: params.runParams.trigger === "memory",
|
|
1967
2204
|
message
|
|
1968
2205
|
}));
|
|
@@ -2086,7 +2323,7 @@ function readCodexErrorNotification(notification) {
|
|
|
2086
2323
|
if (notification?.method !== "error" || !isJsonObject(notification.params)) return;
|
|
2087
2324
|
const error = notification.params.error;
|
|
2088
2325
|
return isJsonObject(error) ? {
|
|
2089
|
-
message: readString$
|
|
2326
|
+
message: readString$5(error, "message"),
|
|
2090
2327
|
codexErrorInfo: error.codexErrorInfo
|
|
2091
2328
|
} : void 0;
|
|
2092
2329
|
}
|
|
@@ -2098,12 +2335,12 @@ function readCodexErrorPayload(error) {
|
|
|
2098
2335
|
const nestedError = isJsonObject(data.error) ? data.error : data;
|
|
2099
2336
|
const rateLimits = nestedError.rateLimits ?? data.rateLimits;
|
|
2100
2337
|
return {
|
|
2101
|
-
message: readString$
|
|
2338
|
+
message: readString$5(nestedError, "message") ?? message,
|
|
2102
2339
|
codexErrorInfo: nestedError.codexErrorInfo,
|
|
2103
2340
|
rateLimits
|
|
2104
2341
|
};
|
|
2105
2342
|
}
|
|
2106
|
-
function readString$
|
|
2343
|
+
function readString$5(record, key) {
|
|
2107
2344
|
const value = record[key];
|
|
2108
2345
|
return typeof value === "string" ? value : void 0;
|
|
2109
2346
|
}
|
|
@@ -2123,14 +2360,21 @@ var CodexAppServerEventProjector = class {
|
|
|
2123
2360
|
this.promptErrorSource = null;
|
|
2124
2361
|
this.synthesizedMissingToolResultError = null;
|
|
2125
2362
|
this.aborted = false;
|
|
2363
|
+
this.responseCompletions = new CodexResponseCompletionProjection();
|
|
2126
2364
|
this.completedCompactionCount = 0;
|
|
2127
2365
|
this.lastTranscriptTimestamp = 0;
|
|
2128
2366
|
this.diagnostics = new CodexProjectionDiagnostics(threadId, turnId);
|
|
2129
2367
|
this.nativeToolLifecycleProjector = new CodexNativeToolLifecycleProjector(params, threadId, turnId, { runAbortSignal: options.runAbortSignal });
|
|
2130
|
-
this.generatedMediaProjection = new CodexGeneratedMediaProjection(params.config
|
|
2368
|
+
this.generatedMediaProjection = new CodexGeneratedMediaProjection(params.config, {
|
|
2369
|
+
remoteWorkspaceRoot: options.remoteWorkspaceRoot,
|
|
2370
|
+
readFile: options.readRemoteWorkspaceFile,
|
|
2371
|
+
requestTimeoutMs: options.remoteWorkspaceRequestTimeoutMs,
|
|
2372
|
+
signal: options.runAbortSignal
|
|
2373
|
+
});
|
|
2131
2374
|
this.toolProgressProjection = new CodexToolProgressProjection(params);
|
|
2132
2375
|
this.toolTranscriptProjection = new CodexToolTranscriptProjection(params, threadId, turnId, this.toolProgressProjection, () => this.nextTranscriptTimestamp(), {
|
|
2133
2376
|
nativePostToolUseRelayEnabled: options.nativePostToolUseRelayEnabled,
|
|
2377
|
+
prepareNativeMcpAppResultDetails: options.prepareNativeMcpAppResultDetails,
|
|
2134
2378
|
trajectoryRecorder: options.trajectoryRecorder
|
|
2135
2379
|
});
|
|
2136
2380
|
this.eventProjection = new CodexEventProjection(threadId, turnId, (event) => this.emitAgentEvent(event), this.toolProgressProjection, this.toolTranscriptProjection, options.onNativeToolResultRecorded);
|
|
@@ -2229,13 +2473,13 @@ var CodexAppServerEventProjector = class {
|
|
|
2229
2473
|
await this.handleTurnCompleted(params);
|
|
2230
2474
|
break;
|
|
2231
2475
|
case "rawResponse/completed":
|
|
2232
|
-
this.
|
|
2476
|
+
this.responseCompletions.record(params);
|
|
2233
2477
|
break;
|
|
2234
2478
|
case "rawResponseItem/completed":
|
|
2235
2479
|
await this.handleRawResponseItemCompleted(params);
|
|
2236
2480
|
break;
|
|
2237
2481
|
case "error":
|
|
2238
|
-
this.
|
|
2482
|
+
this.responseCompletions.clear();
|
|
2239
2483
|
if (params.willRetry === true) break;
|
|
2240
2484
|
this.promptError = this.formatCodexErrorMessage(params) ?? "codex app-server error";
|
|
2241
2485
|
this.promptErrorSource = "prompt";
|
|
@@ -2263,13 +2507,14 @@ var CodexAppServerEventProjector = class {
|
|
|
2263
2507
|
const commentaryMessages = this.assistantProjection.collectCommentaryMessages();
|
|
2264
2508
|
const reasoningText = this.reasoningProjection.reasoningText();
|
|
2265
2509
|
const planText = this.reasoningProjection.planText();
|
|
2266
|
-
const
|
|
2510
|
+
const completedUsage = this.responseCompletions.usage ?? this.tokenUsage;
|
|
2511
|
+
const projectedUsage = this.aborted ? this.tokenUsage : completedUsage;
|
|
2267
2512
|
const hasAssistantItemText = this.assistantProjection.hasAssistantItemTextForSynthesis();
|
|
2268
2513
|
const legacyFailClosed = !this.completedTurn || this.completedTurn.status !== "completed" || hasAssistantItemText;
|
|
2269
2514
|
const hasDeliverableAssistantOnCompletedTurn = this.completedTurn?.status === "completed" && assistantTexts.some((text) => text.trim().length > 0);
|
|
2270
2515
|
const synthesizedMissingToolResultError = this.toolTranscriptProjection.synthesizeMissingToolResults({
|
|
2271
2516
|
synthesize: legacyFailClosed,
|
|
2272
|
-
|
|
2517
|
+
terminalDisposition: this.aborted ? "tool_error" : hasDeliverableAssistantOnCompletedTurn ? "diagnostic_only" : "prompt_error"
|
|
2273
2518
|
});
|
|
2274
2519
|
if (synthesizedMissingToolResultError) {
|
|
2275
2520
|
this.synthesizedMissingToolResultError = synthesizedMissingToolResultError;
|
|
@@ -2305,18 +2550,16 @@ var CodexAppServerEventProjector = class {
|
|
|
2305
2550
|
const toolMetas = this.toolProgressProjection.toolMetas;
|
|
2306
2551
|
const hadPotentialSideEffects = toolTelemetry.didSendViaMessagingTool || (toolTelemetry.successfulCronAdds ?? 0) > 0 || this.generatedMediaProjection.hasGeneratedMedia() || this.toolProgressProjection.hasPotentialSideEffects;
|
|
2307
2552
|
return {
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
timedOutDuringToolExecution: false,
|
|
2314
|
-
promptError,
|
|
2315
|
-
promptErrorSource: promptError ? this.promptErrorSource || "prompt" : null,
|
|
2553
|
+
terminal: attemptTerminal.normalize({
|
|
2554
|
+
aborted: this.aborted,
|
|
2555
|
+
promptError,
|
|
2556
|
+
promptErrorSource: promptError ? this.promptErrorSource || "prompt" : null
|
|
2557
|
+
}),
|
|
2316
2558
|
sessionIdUsed: this.params.sessionId,
|
|
2317
2559
|
...agentHarnessResultClassification ? { agentHarnessResultClassification } : {},
|
|
2318
2560
|
bootstrapPromptWarningSignaturesSeen: this.params.bootstrapPromptWarningSignaturesSeen,
|
|
2319
2561
|
bootstrapPromptWarningSignature: this.params.bootstrapPromptWarningSignature,
|
|
2562
|
+
...this.responseCompletions.modelIterations > 0 ? { modelIterations: this.responseCompletions.modelIterations } : {},
|
|
2320
2563
|
messagesSnapshot,
|
|
2321
2564
|
assistantTexts,
|
|
2322
2565
|
toolMetas,
|
|
@@ -2355,7 +2598,8 @@ var CodexAppServerEventProjector = class {
|
|
|
2355
2598
|
}
|
|
2356
2599
|
recordDynamicToolResult(params) {
|
|
2357
2600
|
this.toolProgressProjection.recordDynamicToolResult(params);
|
|
2358
|
-
this.
|
|
2601
|
+
const source = this.options.resolveDynamicToolResultContentSource?.(params.tool);
|
|
2602
|
+
this.toolTranscriptProjection.recordDynamicToolResult(params, source);
|
|
2359
2603
|
}
|
|
2360
2604
|
markTimedOut() {
|
|
2361
2605
|
this.aborted = true;
|
|
@@ -2364,14 +2608,14 @@ var CodexAppServerEventProjector = class {
|
|
|
2364
2608
|
}
|
|
2365
2609
|
markAborted() {
|
|
2366
2610
|
this.aborted = true;
|
|
2367
|
-
this.
|
|
2611
|
+
this.responseCompletions.clear();
|
|
2368
2612
|
}
|
|
2369
2613
|
isCompacting() {
|
|
2370
2614
|
return this.activeCompactionItemIds.size > 0;
|
|
2371
2615
|
}
|
|
2372
2616
|
async handleItemStarted(params) {
|
|
2373
2617
|
const item = readItem(params.item);
|
|
2374
|
-
const itemId = item?.id ?? readString$
|
|
2618
|
+
const itemId = item?.id ?? readString$6(params, "itemId");
|
|
2375
2619
|
this.assistantProjection.recordItemStarted(item, itemId);
|
|
2376
2620
|
if (itemId) this.activeItemIds.add(itemId);
|
|
2377
2621
|
this.recordNativeToolOutcome(item);
|
|
@@ -2427,14 +2671,14 @@ var CodexAppServerEventProjector = class {
|
|
|
2427
2671
|
this.diagnostics.warnUnknownItemStatus(item);
|
|
2428
2672
|
this.recordNativeToolOutcome(item);
|
|
2429
2673
|
this.clearTerminalPresentationForNativeItem(item);
|
|
2430
|
-
const itemId = item?.id ?? readString$
|
|
2674
|
+
const itemId = item?.id ?? readString$6(params, "itemId");
|
|
2431
2675
|
if (itemId) {
|
|
2432
2676
|
this.activeItemIds.delete(itemId);
|
|
2433
2677
|
this.completedItemIds.add(itemId);
|
|
2434
2678
|
}
|
|
2435
2679
|
this.assistantProjection.recordItemCompleted(item, itemId, this.activeItemIds);
|
|
2436
2680
|
this.reasoningProjection.recordItem(item);
|
|
2437
|
-
this.generatedMediaProjection.recordNative(item);
|
|
2681
|
+
await this.generatedMediaProjection.recordNative(item);
|
|
2438
2682
|
if (item?.type === "contextCompaction" && itemId) {
|
|
2439
2683
|
this.activeCompactionItemIds.delete(itemId);
|
|
2440
2684
|
this.completedCompactionCount += 1;
|
|
@@ -2477,7 +2721,7 @@ var CodexAppServerEventProjector = class {
|
|
|
2477
2721
|
item
|
|
2478
2722
|
});
|
|
2479
2723
|
this.toolTranscriptProjection.recordNativeToolCall(item);
|
|
2480
|
-
this.toolTranscriptProjection.
|
|
2724
|
+
await this.toolTranscriptProjection.recordNativeToolResultWithDetails(item);
|
|
2481
2725
|
this.toolProgressProjection.emitToolResultSummary(item);
|
|
2482
2726
|
this.toolProgressProjection.emitToolResultOutput(item);
|
|
2483
2727
|
this.emitAgentEvent({
|
|
@@ -2489,15 +2733,11 @@ var CodexAppServerEventProjector = class {
|
|
|
2489
2733
|
}
|
|
2490
2734
|
});
|
|
2491
2735
|
}
|
|
2492
|
-
handleRawResponseCompleted(params) {
|
|
2493
|
-
const usage = isJsonObject(params.usage) ? params.usage : void 0;
|
|
2494
|
-
this.responseUsage = usage ? normalizeCodexResponseTokenUsage(usage) : void 0;
|
|
2495
|
-
}
|
|
2496
2736
|
async handleTurnCompleted(params) {
|
|
2497
2737
|
const turn = readCodexTurn(params.turn);
|
|
2498
2738
|
if (!turn || turn.id !== this.turnId) return;
|
|
2499
2739
|
this.completedTurn = turn;
|
|
2500
|
-
if (turn.status !== "completed") this.
|
|
2740
|
+
if (turn.status !== "completed") this.responseCompletions.clear();
|
|
2501
2741
|
if (turn.status === "failed") {
|
|
2502
2742
|
const usageLimitMessage = formatCodexUsageLimitErrorMessage({
|
|
2503
2743
|
message: turn.error?.message,
|
|
@@ -2521,12 +2761,12 @@ var CodexAppServerEventProjector = class {
|
|
|
2521
2761
|
this.diagnostics.warnUnknownItemStatus(item);
|
|
2522
2762
|
this.assistantProjection.recordSnapshotItem(item);
|
|
2523
2763
|
this.reasoningProjection.recordItem(item);
|
|
2524
|
-
this.generatedMediaProjection.recordNative(item);
|
|
2764
|
+
await this.generatedMediaProjection.recordNative(item);
|
|
2525
2765
|
this.toolProgressProjection.recordToolMeta(item);
|
|
2526
2766
|
this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
|
|
2527
2767
|
await this.emitSnapshotOnlyNativeToolProgress(item);
|
|
2528
2768
|
this.toolTranscriptProjection.recordNativeToolCall(item);
|
|
2529
|
-
this.toolTranscriptProjection.
|
|
2769
|
+
await this.toolTranscriptProjection.recordNativeToolResultWithDetails(item);
|
|
2530
2770
|
this.toolTranscriptProjection.emitAfterToolCallObservation(item);
|
|
2531
2771
|
this.toolProgressProjection.emitToolResultSummary(item);
|
|
2532
2772
|
this.toolProgressProjection.emitToolResultOutput(item);
|
|
@@ -2565,6 +2805,7 @@ var CodexAppServerEventProjector = class {
|
|
|
2565
2805
|
async handleRawResponseItemCompleted(params) {
|
|
2566
2806
|
const item = isJsonObject(params.item) ? params.item : void 0;
|
|
2567
2807
|
if (!item) return;
|
|
2808
|
+
this.toolTranscriptProjection.recordRawNativeToolItem(item);
|
|
2568
2809
|
this.assistantProjection.handleRawResponseItemCompleted(item, this.activeItemIds);
|
|
2569
2810
|
await this.generatedMediaProjection.recordRaw(item);
|
|
2570
2811
|
}
|
|
@@ -2584,7 +2825,7 @@ var CodexAppServerEventProjector = class {
|
|
|
2584
2825
|
formatCodexErrorMessage(params) {
|
|
2585
2826
|
const error = isJsonObject(params.error) ? params.error : void 0;
|
|
2586
2827
|
const usageLimitMessage = formatCodexUsageLimitErrorMessage({
|
|
2587
|
-
message: error ? readString$
|
|
2828
|
+
message: error ? readString$6(error, "message") : void 0,
|
|
2588
2829
|
codexErrorInfo: error?.codexErrorInfo,
|
|
2589
2830
|
rateLimits: this.options.readRecentRateLimits?.()
|
|
2590
2831
|
});
|
|
@@ -2616,7 +2857,7 @@ var CodexAppServerEventProjector = class {
|
|
|
2616
2857
|
return threadId === this.threadId && turnId === this.turnId;
|
|
2617
2858
|
}
|
|
2618
2859
|
isHookNotificationForCurrentThread(params) {
|
|
2619
|
-
const threadId = readString$
|
|
2860
|
+
const threadId = readString$6(params, "threadId");
|
|
2620
2861
|
const turnId = params.turnId;
|
|
2621
2862
|
return threadId === this.threadId && (turnId === this.turnId || turnId === null);
|
|
2622
2863
|
}
|
|
@@ -2625,6 +2866,128 @@ function isHookNotificationMethod(method) {
|
|
|
2625
2866
|
return method === "hook/started" || method === "hook/completed";
|
|
2626
2867
|
}
|
|
2627
2868
|
//#endregion
|
|
2869
|
+
//#region extensions/codex/src/app-server/native-mcp-app.ts
|
|
2870
|
+
function asRecord(value) {
|
|
2871
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
2872
|
+
}
|
|
2873
|
+
function readString$4(value) {
|
|
2874
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2875
|
+
}
|
|
2876
|
+
function readMcpAppResourceUri(item) {
|
|
2877
|
+
const uri = readString$4(asRecord(item.appContext)?.resourceUri) ?? readString$4(item.mcpAppResourceUri);
|
|
2878
|
+
return uri?.startsWith("ui://") ? uri : void 0;
|
|
2879
|
+
}
|
|
2880
|
+
function readMcpToolResult(item) {
|
|
2881
|
+
const result = asRecord(item.result);
|
|
2882
|
+
if (!result || !Array.isArray(result.content)) return;
|
|
2883
|
+
const resultMeta = asRecord(result["_meta"]);
|
|
2884
|
+
return {
|
|
2885
|
+
content: result.content,
|
|
2886
|
+
...result.structuredContent !== void 0 ? { structuredContent: result.structuredContent } : {},
|
|
2887
|
+
...result.isError === true ? { isError: true } : {},
|
|
2888
|
+
...resultMeta ? { _meta: resultMeta } : {}
|
|
2889
|
+
};
|
|
2890
|
+
}
|
|
2891
|
+
function statusTools(status) {
|
|
2892
|
+
return Object.entries(status.tools).map(([name, value]) => Object.assign({}, asRecord(value), { name }));
|
|
2893
|
+
}
|
|
2894
|
+
function createNativeMcpRuntime(params) {
|
|
2895
|
+
let catalog = null;
|
|
2896
|
+
let statuses;
|
|
2897
|
+
const createdAt = Date.now();
|
|
2898
|
+
const loadStatuses = async () => {
|
|
2899
|
+
if (statuses) return statuses;
|
|
2900
|
+
statuses = (await params.client.request("mcpServerStatus/list", {
|
|
2901
|
+
threadId: params.threadId,
|
|
2902
|
+
detail: "full"
|
|
2903
|
+
})).data;
|
|
2904
|
+
return statuses;
|
|
2905
|
+
};
|
|
2906
|
+
const getCatalog = async () => {
|
|
2907
|
+
if (catalog) return catalog;
|
|
2908
|
+
const loaded = await loadStatuses();
|
|
2909
|
+
catalog = {
|
|
2910
|
+
version: 1,
|
|
2911
|
+
generatedAt: Date.now(),
|
|
2912
|
+
servers: Object.fromEntries(loaded.map((status) => [status.name, {
|
|
2913
|
+
serverName: status.name,
|
|
2914
|
+
launchSummary: "Codex native MCP connection",
|
|
2915
|
+
toolCount: Object.keys(status.tools).length
|
|
2916
|
+
}])),
|
|
2917
|
+
tools: loaded.flatMap((status) => statusTools(status).map((tool) => ({
|
|
2918
|
+
serverName: status.name,
|
|
2919
|
+
safeServerName: status.name,
|
|
2920
|
+
toolName: String(tool.name),
|
|
2921
|
+
inputSchema: asRecord(tool.inputSchema) ?? { type: "object" },
|
|
2922
|
+
fallbackDescription: readString$4(tool.description) ?? String(tool.name)
|
|
2923
|
+
})))
|
|
2924
|
+
};
|
|
2925
|
+
return catalog;
|
|
2926
|
+
};
|
|
2927
|
+
const runtime = {
|
|
2928
|
+
sessionId: params.attempt.sessionId,
|
|
2929
|
+
sessionKey: params.attempt.sessionKey,
|
|
2930
|
+
workspaceDir: params.attempt.workspaceDir,
|
|
2931
|
+
configFingerprint: `${getCodexAppServerClientInstanceId(params.client)}:${params.threadId}`,
|
|
2932
|
+
mcpAppsEnabled: true,
|
|
2933
|
+
createdAt,
|
|
2934
|
+
lastUsedAt: createdAt,
|
|
2935
|
+
acquireLease: () => retainSharedCodexAppServerClientIfCurrent(params.client) ?? (() => {}),
|
|
2936
|
+
getCatalog,
|
|
2937
|
+
peekCatalog: () => catalog,
|
|
2938
|
+
markUsed: () => {
|
|
2939
|
+
runtime.lastUsedAt = Date.now();
|
|
2940
|
+
},
|
|
2941
|
+
callTool: async (serverName, toolName, input) => await params.client.request("mcpServer/tool/call", {
|
|
2942
|
+
threadId: params.threadId,
|
|
2943
|
+
server: serverName,
|
|
2944
|
+
tool: toolName,
|
|
2945
|
+
arguments: asRecord(input) ?? {}
|
|
2946
|
+
}),
|
|
2947
|
+
listTools: async (serverName) => {
|
|
2948
|
+
const status = (await loadStatuses()).find((entry) => entry.name === serverName);
|
|
2949
|
+
return { tools: status ? statusTools(status) : [] };
|
|
2950
|
+
},
|
|
2951
|
+
readResource: async (serverName, uri) => await params.client.request("mcpServer/resource/read", {
|
|
2952
|
+
threadId: params.threadId,
|
|
2953
|
+
server: serverName,
|
|
2954
|
+
uri
|
|
2955
|
+
}),
|
|
2956
|
+
listResources: async (serverName) => {
|
|
2957
|
+
return { resources: (await loadStatuses()).find((entry) => entry.name === serverName)?.resources ?? [] };
|
|
2958
|
+
},
|
|
2959
|
+
listResourceTemplates: async (serverName) => {
|
|
2960
|
+
return { resourceTemplates: (await loadStatuses()).find((entry) => entry.name === serverName)?.resourceTemplates ?? [] };
|
|
2961
|
+
},
|
|
2962
|
+
dispose: async () => {}
|
|
2963
|
+
};
|
|
2964
|
+
return runtime;
|
|
2965
|
+
}
|
|
2966
|
+
function createCodexNativeMcpAppResultDetailsPreparer(params) {
|
|
2967
|
+
if (params.attempt.config?.mcp?.apps?.enabled !== true) return;
|
|
2968
|
+
const runtime = createNativeMcpRuntime(params);
|
|
2969
|
+
return async (item) => {
|
|
2970
|
+
const serverName = readString$4(item.server);
|
|
2971
|
+
const toolName = readString$4(item.tool);
|
|
2972
|
+
const uiResourceUri = readMcpAppResourceUri(item);
|
|
2973
|
+
const toolResult = readMcpToolResult(item);
|
|
2974
|
+
if (!serverName || !toolName || !uiResourceUri || !toolResult) return;
|
|
2975
|
+
const allowedAppToolNames = new Set((await runtime.getCatalog()).tools.filter((tool) => tool.serverName === serverName).map((tool) => tool.toolName));
|
|
2976
|
+
if (allowedAppToolNames.size === 0) return;
|
|
2977
|
+
return await prepareHarnessNativeMcpAppPreview({
|
|
2978
|
+
runtime,
|
|
2979
|
+
serverName,
|
|
2980
|
+
toolName,
|
|
2981
|
+
uiResourceUri,
|
|
2982
|
+
toolCallId: item.id,
|
|
2983
|
+
toolInput: item.arguments ?? {},
|
|
2984
|
+
toolResult,
|
|
2985
|
+
allowedAppToolNames,
|
|
2986
|
+
...toolResult["_meta"] !== void 0 ? { resultMetaState: "unavailable" } : {}
|
|
2987
|
+
});
|
|
2988
|
+
};
|
|
2989
|
+
}
|
|
2990
|
+
//#endregion
|
|
2628
2991
|
//#region extensions/codex/src/app-server/user-input-bridge.ts
|
|
2629
2992
|
/** Bridges Codex request_user_input calls to gateway questions and secret text prompts. */
|
|
2630
2993
|
const DEFAULT_USER_INPUT_TIMEOUT_MS = 15 * 6e4;
|
|
@@ -2693,6 +3056,7 @@ function createCodexUserInputBridge(params) {
|
|
|
2693
3056
|
questions: requestParams.questions,
|
|
2694
3057
|
sessionKey: params.paramsForRun.sessionKey ?? params.paramsForRun.sessionId,
|
|
2695
3058
|
agentId: params.paramsForRun.agentId,
|
|
3059
|
+
runId: params.paramsForRun.runId,
|
|
2696
3060
|
timeoutMs: requestParams.autoResolutionMs ?? params.paramsForRun.timeoutMs ?? DEFAULT_USER_INPUT_TIMEOUT_MS,
|
|
2697
3061
|
gatewayCall,
|
|
2698
3062
|
delivery: params.paramsForRun,
|
|
@@ -2807,11 +3171,16 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2807
3171
|
const { runtime, attemptTools } = context;
|
|
2808
3172
|
const { connection } = runtime;
|
|
2809
3173
|
const { params, runAbortController, terminalState, abortExplicitly, abortFromUpstream, bindingStore, bindingIdentity, sessionAgentId, sandboxSessionKey, effectiveCwd } = connection;
|
|
2810
|
-
const { dynamicToolParams, computerContextEpoch } = attemptTools;
|
|
3174
|
+
const { dynamicToolParams, computerContextEpoch, toolBridge } = attemptTools;
|
|
2811
3175
|
const { state, userInputBridgeRef, steeringQueueRef, turnWatches } = turnRuntime;
|
|
2812
3176
|
const { emitExecutionPhaseOnce, emitLifecycleStart, maybeAnnounceFastModeAutoOff } = lifecycle;
|
|
2813
3177
|
const { enqueueNotification } = notifications;
|
|
2814
3178
|
const activeTurnId = turn.turn.id;
|
|
3179
|
+
const prepareNativeMcpAppResultDetails = createCodexNativeMcpAppResultDetailsPreparer({
|
|
3180
|
+
client: resourceState.client,
|
|
3181
|
+
threadId: resourceState.thread.threadId,
|
|
3182
|
+
attempt: dynamicToolParams
|
|
3183
|
+
});
|
|
2815
3184
|
const streamState = {
|
|
2816
3185
|
eventEmitted: false,
|
|
2817
3186
|
needsTerminalSnapshot: false
|
|
@@ -2842,8 +3211,19 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2842
3211
|
nativePostToolUseRelayEnabled: resourceState.nativeHookRelay?.allowedEvents.includes("post_tool_use") === true && resourceState.nativeHookRelay.shouldRelayEvent("post_tool_use"),
|
|
2843
3212
|
readRecentRateLimits: () => readRecentCodexRateLimits(resourceState.client),
|
|
2844
3213
|
runAbortSignal: runAbortController.signal,
|
|
3214
|
+
remoteWorkspaceRoot: connection.appServer.remoteWorkspaceRoot,
|
|
3215
|
+
remoteWorkspaceRequestTimeoutMs: connection.appServer.requestTimeoutMs,
|
|
3216
|
+
readRemoteWorkspaceFile: ({ path, maxBytes, signal, timeoutMs }) => readBoundedCodexRemoteWorkspaceFile({
|
|
3217
|
+
client: resourceState.client,
|
|
3218
|
+
path,
|
|
3219
|
+
maxBytes,
|
|
3220
|
+
signal,
|
|
3221
|
+
timeoutMs
|
|
3222
|
+
}),
|
|
2845
3223
|
trajectoryRecorder,
|
|
3224
|
+
resolveDynamicToolResultContentSource: toolBridge.resultContentSourceForTool,
|
|
2846
3225
|
onNativeToolResultRecorded: maybeAnnounceFastModeAutoOff,
|
|
3226
|
+
...prepareNativeMcpAppResultDetails ? { prepareNativeMcpAppResultDetails } : {},
|
|
2847
3227
|
upstreamUserText: turnState.codexTurnPromptText,
|
|
2848
3228
|
onContextCompacted: () => {
|
|
2849
3229
|
computerContextEpoch.value += 1;
|
|
@@ -2909,6 +3289,7 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2909
3289
|
await activeSteeringQueue.queue(text, optionsLocal);
|
|
2910
3290
|
},
|
|
2911
3291
|
isStreaming: () => !state.completed && !runAbortController.signal.aborted,
|
|
3292
|
+
isAborted: () => runAbortController.signal.aborted,
|
|
2912
3293
|
isStopped: () => state.completed || state.timedOut || runAbortController.signal.aborted,
|
|
2913
3294
|
isAbortable: () => !terminalState.terminalOutcomeFrozen || terminalState.sharedAbortAllowedAfterTerminalOutcome,
|
|
2914
3295
|
isCompacting: () => projectorRef.current?.isCompacting() ?? false,
|
|
@@ -3006,15 +3387,27 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
3006
3387
|
});
|
|
3007
3388
|
if (!state.timedOut && !runAbortController.signal.aborted) await steeringQueueRef.current?.flushPending();
|
|
3008
3389
|
const retainLiveIncognitoThread = terminalState.turnSucceeded && isIncognitoSessionKey(params.sessionKey);
|
|
3390
|
+
const retainedPersistentThread = terminalState.turnSucceeded && !isIncognitoSessionKey(params.sessionKey) && params.cleanupBundleMcpOnRunEnd !== true && !params.contextEngine && resourceState.thread.liveThreadConfigFingerprint !== void 0 && resourceState.thread.clientId === resolveCodexAppServerClientInstanceId(resourceState.client) && resourceState.thread.preserveNativeModel !== true && resourceState.thread.connectionScope !== "supervision" && !resourceState.thread.ringZeroConfigFingerprint && !resourceState.thread.contextEngine ? await retainCodexAppServerLiveThread(resourceState.client, resourceState.thread.threadId, async (previousThreadId) => {
|
|
3391
|
+
if (!await unsubscribeCodexThreadBestEffort(resourceState.client, {
|
|
3392
|
+
threadId: previousThreadId,
|
|
3393
|
+
timeoutMs: 5e3
|
|
3394
|
+
})) {
|
|
3395
|
+
await closeCodexStartupClientBestEffort(resourceState.client);
|
|
3396
|
+
throw new CodexAppServerUnsafeSubscriptionError(`Codex retained thread subscription could not be released: ${previousThreadId}`);
|
|
3397
|
+
}
|
|
3398
|
+
}, resourceState.thread.liveThreadConfigFingerprint) : void 0;
|
|
3399
|
+
const retainLiveThread = retainLiveIncognitoThread || retainedPersistentThread !== void 0;
|
|
3009
3400
|
const bindingReleased = isIncognitoSessionKey(params.sessionKey) && !retainLiveIncognitoThread ? await bindingStore.mutate(bindingIdentity, {
|
|
3010
3401
|
kind: "clear",
|
|
3011
3402
|
threadId: resourceState.thread.threadId
|
|
3012
3403
|
}) : true;
|
|
3013
|
-
if (!state.timedOut && !
|
|
3014
|
-
if (bindingReleased)
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3404
|
+
if (!state.timedOut && !retainLiveThread) {
|
|
3405
|
+
if (bindingReleased) {
|
|
3406
|
+
if (!await unsubscribeCodexThreadBestEffort(resourceState.client, {
|
|
3407
|
+
threadId: resourceState.thread.threadId,
|
|
3408
|
+
timeoutMs: 5e3
|
|
3409
|
+
})) await closeCodexStartupClientBestEffort(resourceState.client);
|
|
3410
|
+
}
|
|
3018
3411
|
}
|
|
3019
3412
|
userInputBridgeRef.current?.cancelPending();
|
|
3020
3413
|
turnWatches.clearAllTimers();
|
|
@@ -3049,7 +3442,8 @@ const codexWorkspaceDirCache = /* @__PURE__ */ new Set();
|
|
|
3049
3442
|
//#region extensions/codex/src/app-server/run-attempt-lifecycle.ts
|
|
3050
3443
|
const CODEX_APP_SERVER_PROJECTED_CHARS_PER_TOKEN = 4;
|
|
3051
3444
|
function shouldKeepCodexSharedAbortOpen(params) {
|
|
3052
|
-
|
|
3445
|
+
const terminal = attemptTerminal.project(params.result.terminal);
|
|
3446
|
+
if (params.explicitCancellationObserved || terminal.aborted || terminal.externalAbort) return false;
|
|
3053
3447
|
return params.trigger === "memory" || !params.attemptSucceeded;
|
|
3054
3448
|
}
|
|
3055
3449
|
function withCodexAppServerFastModeServiceTier(appServer, params) {
|
|
@@ -3071,14 +3465,7 @@ function estimateCodexAppServerProjectedTurnTokens(params) {
|
|
|
3071
3465
|
}
|
|
3072
3466
|
async function ensureCodexWorkspaceDirOnce(workspaceDir) {
|
|
3073
3467
|
const normalized = path.resolve(workspaceDir);
|
|
3074
|
-
if (codexWorkspaceDirCache.has(normalized))
|
|
3075
|
-
try {
|
|
3076
|
-
if ((await fs.stat(normalized)).isDirectory()) return;
|
|
3077
|
-
} catch (error) {
|
|
3078
|
-
if ((typeof error === "object" && error ? error.code : void 0) !== "ENOENT") throw error;
|
|
3079
|
-
}
|
|
3080
|
-
codexWorkspaceDirCache.delete(normalized);
|
|
3081
|
-
}
|
|
3468
|
+
if (codexWorkspaceDirCache.has(normalized)) return;
|
|
3082
3469
|
await fs.mkdir(normalized, { recursive: true });
|
|
3083
3470
|
codexWorkspaceDirCache.add(normalized);
|
|
3084
3471
|
}
|
|
@@ -3119,6 +3506,7 @@ const CODEX_APP_SERVER_NATIVE_THREAD_FALLBACK_MAX_TOKENS = 3e5;
|
|
|
3119
3506
|
const CODEX_APP_SERVER_NATIVE_THREAD_DEFAULT_RESERVE_TOKENS = 2e4;
|
|
3120
3507
|
const CODEX_APP_SERVER_NATIVE_THREAD_MIN_PROMPT_BUDGET_TOKENS = 8e3;
|
|
3121
3508
|
const CODEX_APP_SERVER_NATIVE_THREAD_MIN_PROMPT_BUDGET_RATIO = .5;
|
|
3509
|
+
const CODEX_APP_SERVER_ROLLOUT_TAIL_READ_BYTES = 64 * 1024;
|
|
3122
3510
|
const CODEX_APP_SERVER_BYTE_UNITS = {
|
|
3123
3511
|
b: 1,
|
|
3124
3512
|
k: 1024,
|
|
@@ -3147,7 +3535,7 @@ function parseCodexAppServerByteLimit(value) {
|
|
|
3147
3535
|
if (multiplier === void 0) return;
|
|
3148
3536
|
return Math.max(1, Math.round(amount * multiplier));
|
|
3149
3537
|
}
|
|
3150
|
-
async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codexHome) {
|
|
3538
|
+
async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codexHome, rolloutPath) {
|
|
3151
3539
|
const resolvedAgentDir = path.resolve(agentDir);
|
|
3152
3540
|
const resolvedCodexHome = codexHome?.trim() ? path.resolve(codexHome) : resolveCodexAppServerHomeDir(resolvedAgentDir);
|
|
3153
3541
|
const roots = [
|
|
@@ -3156,6 +3544,22 @@ async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codex
|
|
|
3156
3544
|
path.join(resolvedAgentDir, "agent", "codex-home", "sessions"),
|
|
3157
3545
|
path.join(path.dirname(resolvedAgentDir), "codex-home", "sessions")
|
|
3158
3546
|
];
|
|
3547
|
+
const rolloutRoot = rolloutPath ? roots.find((root) => {
|
|
3548
|
+
const relativePath = path.relative(root, rolloutPath);
|
|
3549
|
+
return relativePath !== "" && relativePath !== ".." && !relativePath.startsWith(`..${path.sep}`) && !path.isAbsolute(relativePath);
|
|
3550
|
+
}) : void 0;
|
|
3551
|
+
if (rolloutPath && rolloutRoot && path.isAbsolute(rolloutPath) && path.extname(rolloutPath) === ".jsonl" && path.basename(rolloutPath).includes(threadId)) try {
|
|
3552
|
+
const opened = await (await root(rolloutRoot, {
|
|
3553
|
+
hardlinks: "reject",
|
|
3554
|
+
maxBytes: Number.MAX_SAFE_INTEGER,
|
|
3555
|
+
symlinks: "reject"
|
|
3556
|
+
})).open(path.relative(rolloutRoot, rolloutPath));
|
|
3557
|
+
return [{
|
|
3558
|
+
path: opened.realPath,
|
|
3559
|
+
bytes: opened.stat.size,
|
|
3560
|
+
handle: opened.handle
|
|
3561
|
+
}];
|
|
3562
|
+
} catch {}
|
|
3159
3563
|
const files = [];
|
|
3160
3564
|
const visited = /* @__PURE__ */ new Set();
|
|
3161
3565
|
for (const root of roots) {
|
|
@@ -3234,23 +3638,48 @@ async function readCodexSessionRecordForSessionFile(sessionFile) {
|
|
|
3234
3638
|
function isSqliteSessionFileMarker(sessionFile) {
|
|
3235
3639
|
return parseSqliteSessionFileMarker(sessionFile) !== void 0;
|
|
3236
3640
|
}
|
|
3237
|
-
async function readCodexAppServerRolloutTokenSnapshot(file) {
|
|
3238
|
-
let handle;
|
|
3239
|
-
try {
|
|
3641
|
+
async function readCodexAppServerRolloutTokenSnapshot(file, openedHandle) {
|
|
3642
|
+
let handle = openedHandle;
|
|
3643
|
+
if (!handle) try {
|
|
3240
3644
|
handle = await fs.open(file, "r");
|
|
3241
3645
|
} catch {
|
|
3242
3646
|
return;
|
|
3243
3647
|
}
|
|
3244
3648
|
let snapshot;
|
|
3245
3649
|
try {
|
|
3246
|
-
|
|
3650
|
+
let position = (await handle.stat()).size;
|
|
3651
|
+
const partialLineFragments = [];
|
|
3652
|
+
const applySnapshotLine = (line) => {
|
|
3247
3653
|
const lineSnapshot = readCodexAppServerRolloutTokenSnapshotLine(line);
|
|
3248
|
-
if (lineSnapshot
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3654
|
+
if (lineSnapshot === void 0) return false;
|
|
3655
|
+
snapshot ??= {};
|
|
3656
|
+
snapshot.totalTokens ??= lineSnapshot.totalTokens;
|
|
3657
|
+
snapshot.modelContextWindow ??= lineSnapshot.modelContextWindow;
|
|
3658
|
+
return snapshot.totalTokens !== void 0 && snapshot.modelContextWindow !== void 0;
|
|
3659
|
+
};
|
|
3660
|
+
while (position > 0) {
|
|
3661
|
+
const bytesToRead = Math.min(position, CODEX_APP_SERVER_ROLLOUT_TAIL_READ_BYTES);
|
|
3662
|
+
const nextPosition = position - bytesToRead;
|
|
3663
|
+
const chunk = Buffer.allocUnsafe(bytesToRead);
|
|
3664
|
+
let bytesRead = 0;
|
|
3665
|
+
while (bytesRead < bytesToRead) {
|
|
3666
|
+
const result = await handle.read(chunk, bytesRead, bytesToRead - bytesRead, nextPosition + bytesRead);
|
|
3667
|
+
if (result.bytesRead === 0) return snapshot;
|
|
3668
|
+
bytesRead += result.bytesRead;
|
|
3669
|
+
}
|
|
3670
|
+
let lineEnd = bytesRead;
|
|
3671
|
+
for (let index = bytesRead - 1; index >= 0; index -= 1) {
|
|
3672
|
+
if (chunk[index] !== 10) continue;
|
|
3673
|
+
const lineFragment = chunk.subarray(index + 1, lineEnd);
|
|
3674
|
+
const line = partialLineFragments.length === 0 ? lineFragment.toString("utf8") : Buffer.concat([lineFragment, ...partialLineFragments.toReversed()]).toString("utf8");
|
|
3675
|
+
partialLineFragments.length = 0;
|
|
3676
|
+
if (applySnapshotLine(line)) return snapshot;
|
|
3677
|
+
lineEnd = index;
|
|
3252
3678
|
}
|
|
3679
|
+
if (lineEnd > 0) partialLineFragments.push(chunk.subarray(0, lineEnd));
|
|
3680
|
+
position = nextPosition;
|
|
3253
3681
|
}
|
|
3682
|
+
if (partialLineFragments.length > 0) applySnapshotLine(Buffer.concat(partialLineFragments.toReversed()).toString("utf8"));
|
|
3254
3683
|
} finally {
|
|
3255
3684
|
await handle.close();
|
|
3256
3685
|
}
|
|
@@ -3308,31 +3737,36 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
3308
3737
|
if (!binding?.threadId) return binding;
|
|
3309
3738
|
if (binding.connectionScope === "supervision") return binding;
|
|
3310
3739
|
const sessionRecord = await readCodexSessionRecordForSessionFile(params.sessionFile);
|
|
3311
|
-
const rolloutFiles = await listCodexAppServerRolloutFilesForThread(params.agentDir, binding.threadId, params.codexHome);
|
|
3312
|
-
const
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
}
|
|
3740
|
+
const rolloutFiles = await listCodexAppServerRolloutFilesForThread(params.agentDir, binding.threadId, params.codexHome, binding.rolloutPath);
|
|
3741
|
+
const maxBytes = parseCodexAppServerByteLimit(readCompactionConfig(params.config)?.maxActiveTranscriptBytes);
|
|
3742
|
+
if (maxBytes !== void 0 && params.contextEngineActive === true && hasContextEngineThreadBootstrapProjection(binding)) embeddedAgentLog.debug("codex app-server deferring native transcript byte guard for context-engine thread bootstrap", {
|
|
3743
|
+
threadId: binding.threadId,
|
|
3744
|
+
engineId: binding.contextEngine?.engineId,
|
|
3745
|
+
epoch: binding.contextEngine?.projection?.epoch,
|
|
3746
|
+
fingerprint: binding.contextEngine?.projection?.fingerprint
|
|
3747
|
+
});
|
|
3748
|
+
else if (maxBytes !== void 0) {
|
|
3749
|
+
const oversizedFiles = rolloutFiles.filter((file) => file.bytes >= maxBytes);
|
|
3750
|
+
if (oversizedFiles.length > 0) {
|
|
3751
|
+
await Promise.all(rolloutFiles.map(async (file) => {
|
|
3752
|
+
await file.handle?.close();
|
|
3753
|
+
}));
|
|
3754
|
+
embeddedAgentLog.warn("codex app-server native transcript exceeded active byte limit; starting a fresh thread", {
|
|
3755
|
+
threadId: binding.threadId,
|
|
3756
|
+
maxBytes,
|
|
3757
|
+
files: oversizedFiles.map((file) => ({
|
|
3758
|
+
path: file.path,
|
|
3759
|
+
bytes: file.bytes
|
|
3760
|
+
}))
|
|
3761
|
+
});
|
|
3762
|
+
await params.bindingStore.mutate(params.identity, {
|
|
3763
|
+
kind: "clear",
|
|
3764
|
+
threadId: binding.threadId
|
|
3765
|
+
});
|
|
3766
|
+
return;
|
|
3333
3767
|
}
|
|
3334
3768
|
}
|
|
3335
|
-
const nativeTokenSnapshots = await Promise.all(rolloutFiles.map(async (file) => readCodexAppServerRolloutTokenSnapshot(file.path)));
|
|
3769
|
+
const nativeTokenSnapshots = await Promise.all(rolloutFiles.map(async (file) => readCodexAppServerRolloutTokenSnapshot(file.path, file.handle)));
|
|
3336
3770
|
const nativeTokens = maxFiniteNumber(nativeTokenSnapshots.map((snapshot) => snapshot?.totalTokens));
|
|
3337
3771
|
const nativeModelContextWindow = maxFiniteNumber(nativeTokenSnapshots.map((snapshot) => snapshot?.modelContextWindow));
|
|
3338
3772
|
const sessionModelContextWindow = typeof sessionRecord?.contextTokens === "number" && Number.isFinite(sessionRecord.contextTokens) && sessionRecord.contextTokens > 0 ? Math.floor(sessionRecord.contextTokens) : void 0;
|
|
@@ -3362,16 +3796,6 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
3362
3796
|
});
|
|
3363
3797
|
return;
|
|
3364
3798
|
}
|
|
3365
|
-
if (compaction?.truncateAfterCompaction !== true) return binding;
|
|
3366
|
-
if (shouldDeferByteGuard) {
|
|
3367
|
-
embeddedAgentLog.debug("codex app-server deferring native transcript byte guard for context-engine thread bootstrap", {
|
|
3368
|
-
threadId: binding.threadId,
|
|
3369
|
-
engineId: binding.contextEngine?.engineId,
|
|
3370
|
-
epoch: binding.contextEngine?.projection?.epoch,
|
|
3371
|
-
fingerprint: binding.contextEngine?.projection?.fingerprint
|
|
3372
|
-
});
|
|
3373
|
-
return binding;
|
|
3374
|
-
}
|
|
3375
3799
|
return binding;
|
|
3376
3800
|
}
|
|
3377
3801
|
//#endregion
|
|
@@ -3400,7 +3824,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3400
3824
|
const runtimeArtifactRequest = params.captureRuntimeArtifact || params.expectedRuntimeArtifact ? params.expectedRuntimeArtifact ? { expected: params.expectedRuntimeArtifact } : {} : void 0;
|
|
3401
3825
|
const pluginConfig = readCodexPluginConfig(options.pluginConfig);
|
|
3402
3826
|
const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig });
|
|
3403
|
-
const { sessionAgentId } = resolveSessionAgentIds
|
|
3827
|
+
const { sessionAgentId } = resolveSessionAgentIds({
|
|
3404
3828
|
sessionKey: params.sessionKey,
|
|
3405
3829
|
config: params.config,
|
|
3406
3830
|
agentId: params.agentId
|
|
@@ -3424,23 +3848,46 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3424
3848
|
config: params.config,
|
|
3425
3849
|
agentId: sessionAgentId
|
|
3426
3850
|
});
|
|
3427
|
-
const agentDir = params.agentDir ?? resolveAgentDir(params.config ?? {}, sessionAgentId);
|
|
3428
|
-
|
|
3851
|
+
const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId);
|
|
3852
|
+
let bindingIdentity = sessionBindingIdentity({
|
|
3429
3853
|
sessionId: params.sessionId,
|
|
3430
3854
|
sessionKey: params.sessionKey,
|
|
3431
3855
|
agentId: params.agentId,
|
|
3432
3856
|
config: params.config
|
|
3433
3857
|
});
|
|
3434
|
-
|
|
3858
|
+
let bindingStore = options.bindingStore;
|
|
3435
3859
|
preDynamicStartupStages.mark("session-agent");
|
|
3436
3860
|
let activeContextEngine = isActiveHarnessContextEngine(params.contextEngine) ? params.contextEngine : void 0;
|
|
3437
3861
|
const isInactiveThreadBootstrapBinding = (binding) => !activeContextEngine && binding?.contextEngine?.projection?.mode === "thread_bootstrap";
|
|
3862
|
+
if (bindingIdentity.kind === "session" && bindingIdentity.sessionKey && (params.sessionTarget?.storePath || params.config?.session?.store)) {
|
|
3863
|
+
const authority = resolveCodexRunSessionBindingAuthority({
|
|
3864
|
+
identity: bindingIdentity,
|
|
3865
|
+
config: params.config,
|
|
3866
|
+
storePath: params.sessionTarget?.storePath
|
|
3867
|
+
});
|
|
3868
|
+
if (authority === "superseded") throw createCodexSessionGenerationSupersededError(bindingIdentity.sessionId);
|
|
3869
|
+
if (authority === "ephemeral") {
|
|
3870
|
+
const logicalIdentity = bindingIdentity;
|
|
3871
|
+
const physicalIdentity = {
|
|
3872
|
+
kind: "session",
|
|
3873
|
+
agentId: bindingIdentity.agentId,
|
|
3874
|
+
sessionId: bindingIdentity.sessionId
|
|
3875
|
+
};
|
|
3876
|
+
bindingStore = scopeCodexRunBindingStore({
|
|
3877
|
+
bindingStore,
|
|
3878
|
+
logicalIdentity,
|
|
3879
|
+
physicalIdentity
|
|
3880
|
+
});
|
|
3881
|
+
bindingIdentity = physicalIdentity;
|
|
3882
|
+
}
|
|
3883
|
+
}
|
|
3438
3884
|
let startupBinding = await bindingStore.read(bindingIdentity);
|
|
3439
3885
|
if (!startupBinding && bindingIdentity.kind === "session" && bindingIdentity.sessionKey) {
|
|
3440
3886
|
if (!await reclaimCurrentCodexSessionGeneration({
|
|
3441
3887
|
bindingStore,
|
|
3442
3888
|
identity: bindingIdentity,
|
|
3443
|
-
config: params.config
|
|
3889
|
+
config: params.config,
|
|
3890
|
+
storePath: params.sessionTarget?.storePath
|
|
3444
3891
|
})) throw createCodexSessionGenerationSupersededError(bindingIdentity.sessionId);
|
|
3445
3892
|
startupBinding = await bindingStore.read(bindingIdentity);
|
|
3446
3893
|
}
|
|
@@ -3484,6 +3931,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3484
3931
|
authProfileId: resolvedStartupAuthProfileId,
|
|
3485
3932
|
authProfileStore: params.authProfileStore,
|
|
3486
3933
|
agentDir,
|
|
3934
|
+
homeScope: resolveCodexAppServerHomeScope({ appServer: pluginConfig.appServer }),
|
|
3487
3935
|
config: params.config,
|
|
3488
3936
|
subscriptionProfileRequiredError: "Prepared Codex subscription route requires a forwarded OpenAI OAuth or token profile.",
|
|
3489
3937
|
subscriptionProfileUnusableError: "Prepared Codex subscription auth profile is unusable."
|
|
@@ -3509,15 +3957,16 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3509
3957
|
const requestedCwd = params.cwd ? resolveUserPath(params.cwd) : void 0;
|
|
3510
3958
|
if (sandbox?.enabled && requestedCwd && requestedCwd !== resolvedWorkspace) throw new Error("cwd override is not supported for sandboxed Codex app-server runs; omit cwd or use the agent workspace as cwd");
|
|
3511
3959
|
const effectiveCwd = sandbox?.enabled ? effectiveWorkspace : requestedCwd ?? effectiveWorkspace;
|
|
3512
|
-
await ensureCodexWorkspaceDirOnce(effectiveWorkspace);
|
|
3960
|
+
if (effectiveWorkspace !== resolvedWorkspace) await ensureCodexWorkspaceDirOnce(effectiveWorkspace);
|
|
3513
3961
|
preDynamicStartupStages.mark("effective-workspace");
|
|
3962
|
+
const shouldPromoteApprovalPolicy = beforeToolCallPolicy.hasBeforeToolCallHook || beforeToolCallPolicy.trustedToolPolicies.length > 0;
|
|
3514
3963
|
const resolvePolicyAppServer = () => resolveCodexAppServerForOpenClawToolPolicy({
|
|
3515
3964
|
appServer: configuredAppServer,
|
|
3516
3965
|
pluginConfig,
|
|
3517
3966
|
env: process.env,
|
|
3518
|
-
shouldPromote:
|
|
3967
|
+
shouldPromote: shouldPromoteApprovalPolicy,
|
|
3519
3968
|
execPolicy,
|
|
3520
|
-
canUseUntrustedApprovalPolicy: configuredAppServer.start.transport !== "stdio" || isCodexAppServerApprovalPolicyAllowedByRequirements("untrusted")
|
|
3969
|
+
canUseUntrustedApprovalPolicy: shouldPromoteApprovalPolicy && configuredAppServer.approvalPolicy === "never" && (configuredAppServer.start.transport !== "stdio" || isCodexAppServerApprovalPolicyAllowedByRequirements("untrusted"))
|
|
3521
3970
|
});
|
|
3522
3971
|
let policyAppServer = resolvePolicyAppServer();
|
|
3523
3972
|
let appServer = resolveCodexAppServerForModelProvider({
|
|
@@ -3528,7 +3977,8 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3528
3977
|
env: process.env,
|
|
3529
3978
|
agentDir
|
|
3530
3979
|
});
|
|
3531
|
-
|
|
3980
|
+
let approvalPolicyPromotedForOpenClawToolPolicy = configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted";
|
|
3981
|
+
if (approvalPolicyPromotedForOpenClawToolPolicy) embeddedAgentLog.info("codex app-server approval policy promoted for OpenClaw tool policy", {
|
|
3532
3982
|
from: "never",
|
|
3533
3983
|
to: "untrusted",
|
|
3534
3984
|
beforeToolCallHook: beforeToolCallPolicy.hasBeforeToolCallHook,
|
|
@@ -3565,6 +4015,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3565
4015
|
};
|
|
3566
4016
|
if (params.abortSignal?.aborted) abortFromUpstream();
|
|
3567
4017
|
else params.abortSignal?.addEventListener("abort", abortFromUpstream, { once: true });
|
|
4018
|
+
const startupBindingBeforeRotation = startupBinding;
|
|
3568
4019
|
startupBinding = await rotateOversizedCodexAppServerStartupBinding({
|
|
3569
4020
|
binding: startupBinding,
|
|
3570
4021
|
bindingStore,
|
|
@@ -3577,20 +4028,23 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3577
4028
|
});
|
|
3578
4029
|
const initialInactiveThreadBootstrapBindingForcedFreshStart = initialStartupBindingHadInactiveThreadBootstrap && !startupBinding?.threadId;
|
|
3579
4030
|
preDynamicStartupStages.mark("rotate-binding");
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
appServer
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
4031
|
+
if (startupBinding !== startupBindingBeforeRotation) {
|
|
4032
|
+
reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
|
|
4033
|
+
configuredAppServer = resolveRuntimeOptionsForBinding({
|
|
4034
|
+
modelProvider: reviewerPolicyContext.modelProvider,
|
|
4035
|
+
model: reviewerPolicyContext.model
|
|
4036
|
+
});
|
|
4037
|
+
policyAppServer = resolvePolicyAppServer();
|
|
4038
|
+
appServer = resolveCodexAppServerForModelProvider({
|
|
4039
|
+
appServer: policyAppServer,
|
|
4040
|
+
provider: reviewerPolicyContext.modelProvider,
|
|
4041
|
+
model: reviewerPolicyContext.model,
|
|
4042
|
+
config: params.config,
|
|
4043
|
+
env: process.env,
|
|
4044
|
+
agentDir
|
|
4045
|
+
});
|
|
4046
|
+
approvalPolicyPromotedForOpenClawToolPolicy = configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted";
|
|
4047
|
+
}
|
|
3594
4048
|
const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
|
|
3595
4049
|
configuredEvents: options.nativeHookRelay?.events,
|
|
3596
4050
|
appServer
|
|
@@ -3646,6 +4100,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3646
4100
|
effectiveWorkspace,
|
|
3647
4101
|
effectiveCwd,
|
|
3648
4102
|
appServer,
|
|
4103
|
+
approvalPolicyPromotedForOpenClawToolPolicy,
|
|
3649
4104
|
nativeHookRelayEvents,
|
|
3650
4105
|
runAbortController,
|
|
3651
4106
|
terminalState,
|
|
@@ -3665,20 +4120,18 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3665
4120
|
* system-prompt reports, and context-engine projection decisions.
|
|
3666
4121
|
*/
|
|
3667
4122
|
const CODEX_NATIVE_PROJECT_DOC_BASENAMES = /* @__PURE__ */ new Set(["agents.md"]);
|
|
3668
|
-
const CODEX_INHERITED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES = /* @__PURE__ */ new Set(["tools.md"]);
|
|
3669
4123
|
const CODEX_TURN_SCOPED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES = /* @__PURE__ */ new Set([
|
|
3670
4124
|
"identity.md",
|
|
3671
4125
|
"soul.md",
|
|
3672
4126
|
"user.md"
|
|
3673
4127
|
]);
|
|
3674
|
-
const CODEX_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES =
|
|
4128
|
+
const CODEX_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES = new Set(CODEX_TURN_SCOPED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES);
|
|
3675
4129
|
const CODEX_MEMORY_CONTEXT_BASENAME = "memory.md";
|
|
3676
4130
|
const CODEX_MEMORY_TOOL_NAMES = /* @__PURE__ */ new Set(["memory_search", "memory_get"]);
|
|
3677
4131
|
const CODEX_BOOTSTRAP_CONTEXT_ORDER = /* @__PURE__ */ new Map([
|
|
3678
4132
|
["soul.md", 10],
|
|
3679
4133
|
["identity.md", 20],
|
|
3680
4134
|
["user.md", 30],
|
|
3681
|
-
["tools.md", 40],
|
|
3682
4135
|
["bootstrap.md", 50],
|
|
3683
4136
|
["memory.md", 60]
|
|
3684
4137
|
]);
|
|
@@ -3779,20 +4232,17 @@ async function buildCodexWorkspaceBootstrapContext(params) {
|
|
|
3779
4232
|
excludeMemory: memoryToolsAvailable,
|
|
3780
4233
|
memoryWorkspaceDir: params.effectiveWorkspace
|
|
3781
4234
|
});
|
|
3782
|
-
const developerInstructionFiles = shouldInjectCodexOpenClawPromptContext(params.params) ? selectCodexWorkspaceInheritedDeveloperInstructionFiles(contextFiles) : [];
|
|
3783
4235
|
const turnScopedDeveloperInstructionFiles = shouldInjectCodexOpenClawPromptContext(params.params) ? selectCodexWorkspaceTurnScopedDeveloperInstructionFiles(contextFiles) : [];
|
|
3784
4236
|
return {
|
|
3785
4237
|
bootstrapFiles,
|
|
3786
4238
|
contextFiles,
|
|
3787
4239
|
promptContextFiles,
|
|
3788
|
-
developerInstructionFiles,
|
|
3789
4240
|
turnScopedDeveloperInstructionFiles,
|
|
3790
4241
|
memoryReferenceFiles,
|
|
3791
4242
|
memoryToolRoutedBootstrapFiles,
|
|
3792
4243
|
memoryToolNames: [...params.memoryToolNames],
|
|
3793
4244
|
memoryToolRouted: memoryToolsAvailable,
|
|
3794
4245
|
promptContext: renderCodexWorkspaceBootstrapPromptContext(promptContextFiles),
|
|
3795
|
-
developerInstructions: renderCodexWorkspaceThreadDeveloperInstructions(developerInstructionFiles),
|
|
3796
4246
|
turnScopedDeveloperInstructions: renderCodexWorkspaceCollaborationDeveloperInstructions(turnScopedDeveloperInstructionFiles),
|
|
3797
4247
|
memoryCollaborationInstructions: shouldInjectCodexOpenClawPromptContext(params.params) ? await renderCodexWorkspaceMemoryCollaborationInstructions({
|
|
3798
4248
|
files: memoryReferenceFiles,
|
|
@@ -3841,7 +4291,7 @@ function buildCodexSystemPromptReport(params) {
|
|
|
3841
4291
|
injectedWorkspaceFiles: buildCodexBootstrapInjectionStats({
|
|
3842
4292
|
bootstrapFiles: params.workspaceBootstrapContext.bootstrapFiles,
|
|
3843
4293
|
injectedFiles: params.workspaceBootstrapContext.promptContextFiles ?? [],
|
|
3844
|
-
developerInstructionFiles:
|
|
4294
|
+
developerInstructionFiles: params.workspaceBootstrapContext.turnScopedDeveloperInstructionFiles ?? [],
|
|
3845
4295
|
memoryToolRoutedBootstrapFiles: params.workspaceBootstrapContext.memoryToolRoutedBootstrapFiles ?? [],
|
|
3846
4296
|
memoryToolRouted: params.workspaceBootstrapContext.memoryToolRouted === true
|
|
3847
4297
|
}),
|
|
@@ -3978,7 +4428,7 @@ function buildCodexOpenClawPromptContext(params) {
|
|
|
3978
4428
|
"## OpenClaw Workspace Context",
|
|
3979
4429
|
"",
|
|
3980
4430
|
params.workspacePromptContext.trim()
|
|
3981
|
-
].join("\n") : void 0].filter(isNonEmptyString$1);
|
|
4431
|
+
].join("\n") : void 0, params.watchedSessionsContext?.trim() || void 0].filter(isNonEmptyString$1);
|
|
3982
4432
|
if (sections.length === 0) return;
|
|
3983
4433
|
return [
|
|
3984
4434
|
"OpenClaw runtime context for this turn:",
|
|
@@ -3987,6 +4437,21 @@ function buildCodexOpenClawPromptContext(params) {
|
|
|
3987
4437
|
...sections
|
|
3988
4438
|
].join("\n");
|
|
3989
4439
|
}
|
|
4440
|
+
/**
|
|
4441
|
+
* Renders the watched-sessions block for the Codex per-turn runtime context.
|
|
4442
|
+
* Codex builds its own instruction layers, so the embedded prompt's Watched
|
|
4443
|
+
* Sessions section must be re-surfaced here or Codex-backed main sessions
|
|
4444
|
+
* keep refusing cross-session questions (openclaw#114797).
|
|
4445
|
+
*/
|
|
4446
|
+
function buildCodexWatchedSessionsContext(params) {
|
|
4447
|
+
if (!shouldInjectCodexOpenClawPromptContext(params.attempt)) return;
|
|
4448
|
+
return buildWatchedSessionsHarnessContext({
|
|
4449
|
+
config: params.attempt.config,
|
|
4450
|
+
sessionKey: params.sessionKey,
|
|
4451
|
+
sandboxed: params.sandboxed,
|
|
4452
|
+
toolNames: flattenCodexDynamicToolFunctions(params.dynamicTools).map((tool) => normalizeCodexDynamicToolName(tool.name))
|
|
4453
|
+
});
|
|
4454
|
+
}
|
|
3990
4455
|
function shouldInjectCodexOpenClawPromptContext(params) {
|
|
3991
4456
|
return !(params.bootstrapContextMode === "lightweight" && params.bootstrapContextRunKind === "cron");
|
|
3992
4457
|
}
|
|
@@ -4050,7 +4515,7 @@ function renderCodexWorkspaceBootstrapPromptContext(contextFiles) {
|
|
|
4050
4515
|
const files = contextFiles;
|
|
4051
4516
|
if (files.length === 0) return;
|
|
4052
4517
|
const lines = [
|
|
4053
|
-
"OpenClaw loaded these user-editable workspace files for the current turn. Codex loads AGENTS.md natively.
|
|
4518
|
+
"OpenClaw loaded these user-editable workspace files for the current turn. Codex loads AGENTS.md natively. SOUL.md, IDENTITY.md, and USER.md are provided as turn-scoped collaboration instructions so native Codex subagents do not inherit them. Those files are not repeated here.",
|
|
4054
4519
|
"",
|
|
4055
4520
|
"# Project Context",
|
|
4056
4521
|
"",
|
|
@@ -4070,9 +4535,6 @@ function selectCodexWorkspacePromptContextFiles(contextFiles, options = {}) {
|
|
|
4070
4535
|
})) && !isMissingCodexBootstrapContextFile(file);
|
|
4071
4536
|
}).toSorted(compareCodexContextFiles);
|
|
4072
4537
|
}
|
|
4073
|
-
function selectCodexWorkspaceInheritedDeveloperInstructionFiles(contextFiles) {
|
|
4074
|
-
return selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, CODEX_INHERITED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES);
|
|
4075
|
-
}
|
|
4076
4538
|
function selectCodexWorkspaceTurnScopedDeveloperInstructionFiles(contextFiles) {
|
|
4077
4539
|
return selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, CODEX_TURN_SCOPED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES);
|
|
4078
4540
|
}
|
|
@@ -4082,13 +4544,6 @@ function selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, basenames)
|
|
|
4082
4544
|
return baseName && basenames.has(baseName) && !isMissingCodexBootstrapContextFile(file) && file.content.trim().length > 0;
|
|
4083
4545
|
}).toSorted(compareCodexContextFiles);
|
|
4084
4546
|
}
|
|
4085
|
-
function renderCodexWorkspaceThreadDeveloperInstructions(files) {
|
|
4086
|
-
return renderCodexWorkspaceDeveloperInstructions({
|
|
4087
|
-
files,
|
|
4088
|
-
header: "## OpenClaw Workspace Instructions",
|
|
4089
|
-
preamble: "OpenClaw loaded these workspace instruction files from the active agent workspace. Internalize and follow them accordingly."
|
|
4090
|
-
});
|
|
4091
|
-
}
|
|
4092
4547
|
function renderCodexWorkspaceCollaborationDeveloperInstructions(files) {
|
|
4093
4548
|
return renderCodexWorkspaceDeveloperInstructions({
|
|
4094
4549
|
files,
|
|
@@ -4246,107 +4701,6 @@ function isNonEmptyString$1(value) {
|
|
|
4246
4701
|
return typeof value === "string" && value.length > 0;
|
|
4247
4702
|
}
|
|
4248
4703
|
//#endregion
|
|
4249
|
-
//#region extensions/codex/src/app-server/run-attempt-state.ts
|
|
4250
|
-
async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity, fields) {
|
|
4251
|
-
const currentBinding = await bindingStore.read(identity);
|
|
4252
|
-
const expectedThreadId = fields.threadId ?? currentBinding?.threadId;
|
|
4253
|
-
if (!expectedThreadId) return;
|
|
4254
|
-
if (currentBinding && currentBinding.threadId !== expectedThreadId) {
|
|
4255
|
-
embeddedAgentLog.warn("codex app-server image payload error detected for unbound thread; preserving thread binding", {
|
|
4256
|
-
...fields,
|
|
4257
|
-
boundThreadId: currentBinding.threadId
|
|
4258
|
-
});
|
|
4259
|
-
return;
|
|
4260
|
-
}
|
|
4261
|
-
if (currentBinding?.connectionScope === "supervision") {
|
|
4262
|
-
embeddedAgentLog.warn("codex app-server image payload error detected for supervised thread; preserving native binding", fields);
|
|
4263
|
-
return;
|
|
4264
|
-
}
|
|
4265
|
-
embeddedAgentLog.warn("codex app-server image payload error detected; clearing thread binding", fields);
|
|
4266
|
-
await bindingStore.mutate(identity, {
|
|
4267
|
-
kind: "clear",
|
|
4268
|
-
threadId: expectedThreadId
|
|
4269
|
-
});
|
|
4270
|
-
}
|
|
4271
|
-
async function markCodexAppServerBindingCoveredThroughTurn(params) {
|
|
4272
|
-
await params.bindingStore.mutate(params.identity, {
|
|
4273
|
-
kind: "patch",
|
|
4274
|
-
threadId: params.threadId,
|
|
4275
|
-
patch: { historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString() }
|
|
4276
|
-
});
|
|
4277
|
-
}
|
|
4278
|
-
function isNonEmptyString(value) {
|
|
4279
|
-
return typeof value === "string" && value.length > 0;
|
|
4280
|
-
}
|
|
4281
|
-
function shouldUseFreshCodexThreadAfterContextEngineOverflow(params) {
|
|
4282
|
-
if (!params.contextEngineActive || params.thread.lifecycle.action !== "resumed") return false;
|
|
4283
|
-
const message = formatErrorMessage(params.error);
|
|
4284
|
-
return /ran out of room in the model'?s context window/iu.test(message) || /context window/iu.test(message) || /context length/iu.test(message) || /maximum context/iu.test(message) || /too many tokens/iu.test(message);
|
|
4285
|
-
}
|
|
4286
|
-
function isCodexActiveCompactTurnError(error) {
|
|
4287
|
-
if (!(error instanceof CodexAppServerRpcError)) return false;
|
|
4288
|
-
const data = isJsonObject(error.data) ? error.data : void 0;
|
|
4289
|
-
const codexErrorInfo = isJsonObject(data?.codexErrorInfo) ? data.codexErrorInfo : void 0;
|
|
4290
|
-
return (isJsonObject(codexErrorInfo?.activeTurnNotSteerable) ? codexErrorInfo.activeTurnNotSteerable : void 0)?.turnKind === "compact";
|
|
4291
|
-
}
|
|
4292
|
-
function readCodexFinalizationHookNotification(notification, threadId, turnId) {
|
|
4293
|
-
if (notification.method !== "hook/started" && notification.method !== "hook/completed") return;
|
|
4294
|
-
const params = isJsonObject(notification.params) ? notification.params : void 0;
|
|
4295
|
-
const run = params && isJsonObject(params.run) ? params.run : void 0;
|
|
4296
|
-
if (params?.threadId !== threadId || params.turnId !== turnId || run?.eventName !== "stop" && run?.eventName !== "subagentStop" || typeof run.id !== "string" || !run.id) return;
|
|
4297
|
-
if (notification.method === "hook/started") return {
|
|
4298
|
-
phase: "started",
|
|
4299
|
-
runId: run.id
|
|
4300
|
-
};
|
|
4301
|
-
return {
|
|
4302
|
-
phase: "completed",
|
|
4303
|
-
runId: run.id,
|
|
4304
|
-
status: typeof run.status === "string" ? run.status : void 0
|
|
4305
|
-
};
|
|
4306
|
-
}
|
|
4307
|
-
function joinPresentSections(...sections) {
|
|
4308
|
-
return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
|
|
4309
|
-
}
|
|
4310
|
-
function prependCurrentInboundContext(prompt, context) {
|
|
4311
|
-
const text = context?.text.trim();
|
|
4312
|
-
return text ? [text, prompt].filter(Boolean).join("\n\n") : prompt;
|
|
4313
|
-
}
|
|
4314
|
-
function waitForCodexNotificationDispatchTurn() {
|
|
4315
|
-
return new Promise((resolve) => {
|
|
4316
|
-
setImmediate(resolve);
|
|
4317
|
-
});
|
|
4318
|
-
}
|
|
4319
|
-
function buildCodexAppServerTimeoutDiagnostics(params) {
|
|
4320
|
-
const readString = (key) => {
|
|
4321
|
-
const value = params.details?.[key];
|
|
4322
|
-
return typeof value === "string" && value.trim() ? value : void 0;
|
|
4323
|
-
};
|
|
4324
|
-
const readNumber = (key) => {
|
|
4325
|
-
const value = params.details?.[key];
|
|
4326
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
4327
|
-
};
|
|
4328
|
-
const readBoolean = (key) => {
|
|
4329
|
-
const value = params.details?.[key];
|
|
4330
|
-
return typeof value === "boolean" ? value : void 0;
|
|
4331
|
-
};
|
|
4332
|
-
return {
|
|
4333
|
-
...params.idleMs !== void 0 ? { idleMs: params.idleMs } : {},
|
|
4334
|
-
...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
|
|
4335
|
-
...params.lastActivityReason ? { lastActivityReason: params.lastActivityReason } : {},
|
|
4336
|
-
...readString("lastNotificationMethod") ? { lastNotificationMethod: readString("lastNotificationMethod") } : {},
|
|
4337
|
-
...readString("lastNotificationItemId") ? { lastNotificationItemId: readString("lastNotificationItemId") } : {},
|
|
4338
|
-
...readString("lastNotificationItemType") ? { lastNotificationItemType: readString("lastNotificationItemType") } : {},
|
|
4339
|
-
...readString("lastNotificationItemRole") ? { lastNotificationItemRole: readString("lastNotificationItemRole") } : {},
|
|
4340
|
-
...readString("lastAssistantTextPreview") ? { lastAssistantTextPreview: readString("lastAssistantTextPreview") } : {},
|
|
4341
|
-
...readNumber("activeAppServerTurnRequests") !== void 0 ? { activeAppServerTurnRequests: readNumber("activeAppServerTurnRequests") } : {},
|
|
4342
|
-
...readNumber("activeTurnItemCount") !== void 0 ? { activeTurnItemCount: readNumber("activeTurnItemCount") } : {},
|
|
4343
|
-
...readBoolean("terminalTurnNotificationQueued") !== void 0 ? { terminalTurnNotificationQueued: readBoolean("terminalTurnNotificationQueued") } : {},
|
|
4344
|
-
...readBoolean("completionIdleWatchArmed") !== void 0 ? { completionIdleWatchArmed: readBoolean("completionIdleWatchArmed") } : {},
|
|
4345
|
-
...readBoolean("assistantCompletionIdleWatchArmed") !== void 0 ? { assistantCompletionIdleWatchArmed: readBoolean("assistantCompletionIdleWatchArmed") } : {},
|
|
4346
|
-
...readBoolean("terminalIdleWatchArmed") !== void 0 ? { terminalIdleWatchArmed: readBoolean("terminalIdleWatchArmed") } : {}
|
|
4347
|
-
};
|
|
4348
|
-
}
|
|
4349
|
-
//#endregion
|
|
4350
4704
|
//#region extensions/codex/src/app-server/run-attempt-context.ts
|
|
4351
4705
|
async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
4352
4706
|
const { connection, runtimeParams, activeSessionId, activeSessionFile, buildActiveRunAttemptParams, effectiveContextWindowInfo, effectiveContextTokenBudget, effectiveRuntimeProviderId, effectiveRuntimeModelId, hookChannelId } = runtime;
|
|
@@ -4417,7 +4771,7 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
4417
4771
|
memoryToolNames: getCodexWorkspaceMemoryToolNames(toolBridge.availableSpecs),
|
|
4418
4772
|
sandboxed: sandbox?.enabled === true
|
|
4419
4773
|
});
|
|
4420
|
-
const baseDeveloperInstructions =
|
|
4774
|
+
const baseDeveloperInstructions = buildDeveloperInstructions(runtimeParams, { dynamicTools: toolBridge.availableSpecs });
|
|
4421
4775
|
return {
|
|
4422
4776
|
runtime,
|
|
4423
4777
|
attemptTools,
|
|
@@ -4431,7 +4785,13 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
4431
4785
|
baseDeveloperInstructions,
|
|
4432
4786
|
openClawPromptContext: buildCodexOpenClawPromptContext({
|
|
4433
4787
|
params: runtimeParams,
|
|
4434
|
-
workspacePromptContext: workspaceBootstrapContext.promptContext
|
|
4788
|
+
workspacePromptContext: workspaceBootstrapContext.promptContext,
|
|
4789
|
+
watchedSessionsContext: buildCodexWatchedSessionsContext({
|
|
4790
|
+
attempt: runtimeParams,
|
|
4791
|
+
dynamicTools: toolBridge.availableSpecs,
|
|
4792
|
+
sessionKey: contextSessionKey,
|
|
4793
|
+
sandboxed: sandbox?.enabled === true
|
|
4794
|
+
})
|
|
4435
4795
|
}),
|
|
4436
4796
|
skillsCollaborationInstructions: renderCodexSkillsCollaborationInstructions({
|
|
4437
4797
|
attempt: runtimeParams,
|
|
@@ -4625,14 +4985,10 @@ function resolveCodexAppServerReplayBlockedReason(result) {
|
|
|
4625
4985
|
/** Builds an attempt result for failures before the app-server turn starts. */
|
|
4626
4986
|
function buildCodexTurnStartFailureResult(params) {
|
|
4627
4987
|
return {
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
timedOutDuringCompaction: false,
|
|
4633
|
-
timedOutDuringToolExecution: false,
|
|
4634
|
-
promptError: params.promptError ?? params.message,
|
|
4635
|
-
promptErrorSource: "prompt",
|
|
4988
|
+
terminal: attemptTerminal.normalize({
|
|
4989
|
+
promptError: params.promptError ?? params.message,
|
|
4990
|
+
promptErrorSource: "prompt"
|
|
4991
|
+
}),
|
|
4636
4992
|
sessionIdUsed: params.params.sessionId,
|
|
4637
4993
|
messagesSnapshot: params.messagesSnapshot,
|
|
4638
4994
|
assistantTexts: [],
|
|
@@ -4664,6 +5020,107 @@ function isInvalidCodexImagePayloadError(message) {
|
|
|
4664
5020
|
return /\b(?:invalid|malformed)\b[\s\S]{0,120}\b(?:image|image url|base64)\b/iu.test(normalizedMessage) || /\b(?:image|image url|base64)\b[\s\S]{0,120}\b(?:invalid|malformed)\b/iu.test(normalizedMessage);
|
|
4665
5021
|
}
|
|
4666
5022
|
//#endregion
|
|
5023
|
+
//#region extensions/codex/src/app-server/run-attempt-state.ts
|
|
5024
|
+
async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity, fields) {
|
|
5025
|
+
const currentBinding = await bindingStore.read(identity);
|
|
5026
|
+
const expectedThreadId = fields.threadId ?? currentBinding?.threadId;
|
|
5027
|
+
if (!expectedThreadId) return;
|
|
5028
|
+
if (currentBinding && currentBinding.threadId !== expectedThreadId) {
|
|
5029
|
+
embeddedAgentLog.warn("codex app-server image payload error detected for unbound thread; preserving thread binding", {
|
|
5030
|
+
...fields,
|
|
5031
|
+
boundThreadId: currentBinding.threadId
|
|
5032
|
+
});
|
|
5033
|
+
return;
|
|
5034
|
+
}
|
|
5035
|
+
if (currentBinding?.connectionScope === "supervision") {
|
|
5036
|
+
embeddedAgentLog.warn("codex app-server image payload error detected for supervised thread; preserving native binding", fields);
|
|
5037
|
+
return;
|
|
5038
|
+
}
|
|
5039
|
+
embeddedAgentLog.warn("codex app-server image payload error detected; clearing thread binding", fields);
|
|
5040
|
+
await bindingStore.mutate(identity, {
|
|
5041
|
+
kind: "clear",
|
|
5042
|
+
threadId: expectedThreadId
|
|
5043
|
+
});
|
|
5044
|
+
}
|
|
5045
|
+
async function markCodexAppServerBindingCoveredThroughTurn(params) {
|
|
5046
|
+
await params.bindingStore.mutate(params.identity, {
|
|
5047
|
+
kind: "patch",
|
|
5048
|
+
threadId: params.threadId,
|
|
5049
|
+
patch: { historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString() }
|
|
5050
|
+
});
|
|
5051
|
+
}
|
|
5052
|
+
function isNonEmptyString(value) {
|
|
5053
|
+
return typeof value === "string" && value.length > 0;
|
|
5054
|
+
}
|
|
5055
|
+
function shouldUseFreshCodexThreadAfterContextEngineOverflow(params) {
|
|
5056
|
+
if (!params.contextEngineActive || params.thread.lifecycle.action !== "resumed") return false;
|
|
5057
|
+
const message = formatErrorMessage(params.error);
|
|
5058
|
+
return /ran out of room in the model'?s context window/iu.test(message) || /context window/iu.test(message) || /context length/iu.test(message) || /maximum context/iu.test(message) || /too many tokens/iu.test(message);
|
|
5059
|
+
}
|
|
5060
|
+
function isCodexActiveCompactTurnError(error) {
|
|
5061
|
+
if (!(error instanceof CodexAppServerRpcError)) return false;
|
|
5062
|
+
const data = isJsonObject(error.data) ? error.data : void 0;
|
|
5063
|
+
const codexErrorInfo = isJsonObject(data?.codexErrorInfo) ? data.codexErrorInfo : void 0;
|
|
5064
|
+
return (isJsonObject(codexErrorInfo?.activeTurnNotSteerable) ? codexErrorInfo.activeTurnNotSteerable : void 0)?.turnKind === "compact";
|
|
5065
|
+
}
|
|
5066
|
+
function readCodexFinalizationHookNotification(notification, threadId, turnId) {
|
|
5067
|
+
if (notification.method !== "hook/started" && notification.method !== "hook/completed") return;
|
|
5068
|
+
const params = isJsonObject(notification.params) ? notification.params : void 0;
|
|
5069
|
+
const run = params && isJsonObject(params.run) ? params.run : void 0;
|
|
5070
|
+
if (params?.threadId !== threadId || params.turnId !== turnId || run?.eventName !== "stop" && run?.eventName !== "subagentStop" || typeof run.id !== "string" || !run.id) return;
|
|
5071
|
+
if (notification.method === "hook/started") return {
|
|
5072
|
+
phase: "started",
|
|
5073
|
+
runId: run.id
|
|
5074
|
+
};
|
|
5075
|
+
return {
|
|
5076
|
+
phase: "completed",
|
|
5077
|
+
runId: run.id,
|
|
5078
|
+
status: typeof run.status === "string" ? run.status : void 0
|
|
5079
|
+
};
|
|
5080
|
+
}
|
|
5081
|
+
function joinPresentSections(...sections) {
|
|
5082
|
+
return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
|
|
5083
|
+
}
|
|
5084
|
+
function prependCurrentInboundContext(prompt, context) {
|
|
5085
|
+
const text = context?.text.trim();
|
|
5086
|
+
return text ? [text, prompt].filter(Boolean).join("\n\n") : prompt;
|
|
5087
|
+
}
|
|
5088
|
+
function waitForCodexNotificationDispatchTurn() {
|
|
5089
|
+
return new Promise((resolve) => {
|
|
5090
|
+
setImmediate(resolve);
|
|
5091
|
+
});
|
|
5092
|
+
}
|
|
5093
|
+
function buildCodexAppServerTimeoutDiagnostics(params) {
|
|
5094
|
+
const readString = (key) => {
|
|
5095
|
+
const value = params.details?.[key];
|
|
5096
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
5097
|
+
};
|
|
5098
|
+
const readNumber = (key) => {
|
|
5099
|
+
const value = params.details?.[key];
|
|
5100
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
5101
|
+
};
|
|
5102
|
+
const readBoolean = (key) => {
|
|
5103
|
+
const value = params.details?.[key];
|
|
5104
|
+
return typeof value === "boolean" ? value : void 0;
|
|
5105
|
+
};
|
|
5106
|
+
return {
|
|
5107
|
+
...params.idleMs !== void 0 ? { idleMs: params.idleMs } : {},
|
|
5108
|
+
...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
|
|
5109
|
+
...params.lastActivityReason ? { lastActivityReason: params.lastActivityReason } : {},
|
|
5110
|
+
...readString("lastNotificationMethod") ? { lastNotificationMethod: readString("lastNotificationMethod") } : {},
|
|
5111
|
+
...readString("lastNotificationItemId") ? { lastNotificationItemId: readString("lastNotificationItemId") } : {},
|
|
5112
|
+
...readString("lastNotificationItemType") ? { lastNotificationItemType: readString("lastNotificationItemType") } : {},
|
|
5113
|
+
...readString("lastNotificationItemRole") ? { lastNotificationItemRole: readString("lastNotificationItemRole") } : {},
|
|
5114
|
+
...readString("lastAssistantTextPreview") ? { lastAssistantTextPreview: readString("lastAssistantTextPreview") } : {},
|
|
5115
|
+
...readNumber("activeAppServerTurnRequests") !== void 0 ? { activeAppServerTurnRequests: readNumber("activeAppServerTurnRequests") } : {},
|
|
5116
|
+
...readNumber("activeTurnItemCount") !== void 0 ? { activeTurnItemCount: readNumber("activeTurnItemCount") } : {},
|
|
5117
|
+
...readBoolean("terminalTurnNotificationQueued") !== void 0 ? { terminalTurnNotificationQueued: readBoolean("terminalTurnNotificationQueued") } : {},
|
|
5118
|
+
...readBoolean("completionIdleWatchArmed") !== void 0 ? { completionIdleWatchArmed: readBoolean("completionIdleWatchArmed") } : {},
|
|
5119
|
+
...readBoolean("assistantCompletionIdleWatchArmed") !== void 0 ? { assistantCompletionIdleWatchArmed: readBoolean("assistantCompletionIdleWatchArmed") } : {},
|
|
5120
|
+
...readBoolean("terminalIdleWatchArmed") !== void 0 ? { terminalIdleWatchArmed: readBoolean("terminalIdleWatchArmed") } : {}
|
|
5121
|
+
};
|
|
5122
|
+
}
|
|
5123
|
+
//#endregion
|
|
4667
5124
|
//#region extensions/codex/src/app-server/settled-turn-context.ts
|
|
4668
5125
|
function collectUniqueMessageIdentities(messages) {
|
|
4669
5126
|
const identities = /* @__PURE__ */ new Map();
|
|
@@ -4787,14 +5244,6 @@ function createCodexHostTrajectorySink(params) {
|
|
|
4787
5244
|
/** Creates a trajectory recorder when trajectory capture is enabled for the environment. */
|
|
4788
5245
|
function createCodexTrajectoryRecorder(params) {
|
|
4789
5246
|
if (!parseTrajectoryEnabled(params.env ?? process.env)) return null;
|
|
4790
|
-
const sqliteMarker = parseSqliteSessionFileMarker(params.trajectorySessionFile ?? params.attempt.sessionFile);
|
|
4791
|
-
if (!sqliteMarker || sqliteMarker.sessionId !== params.attempt.sessionId) {
|
|
4792
|
-
params.warn?.("codex trajectory capture requires a matching SQLite session target", {
|
|
4793
|
-
sessionId: params.attempt.sessionId,
|
|
4794
|
-
reason: sqliteMarker ? "session-id-mismatch" : "non-sqlite-session-target"
|
|
4795
|
-
});
|
|
4796
|
-
return null;
|
|
4797
|
-
}
|
|
4798
5247
|
if (!params.trajectoryRecorder) {
|
|
4799
5248
|
params.warn?.("codex trajectory capture requires the SQLite host recorder", {
|
|
4800
5249
|
sessionId: params.attempt.sessionId,
|
|
@@ -4843,13 +5292,14 @@ function recordCodexTrajectoryContext(recorder, params) {
|
|
|
4843
5292
|
/** Records final Codex model completion metadata and assistant snapshots. */
|
|
4844
5293
|
function recordCodexTrajectoryCompletion(recorder, params) {
|
|
4845
5294
|
if (!recorder) return;
|
|
5295
|
+
const terminal = attemptTerminal.project(params.result.terminal);
|
|
4846
5296
|
recorder.recordEvent("model.completed", {
|
|
4847
5297
|
threadId: params.threadId,
|
|
4848
5298
|
turnId: params.turnId,
|
|
4849
5299
|
timedOut: params.timedOut,
|
|
4850
5300
|
yieldDetected: params.yieldDetected ?? false,
|
|
4851
|
-
aborted:
|
|
4852
|
-
promptError: normalizeCodexTrajectoryError(
|
|
5301
|
+
aborted: terminal.aborted,
|
|
5302
|
+
promptError: normalizeCodexTrajectoryError(terminal.promptError),
|
|
4853
5303
|
usage: params.result.attemptUsage,
|
|
4854
5304
|
assistantTexts: params.result.assistantTexts,
|
|
4855
5305
|
messagesSnapshot: params.result.messagesSnapshot
|
|
@@ -4943,11 +5393,12 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4943
5393
|
});
|
|
4944
5394
|
}
|
|
4945
5395
|
const result = activeProjector.buildResult(toolBridge.telemetry, { yieldDetected: toolState.yieldDetected });
|
|
5396
|
+
const projectedTerminal = attemptTerminal.project(result.terminal);
|
|
4946
5397
|
const effectiveTimedOut = state.timedOut && !recoveredTurnWatchTimeout;
|
|
4947
5398
|
const effectiveTurnCompletionIdleTimedOut = state.turnCompletionIdleTimedOut && !recoveredTurnWatchTimeout;
|
|
4948
|
-
const isFinalAborted = () =>
|
|
5399
|
+
const isFinalAborted = () => projectedTerminal.aborted || terminalState.explicitCancellationObserved || runAbortController.signal.aborted && !state.clientClosedAbort && !recoveredTurnWatchTimeout;
|
|
4949
5400
|
const clientClosedPromptErrorForFinal = state.clientClosedPromptError && hasRecoverableCompletedAssistant ? void 0 : state.clientClosedPromptError;
|
|
4950
|
-
let finalPromptError = clientClosedPromptErrorForFinal ?? (effectiveTurnCompletionIdleTimedOut ? state.turnCompletionIdleTimeoutMessage : effectiveTimedOut ? "codex app-server attempt timed out" :
|
|
5401
|
+
let finalPromptError = clientClosedPromptErrorForFinal ?? (effectiveTurnCompletionIdleTimedOut ? state.turnCompletionIdleTimeoutMessage : effectiveTimedOut ? "codex app-server attempt timed out" : projectedTerminal.promptError);
|
|
4951
5402
|
const finalPromptErrorMessage = typeof finalPromptError === "string" ? finalPromptError : finalPromptError instanceof Error ? finalPromptError.message : finalPromptError ? formatErrorMessage(finalPromptError) : void 0;
|
|
4952
5403
|
if (isInvalidCodexImagePayloadError(finalPromptErrorMessage)) await clearCodexBindingAfterInvalidImagePayload(bindingStore, bindingIdentity, {
|
|
4953
5404
|
phase: "turn_completed",
|
|
@@ -4988,7 +5439,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4988
5439
|
authProfileId: startupAuthProfileId,
|
|
4989
5440
|
rateLimits: readRecentCodexRateLimits(resourceState.client)
|
|
4990
5441
|
});
|
|
4991
|
-
const finalPromptErrorSource = effectiveTimedOut || clientClosedPromptErrorForFinal ? "prompt" :
|
|
5442
|
+
const finalPromptErrorSource = effectiveTimedOut || clientClosedPromptErrorForFinal ? "prompt" : projectedTerminal.promptErrorSource;
|
|
4992
5443
|
const codexAppServerFailureKind = clientClosedPromptErrorForFinal ? "client_closed_before_turn_completed" : effectiveTurnCompletionIdleTimedOut ? "turn_completion_idle_timeout" : void 0;
|
|
4993
5444
|
const replayBlockedReason = codexAppServerFailureKind ? resolveCodexAppServerReplayBlockedReason(result) : void 0;
|
|
4994
5445
|
const promptTimeoutOutcome = buildCodexAppServerPromptTimeoutOutcome({
|
|
@@ -5122,7 +5573,29 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
5122
5573
|
...finalPromptError ? { error: formatErrorMessage(finalPromptError) } : {},
|
|
5123
5574
|
durationMs: Date.now() - attemptStartedAt
|
|
5124
5575
|
},
|
|
5125
|
-
ctx:
|
|
5576
|
+
ctx: {
|
|
5577
|
+
...hookContext,
|
|
5578
|
+
modelProviderId: resourceState.thread.modelProvider ?? effectiveRuntimeProviderId,
|
|
5579
|
+
modelId: resourceState.thread.model ?? effectiveRuntimeModelId,
|
|
5580
|
+
authProfileId: resourceState.thread.authProfileId ?? startupAuthProfileId,
|
|
5581
|
+
modelIterations: result.modelIterations ?? 0,
|
|
5582
|
+
skillWorkshopAvailable: flattenCodexDynamicToolFunctions(attemptTools.toolBridge.availableSpecs).some((tool) => tool.name === "skill_workshop"),
|
|
5583
|
+
compacted: (result.compactionCount ?? 0) > 0,
|
|
5584
|
+
messageChannel: params.messageChannel,
|
|
5585
|
+
messageProvider: params.messageProvider,
|
|
5586
|
+
chatType: params.chatType,
|
|
5587
|
+
agentAccountId: params.agentAccountId,
|
|
5588
|
+
groupId: params.groupId,
|
|
5589
|
+
groupChannel: params.groupChannel,
|
|
5590
|
+
groupSpace: params.groupSpace,
|
|
5591
|
+
memberRoleIds: params.memberRoleIds,
|
|
5592
|
+
spawnedBy: params.spawnedBy,
|
|
5593
|
+
senderId: params.senderId ?? void 0,
|
|
5594
|
+
senderName: params.senderName,
|
|
5595
|
+
senderUsername: params.senderUsername,
|
|
5596
|
+
senderE164: params.senderE164,
|
|
5597
|
+
senderIsOwner: params.senderIsOwner
|
|
5598
|
+
},
|
|
5126
5599
|
hookRunner
|
|
5127
5600
|
});
|
|
5128
5601
|
state.shouldDelayNativeHookRelayUnregister = completedTurnStatus === "completed" && !effectiveTimedOut && !runAbortController.signal.aborted && !finalAborted && !finalPromptError;
|
|
@@ -5183,10 +5656,12 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
5183
5656
|
});
|
|
5184
5657
|
return {
|
|
5185
5658
|
...result,
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5659
|
+
terminal: attemptTerminal.normalize({
|
|
5660
|
+
timedOut: effectiveTimedOut,
|
|
5661
|
+
aborted: finalAborted,
|
|
5662
|
+
promptError: finalPromptError,
|
|
5663
|
+
promptErrorSource: finalPromptErrorSource
|
|
5664
|
+
}),
|
|
5190
5665
|
...codexAppServerFailure ? { codexAppServerFailure } : {},
|
|
5191
5666
|
...promptTimeoutOutcome ? { promptTimeoutOutcome } : {},
|
|
5192
5667
|
...assistantTranscriptOwned ? { assistantTranscriptOwned: true } : {},
|
|
@@ -6009,6 +6484,9 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
6009
6484
|
}
|
|
6010
6485
|
//#endregion
|
|
6011
6486
|
//#region extensions/codex/src/app-server/run-attempt-prompt.ts
|
|
6487
|
+
function isRestrictivePromptToolsAllow(toolsAllow) {
|
|
6488
|
+
return toolsAllow !== void 0 && !toolsAllow.some((name) => name.trim() === "*");
|
|
6489
|
+
}
|
|
6012
6490
|
async function prepareCodexAttemptPrompt(context) {
|
|
6013
6491
|
const { runtime, attemptTools, historyState, hookContext, workspaceBootstrapContext, baseDeveloperInstructions, openClawPromptContext, skillsCollaborationInstructions, promptState, codexContextProjectionMaxChars } = context;
|
|
6014
6492
|
const { connection, buildActiveRunAttemptParams, effectiveContextTokenBudget, effectiveRuntimeModelId, effectiveRuntimeProviderId } = runtime;
|
|
@@ -6094,13 +6572,17 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
6094
6572
|
embeddedAgentLog.warn("context engine assemble failed; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
|
|
6095
6573
|
}
|
|
6096
6574
|
const codexModelInputHistoryMessages = [];
|
|
6097
|
-
const buildPromptFromCurrentInputs = () =>
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6575
|
+
const buildPromptFromCurrentInputs = async () => {
|
|
6576
|
+
const result = await resolveAgentHarnessBeforePromptBuildResult({
|
|
6577
|
+
prompt: prependCurrentInboundContext(promptState.promptText, params.currentInboundContext),
|
|
6578
|
+
developerInstructions: promptState.developerInstructions,
|
|
6579
|
+
messages: structuredClone(historyState.messages),
|
|
6580
|
+
ctx: hookContext,
|
|
6581
|
+
bootstrapContextRunKind: params.bootstrapContextRunKind
|
|
6582
|
+
});
|
|
6583
|
+
if (isRestrictivePromptToolsAllow(result.toolsAllow)) throw new Error("Codex app-server cannot enforce before_prompt_build toolsAllow; use the embedded or Copilot runtime for turn-scoped tool policy.");
|
|
6584
|
+
return result;
|
|
6585
|
+
};
|
|
6104
6586
|
const resolveShiftedPromptInputRange = (prompt, promptInputRange, turnPromptText) => {
|
|
6105
6587
|
if (!promptInputRange || promptInputRange.start < 0 || promptInputRange.end < promptInputRange.start || promptInputRange.end > prompt.length || !turnPromptText.endsWith(prompt)) return;
|
|
6106
6588
|
const turnPromptOffset = turnPromptText.length - prompt.length;
|
|
@@ -7769,8 +8251,10 @@ const sandboxExecServerRegistry = {
|
|
|
7769
8251
|
};
|
|
7770
8252
|
//#endregion
|
|
7771
8253
|
//#region extensions/codex/src/app-server/sandbox-exec-server/json-rpc.ts
|
|
7772
|
-
/** JSON-RPC error code used when a sandbox
|
|
8254
|
+
/** JSON-RPC error code used when a sandbox filesystem resource does not exist. */
|
|
7773
8255
|
const JSON_RPC_NOT_FOUND = -32004;
|
|
8256
|
+
/** JSON-RPC error code used when a sandbox exec-server method is unsupported. */
|
|
8257
|
+
const JSON_RPC_METHOD_NOT_FOUND = -32601;
|
|
7774
8258
|
/** Protocol-level error carrying the JSON-RPC error code to send to the client. */
|
|
7775
8259
|
var JsonRpcProtocolError = class extends Error {
|
|
7776
8260
|
constructor(code, message) {
|
|
@@ -8102,6 +8586,101 @@ function requireFsBridge(execServer) {
|
|
|
8102
8586
|
* with OpenClaw sandbox policy checks before every bridge operation.
|
|
8103
8587
|
*/
|
|
8104
8588
|
const CODEX_SANDBOX_EXEC_SERVER_MAX_READ_FILE_BYTES = 512 * 1024 * 1024;
|
|
8589
|
+
const CODEX_SANDBOX_EXEC_SERVER_MAX_OPEN_FILE_READS = 128;
|
|
8590
|
+
const CODEX_SANDBOX_EXEC_SERVER_MAX_BUFFERED_FILE_READ_BYTES = 64 * 1024 * 1024;
|
|
8591
|
+
const CODEX_SANDBOX_EXEC_SERVER_MAX_READ_BLOCK_BYTES = 1024 * 1024;
|
|
8592
|
+
const CODEX_SANDBOX_EXEC_SERVER_MAX_FILE_READ_HANDLE_ID_BYTES = 32;
|
|
8593
|
+
/** Opens a policy-checked sandbox file under a bounded, connection-owned handle. */
|
|
8594
|
+
async function openFile(execServer, handles, params) {
|
|
8595
|
+
const record = requireObject(params, "fs/open params");
|
|
8596
|
+
const handleId = requireFileReadHandleId(record.handleId);
|
|
8597
|
+
if (handles.closed) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, `unknown file read handle \`${handleId}\``);
|
|
8598
|
+
if (handles.has(handleId)) throw new JsonRpcProtocolError(-32600, `file read handle \`${handleId}\` already exists`);
|
|
8599
|
+
if (handles.size >= CODEX_SANDBOX_EXEC_SERVER_MAX_OPEN_FILE_READS) throw new JsonRpcProtocolError(-32600, `at most ${CODEX_SANDBOX_EXEC_SERVER_MAX_OPEN_FILE_READS} file reads may be open per connection`);
|
|
8600
|
+
const filePath = resolveExecServerPath(requireString(record.path, "path"), "read path");
|
|
8601
|
+
assertFsSandboxAccess(execServer, record, [{
|
|
8602
|
+
path: filePath,
|
|
8603
|
+
access: "read"
|
|
8604
|
+
}]);
|
|
8605
|
+
const fsBridge = requireFsBridge(execServer);
|
|
8606
|
+
const handle = {
|
|
8607
|
+
abortController: new AbortController(),
|
|
8608
|
+
closeRequested: false,
|
|
8609
|
+
reservedBytes: 0
|
|
8610
|
+
};
|
|
8611
|
+
handles.set(handleId, handle);
|
|
8612
|
+
try {
|
|
8613
|
+
const stat = await fsBridge.stat({
|
|
8614
|
+
filePath,
|
|
8615
|
+
signal: handle.abortController.signal
|
|
8616
|
+
});
|
|
8617
|
+
if (handles.get(handleId) !== handle || handle.closeRequested || handles.closed) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, `unknown file read handle \`${handleId}\``);
|
|
8618
|
+
if (!stat) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, "file not found");
|
|
8619
|
+
if (stat.type !== "file") throw new JsonRpcProtocolError(-32600, "file read handle requires a regular file");
|
|
8620
|
+
if (!Number.isSafeInteger(stat.size) || stat.size < 0) throw new JsonRpcProtocolError(-32600, "file size must be a non-negative safe integer");
|
|
8621
|
+
if (stat.size > CODEX_SANDBOX_EXEC_SERVER_MAX_BUFFERED_FILE_READ_BYTES - bufferedFileReadBytes(handles)) throw new JsonRpcProtocolError(-32600, "sandbox file read exceeds the per-connection buffered file limit");
|
|
8622
|
+
handle.reservedBytes = stat.size;
|
|
8623
|
+
const data = await fsBridge.readFile({
|
|
8624
|
+
filePath,
|
|
8625
|
+
maxBytes: handle.reservedBytes,
|
|
8626
|
+
signal: handle.abortController.signal
|
|
8627
|
+
});
|
|
8628
|
+
if (handles.get(handleId) !== handle || handle.closeRequested || handles.closed) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, `unknown file read handle \`${handleId}\``);
|
|
8629
|
+
if (data.byteLength > handle.reservedBytes) throw new JsonRpcProtocolError(-32600, "sandbox file read exceeds the per-connection buffered file limit");
|
|
8630
|
+
handle.reservedBytes = data.byteLength;
|
|
8631
|
+
handle.data = data;
|
|
8632
|
+
return { handleId };
|
|
8633
|
+
} catch (error) {
|
|
8634
|
+
if (handles.get(handleId) === handle) handles.delete(handleId);
|
|
8635
|
+
throw error;
|
|
8636
|
+
}
|
|
8637
|
+
}
|
|
8638
|
+
/** Reads a bounded base64 block from a handle belonging to this connection. */
|
|
8639
|
+
function readFileBlock(handles, params) {
|
|
8640
|
+
const record = requireObject(params, "fs/readBlock params");
|
|
8641
|
+
const handleId = requireFileReadHandleId(record.handleId);
|
|
8642
|
+
const handle = handles.get(handleId);
|
|
8643
|
+
if (!handle?.data) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, `unknown file read handle \`${handleId}\``);
|
|
8644
|
+
const offset = requireNumber(record.offset, "offset");
|
|
8645
|
+
const length = requireNumber(record.len, "len");
|
|
8646
|
+
if (!Number.isSafeInteger(offset) || offset < 0) throw new JsonRpcProtocolError(-32600, "file read offset must be a non-negative safe integer");
|
|
8647
|
+
if (!Number.isSafeInteger(length) || length < 1 || length > CODEX_SANDBOX_EXEC_SERVER_MAX_READ_BLOCK_BYTES) throw new JsonRpcProtocolError(-32600, `file read block length must be between 1 and ${CODEX_SANDBOX_EXEC_SERVER_MAX_READ_BLOCK_BYTES}`);
|
|
8648
|
+
const chunk = handle.data.subarray(offset, Math.min(offset + length, handle.data.byteLength));
|
|
8649
|
+
return {
|
|
8650
|
+
chunk: chunk.toString("base64"),
|
|
8651
|
+
eof: offset + chunk.byteLength >= handle.data.byteLength
|
|
8652
|
+
};
|
|
8653
|
+
}
|
|
8654
|
+
/** Closes one connection-owned file handle; repeated closes are harmless. */
|
|
8655
|
+
function closeFile(handles, params) {
|
|
8656
|
+
closeFileReadHandle(handles, requireFileReadHandleId(requireObject(params, "fs/close params").handleId));
|
|
8657
|
+
return {};
|
|
8658
|
+
}
|
|
8659
|
+
/** Cancels a disconnected socket without releasing unsettled read reservations. */
|
|
8660
|
+
function closeAllFileReads(handles) {
|
|
8661
|
+
handles.closed = true;
|
|
8662
|
+
for (const handleId of handles.keys()) closeFileReadHandle(handles, handleId);
|
|
8663
|
+
}
|
|
8664
|
+
function closeFileReadHandle(handles, handleId) {
|
|
8665
|
+
const handle = handles.get(handleId);
|
|
8666
|
+
if (!handle) return;
|
|
8667
|
+
handle.closeRequested = true;
|
|
8668
|
+
if (handle.data !== void 0) {
|
|
8669
|
+
handles.delete(handleId);
|
|
8670
|
+
return;
|
|
8671
|
+
}
|
|
8672
|
+
handle.abortController.abort();
|
|
8673
|
+
}
|
|
8674
|
+
function bufferedFileReadBytes(handles) {
|
|
8675
|
+
let total = 0;
|
|
8676
|
+
for (const handle of handles.values()) total += handle.reservedBytes;
|
|
8677
|
+
return total;
|
|
8678
|
+
}
|
|
8679
|
+
function requireFileReadHandleId(value) {
|
|
8680
|
+
const handleId = requireString(value, "handleId");
|
|
8681
|
+
if (Buffer.byteLength(handleId, "utf8") > CODEX_SANDBOX_EXEC_SERVER_MAX_FILE_READ_HANDLE_ID_BYTES) throw new JsonRpcProtocolError(-32600, `file read handle ID must not exceed ${CODEX_SANDBOX_EXEC_SERVER_MAX_FILE_READ_HANDLE_ID_BYTES} bytes`);
|
|
8682
|
+
return handleId;
|
|
8683
|
+
}
|
|
8105
8684
|
/** Reads a sandbox file as base64 after read-policy and size checks. */
|
|
8106
8685
|
async function readFile(execServer, params) {
|
|
8107
8686
|
const record = requireObject(params, "fs/readFile params");
|
|
@@ -8114,7 +8693,10 @@ async function readFile(execServer, params) {
|
|
|
8114
8693
|
const stat = await fsBridge.stat({ filePath });
|
|
8115
8694
|
if (!stat) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, "file not found");
|
|
8116
8695
|
assertSandboxFileReadWithinLimit(stat);
|
|
8117
|
-
return { dataBase64: (await fsBridge.readFile({
|
|
8696
|
+
return { dataBase64: (await fsBridge.readFile({
|
|
8697
|
+
filePath,
|
|
8698
|
+
maxBytes: CODEX_SANDBOX_EXEC_SERVER_MAX_READ_FILE_BYTES
|
|
8699
|
+
})).toString("base64") };
|
|
8118
8700
|
}
|
|
8119
8701
|
/** Writes base64 data to an existing sandbox directory after write-policy checks. */
|
|
8120
8702
|
async function writeFile(execServer, params) {
|
|
@@ -8263,7 +8845,10 @@ async function copySandboxPath(execServer, params) {
|
|
|
8263
8845
|
return;
|
|
8264
8846
|
}
|
|
8265
8847
|
assertSandboxFileReadWithinLimit(sourceStat);
|
|
8266
|
-
const data = await fsBridge.readFile({
|
|
8848
|
+
const data = await fsBridge.readFile({
|
|
8849
|
+
filePath: params.sourcePath,
|
|
8850
|
+
maxBytes: CODEX_SANDBOX_EXEC_SERVER_MAX_READ_FILE_BYTES
|
|
8851
|
+
});
|
|
8267
8852
|
await fsBridge.writeFile({
|
|
8268
8853
|
filePath: params.destinationPath,
|
|
8269
8854
|
data,
|
|
@@ -8278,6 +8863,7 @@ function metadataResponse(stat) {
|
|
|
8278
8863
|
isDirectory: stat?.type === "directory",
|
|
8279
8864
|
isFile: stat?.type === "file",
|
|
8280
8865
|
isSymlink: false,
|
|
8866
|
+
size: stat?.size ?? 0,
|
|
8281
8867
|
createdAtMs: 0,
|
|
8282
8868
|
modifiedAtMs: stat?.mtimeMs ?? 0
|
|
8283
8869
|
};
|
|
@@ -9139,19 +9725,21 @@ function isAuthorizedExecServerRequest(execServer, request) {
|
|
|
9139
9725
|
}
|
|
9140
9726
|
function handleConnection(execServer, socket) {
|
|
9141
9727
|
const processes = /* @__PURE__ */ new Map();
|
|
9728
|
+
const fileReads = /* @__PURE__ */ new Map();
|
|
9142
9729
|
socket.on("message", (data) => {
|
|
9143
|
-
handleMessage(execServer, processes, socket, data).catch((error) => {
|
|
9730
|
+
handleMessage(execServer, processes, fileReads, socket, data).catch((error) => {
|
|
9144
9731
|
embeddedAgentLog.warn("codex sandbox exec-server message failed", { error });
|
|
9145
9732
|
});
|
|
9146
9733
|
});
|
|
9147
9734
|
socket.on("close", () => {
|
|
9735
|
+
closeAllFileReads(fileReads);
|
|
9148
9736
|
for (const process of processes.values()) process.abortController.abort();
|
|
9149
9737
|
});
|
|
9150
9738
|
}
|
|
9151
9739
|
function handleExecServerSocketError(error) {
|
|
9152
9740
|
embeddedAgentLog.debug("codex sandbox exec-server websocket failed", { error });
|
|
9153
9741
|
}
|
|
9154
|
-
async function handleMessage(execServer, processes, socket, data) {
|
|
9742
|
+
async function handleMessage(execServer, processes, fileReads, socket, data) {
|
|
9155
9743
|
const request = parseRequest(data);
|
|
9156
9744
|
if (!request.method) {
|
|
9157
9745
|
sendError(socket, request.id, -32600, "Invalid Request");
|
|
@@ -9163,7 +9751,7 @@ async function handleMessage(execServer, processes, socket, data) {
|
|
|
9163
9751
|
return;
|
|
9164
9752
|
}
|
|
9165
9753
|
try {
|
|
9166
|
-
const result = await dispatchRequest(execServer, processes, socket, {
|
|
9754
|
+
const result = await dispatchRequest(execServer, processes, fileReads, socket, {
|
|
9167
9755
|
...request,
|
|
9168
9756
|
method
|
|
9169
9757
|
});
|
|
@@ -9172,13 +9760,25 @@ async function handleMessage(execServer, processes, socket, data) {
|
|
|
9172
9760
|
sendError(socket, request.id, error instanceof JsonRpcProtocolError ? error.code : -32603, error instanceof Error ? error.message : String(error));
|
|
9173
9761
|
}
|
|
9174
9762
|
}
|
|
9175
|
-
async function dispatchRequest(execServer, processes, socket, request) {
|
|
9763
|
+
async function dispatchRequest(execServer, processes, fileReads, socket, request) {
|
|
9176
9764
|
switch (request.method) {
|
|
9177
9765
|
case "initialize": return { sessionId: randomUUID() };
|
|
9766
|
+
case "environment/info": return {
|
|
9767
|
+
shell: {
|
|
9768
|
+
name: "sh",
|
|
9769
|
+
path: "/bin/sh"
|
|
9770
|
+
},
|
|
9771
|
+
cwd: pathToFileURL(execServer.sandbox.containerWorkdir, { windows: false }).href,
|
|
9772
|
+
capabilities: { networkProxyLaunch: false }
|
|
9773
|
+
};
|
|
9774
|
+
case "environment/status": return { status: "ready" };
|
|
9178
9775
|
case "process/start": return startProcess(execServer, processes, socket, request.params);
|
|
9179
9776
|
case "process/read": return await readProcess(processes, request.params);
|
|
9180
9777
|
case "process/write": return writeProcess(processes, request.params);
|
|
9181
9778
|
case "process/terminate": return terminateProcess(processes, request.params);
|
|
9779
|
+
case "fs/open": return await openFile(execServer, fileReads, request.params);
|
|
9780
|
+
case "fs/readBlock": return readFileBlock(fileReads, request.params);
|
|
9781
|
+
case "fs/close": return closeFile(fileReads, request.params);
|
|
9182
9782
|
case "fs/readFile": return await readFile(execServer, request.params);
|
|
9183
9783
|
case "fs/writeFile":
|
|
9184
9784
|
await writeFile(execServer, request.params);
|
|
@@ -9195,7 +9795,7 @@ async function dispatchRequest(execServer, processes, socket, request) {
|
|
|
9195
9795
|
await copyPath(execServer, request.params);
|
|
9196
9796
|
return {};
|
|
9197
9797
|
case "http/request": return await httpRequest(execServer, socket, request.params);
|
|
9198
|
-
default: throw new
|
|
9798
|
+
default: throw new JsonRpcProtocolError(JSON_RPC_METHOD_NOT_FOUND, `Unsupported OpenClaw sandbox exec-server method: ${request.method}`);
|
|
9199
9799
|
}
|
|
9200
9800
|
}
|
|
9201
9801
|
//#endregion
|
|
@@ -9213,7 +9813,6 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
9213
9813
|
developerInstructions: buildRenderedCodexDeveloperInstructions(),
|
|
9214
9814
|
prompt: turnState.codexTurnPromptText,
|
|
9215
9815
|
trajectoryRecorder: hostTrajectoryRecorder,
|
|
9216
|
-
trajectorySessionFile: params.trajectorySessionFile,
|
|
9217
9816
|
tools: toolBridge.availableSpecs,
|
|
9218
9817
|
warn: (message, fields) => embeddedAgentLog.warn(message, fields)
|
|
9219
9818
|
});
|
|
@@ -9323,14 +9922,7 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
9323
9922
|
timeoutFloorMs: options.startupTimeoutFloorMs
|
|
9324
9923
|
});
|
|
9325
9924
|
const requesterChannel = params.messageChannel ?? params.messageProvider;
|
|
9326
|
-
const requester =
|
|
9327
|
-
...requesterChannel ? { channel: requesterChannel } : {},
|
|
9328
|
-
...params.agentAccountId ? { accountId: params.agentAccountId } : {},
|
|
9329
|
-
...params.senderId ? { senderId: params.senderId } : {},
|
|
9330
|
-
...params.senderIsOwner !== void 0 ? { senderIsOwner: params.senderIsOwner } : {},
|
|
9331
|
-
...params.memberRoleIds?.length ? { roleIds: [...params.memberRoleIds] } : {}
|
|
9332
|
-
};
|
|
9333
|
-
const hasRequester = Object.keys(requester).length > 0;
|
|
9925
|
+
const requester = buildCodexHookRequester(params);
|
|
9334
9926
|
const buildNativeHookRelayFinalConfigPatch = (decision) => {
|
|
9335
9927
|
state.nativeHookRelay?.unregister();
|
|
9336
9928
|
state.nativeHookRelay = createCodexNativeHookRelay({
|
|
@@ -9344,7 +9936,15 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
9344
9936
|
config: params.config,
|
|
9345
9937
|
runId: params.runId,
|
|
9346
9938
|
channelId: hookChannelId,
|
|
9347
|
-
...
|
|
9939
|
+
...requester ? { requester } : {},
|
|
9940
|
+
approvalContext: {
|
|
9941
|
+
trigger: params.trigger,
|
|
9942
|
+
approvalReviewerDeviceId: params.approvalReviewerDeviceId,
|
|
9943
|
+
turnSourceChannel: requesterChannel,
|
|
9944
|
+
turnSourceTo: params.currentMessagingTarget ?? params.currentChannelId,
|
|
9945
|
+
turnSourceAccountId: params.agentAccountId,
|
|
9946
|
+
turnSourceThreadId: params.currentThreadTs
|
|
9947
|
+
},
|
|
9348
9948
|
attemptTimeoutMs: params.timeoutMs,
|
|
9349
9949
|
startupTimeoutMs,
|
|
9350
9950
|
turnStartTimeoutMs: params.timeoutMs,
|
|
@@ -9454,6 +10054,28 @@ async function prepareCodexAttemptRoute(resources, turnRuntime, notifications, h
|
|
|
9454
10054
|
return { ensureCurrentThreadRoute };
|
|
9455
10055
|
}
|
|
9456
10056
|
//#endregion
|
|
10057
|
+
//#region extensions/codex/src/app-server/run-attempt-client-prewarm.ts
|
|
10058
|
+
/** Starts the shared process while tools and prompt context are still being prepared. */
|
|
10059
|
+
function prewarmCodexAttemptClient(params) {
|
|
10060
|
+
const { connection, authProfileStore, authBindingFingerprint } = params;
|
|
10061
|
+
const { appServer, attemptClientFactory, options, pluginConfig, runtimeArtifactRequest, startupAuthRequirement, startupClientAuthProfileId, startupPreparedAuth, agentDir, params: runParams, runAbortController } = connection;
|
|
10062
|
+
if (options.clientFactory || attemptClientFactory !== getLeasedSharedCodexAppServerClient || runtimeArtifactRequest) return;
|
|
10063
|
+
getSharedCodexAppServerClient({
|
|
10064
|
+
startOptions: appServer.start,
|
|
10065
|
+
pluginConfig,
|
|
10066
|
+
...startupPreparedAuth ? { preparedAuth: startupPreparedAuth } : { authProfileId: startupClientAuthProfileId },
|
|
10067
|
+
authRequirement: startupAuthRequirement,
|
|
10068
|
+
authProfileStore,
|
|
10069
|
+
authBindingFingerprint,
|
|
10070
|
+
agentDir,
|
|
10071
|
+
config: runParams.config,
|
|
10072
|
+
timeoutMs: appServer.requestTimeoutMs,
|
|
10073
|
+
abandonSignal: runAbortController.signal
|
|
10074
|
+
}).catch((error) => {
|
|
10075
|
+
embeddedAgentLog.debug("codex app-server client prewarm failed", { error });
|
|
10076
|
+
});
|
|
10077
|
+
}
|
|
10078
|
+
//#endregion
|
|
9457
10079
|
//#region extensions/codex/src/app-server/run-attempt-runtime.ts
|
|
9458
10080
|
async function prepareCodexAttemptRuntime(connection) {
|
|
9459
10081
|
const { params, pluginConfig, usesSupervisionConnection, appServer, startupAuthProfileId, startupPreparedAuth, startupClientAuthProfileId, agentDir, preDynamicStartupStages, effectiveWorkspace, contextSessionKey, sandboxSessionKey, sessionAgentId, sandbox, attemptClientFactory, runAbortController, activeContextEngine, mutable } = connection;
|
|
@@ -9464,6 +10086,11 @@ async function prepareCodexAttemptRuntime(connection) {
|
|
|
9464
10086
|
config: params.config
|
|
9465
10087
|
}) : void 0;
|
|
9466
10088
|
const attemptAuthProfileStore = preparedAuthBinding?.authProfileStore ?? params.authProfileStore;
|
|
10089
|
+
prewarmCodexAttemptClient({
|
|
10090
|
+
connection,
|
|
10091
|
+
authProfileStore: attemptAuthProfileStore,
|
|
10092
|
+
authBindingFingerprint: preparedAuthBinding?.fingerprint
|
|
10093
|
+
});
|
|
9467
10094
|
const effectiveContextWindowInfo = usesSupervisionConnection ? void 0 : params.contextWindowInfo;
|
|
9468
10095
|
const effectiveContextTokenBudget = usesSupervisionConnection ? void 0 : params.contextTokenBudget;
|
|
9469
10096
|
const effectiveRuntimeProviderId = usesSupervisionConnection ? mutable.startupBinding?.modelProvider ?? "codex" : params.provider;
|
|
@@ -9491,6 +10118,7 @@ async function prepareCodexAttemptRuntime(connection) {
|
|
|
9491
10118
|
modelId: effectiveRuntimeModelId,
|
|
9492
10119
|
model: supervisedRuntimeModel,
|
|
9493
10120
|
thinkLevel: _outerThinkLevel,
|
|
10121
|
+
fastMode: _outerFastMode,
|
|
9494
10122
|
sessionKey: contextSessionKey
|
|
9495
10123
|
} : {
|
|
9496
10124
|
...params,
|
|
@@ -9518,7 +10146,8 @@ async function prepareCodexAttemptRuntime(connection) {
|
|
|
9518
10146
|
cfg: params.config,
|
|
9519
10147
|
toolsEnabled: usesSupervisionConnection || supportsModelTools(params.model),
|
|
9520
10148
|
disableTools: params.disableTools,
|
|
9521
|
-
toolsAllow: params.toolsAllow
|
|
10149
|
+
toolsAllow: params.toolsAllow,
|
|
10150
|
+
toolOverrides: params.toolOverrides
|
|
9522
10151
|
});
|
|
9523
10152
|
preDynamicStartupStages.mark("bundle-mcp");
|
|
9524
10153
|
const sandboxExecServerEnabled = isCodexSandboxExecServerEnabled(pluginConfig);
|
|
@@ -9592,7 +10221,8 @@ function recordCodexDynamicToolResult(projector, call, response, protocolRespons
|
|
|
9592
10221
|
success: protocolResponse.success,
|
|
9593
10222
|
terminalType: response.diagnosticTerminalType ?? (protocolResponse.success ? "completed" : "error"),
|
|
9594
10223
|
sideEffectEvidence: response.sideEffectEvidence === true || response.terminalResolution?.sideEffectEvidence === true,
|
|
9595
|
-
contentItems: protocolResponse.contentItems
|
|
10224
|
+
contentItems: protocolResponse.contentItems,
|
|
10225
|
+
details: response.transcriptDetails
|
|
9596
10226
|
});
|
|
9597
10227
|
}
|
|
9598
10228
|
//#endregion
|
|
@@ -9669,6 +10299,7 @@ function handleApprovalRequest(params) {
|
|
|
9669
10299
|
turnId: params.turnId,
|
|
9670
10300
|
nativeHookRelay: params.nativeHookRelay,
|
|
9671
10301
|
autoApprove: params.autoApprove,
|
|
10302
|
+
autoApproveOpenClawToolPolicy: params.autoApproveOpenClawToolPolicy,
|
|
9672
10303
|
signal: params.signal,
|
|
9673
10304
|
onNativeToolFailureDisposition: params.onNativeToolFailureDisposition
|
|
9674
10305
|
});
|
|
@@ -9686,7 +10317,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
9686
10317
|
const { context } = prompt;
|
|
9687
10318
|
const { runtime, attemptTools } = context;
|
|
9688
10319
|
const { connection } = runtime;
|
|
9689
|
-
const { params, computerUseConfig, runAbortController, appServer, sessionAgentId } = connection;
|
|
10320
|
+
const { params, computerUseConfig, runAbortController, appServer, approvalPolicyPromotedForOpenClawToolPolicy, sessionAgentId } = connection;
|
|
9690
10321
|
const { toolBridge, toolOutcomeOrdinals, suppressedDynamicToolOutcomeOrdinals, allocateCodexToolOutcomeOrdinal } = attemptTools;
|
|
9691
10322
|
const { state, turnIdRef, userInputBridgeRef, openClawDynamicToolExecutions, pendingOpenClawDynamicToolCompletionIds, postToolRawAssistantCompletionIdleTimeoutMs, turnWatches } = turnRuntime;
|
|
9692
10323
|
const { emitExecutionPhaseOnce, scheduleTurnReleaseAfterTerminalDynamicTool, scheduleTerminalDynamicToolReleaseCheck } = lifecycle;
|
|
@@ -9744,6 +10375,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
9744
10375
|
turnId,
|
|
9745
10376
|
nativeHookRelay: resourceState.nativeHookRelay,
|
|
9746
10377
|
autoApprove: shouldAutoApproveCodexAppServerApprovals(appServer),
|
|
10378
|
+
autoApproveOpenClawToolPolicy: approvalPolicyPromotedForOpenClawToolPolicy,
|
|
9747
10379
|
signal,
|
|
9748
10380
|
onNativeToolFailureDisposition: (itemId, disposition) => projector?.recordNativeToolApprovalFailure(itemId, disposition)
|
|
9749
10381
|
});
|
|
@@ -10045,8 +10677,8 @@ var CodexPluginMetadataCache = class {
|
|
|
10045
10677
|
this.clearGeneration = 0;
|
|
10046
10678
|
}
|
|
10047
10679
|
/** Returns a fresh cached snapshot without issuing a request. */
|
|
10048
|
-
read(appCacheKey, queryKind) {
|
|
10049
|
-
const entryKey = buildMetadataCacheEntryKey(appCacheKey, queryKind);
|
|
10680
|
+
read(appCacheKey, queryKind, requestParams) {
|
|
10681
|
+
const entryKey = buildMetadataCacheEntryKey(appCacheKey, queryKind, requestParams);
|
|
10050
10682
|
const entry = this.entries.get(entryKey);
|
|
10051
10683
|
if (!entry) return;
|
|
10052
10684
|
if (entry.expiresAtMs <= this.nowMs()) {
|
|
@@ -10055,10 +10687,10 @@ var CodexPluginMetadataCache = class {
|
|
|
10055
10687
|
}
|
|
10056
10688
|
return entry.snapshot;
|
|
10057
10689
|
}
|
|
10058
|
-
/** Returns a fresh
|
|
10690
|
+
/** Returns a fresh snapshot or coalesces one catalog or installed-plugin request. */
|
|
10059
10691
|
async load(params) {
|
|
10060
|
-
const entryKey = buildMetadataCacheEntryKey(params.appCacheKey, params.queryKind);
|
|
10061
|
-
const cached = this.read(params.appCacheKey, params.queryKind);
|
|
10692
|
+
const entryKey = buildMetadataCacheEntryKey(params.appCacheKey, params.queryKind, params.requestParams);
|
|
10693
|
+
const cached = this.read(params.appCacheKey, params.queryKind, params.requestParams);
|
|
10062
10694
|
if (cached) return cached;
|
|
10063
10695
|
const pending = this.inFlight.get(entryKey);
|
|
10064
10696
|
if (pending) try {
|
|
@@ -10070,7 +10702,8 @@ var CodexPluginMetadataCache = class {
|
|
|
10070
10702
|
const generation = this.generations.get(params.appCacheKey) ?? 0;
|
|
10071
10703
|
const clearGeneration = this.clearGeneration;
|
|
10072
10704
|
const promise = (async () => {
|
|
10073
|
-
const
|
|
10705
|
+
const method = params.queryKind === "installed" ? "plugin/installed" : "plugin/list";
|
|
10706
|
+
const response = await params.request(method, params.requestParams);
|
|
10074
10707
|
const snapshot = {
|
|
10075
10708
|
appCacheKey: params.appCacheKey,
|
|
10076
10709
|
queryKind: params.queryKind,
|
|
@@ -10109,10 +10742,17 @@ var CodexPluginMetadataCache = class {
|
|
|
10109
10742
|
/** Shared plugin metadata cache used by Codex app-server runtime paths. */
|
|
10110
10743
|
const defaultCodexPluginMetadataCache = new CodexPluginMetadataCache();
|
|
10111
10744
|
function hasMarketplaceLoadErrors(response) {
|
|
10112
|
-
return
|
|
10113
|
-
}
|
|
10114
|
-
function buildMetadataCacheEntryKey(appCacheKey, queryKind) {
|
|
10115
|
-
return JSON.stringify([appCacheKey, queryKind]);
|
|
10745
|
+
return response.marketplaceLoadErrors.length > 0;
|
|
10746
|
+
}
|
|
10747
|
+
function buildMetadataCacheEntryKey(appCacheKey, queryKind, requestParams) {
|
|
10748
|
+
if (queryKind !== "installed") return JSON.stringify([appCacheKey, queryKind]);
|
|
10749
|
+
const installedParams = requestParams;
|
|
10750
|
+
return JSON.stringify([
|
|
10751
|
+
appCacheKey,
|
|
10752
|
+
queryKind,
|
|
10753
|
+
installedParams?.cwds ?? [],
|
|
10754
|
+
Array.from(new Set(installedParams?.installSuggestionPluginNames ?? [])).toSorted()
|
|
10755
|
+
]);
|
|
10116
10756
|
}
|
|
10117
10757
|
//#endregion
|
|
10118
10758
|
//#region extensions/codex/src/app-server/plugin-thread-config-deadline.ts
|
|
@@ -10206,7 +10846,8 @@ function createCodexPluginThreadConfigStartupProvider(params) {
|
|
|
10206
10846
|
recoverablePluginConfigKeys: policy ? resolveRecoverableCodexPluginConfigKeys({
|
|
10207
10847
|
policy,
|
|
10208
10848
|
metadataCache,
|
|
10209
|
-
appCacheKey: params.appCacheKey
|
|
10849
|
+
appCacheKey: params.appCacheKey,
|
|
10850
|
+
configCwd: params.configCwd
|
|
10210
10851
|
}) : void 0,
|
|
10211
10852
|
build: () => buildCodexPluginThreadConfigWithinDeadline({
|
|
10212
10853
|
...buildParams,
|
|
@@ -10284,6 +10925,7 @@ async function startCodexAttemptThread(params) {
|
|
|
10284
10925
|
const attemptParams = params.buildAttemptParams();
|
|
10285
10926
|
startupClient = await params.attemptClientFactory({
|
|
10286
10927
|
startOptions: params.appServer.start,
|
|
10928
|
+
pluginConfig: params.pluginConfig,
|
|
10287
10929
|
...params.startupPreparedAuth ? { preparedAuth: params.startupPreparedAuth } : { authProfileId: params.startupAuthProfileId },
|
|
10288
10930
|
authRequirement: params.startupAuthRequirement,
|
|
10289
10931
|
authProfileStore: attemptParams.authProfileStore,
|
|
@@ -10315,7 +10957,7 @@ async function startCodexAttemptThread(params) {
|
|
|
10315
10957
|
if (startupAbandonController.signal.aborted) throw new CodexAppServerStartupError("aborted");
|
|
10316
10958
|
let runtimeArtifact;
|
|
10317
10959
|
if (params.runtimeArtifactRequest) {
|
|
10318
|
-
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-
|
|
10960
|
+
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-CmtG_t1L.js");
|
|
10319
10961
|
runtimeArtifact = readCodexAppServerClientRuntimeArtifact(activeStartupClient);
|
|
10320
10962
|
const expected = params.runtimeArtifactRequest.expected;
|
|
10321
10963
|
const matchesExpected = !expected || Boolean(runtimeArtifact && runtimeArtifact.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint);
|
|
@@ -10332,14 +10974,19 @@ async function startCodexAttemptThread(params) {
|
|
|
10332
10974
|
config: params.config
|
|
10333
10975
|
});
|
|
10334
10976
|
const turnRouter = getCodexAppServerTurnRouter(activeStartupClient);
|
|
10335
|
-
|
|
10336
|
-
|
|
10337
|
-
|
|
10338
|
-
|
|
10339
|
-
|
|
10340
|
-
|
|
10341
|
-
|
|
10342
|
-
|
|
10977
|
+
try {
|
|
10978
|
+
await ensureCodexComputerUse({
|
|
10979
|
+
client: activeStartupClient,
|
|
10980
|
+
pluginConfig: params.pluginConfig,
|
|
10981
|
+
config: params.config,
|
|
10982
|
+
agentDir: params.agentDir,
|
|
10983
|
+
timeoutMs: params.appServer.requestTimeoutMs,
|
|
10984
|
+
signal: startupAbandonController.signal
|
|
10985
|
+
});
|
|
10986
|
+
} catch (error) {
|
|
10987
|
+
if (startupAbandonController.signal.aborted) throw error;
|
|
10988
|
+
throw new AgentHarnessPreflightError(`Codex Computer Use readiness failed: ${formatErrorMessage(error)}`, { cause: error });
|
|
10989
|
+
}
|
|
10343
10990
|
const startupRuntimeIdentity = activeStartupClient.getRuntimeIdentity();
|
|
10344
10991
|
const pluginAppCacheKey = buildCodexPluginAppCacheKey({
|
|
10345
10992
|
appServer: params.appServer,
|
|
@@ -10655,6 +11302,14 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
10655
11302
|
spawnedBy: params.spawnedBy
|
|
10656
11303
|
});
|
|
10657
11304
|
state.client = startupResult.client;
|
|
11305
|
+
toolBridge.setRemoteWorkspaceFileReader?.(({ path, maxBytes, workspaceRoot, signal, timeoutMs }) => readBoundedCodexRemoteWorkspaceFile({
|
|
11306
|
+
client: startupResult.client,
|
|
11307
|
+
path,
|
|
11308
|
+
maxBytes,
|
|
11309
|
+
workspaceRoot,
|
|
11310
|
+
signal,
|
|
11311
|
+
timeoutMs
|
|
11312
|
+
}));
|
|
10658
11313
|
state.thread = startupResult.thread;
|
|
10659
11314
|
state.runtimeArtifact = startupResult.runtimeArtifact;
|
|
10660
11315
|
state.turnRouter = startupResult.turnRouter;
|
|
@@ -10807,7 +11462,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
10807
11462
|
sessionId: params.sessionId,
|
|
10808
11463
|
sessionKey: params.sessionKey,
|
|
10809
11464
|
workspaceDir: effectiveWorkspace,
|
|
10810
|
-
agentDir: agentDir ?? resolveAgentDir
|
|
11465
|
+
agentDir: agentDir ?? resolveAgentDir(params.config ?? {}, sessionAgentId),
|
|
10811
11466
|
cfg: params.config,
|
|
10812
11467
|
requesterSenderId: params.senderId,
|
|
10813
11468
|
agentAccountId: params.agentAccountId,
|
|
@@ -10821,7 +11476,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
10821
11476
|
sessionId: params.sessionId,
|
|
10822
11477
|
runId: params.runId,
|
|
10823
11478
|
agentId: sessionAgentId,
|
|
10824
|
-
agentDir: agentDir ?? resolveAgentDir
|
|
11479
|
+
agentDir: agentDir ?? resolveAgentDir(params.config ?? {}, sessionAgentId),
|
|
10825
11480
|
agentAccountId: params.agentAccountId,
|
|
10826
11481
|
messageProvider: params.messageProvider ?? params.messageChannel,
|
|
10827
11482
|
messageChannel: params.messageChannel,
|
|
@@ -10873,7 +11528,10 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
10873
11528
|
hookContext: {
|
|
10874
11529
|
agentId: sessionAgentId,
|
|
10875
11530
|
config: params.config,
|
|
11531
|
+
contextWindowTokens: params.contextTokenBudget ?? params.model.contextWindow,
|
|
10876
11532
|
workspaceDir: effectiveWorkspace,
|
|
11533
|
+
remoteWorkspaceRoot: connection.appServer.remoteWorkspaceRoot,
|
|
11534
|
+
remoteWorkspaceRequestTimeoutMs: connection.appServer.requestTimeoutMs,
|
|
10877
11535
|
sessionId: params.sessionId,
|
|
10878
11536
|
sessionKey: sandboxSessionKey,
|
|
10879
11537
|
runId: params.runId,
|