@openclaw/codex 2026.7.2-beta.5 → 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-BmDgseo_.js → app-server-policy-BSaO2JIT.js} +1 -1
- package/dist/{attempt-notifications-CMR2_fmR.js → attempt-notifications-AP-a-Q5k.js} +1 -1
- package/dist/{bounded-turn-FEbUXoYT.js → bounded-turn-D2ZAgZVz.js} +29 -22
- package/dist/{capabilities-BHRSI6Cn.js → capabilities-BFDTVYr4.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-ico4ZFnk.js → command-formatters-C336eRVS.js} +2 -2
- package/dist/{command-handlers-CRmnwI2N.js → command-handlers-DAHUSry9.js} +12 -12
- package/dist/{compact-dEN49UH6.js → compact-D_uvHurS.js} +5 -5
- package/dist/{computer-use-BjGylO-E.js → computer-use-CYEc8U3w.js} +111 -113
- package/dist/{conversation-control-DE7d9DOj.js → conversation-control-xsIeXbo4.js} +6 -6
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{dynamic-tools-LIt9ojep.js → dynamic-tools-D2gYkSBO.js} +438 -51
- package/dist/effective-mcp-catalog-Bbd98Inw.js +114 -0
- package/dist/{event-projector-usage-tvgb1NCX.js → event-projector-usage-Xp4AlR2k.js} +20 -3
- package/dist/harness.js +13 -9
- package/dist/index.js +131 -108
- package/dist/media-understanding-provider.js +1 -1
- package/dist/{models-BA01NEez.js → models-BBMKU4jA.js} +2 -2
- package/dist/{notification-correlation-Bj_Ak_jI.js → notification-correlation-CU6_AnOb.js} +3 -3
- package/dist/{plugin-app-cache-key-DSXX-rXO.js → plugin-app-cache-key-DztPafOA.js} +132 -39
- package/dist/{rate-limits-S_PXs0ul.js → rate-limits-CU-gVCCS.js} +1 -1
- package/dist/{request-CXpPennK.js → request-qKh331yu.js} +3 -3
- package/dist/{run-attempt-C5GTPJOE.js → run-attempt-CY9WlDLc.js} +677 -199
- 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-DlVQ-Pxs.js → session-binding-BXpo9ymA.js} +60 -7
- package/dist/{session-catalog-CP2oCcEb.js → session-catalog-DyOgR4WH.js} +268 -44
- package/dist/{session-cli-CqZ0Fp2a.js → session-cli-2PZaFLRh.js} +1 -1
- package/dist/{session-upstream-marker-QE-m5QFG.js → session-upstream-marker-B6U7tLw5.js} +1 -1
- package/dist/{settled-turn-finalizer-CA_2QXIE.js → settled-turn-finalizer-CXY2Z9dT.js} +19 -6
- package/dist/{shared-client-BVKE40c-.js → shared-client-DTbvH-XV.js} +166 -49
- package/dist/{side-question-CO12sHxo.js → side-question-_ulBk1AL.js} +10 -10
- package/dist/{thread-lifecycle-DRg_FdzC.js → thread-lifecycle-DF53ogiA.js} +968 -214
- package/dist/{protocol-validators-Dm4eXZmt.js → transcript-mirror-DzsdNCf5.js} +589 -2
- package/dist/{upstream-session-fork-_Vrz4WJr.js → upstream-session-fork-Dy4Xvuoj.js} +3 -3
- package/dist/{usage-UpVbdX5G.js → usage-CQ6GhD5-.js} +3 -3
- package/dist/{web-search-provider.runtime-CaQMYDbp.js → web-search-provider.runtime-CCFhg2z5.js} +3 -3
- package/package.json +6 -7
- package/dist/attempt-client-cleanup-Ia52yRWc.js +0 -127
- package/dist/realtime-voice-api-BPcA1uN9.js +0 -494
- package/dist/realtime-voice-api.js +0 -2
- package/dist/transcript-mirror-uKA-A4tB.js +0 -550
|
@@ -1,37 +1,36 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import {
|
|
3
|
-
import { a as
|
|
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-
|
|
5
|
-
import {
|
|
6
|
-
import { n as
|
|
7
|
-
import {
|
|
8
|
-
import { i as defaultCodexAppInventoryCache, n as buildCodexAppServerRuntimeFingerprint, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-DSXX-rXO.js";
|
|
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";
|
|
9
8
|
import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { n as
|
|
15
|
-
import { a as resolveCodexBindingAppServerConnection, n as readCodexNotificationThreadId, r as readCodexNotificationTurnId, t as isCodexNotificationForTurn } from "./notification-correlation-Bj_Ak_jI.js";
|
|
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";
|
|
16
14
|
import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-B4FfbcCg.js";
|
|
17
15
|
import { i as resolveCodexLocalRuntimeAttribution, n as createAssistantMessage, r as createAssistantMirrorMessage, t as createAssistantCommentaryMessage } from "./event-projector-assistant-message-DTgnPPVF.js";
|
|
18
|
-
import { $ as
|
|
19
|
-
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";
|
|
20
18
|
import fs from "node:fs/promises";
|
|
21
19
|
import path, { posix } from "node:path";
|
|
22
20
|
import { asDateTimestampMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
23
|
-
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, 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";
|
|
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";
|
|
24
22
|
import { createHash, randomUUID } from "node:crypto";
|
|
25
23
|
import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
26
24
|
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
27
25
|
import { asFiniteNumber, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
28
|
-
import {
|
|
26
|
+
import { SsrFBlockedError, isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
27
|
+
import { getSessionEntry, parseSqliteSessionFileMarker, resolveTranscriptSessionKeyBySessionId } from "openclaw/plugin-sdk/session-store-runtime";
|
|
29
28
|
import { spawn } from "node:child_process";
|
|
30
29
|
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
31
30
|
import { once } from "node:events";
|
|
32
31
|
import { isIP } from "node:net";
|
|
33
32
|
import { WebSocketServer } from "ws";
|
|
34
|
-
import { fileURLToPath } from "node:url";
|
|
33
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
35
34
|
import { redactSensitiveFieldValue, redactSensitiveText, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
|
|
36
35
|
import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
37
36
|
import { readSessionTranscriptEvents } from "openclaw/plugin-sdk/session-transcript-runtime";
|
|
@@ -41,9 +40,9 @@ import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from
|
|
|
41
40
|
import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
|
|
42
41
|
import { resolveGeneratedMediaMaxBytes } from "openclaw/plugin-sdk/media-generation-runtime";
|
|
43
42
|
import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
|
|
43
|
+
import { root } from "openclaw/plugin-sdk/file-access-runtime";
|
|
44
44
|
import { MESSAGE_TOOL_DELIVERY_HINTS } from "openclaw/plugin-sdk/message-tool-delivery-hints";
|
|
45
45
|
import { createAgentHarnessTaskRuntime, deliverAgentHarnessTaskCompletion, isDurableAgentHarnessCompletionDelivery } from "openclaw/plugin-sdk/agent-harness-task-runtime";
|
|
46
|
-
import { SsrFBlockedError, isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
47
46
|
//#region extensions/codex/src/app-server/attempt-steering.ts
|
|
48
47
|
/**
|
|
49
48
|
* Debounced steering queue for forwarding user messages to an active Codex
|
|
@@ -394,7 +393,11 @@ var CodexAssistantProjection = class {
|
|
|
394
393
|
return;
|
|
395
394
|
}
|
|
396
395
|
const turnItems = turn.items ?? [];
|
|
397
|
-
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
|
+
});
|
|
398
401
|
const authoritative = authoritativeIndex >= 0 ? turnItems[authoritativeIndex] : void 0;
|
|
399
402
|
if (turnItems.slice(authoritativeIndex + 1).some(shouldClearTerminalPresentationForNativeItem) || authoritative?.id === this.latestTerminalAssistantCandidateItemId && this.latestTerminalAssistantCandidateSuperseded) {
|
|
400
403
|
this.supersedeVisibleAnswerCandidate();
|
|
@@ -1282,13 +1285,6 @@ var CodexToolProgressProjection = class {
|
|
|
1282
1285
|
function isMissingFileError(error) {
|
|
1283
1286
|
return Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
|
|
1284
1287
|
}
|
|
1285
|
-
function selectPreferredSessionKey(matches, sessionId) {
|
|
1286
|
-
const structural = matches.filter(({ sessionKey }) => sessionKey === sessionId || sessionKey.endsWith(`:${sessionId}`));
|
|
1287
|
-
const candidates = structural.length > 0 ? structural : matches;
|
|
1288
|
-
if (candidates.length === 1) return candidates[0]?.sessionKey;
|
|
1289
|
-
const sorted = candidates.toSorted((left, right) => (right.entry.updatedAt ?? 0) - (left.entry.updatedAt ?? 0));
|
|
1290
|
-
return (sorted[0]?.entry.updatedAt ?? 0) > (sorted[1]?.entry.updatedAt ?? 0) ? sorted[0]?.sessionKey : void 0;
|
|
1291
|
-
}
|
|
1292
1288
|
/** Returns sanitized session-context messages for a Codex mirrored session file. */
|
|
1293
1289
|
async function readCodexMirroredSessionHistoryMessages(target) {
|
|
1294
1290
|
try {
|
|
@@ -1323,16 +1319,19 @@ async function readCodexMirroredSessionEntries(target) {
|
|
|
1323
1319
|
}
|
|
1324
1320
|
function resolveSqliteMarkerSessionKey(target, marker) {
|
|
1325
1321
|
const explicitSessionKey = target.sessionKey?.trim();
|
|
1326
|
-
|
|
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({
|
|
1327
1331
|
agentId: marker.agentId,
|
|
1328
|
-
|
|
1332
|
+
sessionId: marker.sessionId,
|
|
1329
1333
|
storePath: marker.storePath
|
|
1330
1334
|
});
|
|
1331
|
-
if (explicitSessionKey) {
|
|
1332
|
-
const explicitEntry = entries.find(({ sessionKey }) => sessionKey === explicitSessionKey);
|
|
1333
|
-
if (explicitEntry) return explicitEntry.entry.sessionId === marker.sessionId ? explicitSessionKey : void 0;
|
|
1334
|
-
}
|
|
1335
|
-
return selectPreferredSessionKey(entries.filter(({ entry }) => entry.sessionId === marker.sessionId), marker.sessionId);
|
|
1336
1335
|
}
|
|
1337
1336
|
//#endregion
|
|
1338
1337
|
//#region extensions/codex/src/app-server/event-projector-tool-transcript.ts
|
|
@@ -1351,6 +1350,35 @@ const ZERO_USAGE = {
|
|
|
1351
1350
|
}
|
|
1352
1351
|
};
|
|
1353
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
|
+
}
|
|
1354
1382
|
var CodexToolTranscriptProjection = class {
|
|
1355
1383
|
constructor(params, threadId, turnId, progress, nextTranscriptTimestamp, options = {}) {
|
|
1356
1384
|
this.params = params;
|
|
@@ -1370,6 +1398,8 @@ var CodexToolTranscriptProjection = class {
|
|
|
1370
1398
|
this.afterToolCallObservedItemIds = /* @__PURE__ */ new Set();
|
|
1371
1399
|
this.nativeMcpAppResultDetails = /* @__PURE__ */ new Map();
|
|
1372
1400
|
this.nativeMcpAppResultDetailsAttempted = /* @__PURE__ */ new Set();
|
|
1401
|
+
this.rawNativeToolOutputByCallId = /* @__PURE__ */ new Map();
|
|
1402
|
+
this.codeModeNativePatchInputsByCallId = /* @__PURE__ */ new Map();
|
|
1373
1403
|
}
|
|
1374
1404
|
get transcriptMessages() {
|
|
1375
1405
|
return this.messages;
|
|
@@ -1381,13 +1411,14 @@ var CodexToolTranscriptProjection = class {
|
|
|
1381
1411
|
arguments: sanitizeCodexToolArguments(params.arguments)
|
|
1382
1412
|
});
|
|
1383
1413
|
}
|
|
1384
|
-
recordDynamicToolResult(params) {
|
|
1414
|
+
recordDynamicToolResult(params, resultContentSource) {
|
|
1385
1415
|
this.recordToolResult({
|
|
1386
1416
|
id: params.callId,
|
|
1387
1417
|
name: params.tool,
|
|
1388
1418
|
text: collectDynamicToolContentText(params.contentItems),
|
|
1389
1419
|
isError: !params.success,
|
|
1390
|
-
details: params.details
|
|
1420
|
+
details: params.details,
|
|
1421
|
+
...resultContentSource ? { resultContentSource } : {}
|
|
1391
1422
|
});
|
|
1392
1423
|
}
|
|
1393
1424
|
recordNativeToolCall(item) {
|
|
@@ -1405,10 +1436,91 @@ var CodexToolTranscriptProjection = class {
|
|
|
1405
1436
|
if (name) this.recordToolResult({
|
|
1406
1437
|
id: item.id,
|
|
1407
1438
|
name,
|
|
1408
|
-
text: itemTranscriptResultText(item, this.progress.outputTextByItem),
|
|
1439
|
+
text: this.rawNativeToolOutputByCallId.get(item.id) ?? itemTranscriptResultText(item, this.progress.outputTextByItem),
|
|
1409
1440
|
isError: isNonSuccessItemStatus(itemStatus(item)),
|
|
1410
|
-
details
|
|
1411
|
-
|
|
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;
|
|
1412
1524
|
}
|
|
1413
1525
|
async recordNativeToolResultWithDetails(item) {
|
|
1414
1526
|
this.recordNativeToolResult(item, await this.prepareNativeMcpAppResultDetails(item));
|
|
@@ -1525,10 +1637,11 @@ var CodexToolTranscriptProjection = class {
|
|
|
1525
1637
|
output: text
|
|
1526
1638
|
});
|
|
1527
1639
|
}
|
|
1528
|
-
if (
|
|
1640
|
+
if (params.terminalDisposition === "tool_error") {
|
|
1529
1641
|
this.recordMissingToolError(missingTranscriptIds, missingTrajectoryIds);
|
|
1530
1642
|
return;
|
|
1531
1643
|
}
|
|
1644
|
+
if (params.terminalDisposition === "diagnostic_only") return;
|
|
1532
1645
|
const missingCount = (/* @__PURE__ */ new Set([...missingTranscriptIds, ...missingTrajectoryIds])).size;
|
|
1533
1646
|
return missingCount === 1 ? MISSING_TOOL_RESULT_ERROR : `${MISSING_TOOL_RESULT_ERROR} missingToolResultCount=${missingCount}`;
|
|
1534
1647
|
}
|
|
@@ -1615,6 +1728,7 @@ var CodexToolTranscriptProjection = class {
|
|
|
1615
1728
|
text
|
|
1616
1729
|
}],
|
|
1617
1730
|
...params.details !== void 0 ? { details: params.details } : {},
|
|
1731
|
+
...params.resultContentSource ? { __openclaw: { resultContentSource: params.resultContentSource } } : {},
|
|
1618
1732
|
timestamp: this.nextTranscriptTimestamp()
|
|
1619
1733
|
};
|
|
1620
1734
|
}
|
|
@@ -1774,56 +1888,127 @@ var CodexEventProjection = class {
|
|
|
1774
1888
|
//#region extensions/codex/src/app-server/event-projector-media.ts
|
|
1775
1889
|
const GENERATED_IMAGE_MEDIA_SUBDIR = "tool-image-generation";
|
|
1776
1890
|
var CodexGeneratedMediaProjection = class {
|
|
1777
|
-
constructor(config) {
|
|
1891
|
+
constructor(config, remote) {
|
|
1778
1892
|
this.config = config;
|
|
1893
|
+
this.remote = remote;
|
|
1779
1894
|
this.itemIds = /* @__PURE__ */ new Set();
|
|
1780
1895
|
this.urlsByItemId = /* @__PURE__ */ new Map();
|
|
1896
|
+
this.gatewayMaterializedItemIds = /* @__PURE__ */ new Set();
|
|
1897
|
+
this.pendingMaterializationsByItemId = /* @__PURE__ */ new Map();
|
|
1781
1898
|
}
|
|
1782
1899
|
hasGeneratedMedia() {
|
|
1783
1900
|
return this.itemIds.size > 0;
|
|
1784
1901
|
}
|
|
1785
|
-
recordNative(item) {
|
|
1902
|
+
async recordNative(item) {
|
|
1786
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
|
+
}
|
|
1787
1915
|
const savedPath = readItemString(item, "savedPath")?.trim();
|
|
1788
|
-
if (savedPath)
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
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
|
+
}
|
|
1792
1952
|
}
|
|
1793
1953
|
async recordRaw(item) {
|
|
1794
1954
|
if (readString$6(item, "type") !== "image_generation_call") return;
|
|
1795
1955
|
const result = readString$6(item, "result");
|
|
1796
1956
|
if (!result) return;
|
|
1797
1957
|
const itemId = readString$6(item, "id") ?? `raw-image-${this.itemIds.size}`;
|
|
1798
|
-
this.
|
|
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) {
|
|
1799
1983
|
const maxBytes = resolveGeneratedMediaMaxBytes(this.config, "image");
|
|
1800
|
-
const estimatedDecodedBytes = estimateBase64DecodedBytes(result);
|
|
1984
|
+
const estimatedDecodedBytes = estimateBase64DecodedBytes(params.result);
|
|
1801
1985
|
if (estimatedDecodedBytes !== void 0 && estimatedDecodedBytes > maxBytes) {
|
|
1802
|
-
embeddedAgentLog.warn(
|
|
1803
|
-
itemId,
|
|
1986
|
+
embeddedAgentLog.warn(`codex app-server ${params.source} image generation result exceeds media limit`, {
|
|
1987
|
+
itemId: params.itemId,
|
|
1804
1988
|
estimatedDecodedBytes,
|
|
1805
1989
|
maxBytes
|
|
1806
1990
|
});
|
|
1807
1991
|
return;
|
|
1808
1992
|
}
|
|
1809
1993
|
const asset = generatedImageAssetFromBase64({
|
|
1810
|
-
base64: result,
|
|
1994
|
+
base64: params.result,
|
|
1811
1995
|
index: this.itemIds.size,
|
|
1812
|
-
revisedPrompt:
|
|
1996
|
+
revisedPrompt: params.revisedPrompt,
|
|
1813
1997
|
fileNamePrefix: "codex-image-generation",
|
|
1814
1998
|
sniffMimeType: true
|
|
1815
1999
|
});
|
|
1816
2000
|
if (!asset) return;
|
|
1817
2001
|
try {
|
|
1818
2002
|
const saved = await saveMediaBuffer(asset.buffer, asset.mimeType, GENERATED_IMAGE_MEDIA_SUBDIR, maxBytes, asset.fileName);
|
|
2003
|
+
this.gatewayMaterializedItemIds.add(params.itemId);
|
|
1819
2004
|
this.recordUrl({
|
|
1820
|
-
itemId,
|
|
2005
|
+
itemId: params.itemId,
|
|
1821
2006
|
mediaUrl: saved.path,
|
|
1822
2007
|
replaceExisting: true
|
|
1823
2008
|
});
|
|
1824
2009
|
} catch (error) {
|
|
1825
|
-
embeddedAgentLog.warn(
|
|
1826
|
-
itemId,
|
|
2010
|
+
embeddedAgentLog.warn(`codex app-server ${params.source} image generation result save failed`, {
|
|
2011
|
+
itemId: params.itemId,
|
|
1827
2012
|
error
|
|
1828
2013
|
});
|
|
1829
2014
|
}
|
|
@@ -1985,6 +2170,28 @@ function reasoningMethodOrder(method) {
|
|
|
1985
2170
|
}
|
|
1986
2171
|
//#endregion
|
|
1987
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
|
+
}
|
|
1988
2195
|
function buildCodexMessagesSnapshot(params) {
|
|
1989
2196
|
const messages = promptSnapshot(params.runParams, params.turnId, params.upstreamUserText);
|
|
1990
2197
|
if (params.reasoningText) messages.push(attachCodexMirrorIdentity(params.createAssistantMirrorMessage("Codex reasoning", params.reasoningText), `${params.turnId}:reasoning`));
|
|
@@ -1992,7 +2199,7 @@ function buildCodexMessagesSnapshot(params) {
|
|
|
1992
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));
|
|
1993
2200
|
messages.push(...visibleWorkMessages);
|
|
1994
2201
|
if (params.lastAssistant) messages.push(attachCodexMirrorIdentity(params.lastAssistant, `${params.turnId}:assistant`));
|
|
1995
|
-
return messages.map((message) => projectAgentHarnessTranscriptMessageForDisplay({
|
|
2202
|
+
return applyStickyTurnTaint(messages).map((message) => projectAgentHarnessTranscriptMessageForDisplay({
|
|
1996
2203
|
hidden: params.runParams.trigger === "memory",
|
|
1997
2204
|
message
|
|
1998
2205
|
}));
|
|
@@ -2153,11 +2360,17 @@ var CodexAppServerEventProjector = class {
|
|
|
2153
2360
|
this.promptErrorSource = null;
|
|
2154
2361
|
this.synthesizedMissingToolResultError = null;
|
|
2155
2362
|
this.aborted = false;
|
|
2363
|
+
this.responseCompletions = new CodexResponseCompletionProjection();
|
|
2156
2364
|
this.completedCompactionCount = 0;
|
|
2157
2365
|
this.lastTranscriptTimestamp = 0;
|
|
2158
2366
|
this.diagnostics = new CodexProjectionDiagnostics(threadId, turnId);
|
|
2159
2367
|
this.nativeToolLifecycleProjector = new CodexNativeToolLifecycleProjector(params, threadId, turnId, { runAbortSignal: options.runAbortSignal });
|
|
2160
|
-
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
|
+
});
|
|
2161
2374
|
this.toolProgressProjection = new CodexToolProgressProjection(params);
|
|
2162
2375
|
this.toolTranscriptProjection = new CodexToolTranscriptProjection(params, threadId, turnId, this.toolProgressProjection, () => this.nextTranscriptTimestamp(), {
|
|
2163
2376
|
nativePostToolUseRelayEnabled: options.nativePostToolUseRelayEnabled,
|
|
@@ -2260,13 +2473,13 @@ var CodexAppServerEventProjector = class {
|
|
|
2260
2473
|
await this.handleTurnCompleted(params);
|
|
2261
2474
|
break;
|
|
2262
2475
|
case "rawResponse/completed":
|
|
2263
|
-
this.
|
|
2476
|
+
this.responseCompletions.record(params);
|
|
2264
2477
|
break;
|
|
2265
2478
|
case "rawResponseItem/completed":
|
|
2266
2479
|
await this.handleRawResponseItemCompleted(params);
|
|
2267
2480
|
break;
|
|
2268
2481
|
case "error":
|
|
2269
|
-
this.
|
|
2482
|
+
this.responseCompletions.clear();
|
|
2270
2483
|
if (params.willRetry === true) break;
|
|
2271
2484
|
this.promptError = this.formatCodexErrorMessage(params) ?? "codex app-server error";
|
|
2272
2485
|
this.promptErrorSource = "prompt";
|
|
@@ -2294,13 +2507,14 @@ var CodexAppServerEventProjector = class {
|
|
|
2294
2507
|
const commentaryMessages = this.assistantProjection.collectCommentaryMessages();
|
|
2295
2508
|
const reasoningText = this.reasoningProjection.reasoningText();
|
|
2296
2509
|
const planText = this.reasoningProjection.planText();
|
|
2297
|
-
const
|
|
2510
|
+
const completedUsage = this.responseCompletions.usage ?? this.tokenUsage;
|
|
2511
|
+
const projectedUsage = this.aborted ? this.tokenUsage : completedUsage;
|
|
2298
2512
|
const hasAssistantItemText = this.assistantProjection.hasAssistantItemTextForSynthesis();
|
|
2299
2513
|
const legacyFailClosed = !this.completedTurn || this.completedTurn.status !== "completed" || hasAssistantItemText;
|
|
2300
2514
|
const hasDeliverableAssistantOnCompletedTurn = this.completedTurn?.status === "completed" && assistantTexts.some((text) => text.trim().length > 0);
|
|
2301
2515
|
const synthesizedMissingToolResultError = this.toolTranscriptProjection.synthesizeMissingToolResults({
|
|
2302
2516
|
synthesize: legacyFailClosed,
|
|
2303
|
-
|
|
2517
|
+
terminalDisposition: this.aborted ? "tool_error" : hasDeliverableAssistantOnCompletedTurn ? "diagnostic_only" : "prompt_error"
|
|
2304
2518
|
});
|
|
2305
2519
|
if (synthesizedMissingToolResultError) {
|
|
2306
2520
|
this.synthesizedMissingToolResultError = synthesizedMissingToolResultError;
|
|
@@ -2345,6 +2559,7 @@ var CodexAppServerEventProjector = class {
|
|
|
2345
2559
|
...agentHarnessResultClassification ? { agentHarnessResultClassification } : {},
|
|
2346
2560
|
bootstrapPromptWarningSignaturesSeen: this.params.bootstrapPromptWarningSignaturesSeen,
|
|
2347
2561
|
bootstrapPromptWarningSignature: this.params.bootstrapPromptWarningSignature,
|
|
2562
|
+
...this.responseCompletions.modelIterations > 0 ? { modelIterations: this.responseCompletions.modelIterations } : {},
|
|
2348
2563
|
messagesSnapshot,
|
|
2349
2564
|
assistantTexts,
|
|
2350
2565
|
toolMetas,
|
|
@@ -2383,7 +2598,8 @@ var CodexAppServerEventProjector = class {
|
|
|
2383
2598
|
}
|
|
2384
2599
|
recordDynamicToolResult(params) {
|
|
2385
2600
|
this.toolProgressProjection.recordDynamicToolResult(params);
|
|
2386
|
-
this.
|
|
2601
|
+
const source = this.options.resolveDynamicToolResultContentSource?.(params.tool);
|
|
2602
|
+
this.toolTranscriptProjection.recordDynamicToolResult(params, source);
|
|
2387
2603
|
}
|
|
2388
2604
|
markTimedOut() {
|
|
2389
2605
|
this.aborted = true;
|
|
@@ -2392,7 +2608,7 @@ var CodexAppServerEventProjector = class {
|
|
|
2392
2608
|
}
|
|
2393
2609
|
markAborted() {
|
|
2394
2610
|
this.aborted = true;
|
|
2395
|
-
this.
|
|
2611
|
+
this.responseCompletions.clear();
|
|
2396
2612
|
}
|
|
2397
2613
|
isCompacting() {
|
|
2398
2614
|
return this.activeCompactionItemIds.size > 0;
|
|
@@ -2462,7 +2678,7 @@ var CodexAppServerEventProjector = class {
|
|
|
2462
2678
|
}
|
|
2463
2679
|
this.assistantProjection.recordItemCompleted(item, itemId, this.activeItemIds);
|
|
2464
2680
|
this.reasoningProjection.recordItem(item);
|
|
2465
|
-
this.generatedMediaProjection.recordNative(item);
|
|
2681
|
+
await this.generatedMediaProjection.recordNative(item);
|
|
2466
2682
|
if (item?.type === "contextCompaction" && itemId) {
|
|
2467
2683
|
this.activeCompactionItemIds.delete(itemId);
|
|
2468
2684
|
this.completedCompactionCount += 1;
|
|
@@ -2517,15 +2733,11 @@ var CodexAppServerEventProjector = class {
|
|
|
2517
2733
|
}
|
|
2518
2734
|
});
|
|
2519
2735
|
}
|
|
2520
|
-
handleRawResponseCompleted(params) {
|
|
2521
|
-
const usage = isJsonObject(params.usage) ? params.usage : void 0;
|
|
2522
|
-
this.responseUsage = usage ? normalizeCodexResponseTokenUsage(usage) : void 0;
|
|
2523
|
-
}
|
|
2524
2736
|
async handleTurnCompleted(params) {
|
|
2525
2737
|
const turn = readCodexTurn(params.turn);
|
|
2526
2738
|
if (!turn || turn.id !== this.turnId) return;
|
|
2527
2739
|
this.completedTurn = turn;
|
|
2528
|
-
if (turn.status !== "completed") this.
|
|
2740
|
+
if (turn.status !== "completed") this.responseCompletions.clear();
|
|
2529
2741
|
if (turn.status === "failed") {
|
|
2530
2742
|
const usageLimitMessage = formatCodexUsageLimitErrorMessage({
|
|
2531
2743
|
message: turn.error?.message,
|
|
@@ -2549,7 +2761,7 @@ var CodexAppServerEventProjector = class {
|
|
|
2549
2761
|
this.diagnostics.warnUnknownItemStatus(item);
|
|
2550
2762
|
this.assistantProjection.recordSnapshotItem(item);
|
|
2551
2763
|
this.reasoningProjection.recordItem(item);
|
|
2552
|
-
this.generatedMediaProjection.recordNative(item);
|
|
2764
|
+
await this.generatedMediaProjection.recordNative(item);
|
|
2553
2765
|
this.toolProgressProjection.recordToolMeta(item);
|
|
2554
2766
|
this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
|
|
2555
2767
|
await this.emitSnapshotOnlyNativeToolProgress(item);
|
|
@@ -2593,6 +2805,7 @@ var CodexAppServerEventProjector = class {
|
|
|
2593
2805
|
async handleRawResponseItemCompleted(params) {
|
|
2594
2806
|
const item = isJsonObject(params.item) ? params.item : void 0;
|
|
2595
2807
|
if (!item) return;
|
|
2808
|
+
this.toolTranscriptProjection.recordRawNativeToolItem(item);
|
|
2596
2809
|
this.assistantProjection.handleRawResponseItemCompleted(item, this.activeItemIds);
|
|
2597
2810
|
await this.generatedMediaProjection.recordRaw(item);
|
|
2598
2811
|
}
|
|
@@ -2958,7 +3171,7 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2958
3171
|
const { runtime, attemptTools } = context;
|
|
2959
3172
|
const { connection } = runtime;
|
|
2960
3173
|
const { params, runAbortController, terminalState, abortExplicitly, abortFromUpstream, bindingStore, bindingIdentity, sessionAgentId, sandboxSessionKey, effectiveCwd } = connection;
|
|
2961
|
-
const { dynamicToolParams, computerContextEpoch } = attemptTools;
|
|
3174
|
+
const { dynamicToolParams, computerContextEpoch, toolBridge } = attemptTools;
|
|
2962
3175
|
const { state, userInputBridgeRef, steeringQueueRef, turnWatches } = turnRuntime;
|
|
2963
3176
|
const { emitExecutionPhaseOnce, emitLifecycleStart, maybeAnnounceFastModeAutoOff } = lifecycle;
|
|
2964
3177
|
const { enqueueNotification } = notifications;
|
|
@@ -2998,7 +3211,17 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2998
3211
|
nativePostToolUseRelayEnabled: resourceState.nativeHookRelay?.allowedEvents.includes("post_tool_use") === true && resourceState.nativeHookRelay.shouldRelayEvent("post_tool_use"),
|
|
2999
3212
|
readRecentRateLimits: () => readRecentCodexRateLimits(resourceState.client),
|
|
3000
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
|
+
}),
|
|
3001
3223
|
trajectoryRecorder,
|
|
3224
|
+
resolveDynamicToolResultContentSource: toolBridge.resultContentSourceForTool,
|
|
3002
3225
|
onNativeToolResultRecorded: maybeAnnounceFastModeAutoOff,
|
|
3003
3226
|
...prepareNativeMcpAppResultDetails ? { prepareNativeMcpAppResultDetails } : {},
|
|
3004
3227
|
upstreamUserText: turnState.codexTurnPromptText,
|
|
@@ -3164,15 +3387,27 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
3164
3387
|
});
|
|
3165
3388
|
if (!state.timedOut && !runAbortController.signal.aborted) await steeringQueueRef.current?.flushPending();
|
|
3166
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;
|
|
3167
3400
|
const bindingReleased = isIncognitoSessionKey(params.sessionKey) && !retainLiveIncognitoThread ? await bindingStore.mutate(bindingIdentity, {
|
|
3168
3401
|
kind: "clear",
|
|
3169
3402
|
threadId: resourceState.thread.threadId
|
|
3170
3403
|
}) : true;
|
|
3171
|
-
if (!state.timedOut && !
|
|
3172
|
-
if (bindingReleased)
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
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
|
+
}
|
|
3176
3411
|
}
|
|
3177
3412
|
userInputBridgeRef.current?.cancelPending();
|
|
3178
3413
|
turnWatches.clearAllTimers();
|
|
@@ -3230,14 +3465,7 @@ function estimateCodexAppServerProjectedTurnTokens(params) {
|
|
|
3230
3465
|
}
|
|
3231
3466
|
async function ensureCodexWorkspaceDirOnce(workspaceDir) {
|
|
3232
3467
|
const normalized = path.resolve(workspaceDir);
|
|
3233
|
-
if (codexWorkspaceDirCache.has(normalized))
|
|
3234
|
-
try {
|
|
3235
|
-
if ((await fs.stat(normalized)).isDirectory()) return;
|
|
3236
|
-
} catch (error) {
|
|
3237
|
-
if ((typeof error === "object" && error ? error.code : void 0) !== "ENOENT") throw error;
|
|
3238
|
-
}
|
|
3239
|
-
codexWorkspaceDirCache.delete(normalized);
|
|
3240
|
-
}
|
|
3468
|
+
if (codexWorkspaceDirCache.has(normalized)) return;
|
|
3241
3469
|
await fs.mkdir(normalized, { recursive: true });
|
|
3242
3470
|
codexWorkspaceDirCache.add(normalized);
|
|
3243
3471
|
}
|
|
@@ -3278,6 +3506,7 @@ const CODEX_APP_SERVER_NATIVE_THREAD_FALLBACK_MAX_TOKENS = 3e5;
|
|
|
3278
3506
|
const CODEX_APP_SERVER_NATIVE_THREAD_DEFAULT_RESERVE_TOKENS = 2e4;
|
|
3279
3507
|
const CODEX_APP_SERVER_NATIVE_THREAD_MIN_PROMPT_BUDGET_TOKENS = 8e3;
|
|
3280
3508
|
const CODEX_APP_SERVER_NATIVE_THREAD_MIN_PROMPT_BUDGET_RATIO = .5;
|
|
3509
|
+
const CODEX_APP_SERVER_ROLLOUT_TAIL_READ_BYTES = 64 * 1024;
|
|
3281
3510
|
const CODEX_APP_SERVER_BYTE_UNITS = {
|
|
3282
3511
|
b: 1,
|
|
3283
3512
|
k: 1024,
|
|
@@ -3306,7 +3535,7 @@ function parseCodexAppServerByteLimit(value) {
|
|
|
3306
3535
|
if (multiplier === void 0) return;
|
|
3307
3536
|
return Math.max(1, Math.round(amount * multiplier));
|
|
3308
3537
|
}
|
|
3309
|
-
async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codexHome) {
|
|
3538
|
+
async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codexHome, rolloutPath) {
|
|
3310
3539
|
const resolvedAgentDir = path.resolve(agentDir);
|
|
3311
3540
|
const resolvedCodexHome = codexHome?.trim() ? path.resolve(codexHome) : resolveCodexAppServerHomeDir(resolvedAgentDir);
|
|
3312
3541
|
const roots = [
|
|
@@ -3315,6 +3544,22 @@ async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codex
|
|
|
3315
3544
|
path.join(resolvedAgentDir, "agent", "codex-home", "sessions"),
|
|
3316
3545
|
path.join(path.dirname(resolvedAgentDir), "codex-home", "sessions")
|
|
3317
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 {}
|
|
3318
3563
|
const files = [];
|
|
3319
3564
|
const visited = /* @__PURE__ */ new Set();
|
|
3320
3565
|
for (const root of roots) {
|
|
@@ -3393,23 +3638,48 @@ async function readCodexSessionRecordForSessionFile(sessionFile) {
|
|
|
3393
3638
|
function isSqliteSessionFileMarker(sessionFile) {
|
|
3394
3639
|
return parseSqliteSessionFileMarker(sessionFile) !== void 0;
|
|
3395
3640
|
}
|
|
3396
|
-
async function readCodexAppServerRolloutTokenSnapshot(file) {
|
|
3397
|
-
let handle;
|
|
3398
|
-
try {
|
|
3641
|
+
async function readCodexAppServerRolloutTokenSnapshot(file, openedHandle) {
|
|
3642
|
+
let handle = openedHandle;
|
|
3643
|
+
if (!handle) try {
|
|
3399
3644
|
handle = await fs.open(file, "r");
|
|
3400
3645
|
} catch {
|
|
3401
3646
|
return;
|
|
3402
3647
|
}
|
|
3403
3648
|
let snapshot;
|
|
3404
3649
|
try {
|
|
3405
|
-
|
|
3650
|
+
let position = (await handle.stat()).size;
|
|
3651
|
+
const partialLineFragments = [];
|
|
3652
|
+
const applySnapshotLine = (line) => {
|
|
3406
3653
|
const lineSnapshot = readCodexAppServerRolloutTokenSnapshotLine(line);
|
|
3407
|
-
if (lineSnapshot
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
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;
|
|
3411
3678
|
}
|
|
3679
|
+
if (lineEnd > 0) partialLineFragments.push(chunk.subarray(0, lineEnd));
|
|
3680
|
+
position = nextPosition;
|
|
3412
3681
|
}
|
|
3682
|
+
if (partialLineFragments.length > 0) applySnapshotLine(Buffer.concat(partialLineFragments.toReversed()).toString("utf8"));
|
|
3413
3683
|
} finally {
|
|
3414
3684
|
await handle.close();
|
|
3415
3685
|
}
|
|
@@ -3467,31 +3737,36 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
3467
3737
|
if (!binding?.threadId) return binding;
|
|
3468
3738
|
if (binding.connectionScope === "supervision") return binding;
|
|
3469
3739
|
const sessionRecord = await readCodexSessionRecordForSessionFile(params.sessionFile);
|
|
3470
|
-
const rolloutFiles = await listCodexAppServerRolloutFilesForThread(params.agentDir, binding.threadId, params.codexHome);
|
|
3471
|
-
const
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
}
|
|
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;
|
|
3492
3767
|
}
|
|
3493
3768
|
}
|
|
3494
|
-
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)));
|
|
3495
3770
|
const nativeTokens = maxFiniteNumber(nativeTokenSnapshots.map((snapshot) => snapshot?.totalTokens));
|
|
3496
3771
|
const nativeModelContextWindow = maxFiniteNumber(nativeTokenSnapshots.map((snapshot) => snapshot?.modelContextWindow));
|
|
3497
3772
|
const sessionModelContextWindow = typeof sessionRecord?.contextTokens === "number" && Number.isFinite(sessionRecord.contextTokens) && sessionRecord.contextTokens > 0 ? Math.floor(sessionRecord.contextTokens) : void 0;
|
|
@@ -3521,16 +3796,6 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
3521
3796
|
});
|
|
3522
3797
|
return;
|
|
3523
3798
|
}
|
|
3524
|
-
if (compaction?.truncateAfterCompaction !== true) return binding;
|
|
3525
|
-
if (shouldDeferByteGuard) {
|
|
3526
|
-
embeddedAgentLog.debug("codex app-server deferring native transcript byte guard for context-engine thread bootstrap", {
|
|
3527
|
-
threadId: binding.threadId,
|
|
3528
|
-
engineId: binding.contextEngine?.engineId,
|
|
3529
|
-
epoch: binding.contextEngine?.projection?.epoch,
|
|
3530
|
-
fingerprint: binding.contextEngine?.projection?.fingerprint
|
|
3531
|
-
});
|
|
3532
|
-
return binding;
|
|
3533
|
-
}
|
|
3534
3799
|
return binding;
|
|
3535
3800
|
}
|
|
3536
3801
|
//#endregion
|
|
@@ -3584,22 +3849,45 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3584
3849
|
agentId: sessionAgentId
|
|
3585
3850
|
});
|
|
3586
3851
|
const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId);
|
|
3587
|
-
|
|
3852
|
+
let bindingIdentity = sessionBindingIdentity({
|
|
3588
3853
|
sessionId: params.sessionId,
|
|
3589
3854
|
sessionKey: params.sessionKey,
|
|
3590
3855
|
agentId: params.agentId,
|
|
3591
3856
|
config: params.config
|
|
3592
3857
|
});
|
|
3593
|
-
|
|
3858
|
+
let bindingStore = options.bindingStore;
|
|
3594
3859
|
preDynamicStartupStages.mark("session-agent");
|
|
3595
3860
|
let activeContextEngine = isActiveHarnessContextEngine(params.contextEngine) ? params.contextEngine : void 0;
|
|
3596
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
|
+
}
|
|
3597
3884
|
let startupBinding = await bindingStore.read(bindingIdentity);
|
|
3598
3885
|
if (!startupBinding && bindingIdentity.kind === "session" && bindingIdentity.sessionKey) {
|
|
3599
3886
|
if (!await reclaimCurrentCodexSessionGeneration({
|
|
3600
3887
|
bindingStore,
|
|
3601
3888
|
identity: bindingIdentity,
|
|
3602
|
-
config: params.config
|
|
3889
|
+
config: params.config,
|
|
3890
|
+
storePath: params.sessionTarget?.storePath
|
|
3603
3891
|
})) throw createCodexSessionGenerationSupersededError(bindingIdentity.sessionId);
|
|
3604
3892
|
startupBinding = await bindingStore.read(bindingIdentity);
|
|
3605
3893
|
}
|
|
@@ -3643,7 +3931,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3643
3931
|
authProfileId: resolvedStartupAuthProfileId,
|
|
3644
3932
|
authProfileStore: params.authProfileStore,
|
|
3645
3933
|
agentDir,
|
|
3646
|
-
|
|
3934
|
+
homeScope: resolveCodexAppServerHomeScope({ appServer: pluginConfig.appServer }),
|
|
3647
3935
|
config: params.config,
|
|
3648
3936
|
subscriptionProfileRequiredError: "Prepared Codex subscription route requires a forwarded OpenAI OAuth or token profile.",
|
|
3649
3937
|
subscriptionProfileUnusableError: "Prepared Codex subscription auth profile is unusable."
|
|
@@ -3669,15 +3957,16 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3669
3957
|
const requestedCwd = params.cwd ? resolveUserPath(params.cwd) : void 0;
|
|
3670
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");
|
|
3671
3959
|
const effectiveCwd = sandbox?.enabled ? effectiveWorkspace : requestedCwd ?? effectiveWorkspace;
|
|
3672
|
-
await ensureCodexWorkspaceDirOnce(effectiveWorkspace);
|
|
3960
|
+
if (effectiveWorkspace !== resolvedWorkspace) await ensureCodexWorkspaceDirOnce(effectiveWorkspace);
|
|
3673
3961
|
preDynamicStartupStages.mark("effective-workspace");
|
|
3962
|
+
const shouldPromoteApprovalPolicy = beforeToolCallPolicy.hasBeforeToolCallHook || beforeToolCallPolicy.trustedToolPolicies.length > 0;
|
|
3674
3963
|
const resolvePolicyAppServer = () => resolveCodexAppServerForOpenClawToolPolicy({
|
|
3675
3964
|
appServer: configuredAppServer,
|
|
3676
3965
|
pluginConfig,
|
|
3677
3966
|
env: process.env,
|
|
3678
|
-
shouldPromote:
|
|
3967
|
+
shouldPromote: shouldPromoteApprovalPolicy,
|
|
3679
3968
|
execPolicy,
|
|
3680
|
-
canUseUntrustedApprovalPolicy: configuredAppServer.start.transport !== "stdio" || isCodexAppServerApprovalPolicyAllowedByRequirements("untrusted")
|
|
3969
|
+
canUseUntrustedApprovalPolicy: shouldPromoteApprovalPolicy && configuredAppServer.approvalPolicy === "never" && (configuredAppServer.start.transport !== "stdio" || isCodexAppServerApprovalPolicyAllowedByRequirements("untrusted"))
|
|
3681
3970
|
});
|
|
3682
3971
|
let policyAppServer = resolvePolicyAppServer();
|
|
3683
3972
|
let appServer = resolveCodexAppServerForModelProvider({
|
|
@@ -3688,7 +3977,8 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3688
3977
|
env: process.env,
|
|
3689
3978
|
agentDir
|
|
3690
3979
|
});
|
|
3691
|
-
|
|
3980
|
+
let approvalPolicyPromotedForOpenClawToolPolicy = configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted";
|
|
3981
|
+
if (approvalPolicyPromotedForOpenClawToolPolicy) embeddedAgentLog.info("codex app-server approval policy promoted for OpenClaw tool policy", {
|
|
3692
3982
|
from: "never",
|
|
3693
3983
|
to: "untrusted",
|
|
3694
3984
|
beforeToolCallHook: beforeToolCallPolicy.hasBeforeToolCallHook,
|
|
@@ -3725,6 +4015,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3725
4015
|
};
|
|
3726
4016
|
if (params.abortSignal?.aborted) abortFromUpstream();
|
|
3727
4017
|
else params.abortSignal?.addEventListener("abort", abortFromUpstream, { once: true });
|
|
4018
|
+
const startupBindingBeforeRotation = startupBinding;
|
|
3728
4019
|
startupBinding = await rotateOversizedCodexAppServerStartupBinding({
|
|
3729
4020
|
binding: startupBinding,
|
|
3730
4021
|
bindingStore,
|
|
@@ -3737,20 +4028,23 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3737
4028
|
});
|
|
3738
4029
|
const initialInactiveThreadBootstrapBindingForcedFreshStart = initialStartupBindingHadInactiveThreadBootstrap && !startupBinding?.threadId;
|
|
3739
4030
|
preDynamicStartupStages.mark("rotate-binding");
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
appServer
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
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
|
+
}
|
|
3754
4048
|
const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
|
|
3755
4049
|
configuredEvents: options.nativeHookRelay?.events,
|
|
3756
4050
|
appServer
|
|
@@ -3806,6 +4100,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3806
4100
|
effectiveWorkspace,
|
|
3807
4101
|
effectiveCwd,
|
|
3808
4102
|
appServer,
|
|
4103
|
+
approvalPolicyPromotedForOpenClawToolPolicy,
|
|
3809
4104
|
nativeHookRelayEvents,
|
|
3810
4105
|
runAbortController,
|
|
3811
4106
|
terminalState,
|
|
@@ -4133,7 +4428,7 @@ function buildCodexOpenClawPromptContext(params) {
|
|
|
4133
4428
|
"## OpenClaw Workspace Context",
|
|
4134
4429
|
"",
|
|
4135
4430
|
params.workspacePromptContext.trim()
|
|
4136
|
-
].join("\n") : void 0].filter(isNonEmptyString$1);
|
|
4431
|
+
].join("\n") : void 0, params.watchedSessionsContext?.trim() || void 0].filter(isNonEmptyString$1);
|
|
4137
4432
|
if (sections.length === 0) return;
|
|
4138
4433
|
return [
|
|
4139
4434
|
"OpenClaw runtime context for this turn:",
|
|
@@ -4142,6 +4437,21 @@ function buildCodexOpenClawPromptContext(params) {
|
|
|
4142
4437
|
...sections
|
|
4143
4438
|
].join("\n");
|
|
4144
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
|
+
}
|
|
4145
4455
|
function shouldInjectCodexOpenClawPromptContext(params) {
|
|
4146
4456
|
return !(params.bootstrapContextMode === "lightweight" && params.bootstrapContextRunKind === "cron");
|
|
4147
4457
|
}
|
|
@@ -4475,7 +4785,13 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
4475
4785
|
baseDeveloperInstructions,
|
|
4476
4786
|
openClawPromptContext: buildCodexOpenClawPromptContext({
|
|
4477
4787
|
params: runtimeParams,
|
|
4478
|
-
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
|
+
})
|
|
4479
4795
|
}),
|
|
4480
4796
|
skillsCollaborationInstructions: renderCodexSkillsCollaborationInstructions({
|
|
4481
4797
|
attempt: runtimeParams,
|
|
@@ -4928,14 +5244,6 @@ function createCodexHostTrajectorySink(params) {
|
|
|
4928
5244
|
/** Creates a trajectory recorder when trajectory capture is enabled for the environment. */
|
|
4929
5245
|
function createCodexTrajectoryRecorder(params) {
|
|
4930
5246
|
if (!parseTrajectoryEnabled(params.env ?? process.env)) return null;
|
|
4931
|
-
const sqliteMarker = parseSqliteSessionFileMarker(params.trajectorySessionFile ?? params.attempt.sessionFile);
|
|
4932
|
-
if (!sqliteMarker || sqliteMarker.sessionId !== params.attempt.sessionId) {
|
|
4933
|
-
params.warn?.("codex trajectory capture requires a matching SQLite session target", {
|
|
4934
|
-
sessionId: params.attempt.sessionId,
|
|
4935
|
-
reason: sqliteMarker ? "session-id-mismatch" : "non-sqlite-session-target"
|
|
4936
|
-
});
|
|
4937
|
-
return null;
|
|
4938
|
-
}
|
|
4939
5247
|
if (!params.trajectoryRecorder) {
|
|
4940
5248
|
params.warn?.("codex trajectory capture requires the SQLite host recorder", {
|
|
4941
5249
|
sessionId: params.attempt.sessionId,
|
|
@@ -5265,7 +5573,29 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
5265
5573
|
...finalPromptError ? { error: formatErrorMessage(finalPromptError) } : {},
|
|
5266
5574
|
durationMs: Date.now() - attemptStartedAt
|
|
5267
5575
|
},
|
|
5268
|
-
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
|
+
},
|
|
5269
5599
|
hookRunner
|
|
5270
5600
|
});
|
|
5271
5601
|
state.shouldDelayNativeHookRelayUnregister = completedTurnStatus === "completed" && !effectiveTimedOut && !runAbortController.signal.aborted && !finalAborted && !finalPromptError;
|
|
@@ -6154,6 +6484,9 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
6154
6484
|
}
|
|
6155
6485
|
//#endregion
|
|
6156
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
|
+
}
|
|
6157
6490
|
async function prepareCodexAttemptPrompt(context) {
|
|
6158
6491
|
const { runtime, attemptTools, historyState, hookContext, workspaceBootstrapContext, baseDeveloperInstructions, openClawPromptContext, skillsCollaborationInstructions, promptState, codexContextProjectionMaxChars } = context;
|
|
6159
6492
|
const { connection, buildActiveRunAttemptParams, effectiveContextTokenBudget, effectiveRuntimeModelId, effectiveRuntimeProviderId } = runtime;
|
|
@@ -6239,13 +6572,17 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
6239
6572
|
embeddedAgentLog.warn("context engine assemble failed; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
|
|
6240
6573
|
}
|
|
6241
6574
|
const codexModelInputHistoryMessages = [];
|
|
6242
|
-
const buildPromptFromCurrentInputs = () =>
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
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
|
+
};
|
|
6249
6586
|
const resolveShiftedPromptInputRange = (prompt, promptInputRange, turnPromptText) => {
|
|
6250
6587
|
if (!promptInputRange || promptInputRange.start < 0 || promptInputRange.end < promptInputRange.start || promptInputRange.end > prompt.length || !turnPromptText.endsWith(prompt)) return;
|
|
6251
6588
|
const turnPromptOffset = turnPromptText.length - prompt.length;
|
|
@@ -7914,8 +8251,10 @@ const sandboxExecServerRegistry = {
|
|
|
7914
8251
|
};
|
|
7915
8252
|
//#endregion
|
|
7916
8253
|
//#region extensions/codex/src/app-server/sandbox-exec-server/json-rpc.ts
|
|
7917
|
-
/** JSON-RPC error code used when a sandbox
|
|
8254
|
+
/** JSON-RPC error code used when a sandbox filesystem resource does not exist. */
|
|
7918
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;
|
|
7919
8258
|
/** Protocol-level error carrying the JSON-RPC error code to send to the client. */
|
|
7920
8259
|
var JsonRpcProtocolError = class extends Error {
|
|
7921
8260
|
constructor(code, message) {
|
|
@@ -8247,6 +8586,101 @@ function requireFsBridge(execServer) {
|
|
|
8247
8586
|
* with OpenClaw sandbox policy checks before every bridge operation.
|
|
8248
8587
|
*/
|
|
8249
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
|
+
}
|
|
8250
8684
|
/** Reads a sandbox file as base64 after read-policy and size checks. */
|
|
8251
8685
|
async function readFile(execServer, params) {
|
|
8252
8686
|
const record = requireObject(params, "fs/readFile params");
|
|
@@ -8259,7 +8693,10 @@ async function readFile(execServer, params) {
|
|
|
8259
8693
|
const stat = await fsBridge.stat({ filePath });
|
|
8260
8694
|
if (!stat) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, "file not found");
|
|
8261
8695
|
assertSandboxFileReadWithinLimit(stat);
|
|
8262
|
-
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") };
|
|
8263
8700
|
}
|
|
8264
8701
|
/** Writes base64 data to an existing sandbox directory after write-policy checks. */
|
|
8265
8702
|
async function writeFile(execServer, params) {
|
|
@@ -8408,7 +8845,10 @@ async function copySandboxPath(execServer, params) {
|
|
|
8408
8845
|
return;
|
|
8409
8846
|
}
|
|
8410
8847
|
assertSandboxFileReadWithinLimit(sourceStat);
|
|
8411
|
-
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
|
+
});
|
|
8412
8852
|
await fsBridge.writeFile({
|
|
8413
8853
|
filePath: params.destinationPath,
|
|
8414
8854
|
data,
|
|
@@ -8423,6 +8863,7 @@ function metadataResponse(stat) {
|
|
|
8423
8863
|
isDirectory: stat?.type === "directory",
|
|
8424
8864
|
isFile: stat?.type === "file",
|
|
8425
8865
|
isSymlink: false,
|
|
8866
|
+
size: stat?.size ?? 0,
|
|
8426
8867
|
createdAtMs: 0,
|
|
8427
8868
|
modifiedAtMs: stat?.mtimeMs ?? 0
|
|
8428
8869
|
};
|
|
@@ -9284,19 +9725,21 @@ function isAuthorizedExecServerRequest(execServer, request) {
|
|
|
9284
9725
|
}
|
|
9285
9726
|
function handleConnection(execServer, socket) {
|
|
9286
9727
|
const processes = /* @__PURE__ */ new Map();
|
|
9728
|
+
const fileReads = /* @__PURE__ */ new Map();
|
|
9287
9729
|
socket.on("message", (data) => {
|
|
9288
|
-
handleMessage(execServer, processes, socket, data).catch((error) => {
|
|
9730
|
+
handleMessage(execServer, processes, fileReads, socket, data).catch((error) => {
|
|
9289
9731
|
embeddedAgentLog.warn("codex sandbox exec-server message failed", { error });
|
|
9290
9732
|
});
|
|
9291
9733
|
});
|
|
9292
9734
|
socket.on("close", () => {
|
|
9735
|
+
closeAllFileReads(fileReads);
|
|
9293
9736
|
for (const process of processes.values()) process.abortController.abort();
|
|
9294
9737
|
});
|
|
9295
9738
|
}
|
|
9296
9739
|
function handleExecServerSocketError(error) {
|
|
9297
9740
|
embeddedAgentLog.debug("codex sandbox exec-server websocket failed", { error });
|
|
9298
9741
|
}
|
|
9299
|
-
async function handleMessage(execServer, processes, socket, data) {
|
|
9742
|
+
async function handleMessage(execServer, processes, fileReads, socket, data) {
|
|
9300
9743
|
const request = parseRequest(data);
|
|
9301
9744
|
if (!request.method) {
|
|
9302
9745
|
sendError(socket, request.id, -32600, "Invalid Request");
|
|
@@ -9308,7 +9751,7 @@ async function handleMessage(execServer, processes, socket, data) {
|
|
|
9308
9751
|
return;
|
|
9309
9752
|
}
|
|
9310
9753
|
try {
|
|
9311
|
-
const result = await dispatchRequest(execServer, processes, socket, {
|
|
9754
|
+
const result = await dispatchRequest(execServer, processes, fileReads, socket, {
|
|
9312
9755
|
...request,
|
|
9313
9756
|
method
|
|
9314
9757
|
});
|
|
@@ -9317,13 +9760,25 @@ async function handleMessage(execServer, processes, socket, data) {
|
|
|
9317
9760
|
sendError(socket, request.id, error instanceof JsonRpcProtocolError ? error.code : -32603, error instanceof Error ? error.message : String(error));
|
|
9318
9761
|
}
|
|
9319
9762
|
}
|
|
9320
|
-
async function dispatchRequest(execServer, processes, socket, request) {
|
|
9763
|
+
async function dispatchRequest(execServer, processes, fileReads, socket, request) {
|
|
9321
9764
|
switch (request.method) {
|
|
9322
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" };
|
|
9323
9775
|
case "process/start": return startProcess(execServer, processes, socket, request.params);
|
|
9324
9776
|
case "process/read": return await readProcess(processes, request.params);
|
|
9325
9777
|
case "process/write": return writeProcess(processes, request.params);
|
|
9326
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);
|
|
9327
9782
|
case "fs/readFile": return await readFile(execServer, request.params);
|
|
9328
9783
|
case "fs/writeFile":
|
|
9329
9784
|
await writeFile(execServer, request.params);
|
|
@@ -9340,7 +9795,7 @@ async function dispatchRequest(execServer, processes, socket, request) {
|
|
|
9340
9795
|
await copyPath(execServer, request.params);
|
|
9341
9796
|
return {};
|
|
9342
9797
|
case "http/request": return await httpRequest(execServer, socket, request.params);
|
|
9343
|
-
default: throw new
|
|
9798
|
+
default: throw new JsonRpcProtocolError(JSON_RPC_METHOD_NOT_FOUND, `Unsupported OpenClaw sandbox exec-server method: ${request.method}`);
|
|
9344
9799
|
}
|
|
9345
9800
|
}
|
|
9346
9801
|
//#endregion
|
|
@@ -9358,7 +9813,6 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
9358
9813
|
developerInstructions: buildRenderedCodexDeveloperInstructions(),
|
|
9359
9814
|
prompt: turnState.codexTurnPromptText,
|
|
9360
9815
|
trajectoryRecorder: hostTrajectoryRecorder,
|
|
9361
|
-
trajectorySessionFile: params.trajectorySessionFile,
|
|
9362
9816
|
tools: toolBridge.availableSpecs,
|
|
9363
9817
|
warn: (message, fields) => embeddedAgentLog.warn(message, fields)
|
|
9364
9818
|
});
|
|
@@ -9468,14 +9922,7 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
9468
9922
|
timeoutFloorMs: options.startupTimeoutFloorMs
|
|
9469
9923
|
});
|
|
9470
9924
|
const requesterChannel = params.messageChannel ?? params.messageProvider;
|
|
9471
|
-
const requester =
|
|
9472
|
-
...requesterChannel ? { channel: requesterChannel } : {},
|
|
9473
|
-
...params.agentAccountId ? { accountId: params.agentAccountId } : {},
|
|
9474
|
-
...params.senderId ? { senderId: params.senderId } : {},
|
|
9475
|
-
...params.senderIsOwner !== void 0 ? { senderIsOwner: params.senderIsOwner } : {},
|
|
9476
|
-
...params.memberRoleIds?.length ? { roleIds: [...params.memberRoleIds] } : {}
|
|
9477
|
-
};
|
|
9478
|
-
const hasRequester = Object.keys(requester).length > 0;
|
|
9925
|
+
const requester = buildCodexHookRequester(params);
|
|
9479
9926
|
const buildNativeHookRelayFinalConfigPatch = (decision) => {
|
|
9480
9927
|
state.nativeHookRelay?.unregister();
|
|
9481
9928
|
state.nativeHookRelay = createCodexNativeHookRelay({
|
|
@@ -9489,7 +9936,15 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
9489
9936
|
config: params.config,
|
|
9490
9937
|
runId: params.runId,
|
|
9491
9938
|
channelId: hookChannelId,
|
|
9492
|
-
...
|
|
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
|
+
},
|
|
9493
9948
|
attemptTimeoutMs: params.timeoutMs,
|
|
9494
9949
|
startupTimeoutMs,
|
|
9495
9950
|
turnStartTimeoutMs: params.timeoutMs,
|
|
@@ -9663,6 +10118,7 @@ async function prepareCodexAttemptRuntime(connection) {
|
|
|
9663
10118
|
modelId: effectiveRuntimeModelId,
|
|
9664
10119
|
model: supervisedRuntimeModel,
|
|
9665
10120
|
thinkLevel: _outerThinkLevel,
|
|
10121
|
+
fastMode: _outerFastMode,
|
|
9666
10122
|
sessionKey: contextSessionKey
|
|
9667
10123
|
} : {
|
|
9668
10124
|
...params,
|
|
@@ -9690,7 +10146,8 @@ async function prepareCodexAttemptRuntime(connection) {
|
|
|
9690
10146
|
cfg: params.config,
|
|
9691
10147
|
toolsEnabled: usesSupervisionConnection || supportsModelTools(params.model),
|
|
9692
10148
|
disableTools: params.disableTools,
|
|
9693
|
-
toolsAllow: params.toolsAllow
|
|
10149
|
+
toolsAllow: params.toolsAllow,
|
|
10150
|
+
toolOverrides: params.toolOverrides
|
|
9694
10151
|
});
|
|
9695
10152
|
preDynamicStartupStages.mark("bundle-mcp");
|
|
9696
10153
|
const sandboxExecServerEnabled = isCodexSandboxExecServerEnabled(pluginConfig);
|
|
@@ -9842,6 +10299,7 @@ function handleApprovalRequest(params) {
|
|
|
9842
10299
|
turnId: params.turnId,
|
|
9843
10300
|
nativeHookRelay: params.nativeHookRelay,
|
|
9844
10301
|
autoApprove: params.autoApprove,
|
|
10302
|
+
autoApproveOpenClawToolPolicy: params.autoApproveOpenClawToolPolicy,
|
|
9845
10303
|
signal: params.signal,
|
|
9846
10304
|
onNativeToolFailureDisposition: params.onNativeToolFailureDisposition
|
|
9847
10305
|
});
|
|
@@ -9859,7 +10317,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
9859
10317
|
const { context } = prompt;
|
|
9860
10318
|
const { runtime, attemptTools } = context;
|
|
9861
10319
|
const { connection } = runtime;
|
|
9862
|
-
const { params, computerUseConfig, runAbortController, appServer, sessionAgentId } = connection;
|
|
10320
|
+
const { params, computerUseConfig, runAbortController, appServer, approvalPolicyPromotedForOpenClawToolPolicy, sessionAgentId } = connection;
|
|
9863
10321
|
const { toolBridge, toolOutcomeOrdinals, suppressedDynamicToolOutcomeOrdinals, allocateCodexToolOutcomeOrdinal } = attemptTools;
|
|
9864
10322
|
const { state, turnIdRef, userInputBridgeRef, openClawDynamicToolExecutions, pendingOpenClawDynamicToolCompletionIds, postToolRawAssistantCompletionIdleTimeoutMs, turnWatches } = turnRuntime;
|
|
9865
10323
|
const { emitExecutionPhaseOnce, scheduleTurnReleaseAfterTerminalDynamicTool, scheduleTerminalDynamicToolReleaseCheck } = lifecycle;
|
|
@@ -9917,6 +10375,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
9917
10375
|
turnId,
|
|
9918
10376
|
nativeHookRelay: resourceState.nativeHookRelay,
|
|
9919
10377
|
autoApprove: shouldAutoApproveCodexAppServerApprovals(appServer),
|
|
10378
|
+
autoApproveOpenClawToolPolicy: approvalPolicyPromotedForOpenClawToolPolicy,
|
|
9920
10379
|
signal,
|
|
9921
10380
|
onNativeToolFailureDisposition: (itemId, disposition) => projector?.recordNativeToolApprovalFailure(itemId, disposition)
|
|
9922
10381
|
});
|
|
@@ -10218,8 +10677,8 @@ var CodexPluginMetadataCache = class {
|
|
|
10218
10677
|
this.clearGeneration = 0;
|
|
10219
10678
|
}
|
|
10220
10679
|
/** Returns a fresh cached snapshot without issuing a request. */
|
|
10221
|
-
read(appCacheKey, queryKind) {
|
|
10222
|
-
const entryKey = buildMetadataCacheEntryKey(appCacheKey, queryKind);
|
|
10680
|
+
read(appCacheKey, queryKind, requestParams) {
|
|
10681
|
+
const entryKey = buildMetadataCacheEntryKey(appCacheKey, queryKind, requestParams);
|
|
10223
10682
|
const entry = this.entries.get(entryKey);
|
|
10224
10683
|
if (!entry) return;
|
|
10225
10684
|
if (entry.expiresAtMs <= this.nowMs()) {
|
|
@@ -10228,10 +10687,10 @@ var CodexPluginMetadataCache = class {
|
|
|
10228
10687
|
}
|
|
10229
10688
|
return entry.snapshot;
|
|
10230
10689
|
}
|
|
10231
|
-
/** Returns a fresh
|
|
10690
|
+
/** Returns a fresh snapshot or coalesces one catalog or installed-plugin request. */
|
|
10232
10691
|
async load(params) {
|
|
10233
|
-
const entryKey = buildMetadataCacheEntryKey(params.appCacheKey, params.queryKind);
|
|
10234
|
-
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);
|
|
10235
10694
|
if (cached) return cached;
|
|
10236
10695
|
const pending = this.inFlight.get(entryKey);
|
|
10237
10696
|
if (pending) try {
|
|
@@ -10243,7 +10702,8 @@ var CodexPluginMetadataCache = class {
|
|
|
10243
10702
|
const generation = this.generations.get(params.appCacheKey) ?? 0;
|
|
10244
10703
|
const clearGeneration = this.clearGeneration;
|
|
10245
10704
|
const promise = (async () => {
|
|
10246
|
-
const
|
|
10705
|
+
const method = params.queryKind === "installed" ? "plugin/installed" : "plugin/list";
|
|
10706
|
+
const response = await params.request(method, params.requestParams);
|
|
10247
10707
|
const snapshot = {
|
|
10248
10708
|
appCacheKey: params.appCacheKey,
|
|
10249
10709
|
queryKind: params.queryKind,
|
|
@@ -10282,10 +10742,17 @@ var CodexPluginMetadataCache = class {
|
|
|
10282
10742
|
/** Shared plugin metadata cache used by Codex app-server runtime paths. */
|
|
10283
10743
|
const defaultCodexPluginMetadataCache = new CodexPluginMetadataCache();
|
|
10284
10744
|
function hasMarketplaceLoadErrors(response) {
|
|
10285
|
-
return
|
|
10286
|
-
}
|
|
10287
|
-
function buildMetadataCacheEntryKey(appCacheKey, queryKind) {
|
|
10288
|
-
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
|
+
]);
|
|
10289
10756
|
}
|
|
10290
10757
|
//#endregion
|
|
10291
10758
|
//#region extensions/codex/src/app-server/plugin-thread-config-deadline.ts
|
|
@@ -10379,7 +10846,8 @@ function createCodexPluginThreadConfigStartupProvider(params) {
|
|
|
10379
10846
|
recoverablePluginConfigKeys: policy ? resolveRecoverableCodexPluginConfigKeys({
|
|
10380
10847
|
policy,
|
|
10381
10848
|
metadataCache,
|
|
10382
|
-
appCacheKey: params.appCacheKey
|
|
10849
|
+
appCacheKey: params.appCacheKey,
|
|
10850
|
+
configCwd: params.configCwd
|
|
10383
10851
|
}) : void 0,
|
|
10384
10852
|
build: () => buildCodexPluginThreadConfigWithinDeadline({
|
|
10385
10853
|
...buildParams,
|
|
@@ -10489,7 +10957,7 @@ async function startCodexAttemptThread(params) {
|
|
|
10489
10957
|
if (startupAbandonController.signal.aborted) throw new CodexAppServerStartupError("aborted");
|
|
10490
10958
|
let runtimeArtifact;
|
|
10491
10959
|
if (params.runtimeArtifactRequest) {
|
|
10492
|
-
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-
|
|
10960
|
+
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-CmtG_t1L.js");
|
|
10493
10961
|
runtimeArtifact = readCodexAppServerClientRuntimeArtifact(activeStartupClient);
|
|
10494
10962
|
const expected = params.runtimeArtifactRequest.expected;
|
|
10495
10963
|
const matchesExpected = !expected || Boolean(runtimeArtifact && runtimeArtifact.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint);
|
|
@@ -10834,6 +11302,14 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
10834
11302
|
spawnedBy: params.spawnedBy
|
|
10835
11303
|
});
|
|
10836
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
|
+
}));
|
|
10837
11313
|
state.thread = startupResult.thread;
|
|
10838
11314
|
state.runtimeArtifact = startupResult.runtimeArtifact;
|
|
10839
11315
|
state.turnRouter = startupResult.turnRouter;
|
|
@@ -11054,6 +11530,8 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
11054
11530
|
config: params.config,
|
|
11055
11531
|
contextWindowTokens: params.contextTokenBudget ?? params.model.contextWindow,
|
|
11056
11532
|
workspaceDir: effectiveWorkspace,
|
|
11533
|
+
remoteWorkspaceRoot: connection.appServer.remoteWorkspaceRoot,
|
|
11534
|
+
remoteWorkspaceRequestTimeoutMs: connection.appServer.requestTimeoutMs,
|
|
11057
11535
|
sessionId: params.sessionId,
|
|
11058
11536
|
sessionKey: sandboxSessionKey,
|
|
11059
11537
|
runId: params.runId,
|