@openclaw/codex 2026.8.1-beta.2 → 2026.8.1-beta.3
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/api.js +147 -0
- package/dist/app-server-policy-bg5QPSVP.js +25 -0
- package/dist/{attempt-client-cleanup-DMLXUfa8.js → attempt-client-cleanup-URjUlCHg.js} +1 -1
- package/dist/{binding-connection-I5Bo-AsX.js → binding-connection-DAvZwp96.js} +15 -3
- package/dist/{bounded-turn-qgZmzy_4.js → bounded-turn-4BjrZEwW.js} +22 -16
- package/dist/{capabilities-CybGI1oz.js → capabilities-CH3K57v4.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-B1AEz8ZA.js → command-formatters-D0nZ3qtd.js} +2 -2
- package/dist/{command-handlers-Db8pu_ds.js → command-handlers-DC86lgT4.js} +39 -22
- package/dist/command-rpc-xUIIonsO.js +90 -0
- package/dist/{compact-LspQaGfl.js → compact-COqgBRny.js} +35 -29
- package/dist/{session-binding-DPxIvMgE.js → config-CpNeo5AE.js} +28 -888
- package/dist/context-compaction-activity-BOeJf7yo.js +58 -0
- package/dist/doctor-contract-api.js +15 -14
- package/dist/{dynamic-tools-BVdyWkUD.js → dynamic-tools-fJZhl4CE.js} +1284 -651
- package/dist/{effective-mcp-catalog-DIIhAtOZ.js → effective-mcp-catalog-4YKn51aG.js} +2 -2
- package/dist/elicitation-input-DMkeki8d.js +71 -0
- package/dist/{event-projector-usage-e5huIQWu.js → event-projector-usage-CLwNEJqW.js} +16 -16
- package/dist/harness-DoKQcF8n.js +258 -0
- package/dist/harness.js +2 -226
- package/dist/index.js +171 -48
- package/dist/{isolated-completion-C58NbL40.js → isolated-completion-DPMtlH9r.js} +3 -3
- package/dist/managed-binary-By4FZC6i.js +212 -0
- package/dist/media-understanding-provider.js +2 -2
- package/dist/model-catalog-CmGoqVKB.js +48 -0
- package/dist/{models-BFlpn1Ex.js → models-CZw1wClT.js} +2 -2
- package/dist/{native-subagent-monitor-DyTGmTUx.js → native-subagent-monitor-GGq3RnOo.js} +185 -71
- package/dist/node-exec-server.runtime-Bsu1LdFZ.js +192 -0
- package/dist/{plugin-app-cache-key-C3H2CVp6.js → plugin-app-cache-key-DMNQ8Zi8.js} +15 -3
- package/dist/plugin-approval-roundtrip-C75Yiiwc.js +95 -0
- package/dist/{plugin-marketplace-discovery-CzrGJdCR.js → plugin-marketplace-discovery-CSWDkMrP.js} +40 -26
- package/dist/{plugin-metadata-cache-CNJPj4_b.js → plugin-metadata-cache-BXH5NF-4.js} +8 -5
- package/dist/{protocol-validators-B4F7L8Rf.js → protocol-validators-VAVyEnDp.js} +55 -2
- package/dist/{rate-limits-DZXmOL8-.js → rate-limits-BI1dMHDG.js} +1 -1
- package/dist/{request-BRl5_UfX.js → request-DSK0W6YI.js} +2 -2
- package/dist/{run-attempt-P8BdxC1I.js → run-attempt-BV3HzuCf.js} +1098 -666
- package/dist/{runtime-artifact-BVSPdd6g.js → runtime-artifact-BvyT1uyd.js} +4 -7
- package/dist/{sandbox-guard-Cmwc9eIk.js → sandbox-guard-C1qEeZ5C.js} +25 -19
- package/dist/session-binding-BTrLf9Qm.js +874 -0
- package/dist/{session-catalog-xwNi_SDM.js → session-catalog-ezP_UcRM.js} +1541 -1296
- package/dist/session-catalog-home-id-BNwAJ9D7.js +18 -0
- package/dist/{session-cli-7hgXZDV7.js → session-cli-B1hKvfkI.js} +20 -7
- package/dist/{session-retirement-DoMMJFKm.js → session-retirement-CE4iMiLh.js} +3 -3
- package/dist/{session-upstream-marker-CrIFX06J.js → session-upstream-marker-D_2npHlA.js} +1 -1
- package/dist/{settled-turn-finalizer-BRWBO4MO.js → settled-turn-finalizer-Dx1onIqg.js} +23 -19
- package/dist/{shared-client-kIBbGjk4.js → shared-client-Dw-rzii0.js} +755 -273
- package/dist/{side-question-9HAL26l9.js → side-question-DbXkJZzg.js} +52 -30
- package/dist/{thread-lifecycle-Bu1BTDXr.js → thread-lifecycle-DKdrnTMX.js} +310 -92
- package/dist/{thread-ownership-6kOQHlyC.js → thread-ownership-i2NBwDUL.js} +2 -2
- package/dist/{thread-resume-CPrJNQVM.js → thread-resume-CdJk2Ehf.js} +3 -3
- package/dist/{transcript-mirror-B9gGgnJS.js → transcript-mirror-BU0_LKAL.js} +46 -28
- package/dist/{transport-stdio-DIImwDVS.js → transport-stdio-DhoGy33Z.js} +2 -2
- package/dist/{upstream-prompt-provenance-ClRBije0.js → upstream-prompt-provenance-CFmsKwr9.js} +12 -14
- package/dist/{upstream-session-fork-CE-_LdnP.js → upstream-session-fork-BDVJCLAD.js} +12 -6
- package/dist/{usage-CHlV0e-o.js → usage-9dKJCgcy.js} +3 -3
- package/dist/{web-search-provider.runtime-DRw2Vl42.js → web-search-provider.runtime-DCdx4DGu.js} +3 -3
- package/openclaw.plugin.json +31 -1
- package/package.json +6 -5
- package/dist/app-server-policy-zcBDc1JU.js +0 -49
|
@@ -1,42 +1,47 @@
|
|
|
1
|
-
import { C as
|
|
2
|
-
import { $ as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { l as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { A as resolveOpenClawExecPolicyForCodexAppServer, C as parseAllowedApprovalPoliciesFromCodexRequirements, D as selectGuardianApprovalPolicy, E as readCodexRequirementsToml, O as selectGuardianApprovalsReviewer, S as resolveCodexModelBackedReviewerPolicyContext, T as parseAllowedSandboxModesFromCodexRequirements, b as canUseCodexModelBackedApprovalsReviewerForModel, d as withMcpElicitationsApprovalPolicy, f as isCodexPairedNodeRemoteExecPlacementSandbox, g as resolveCodexPluginsPolicy, h as readCodexPluginConfig, j as selectGuardianSandbox, k as selectUserApprovalsReviewer, l as resolveCodexAppServerNetworkProxy, m as isCodexSandboxExecServerEnabled, o as resolveCodexComputerUseConfig, p as isCodexRemoteExecPlacementSandbox, r as resolveCodexAppServerHomeScope, u as shouldAutoApproveCodexAppServerApprovals, w as parseAllowedApprovalsReviewersFromCodexRequirements } from "./config-CpNeo5AE.js";
|
|
2
|
+
import { $ as rememberCodexRateLimitsRead, A as isCodexAppServerApprovalRequest, B as CodexAppServerRpcError, C as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, D as resolveCodexTurnTerminalIdleTimeoutMs, E as resolveCodexTurnCompletionIdleTimeoutMs, I as isCodexAppServerRequestTimeoutError, M as isCodexAppServerConnectionClosedError, N as isCodexAppServerIndeterminateRequestCancellationError, O as withCodexStartupTimeout, P as isCodexAppServerIndeterminateTransportError, Q as readRecentCodexRateLimits, R as resolveCodexAppServerClientInstanceId, T as resolveCodexTurnAssistantCompletionIdleTimeoutMs, V as createCodexElicitationResponse, W as ensureCodexAppServerClientRuntime, Y as retainCodexAppServerLiveThread, Z as readCodexRateLimitsRevision, a as getLeasedSharedCodexAppServerClient, at as resolveCodexAppServerPreparedAuthHandoff, b as CodexAppServerStartupError, et as resolveCodexAppServerAuthAccountCacheKey, f as retainSharedCodexAppServerClientIfCurrent, ft as resolveCodexAppServerHomeDir, g as withAbortableTimeout, i as createIsolatedCodexAppServerClient, it as resolveCodexAppServerPreparedApiKeyCacheKey, j as isCodexAppServerBrokenPipeError, k as getCodexAppServerClientInstanceId, l as releaseLeasedSharedCodexAppServerClient, lt as flattenCodexDynamicToolFunctions, n as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, nt as resolveCodexAppServerAuthProfileIdForAgent, o as getSharedCodexAppServerClient, p as retireSharedCodexAppServerClientIfCurrent, q as protectCodexAppServerLiveThread, rt as resolveCodexAppServerFallbackApiKeyCacheKey, s as isCodexAppServerStartSelectionChangedError, t as clearSharedCodexAppServerClientIfCurrent, tt as resolveCodexAppServerAuthProfileId, ut as isJsonObject, w as resolveCodexStartupTimeoutMs, x as isCodexAppServerStartupError, y as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS } from "./shared-client-Dw-rzii0.js";
|
|
3
|
+
import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, i as createCodexSessionGenerationSupersededError, l as resolveCodexRunSessionBindingAuthority, u as scopeCodexRunBindingStore } from "./session-binding-BTrLf9Qm.js";
|
|
4
|
+
import { A as shouldSynthesizeToolProgressForItem, B as readNullableString, E as itemStatus, F as readItem, I as readItemString, N as readCodexErrorNotificationMessage, O as shouldClearTerminalPresentationForNativeItem, T as itemName, V as splitPlanText, a as closeCodexStartupClientBestEffort, d as unsubscribeCodexThreadBestEffort, f as CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS, g as readCodexNotificationThreadId, h as isCodexNotificationForTurn, j as extractRawAssistantText, l as retireCodexAppServerClientAfterTimedOutTurn, m as CodexProjectionDiagnostics, o as interruptCodexTurnAndWaitBestEffort, p as getCodexAppServerTurnRouter, r as CodexAppServerUnsafeSubscriptionError, t as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS, u as retireUnsafeCodexTurnClientBestEffort, z as readNonNegativeInteger } from "./attempt-client-cleanup-URjUlCHg.js";
|
|
5
|
+
import { C as readRawResponseToolCallId, E as updateActiveTurnItemIds, S as readNotificationItemId, T as updateActiveCompletionBlockerItemIds, _ as isReasoningItemCompletionNotification, a as codexExecutionToolName, b as isTerminalTurnStatus, c as isAssistantCompletionReleaseNotification, d as isNativeToolProgressNotification, f as isPendingOpenClawDynamicToolCompletionNotification, g as isRawToolOutputCompletionNotification, h as isRawReasoningCompletionNotification, l as isCodexTurnAbortMarkerNotification, m as isRawFunctionToolOutputCompletionNotification, o as describeNotificationActivity, p as isRawAssistantProgressNotification, r as projectCodexThreadUsageUpdate, s as isAssistantCommentaryCompletionNotification, t as CodexResponseCompletionProjection, u as isFileChangePatchUpdatedNotification, v as isReasoningProgressNotification, w as shouldDisarmAssistantCompletionIdleWatch, x as readCodexNotificationItem, y as isRetryableErrorNotification } from "./event-projector-usage-CLwNEJqW.js";
|
|
6
|
+
import { l as readCodexTurn, o as assertCodexTurnStartResponse, s as readCodexDynamicToolCallParams, u as readCodexTurnCompletedNotification } from "./protocol-validators-VAVyEnDp.js";
|
|
7
|
+
import { n as buildCodexAppServerRuntimeFingerprint, o as defaultCodexAppInventoryCache, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-DMNQ8Zi8.js";
|
|
8
|
+
import { B as neutralizeCodexExplicitMentionSigils, D as codexLegacyDynamicToolsFingerprint, E as codexDynamicToolsFingerprint, F as resolveCodexDynamicToolsLoadingForRuntime, G as buildCodexPluginAppsConfigPatchFromPolicyContext, H as resolveCodexContextEngineProjectionMaxChars, I as buildContextEngineBinding, J as buildCodexPluginThreadConfigTimeoutFallback, K as buildCodexPluginThreadConfig, L as isContextEngineBindingCompatible, M as isSystemAgentOnlyCodexDynamicToolAllowlist, O as filterCodexDynamicTools, Q as shouldBuildCodexPluginThreadConfig, R as buildCodexContinuityCalibration, T as areCodexDynamicToolFingerprintsCompatible, U as resolveCodexContextEngineProjectionReserveTokens, V as projectContextEngineAssemblyForCodex, W as resolveCodexContinuityProjectionMaxChars, X as buildPluginAppPolicyContext, Z as mergeCodexThreadConfigs, a as isCodexAppServerProfilerEnabled, f as resolveCodexWebSearchPlan, i as startOrResumeThread, it as resolveRecoverableCodexPluginConfigKeys, j as isMessageOnlyCodexSourceReply, n as buildTurnStartParams, p as buildDeveloperInstructions, q as buildCodexPluginThreadConfigInputFingerprint, r as buildCodexUserInput, t as buildTurnCollaborationMode, v as resolveCodexAppServerThreadModelSelection, z as fitCodexProjectedContextForTurnStart } from "./thread-lifecycle-DKdrnTMX.js";
|
|
8
9
|
import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
|
|
9
|
-
import { i as readUpstreamUserText, n as attachUpstreamUserText, r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-
|
|
10
|
-
import { a as buildCodexUserPromptMessage, c as readCodexMirrorSourceFingerprint, i as mirrorPromptAtTurnStartBestEffort, l as serializeCodexMirrorSourceEvidence, n as createCodexAppServerUserMessagePersistenceNotifier, o as promptSnapshot, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-
|
|
11
|
-
import { t as CODEX_CONTROL_METHODS } from "./capabilities-
|
|
12
|
-
import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-
|
|
13
|
-
import { r as formatCodexDisplayText } from "./command-formatters-
|
|
14
|
-
import {
|
|
15
|
-
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-
|
|
10
|
+
import { i as readUpstreamUserText, n as attachUpstreamUserText, r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-CFmsKwr9.js";
|
|
11
|
+
import { a as buildCodexUserPromptMessage, c as readCodexMirrorSourceFingerprint, i as mirrorPromptAtTurnStartBestEffort, l as serializeCodexMirrorSourceEvidence, n as createCodexAppServerUserMessagePersistenceNotifier, o as promptSnapshot, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-BU0_LKAL.js";
|
|
12
|
+
import { t as CODEX_CONTROL_METHODS } from "./capabilities-CH3K57v4.js";
|
|
13
|
+
import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-BI1dMHDG.js";
|
|
14
|
+
import { r as formatCodexDisplayText } from "./command-formatters-D0nZ3qtd.js";
|
|
15
|
+
import { t as resolveCodexAppServerForModelProvider } from "./app-server-policy-bg5QPSVP.js";
|
|
16
|
+
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-DAvZwp96.js";
|
|
16
17
|
import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-B4FfbcCg.js";
|
|
17
|
-
import { t as
|
|
18
|
+
import { t as persistCodexContextCompactionActivity } from "./context-compaction-activity-BOeJf7yo.js";
|
|
18
19
|
import { n as createAssistantMessage, r as createAssistantMirrorMessage, t as createAssistantCommentaryMessage } from "./event-projector-assistant-message-BwxV4d6N.js";
|
|
19
|
-
import { a as CodexToolProgressProjection, c as isCodexCommandBearingToolCall, d as sanitizeCodexToolResponse, i as readCodexMirroredSessionHistoryMessages, l as resolveCodexToolProgressDetailMode, n as CodexEventProjection, o as shouldEmitTranscriptToolProgress, r as CodexToolTranscriptProjection, s as inferCodexDynamicToolMeta, t as codexNativeSubagentMonitorRuntime, u as sanitizeCodexToolArguments } from "./native-subagent-monitor-
|
|
20
|
-
import { A as
|
|
21
|
-
import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse, o as killStaleComputerUseMcpChildren, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-
|
|
20
|
+
import { a as CodexToolProgressProjection, c as isCodexCommandBearingToolCall, d as sanitizeCodexToolResponse, i as readCodexMirroredSessionHistoryMessages, l as resolveCodexToolProgressDetailMode, n as CodexEventProjection, o as shouldEmitTranscriptToolProgress, r as CodexToolTranscriptProjection, s as inferCodexDynamicToolMeta, t as codexNativeSubagentMonitorRuntime, u as sanitizeCodexToolArguments } from "./native-subagent-monitor-GGq3RnOo.js";
|
|
21
|
+
import { A as buildCodexNativeHookRelayConfig, B as isMatchingDynamicToolTerminalDiagnostic, C as shouldRequireCodexSandboxExecServerEnvironment, D as CodexNativeToolLifecycleProjector, E as readBoundedCodexRemoteWorkspaceFile, F as resolveCodexNativeHookRelayTtlMs, G as toCodexDynamicToolProgressResponse, H as resolveTerminalDynamicToolBatchAction, I as scheduleCodexNativeHookRelayUnregister, K as toCodexDynamicToolProtocolResponse, L as handleDynamicToolCallWithTimeout, M as createCodexNativeHookRelay, N as emitCodexNativePreToolUseFailureDiagnostic, P as resolveCodexNativeHookRelayEvents, R as hasPendingDynamicToolTerminalDiagnostic, S as shouldEnableCodexAppServerNativeToolSurface, U as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, V as resolveDynamicToolCallTimeoutMs, W as shouldReleaseTurnAfterTerminalDynamicTool, _ as resolveCodexAppServerHookChannelId, a as emitDynamicToolStartedDiagnostic, c as resolveCodexProviderWebSearchSupport, d as releaseCodexSandboxExecServerEnvironment, f as buildDynamicTools, g as resolveCodexAppServerExecutionCwd, h as formatCodexDynamicToolBuildStageSummary, i as emitDynamicToolErrorDiagnostic, j as buildCodexNativeHookRelayDisabledConfig, k as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, m as disableCodexPluginThreadConfig, n as projectCodexExecutableDynamicTools, o as emitDynamicToolTerminalDiagnostic, p as createCodexDynamicToolBuildStageTracker, q as resolveCodexToolAbortTerminalReason, r as routeCodexAppServerElicitationRequest, s as handleCodexAppServerApprovalRequest, t as createCodexDynamicToolBridge, u as ensureCodexSandboxExecServerEnvironment, v as resolveCodexExternalSandboxPolicyForOpenClawSandbox, w as shouldWarnCodexDynamicToolBuildStageSummary, x as resolveCodexSandboxEnvironmentSelection, y as resolveCodexMessageToolProvider, z as isDynamicToolTerminalDiagnosticEvent } from "./dynamic-tools-fJZhl4CE.js";
|
|
22
|
+
import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse, o as killStaleComputerUseMcpChildren, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-BXH5NF-4.js";
|
|
22
23
|
import { asBoolean, asFiniteNumber, asOptionalRecord, hasNonEmptyString, normalizeOptionalString, readNonBlankString, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
23
24
|
import fs from "node:fs/promises";
|
|
24
25
|
import path from "node:path";
|
|
25
26
|
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
26
27
|
import { asDateTimestampMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
27
|
-
import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, agentHarnessAttemptTerminal, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine,
|
|
28
|
+
import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, agentHarnessAttemptTerminal, agentHarnessStructuredInput, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine, buildBootstrapContextForFiles, buildHarnessContextEngineRuntimeContext, buildWatchedSessionsHarnessContext, callGatewayTool, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, formatErrorMessage, formatFastModeAutoProgressText, getAgentHarnessHookRunner, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, prepareHarnessNativeMcpAppPreview, projectAgentHarnessTranscriptMessageForDisplay, resolveAgentDir, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveBootstrapFilesForRun, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveSessionAgentIds, resolveUserPath, runAgentCleanupStep, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
28
29
|
import crypto, { createHash } from "node:crypto";
|
|
30
|
+
import { hostname } from "node:os";
|
|
29
31
|
import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
30
32
|
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
31
33
|
import { parseSqliteSessionFileMarker } from "openclaw/plugin-sdk/session-store-runtime";
|
|
32
|
-
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
34
|
+
import { truncateUtf16Safe, truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
35
|
+
import { isPathInside, isPathStrictlyInside, root } from "openclaw/plugin-sdk/file-access-runtime";
|
|
33
36
|
import { captureFinalCodexCronCreatorToolAllowlist, materializeStaticMcpToolsForScheduledHarnessRun, resolveCodexMcpToolOverridesForAgent } from "openclaw/plugin-sdk/codex-mcp-projection";
|
|
34
37
|
import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
38
|
+
import { Buffer as Buffer$1 } from "node:buffer";
|
|
35
39
|
import { prepareMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
|
|
40
|
+
import { isSilentReplyPayloadText } from "openclaw/plugin-sdk/reply-chunking";
|
|
36
41
|
import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
|
|
37
42
|
import { resolveGeneratedMediaMaxBytes } from "openclaw/plugin-sdk/media-generation-runtime";
|
|
38
43
|
import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
|
|
39
|
-
import {
|
|
44
|
+
import { stripInvisibleUnicode } from "openclaw/plugin-sdk/web-content-extractor";
|
|
40
45
|
import { MESSAGE_TOOL_DELIVERY_HINTS } from "openclaw/plugin-sdk/message-tool-delivery-hints";
|
|
41
46
|
//#region extensions/codex/src/app-server/attempt-steering.ts
|
|
42
47
|
/**
|
|
@@ -173,10 +178,12 @@ function createCodexSteeringQueue(params) {
|
|
|
173
178
|
acceptance: "open",
|
|
174
179
|
text,
|
|
175
180
|
images: options?.images,
|
|
181
|
+
isInboundUserMessage: options?.isInboundUserMessage,
|
|
176
182
|
onQueueAccepted: options?.onQueueAccepted,
|
|
177
183
|
resolve: resolveDelivery,
|
|
178
184
|
reject: rejectDelivery,
|
|
179
|
-
settled: false
|
|
185
|
+
settled: false,
|
|
186
|
+
userTurnTranscriptRecorder: options?.userTurnTranscriptRecorder
|
|
180
187
|
};
|
|
181
188
|
pendingMessages.add(item);
|
|
182
189
|
return {
|
|
@@ -193,19 +200,6 @@ function createCodexSteeringQueue(params) {
|
|
|
193
200
|
options?.onQueueAccepted?.(false);
|
|
194
201
|
throw unavailableError;
|
|
195
202
|
}
|
|
196
|
-
const pendingUserInput = options?.isInboundUserMessage === true ? params.claimPendingUserInput() : void 0;
|
|
197
|
-
if (pendingUserInput) {
|
|
198
|
-
if (!options?.images?.length) {
|
|
199
|
-
const answered = pendingUserInput.answer(text);
|
|
200
|
-
options?.onQueueAccepted?.(answered);
|
|
201
|
-
if (!answered) throw new Error("codex pending user input rejected the answer");
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
flushBatch().catch(() => void 0);
|
|
205
|
-
const { item, delivery } = createPendingMessage(text, options);
|
|
206
|
-
await Promise.all([enqueueSend([item]).finally(() => pendingUserInput.cancel()), delivery]);
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
203
|
const { item, delivery } = createPendingMessage(text, options);
|
|
210
204
|
batchedMessages.push(item);
|
|
211
205
|
clearBatchTimer();
|
|
@@ -221,8 +215,21 @@ function createCodexSteeringQueue(params) {
|
|
|
221
215
|
const batch = dispatchedBatches.get(clientUserMessageId);
|
|
222
216
|
if (!batch) return false;
|
|
223
217
|
dispatchedBatches.delete(clientUserMessageId);
|
|
224
|
-
for (const item of batch.items)
|
|
225
|
-
|
|
218
|
+
for (const item of batch.items) reportItemAcceptance(item, true);
|
|
219
|
+
const resolveBatch = () => {
|
|
220
|
+
for (const item of batch.items) resolveItem(item);
|
|
221
|
+
return true;
|
|
222
|
+
};
|
|
223
|
+
const rejectBatch = (error) => {
|
|
224
|
+
for (const item of batch.items) rejectItem(item, error);
|
|
225
|
+
return true;
|
|
226
|
+
};
|
|
227
|
+
if (!params.beforeConfirmConsumed) return resolveBatch();
|
|
228
|
+
try {
|
|
229
|
+
return params.beforeConfirmConsumed(batch.items).then(resolveBatch, rejectBatch);
|
|
230
|
+
} catch (error) {
|
|
231
|
+
return rejectBatch(error);
|
|
232
|
+
}
|
|
226
233
|
},
|
|
227
234
|
sealAdmission: sealQueueAdmission,
|
|
228
235
|
cancel: cancelQueue
|
|
@@ -253,6 +260,8 @@ var CodexAssistantProjection = class {
|
|
|
253
260
|
this.rawPromotedAssistantItemIds = /* @__PURE__ */ new Set();
|
|
254
261
|
this.assistantStarted = false;
|
|
255
262
|
this.streamedPartialAssistantItemReplaceable = false;
|
|
263
|
+
this.persistableAssistantBarrier = 0;
|
|
264
|
+
this.persistableAssistantBarrierItemIds = /* @__PURE__ */ new Set();
|
|
256
265
|
}
|
|
257
266
|
hasCompletedTerminalAssistantText(completedItemIds) {
|
|
258
267
|
const latestCompletedItemId = this.latestCompletedTerminalAssistantItemId;
|
|
@@ -322,6 +331,7 @@ var CodexAssistantProjection = class {
|
|
|
322
331
|
if (knownFinalAnswer && !replaceable) await this.params.onPartialReply?.(streamPayload);
|
|
323
332
|
}
|
|
324
333
|
recordItemStarted(item, itemId) {
|
|
334
|
+
this.noteNativeWorkBarrier(item);
|
|
325
335
|
if (item?.type === "agentMessage" && itemId && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
326
336
|
this.rememberAssistantPhase(item);
|
|
327
337
|
if (item?.type === "agentMessage" && itemId) this.rememberAssistantItem(itemId);
|
|
@@ -331,6 +341,7 @@ var CodexAssistantProjection = class {
|
|
|
331
341
|
}
|
|
332
342
|
}
|
|
333
343
|
recordItemCompleted(item, itemId, activeItemIds) {
|
|
344
|
+
this.noteNativeWorkBarrier(item);
|
|
334
345
|
if (item?.type === "agentMessage" && itemId && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
335
346
|
if (itemId) this.latestCompletedItemId = itemId;
|
|
336
347
|
this.rememberAssistantPhase(item);
|
|
@@ -403,8 +414,14 @@ var CodexAssistantProjection = class {
|
|
|
403
414
|
else this.markLatestTerminalAssistantCandidate(itemId, activeItemIds, { canReleaseAfterToolHandoff: isIdlessTerminalAssistantAfterCompletedWork });
|
|
404
415
|
}
|
|
405
416
|
collectAssistantTexts() {
|
|
406
|
-
const
|
|
407
|
-
|
|
417
|
+
const afterHandoff = this.collectPersistableAssistantTexts(this.persistableAssistantBarrier);
|
|
418
|
+
const audibleAfterHandoff = afterHandoff.filter((text) => !isSilentReplyPayloadText(text));
|
|
419
|
+
if (audibleAfterHandoff.length > 0) return audibleAfterHandoff;
|
|
420
|
+
if (afterHandoff.length > 0) return afterHandoff.slice(-1);
|
|
421
|
+
const recoveredAudible = this.collectPersistableAssistantTexts(0).filter((text) => !isSilentReplyPayloadText(text));
|
|
422
|
+
if (recoveredAudible.length > 0) return recoveredAudible.slice(-1);
|
|
423
|
+
const recovered = this.resolveFinalAssistantTextItem()?.text;
|
|
424
|
+
return recovered ? [recovered] : [];
|
|
408
425
|
}
|
|
409
426
|
collectCommentaryMessages() {
|
|
410
427
|
return this.assistantItemOrder.flatMap((itemId) => {
|
|
@@ -560,6 +577,34 @@ var CodexAssistantProjection = class {
|
|
|
560
577
|
};
|
|
561
578
|
}
|
|
562
579
|
}
|
|
580
|
+
collectPersistableAssistantTexts(minIndex) {
|
|
581
|
+
let texts = [];
|
|
582
|
+
let replaceable = false;
|
|
583
|
+
for (let index = minIndex; index < this.assistantItemOrder.length; index += 1) {
|
|
584
|
+
const itemId = this.assistantItemOrder[index];
|
|
585
|
+
if (!itemId || this.assistantPhaseByItem.get(itemId) === "commentary") continue;
|
|
586
|
+
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
587
|
+
if (!text || this.isToolProgressEchoText(itemId, text)) continue;
|
|
588
|
+
if (isSilentReplyPayloadText(text)) {
|
|
589
|
+
texts.push(text);
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
const isTerminalFinal = this.assistantPhaseByItem.get(itemId) === "final_answer";
|
|
593
|
+
if (!isTerminalFinal || replaceable) {
|
|
594
|
+
texts = [text];
|
|
595
|
+
replaceable = !isTerminalFinal;
|
|
596
|
+
continue;
|
|
597
|
+
}
|
|
598
|
+
texts.push(text);
|
|
599
|
+
}
|
|
600
|
+
return texts;
|
|
601
|
+
}
|
|
602
|
+
noteNativeWorkBarrier(item) {
|
|
603
|
+
if (!item || !shouldAdvancePersistableAssistantBarrier(item)) return;
|
|
604
|
+
if (item.id && this.persistableAssistantBarrierItemIds.has(item.id)) return;
|
|
605
|
+
if (item.id) this.persistableAssistantBarrierItemIds.add(item.id);
|
|
606
|
+
this.persistableAssistantBarrier = this.assistantItemOrder.length;
|
|
607
|
+
}
|
|
563
608
|
rememberAssistantItem(itemId) {
|
|
564
609
|
if (!itemId || this.assistantItemOrder.includes(itemId)) return;
|
|
565
610
|
this.assistantItemOrder.push(itemId);
|
|
@@ -569,6 +614,9 @@ var CodexAssistantProjection = class {
|
|
|
569
614
|
return this.rawPromotedAssistantItemIds.has(itemId) && this.matchesToolProgressEcho(text);
|
|
570
615
|
}
|
|
571
616
|
};
|
|
617
|
+
function shouldAdvancePersistableAssistantBarrier(item) {
|
|
618
|
+
return shouldClearTerminalPresentationForNativeItem(item) || item.type === "dynamicToolCall" || item.type === "sleep";
|
|
619
|
+
}
|
|
572
620
|
//#endregion
|
|
573
621
|
//#region extensions/codex/src/app-server/event-projector-media.ts
|
|
574
622
|
const GENERATED_IMAGE_MEDIA_SUBDIR = "tool-image-generation";
|
|
@@ -739,9 +787,10 @@ function isBase64WhitespaceCode(code) {
|
|
|
739
787
|
//#endregion
|
|
740
788
|
//#region extensions/codex/src/app-server/event-projector-reasoning.ts
|
|
741
789
|
var CodexReasoningProjection = class {
|
|
742
|
-
constructor(params, emitAgentEvent) {
|
|
790
|
+
constructor(params, emitAgentEvent, onNativePlanUpdate) {
|
|
743
791
|
this.params = params;
|
|
744
792
|
this.emitAgentEvent = emitAgentEvent;
|
|
793
|
+
this.onNativePlanUpdate = onNativePlanUpdate;
|
|
745
794
|
this.reasoningTextByGroup = /* @__PURE__ */ new Map();
|
|
746
795
|
this.reasoningItemOrder = /* @__PURE__ */ new Map();
|
|
747
796
|
this.planTextByItem = /* @__PURE__ */ new Map();
|
|
@@ -782,7 +831,7 @@ var CodexReasoningProjection = class {
|
|
|
782
831
|
}))
|
|
783
832
|
});
|
|
784
833
|
}
|
|
785
|
-
handleTurnPlanUpdated(params, source = "codex-app-server") {
|
|
834
|
+
async handleTurnPlanUpdated(params, source = "codex-app-server") {
|
|
786
835
|
const explanation = readNullableString(params, "explanation");
|
|
787
836
|
const plan = Array.isArray(params.plan) ? params.plan.flatMap((entry) => {
|
|
788
837
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return [];
|
|
@@ -796,6 +845,10 @@ var CodexReasoningProjection = class {
|
|
|
796
845
|
}) : void 0;
|
|
797
846
|
const planText = [explanation, ...(plan ?? []).map(({ step, status }) => `- [${status}] ${step}`)].filter((part) => Boolean(part)).join("\n");
|
|
798
847
|
if (planText) this.turnPlanText = planText;
|
|
848
|
+
if (source === "codex-app-server" && plan) await this.onNativePlanUpdate?.({
|
|
849
|
+
...typeof explanation === "string" ? { markdown: explanation } : {},
|
|
850
|
+
steps: plan
|
|
851
|
+
});
|
|
799
852
|
this.emitPlanUpdate({
|
|
800
853
|
explanation,
|
|
801
854
|
steps: plan
|
|
@@ -825,7 +878,7 @@ var CodexReasoningProjection = class {
|
|
|
825
878
|
return this.turnPlanText ?? [...this.planTextByItem.values()].filter((text) => text.trim().length > 0).join("\n\n");
|
|
826
879
|
}
|
|
827
880
|
emitPlanUpdate(params, source = "codex-app-server") {
|
|
828
|
-
if (!params.explanation &&
|
|
881
|
+
if (!params.explanation && params.steps === void 0) return;
|
|
829
882
|
this.emitAgentEvent({
|
|
830
883
|
stream: "plan",
|
|
831
884
|
data: {
|
|
@@ -833,7 +886,7 @@ var CodexReasoningProjection = class {
|
|
|
833
886
|
title: "Plan updated",
|
|
834
887
|
source,
|
|
835
888
|
...params.explanation ? { explanation: params.explanation } : {},
|
|
836
|
-
...params.steps
|
|
889
|
+
...params.steps ? { steps: params.steps } : {}
|
|
837
890
|
}
|
|
838
891
|
});
|
|
839
892
|
}
|
|
@@ -858,9 +911,9 @@ function reasoningMethodOrder(method) {
|
|
|
858
911
|
const attemptTerminal = agentHarnessAttemptTerminal;
|
|
859
912
|
//#endregion
|
|
860
913
|
//#region extensions/codex/src/app-server/event-projector-snapshot.ts
|
|
914
|
+
const CODEX_META_KEY$1 = "__openclaw";
|
|
861
915
|
function readTurnTaintMetadata(message) {
|
|
862
|
-
|
|
863
|
-
return metadata && typeof metadata === "object" && !Array.isArray(metadata) ? metadata : void 0;
|
|
916
|
+
return asOptionalRecord(CODEX_META_KEY$1 in message ? message[CODEX_META_KEY$1] : void 0);
|
|
864
917
|
}
|
|
865
918
|
function applyStickyTurnTaint(messages) {
|
|
866
919
|
let tainted = false;
|
|
@@ -900,8 +953,12 @@ function buildCodexAttemptResult(input) {
|
|
|
900
953
|
const commentaryMessages = input.assistantProjection.collectCommentaryMessages();
|
|
901
954
|
const reasoningText = input.reasoningProjection.reasoningText();
|
|
902
955
|
const planText = input.reasoningProjection.planText();
|
|
903
|
-
const
|
|
904
|
-
|
|
956
|
+
const unavailableThreadUsage = input.tokenUsage ? {
|
|
957
|
+
...input.tokenUsage,
|
|
958
|
+
contextUsage: { state: "unavailable" }
|
|
959
|
+
} : void 0;
|
|
960
|
+
const completedUsage = input.responseCompletions.usage ?? (input.responseCompletions.modelIterations > 0 ? unavailableThreadUsage : input.tokenUsage);
|
|
961
|
+
const projectedUsage = input.aborted ? unavailableThreadUsage : completedUsage;
|
|
905
962
|
const hasAssistantItemText = input.assistantProjection.hasAssistantItemTextForSynthesis();
|
|
906
963
|
const legacyFailClosed = !input.completedTurn || input.completedTurn.status !== "completed" || hasAssistantItemText;
|
|
907
964
|
const hasDeliverableAssistantOnCompletedTurn = input.completedTurn?.status === "completed" && assistantTexts.some((text) => text.trim().length > 0);
|
|
@@ -976,6 +1033,7 @@ function buildCodexAttemptResult(input) {
|
|
|
976
1033
|
acceptedSessionSpawns: input.toolTelemetry.acceptedSessionSpawns,
|
|
977
1034
|
cloudCodeAssistFormatError: false,
|
|
978
1035
|
contextTokens: input.contextTokens,
|
|
1036
|
+
contextTokensSource: input.contextTokensSource,
|
|
979
1037
|
attemptUsage: projectedUsage,
|
|
980
1038
|
...input.completedCompactionCount > 0 ? { compactionCount: input.completedCompactionCount } : {},
|
|
981
1039
|
replayMetadata: {
|
|
@@ -1148,6 +1206,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1148
1206
|
this.completedCompactionCount = 0;
|
|
1149
1207
|
this.lastTranscriptTimestamp = 0;
|
|
1150
1208
|
this.contextTokens = options.initialContextTokens;
|
|
1209
|
+
this.contextTokensSource = options.initialContextTokens === void 0 ? void 0 : "resolved";
|
|
1151
1210
|
this.diagnostics = new CodexProjectionDiagnostics(threadId, turnId);
|
|
1152
1211
|
this.nativeToolLifecycleProjector = new CodexNativeToolLifecycleProjector(params, threadId, turnId, { runAbortSignal: options.runAbortSignal });
|
|
1153
1212
|
this.generatedMediaProjection = new CodexGeneratedMediaProjection(params.config, {
|
|
@@ -1164,7 +1223,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1164
1223
|
});
|
|
1165
1224
|
this.eventProjection = new CodexEventProjection(threadId, turnId, (event) => this.emitAgentEvent(event), this.toolProgressProjection, this.toolTranscriptProjection, options.onNativeToolResultRecorded);
|
|
1166
1225
|
this.assistantProjection = new CodexAssistantProjection(params, (event) => this.emitAgentEvent(event), (text) => this.toolProgressProjection.matchesEcho(text), () => this.nextTranscriptTimestamp());
|
|
1167
|
-
this.reasoningProjection = new CodexReasoningProjection(params, (event) => this.emitAgentEvent(event));
|
|
1226
|
+
this.reasoningProjection = new CodexReasoningProjection(params, (event) => this.emitAgentEvent(event), options.onNativePlanUpdate);
|
|
1168
1227
|
}
|
|
1169
1228
|
nextTranscriptTimestamp() {
|
|
1170
1229
|
this.lastTranscriptTimestamp = Math.max(Date.now(), this.lastTranscriptTimestamp + 1);
|
|
@@ -1173,6 +1232,20 @@ var CodexAppServerEventProjector = class {
|
|
|
1173
1232
|
getCompletedTurnStatus() {
|
|
1174
1233
|
return this.completedTurn?.status;
|
|
1175
1234
|
}
|
|
1235
|
+
buildSteeringTranscriptPrefix() {
|
|
1236
|
+
const commentaryMessages = this.assistantProjection.collectCommentaryMessages().filter(({ itemId }) => this.completedItemIds.has(itemId));
|
|
1237
|
+
return buildCodexMessagesSnapshot({
|
|
1238
|
+
runParams: this.params,
|
|
1239
|
+
turnId: this.turnId,
|
|
1240
|
+
upstreamUserText: this.options.upstreamUserText,
|
|
1241
|
+
reasoningText: void 0,
|
|
1242
|
+
planText: void 0,
|
|
1243
|
+
commentaryMessages,
|
|
1244
|
+
toolMessages: this.toolTranscriptProjection.transcriptMessages,
|
|
1245
|
+
lastAssistant: void 0,
|
|
1246
|
+
createAssistantMirrorMessage: (title, text) => this.assistantProjection.createAssistantMirrorMessage(title, text)
|
|
1247
|
+
}).filter((message) => message.role !== "user");
|
|
1248
|
+
}
|
|
1176
1249
|
hasCompletedTerminalAssistantText() {
|
|
1177
1250
|
return this.assistantProjection.hasCompletedTerminalAssistantText(this.completedItemIds);
|
|
1178
1251
|
}
|
|
@@ -1199,8 +1272,9 @@ var CodexAppServerEventProjector = class {
|
|
|
1199
1272
|
const ordinal = this.params.allocateToolOutcomeOrdinal?.(item.id);
|
|
1200
1273
|
if (ordinal !== void 0) this.nativeToolOutcomeOrdinals.set(item.id, ordinal);
|
|
1201
1274
|
}
|
|
1202
|
-
recordNativeToolApprovalFailure(toolCallId, disposition) {
|
|
1275
|
+
recordNativeToolApprovalFailure(toolCallId, disposition, approvalKind) {
|
|
1203
1276
|
this.nativeToolLifecycleProjector.recordApprovalFailureDisposition(toolCallId, disposition);
|
|
1277
|
+
if (disposition === "timed_out" && approvalKind) this.toolProgressProjection.approvalTimeoutKinds.set(toolCallId, approvalKind);
|
|
1204
1278
|
}
|
|
1205
1279
|
recordNativeToolPreToolUseFailure(failure) {
|
|
1206
1280
|
this.nativeToolLifecycleProjector.recordPreToolUseFailure(failure);
|
|
@@ -1213,6 +1287,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1213
1287
|
} else if (notification.method === "guardianWarning") {
|
|
1214
1288
|
if (readCodexNotificationThreadId(params) !== this.threadId) return;
|
|
1215
1289
|
} else if (!isCodexNotificationForTurn(params, this.threadId, this.turnId)) return;
|
|
1290
|
+
if (notification.method !== "guardianWarning" && notification.method !== "item/autoApprovalReview/started" && notification.method !== "item/autoApprovalReview/completed") this.eventProjection.flushPendingGuardianWarning();
|
|
1216
1291
|
this.nativeToolLifecycleProjector.handleNotification(notification);
|
|
1217
1292
|
this.assistantProjection.handleNotification(notification.method, params);
|
|
1218
1293
|
switch (notification.method) {
|
|
@@ -1227,7 +1302,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1227
1302
|
this.reasoningProjection.handlePlanDelta(params);
|
|
1228
1303
|
break;
|
|
1229
1304
|
case "turn/plan/updated":
|
|
1230
|
-
this.reasoningProjection.handleTurnPlanUpdated(params);
|
|
1305
|
+
await this.reasoningProjection.handleTurnPlanUpdated(params);
|
|
1231
1306
|
break;
|
|
1232
1307
|
case "item/started":
|
|
1233
1308
|
await this.handleItemStarted(params);
|
|
@@ -1251,7 +1326,10 @@ var CodexAppServerEventProjector = class {
|
|
|
1251
1326
|
break;
|
|
1252
1327
|
case "thread/tokenUsage/updated":
|
|
1253
1328
|
projectCodexThreadUsageUpdate(params, this.tokenUsage, (usage) => this.tokenUsage = usage, (data) => {
|
|
1254
|
-
|
|
1329
|
+
if (data.modelContextWindow !== void 0) {
|
|
1330
|
+
this.contextTokens = data.modelContextWindow;
|
|
1331
|
+
this.contextTokensSource = this.params.authoredContextTokenCap === void 0 ? "runtime" : "runtime-configured";
|
|
1332
|
+
}
|
|
1255
1333
|
this.emitAgentEvent({
|
|
1256
1334
|
stream: "codex_app_server.usage",
|
|
1257
1335
|
data
|
|
@@ -1267,13 +1345,16 @@ var CodexAppServerEventProjector = class {
|
|
|
1267
1345
|
case "rawResponseItem/completed":
|
|
1268
1346
|
await this.handleRawResponseItemCompleted(params);
|
|
1269
1347
|
break;
|
|
1270
|
-
case "error":
|
|
1348
|
+
case "error": {
|
|
1271
1349
|
this.responseCompletions.clear();
|
|
1272
1350
|
if (params.willRetry === true) break;
|
|
1273
|
-
|
|
1351
|
+
const codexErrorInfo = isJsonObject(params.error) ? params.error.codexErrorInfo : void 0;
|
|
1352
|
+
const compactionFailure = codexErrorInfo === "other" && this.isCompacting();
|
|
1353
|
+
this.settledTurnFailureFinalizationAllowed = codexErrorInfo === "serverOverloaded" || compactionFailure;
|
|
1274
1354
|
this.promptError = this.formatCodexErrorMessage(params) ?? "codex app-server error";
|
|
1275
|
-
this.promptErrorSource = "prompt";
|
|
1355
|
+
this.promptErrorSource = compactionFailure ? "compaction" : "prompt";
|
|
1276
1356
|
break;
|
|
1357
|
+
}
|
|
1277
1358
|
case "thread/compacted":
|
|
1278
1359
|
case "turn/started":
|
|
1279
1360
|
case "turn/diff/updated":
|
|
@@ -1292,6 +1373,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1292
1373
|
}
|
|
1293
1374
|
}
|
|
1294
1375
|
buildResult(toolTelemetry, options) {
|
|
1376
|
+
this.eventProjection.flushPendingGuardianWarning();
|
|
1295
1377
|
return buildCodexAttemptResult({
|
|
1296
1378
|
runParams: this.params,
|
|
1297
1379
|
turnId: this.turnId,
|
|
@@ -1307,6 +1389,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1307
1389
|
aborted: this.aborted,
|
|
1308
1390
|
tokenUsage: this.tokenUsage,
|
|
1309
1391
|
contextTokens: this.contextTokens,
|
|
1392
|
+
contextTokensSource: this.contextTokensSource,
|
|
1310
1393
|
completedCompactionCount: this.completedCompactionCount,
|
|
1311
1394
|
activeItemCount: this.activeItemIds.size,
|
|
1312
1395
|
completedItemCount: this.completedItemIds.size,
|
|
@@ -1325,9 +1408,12 @@ var CodexAppServerEventProjector = class {
|
|
|
1325
1408
|
recordDynamicToolCall(params) {
|
|
1326
1409
|
this.toolTranscriptProjection.recordDynamicToolCall(params);
|
|
1327
1410
|
}
|
|
1328
|
-
/** Projects a successful OpenClaw
|
|
1329
|
-
|
|
1330
|
-
if (isJsonObject(params))
|
|
1411
|
+
/** Projects a successful OpenClaw progress_card call through the native plan stream. */
|
|
1412
|
+
async recordDynamicProgressCardUpdate(params) {
|
|
1413
|
+
if (isJsonObject(params)) {
|
|
1414
|
+
const projected = { plan: Array.isArray(params.plan) ? params.plan : [] };
|
|
1415
|
+
await this.reasoningProjection.handleTurnPlanUpdated(projected, "openclaw");
|
|
1416
|
+
}
|
|
1331
1417
|
}
|
|
1332
1418
|
recordDynamicToolResult(params) {
|
|
1333
1419
|
this.toolProgressProjection.recordDynamicToolResult(params);
|
|
@@ -1415,7 +1501,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1415
1501
|
if (item?.type === "contextCompaction" && itemId) {
|
|
1416
1502
|
this.activeCompactionItemIds.delete(itemId);
|
|
1417
1503
|
this.completedCompactionCount += 1;
|
|
1418
|
-
this.options.onContextCompacted?.();
|
|
1504
|
+
await this.options.onContextCompacted?.();
|
|
1419
1505
|
await runAgentHarnessAfterCompactionHook({
|
|
1420
1506
|
sessionFile: this.params.sessionFile,
|
|
1421
1507
|
messages: await this.toolTranscriptProjection.readMirroredSessionMessages(),
|
|
@@ -1431,17 +1517,17 @@ var CodexAppServerEventProjector = class {
|
|
|
1431
1517
|
channelId: this.params.messageChannel ?? this.params.messageProvider ?? void 0
|
|
1432
1518
|
}
|
|
1433
1519
|
});
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
}
|
|
1520
|
+
await persistCodexContextCompactionActivity({
|
|
1521
|
+
sessionTarget: this.params.sessionTarget,
|
|
1522
|
+
config: this.params.config,
|
|
1523
|
+
cwd: this.params.workspaceDir,
|
|
1524
|
+
runId: this.params.runId,
|
|
1525
|
+
threadId: this.threadId,
|
|
1526
|
+
turnId: this.turnId,
|
|
1527
|
+
itemId,
|
|
1528
|
+
timestamp: this.nextTranscriptTimestamp()
|
|
1444
1529
|
});
|
|
1530
|
+
this.emitCompactionEnd(itemId, true);
|
|
1445
1531
|
}
|
|
1446
1532
|
this.toolProgressProjection.recordToolMeta(item);
|
|
1447
1533
|
this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
|
|
@@ -1470,7 +1556,8 @@ var CodexAppServerEventProjector = class {
|
|
|
1470
1556
|
const turn = readCodexTurn(params.turn);
|
|
1471
1557
|
if (!turn || turn.id !== this.turnId) return;
|
|
1472
1558
|
this.completedTurn = turn;
|
|
1473
|
-
|
|
1559
|
+
const compactionFailure = turn.status === "failed" && (this.promptErrorSource === "compaction" || turn.error?.codexErrorInfo === "other" && this.isCompacting());
|
|
1560
|
+
this.settledTurnFailureFinalizationAllowed = turn.status === "failed" && (turn.error?.codexErrorInfo === "serverOverloaded" || compactionFailure);
|
|
1474
1561
|
if (turn.status !== "completed") this.responseCompletions.clear();
|
|
1475
1562
|
if (turn.status === "failed") {
|
|
1476
1563
|
const usageLimitMessage = formatCodexUsageLimitErrorMessage({
|
|
@@ -1479,7 +1566,15 @@ var CodexAppServerEventProjector = class {
|
|
|
1479
1566
|
rateLimits: this.options.readRecentRateLimits?.()
|
|
1480
1567
|
});
|
|
1481
1568
|
this.promptError = usageLimitMessage ? createCodexUsageLimitPromptError(usageLimitMessage) : turn.error?.message ?? "codex app-server turn failed";
|
|
1482
|
-
this.promptErrorSource = "prompt";
|
|
1569
|
+
this.promptErrorSource = compactionFailure ? "compaction" : "prompt";
|
|
1570
|
+
}
|
|
1571
|
+
if (compactionFailure) {
|
|
1572
|
+
const failedCompactionItemIds = [...this.activeCompactionItemIds];
|
|
1573
|
+
for (const itemId of failedCompactionItemIds) {
|
|
1574
|
+
this.activeItemIds.delete(itemId);
|
|
1575
|
+
this.activeCompactionItemIds.delete(itemId);
|
|
1576
|
+
this.emitCompactionEnd(itemId, false);
|
|
1577
|
+
}
|
|
1483
1578
|
}
|
|
1484
1579
|
const turnItems = turn.items ?? [];
|
|
1485
1580
|
for (let index = turnItems.length - 1; index >= 0; index -= 1) {
|
|
@@ -1505,10 +1600,24 @@ var CodexAppServerEventProjector = class {
|
|
|
1505
1600
|
this.toolProgressProjection.emitToolResultSummary(item);
|
|
1506
1601
|
this.toolProgressProjection.emitToolResultOutput(item);
|
|
1507
1602
|
}
|
|
1603
|
+
this.toolProgressProjection.approvalTimeoutKinds.clear();
|
|
1508
1604
|
this.assistantProjection.finalizeAnswerCandidate(turn);
|
|
1509
1605
|
this.activeCompactionItemIds.clear();
|
|
1510
1606
|
await this.reasoningProjection.maybeEndReasoning();
|
|
1511
1607
|
}
|
|
1608
|
+
emitCompactionEnd(itemId, completed) {
|
|
1609
|
+
this.emitAgentEvent({
|
|
1610
|
+
stream: "compaction",
|
|
1611
|
+
data: {
|
|
1612
|
+
phase: "end",
|
|
1613
|
+
backend: "codex-app-server",
|
|
1614
|
+
completed,
|
|
1615
|
+
threadId: this.threadId,
|
|
1616
|
+
turnId: this.turnId,
|
|
1617
|
+
itemId
|
|
1618
|
+
}
|
|
1619
|
+
});
|
|
1620
|
+
}
|
|
1512
1621
|
async emitSnapshotOnlyNativeToolProgress(item) {
|
|
1513
1622
|
if (!shouldSynthesizeToolProgressForItem(item) || !this.isCurrentTurnSnapshotItem(item) || this.completedItemIds.has(item.id) || itemStatus(item) === "running") return;
|
|
1514
1623
|
if (!this.activeItemIds.has(item.id)) {
|
|
@@ -1708,184 +1817,347 @@ function createCodexNativeMcpAppResultDetailsPreparer(params) {
|
|
|
1708
1817
|
};
|
|
1709
1818
|
}
|
|
1710
1819
|
//#endregion
|
|
1820
|
+
//#region extensions/codex/src/app-server/plan-compaction-state.ts
|
|
1821
|
+
const RESTORED_PLAN_PREAMBLE = "OpenClaw restored the session progress card after context compaction. This is application state, not a new user request. Continue the current task and call progress_card whenever the status meaningfully changes.";
|
|
1822
|
+
const PROGRESS_CARD_MAX_STEPS = 50;
|
|
1823
|
+
const PROGRESS_CARD_MAX_STEP_UTF8_BYTES = 512;
|
|
1824
|
+
const PROGRESS_CARD_MAX_UTF8_BYTES = 8 * 1024;
|
|
1825
|
+
const RESTORED_PLAN_MAX_MARKDOWN_BYTES = 2 * 1024;
|
|
1826
|
+
const RESTORED_PLAN_MAX_PAYLOAD_BYTES = 32 * 1024;
|
|
1827
|
+
const RESTORED_PLAN_TRUNCATION_SUFFIX = "…";
|
|
1828
|
+
function canonicalizeNativeProgressCardInput(input) {
|
|
1829
|
+
const markdown = input.markdown === void 0 ? void 0 : truncateUtf8(stripInvisibleUnicode(input.markdown), PROGRESS_CARD_MAX_UTF8_BYTES);
|
|
1830
|
+
const plan = [];
|
|
1831
|
+
let hasInProgressStep = false;
|
|
1832
|
+
for (const step of input.steps.slice(0, PROGRESS_CARD_MAX_STEPS)) {
|
|
1833
|
+
const text = truncateUtf8(stripInvisibleUnicode(step.step), PROGRESS_CARD_MAX_STEP_UTF8_BYTES);
|
|
1834
|
+
if (!text.trim()) continue;
|
|
1835
|
+
let status = step.status;
|
|
1836
|
+
if (status === "in_progress") if (hasInProgressStep) status = "pending";
|
|
1837
|
+
else hasInProgressStep = true;
|
|
1838
|
+
plan.push({
|
|
1839
|
+
step: text,
|
|
1840
|
+
status
|
|
1841
|
+
});
|
|
1842
|
+
}
|
|
1843
|
+
return {
|
|
1844
|
+
...markdown !== void 0 ? { markdown } : {},
|
|
1845
|
+
plan
|
|
1846
|
+
};
|
|
1847
|
+
}
|
|
1848
|
+
/** Retains the latest projected plan so Codex compaction cannot discard it. */
|
|
1849
|
+
var CodexCompactionPlanState = class {
|
|
1850
|
+
record(event) {
|
|
1851
|
+
if (event.stream !== "plan") return;
|
|
1852
|
+
const plan = readBoundedPlan(event.data.explanation, event.data.steps);
|
|
1853
|
+
this.latestPlan = plan;
|
|
1854
|
+
}
|
|
1855
|
+
/** Retains markdown that migration-only plan events intentionally omit. */
|
|
1856
|
+
recordProgressCardInput(value) {
|
|
1857
|
+
if (!isJsonObject(value)) return;
|
|
1858
|
+
this.latestPlan = readBoundedPlan(value.markdown, value.plan);
|
|
1859
|
+
}
|
|
1860
|
+
async restore(params) {
|
|
1861
|
+
if (!this.latestPlan) return;
|
|
1862
|
+
await params.client.request("thread/inject_items", {
|
|
1863
|
+
threadId: params.threadId,
|
|
1864
|
+
items: [{
|
|
1865
|
+
type: "message",
|
|
1866
|
+
role: "user",
|
|
1867
|
+
content: [{
|
|
1868
|
+
type: "input_text",
|
|
1869
|
+
text: `${RESTORED_PLAN_PREAMBLE}\n${serializePlan(this.latestPlan)}`
|
|
1870
|
+
}]
|
|
1871
|
+
}]
|
|
1872
|
+
}, {
|
|
1873
|
+
timeoutMs: params.timeoutMs,
|
|
1874
|
+
signal: params.signal
|
|
1875
|
+
});
|
|
1876
|
+
}
|
|
1877
|
+
};
|
|
1878
|
+
function readBoundedPlan(markdownValue, stepsValue) {
|
|
1879
|
+
const canonical = canonicalizeNativeProgressCardInput({
|
|
1880
|
+
...typeof markdownValue === "string" ? { markdown: markdownValue } : {},
|
|
1881
|
+
steps: readPlanSteps(stepsValue)
|
|
1882
|
+
});
|
|
1883
|
+
const markdown = canonical.markdown === void 0 ? void 0 : truncateUtf8(canonical.markdown, RESTORED_PLAN_MAX_MARKDOWN_BYTES);
|
|
1884
|
+
const steps = [];
|
|
1885
|
+
for (const step of canonical.plan) {
|
|
1886
|
+
const candidate = {
|
|
1887
|
+
...markdown?.trim() ? { markdown } : {},
|
|
1888
|
+
steps: [...steps, step]
|
|
1889
|
+
};
|
|
1890
|
+
if (Buffer$1.byteLength(serializePlan(candidate), "utf8") > RESTORED_PLAN_MAX_PAYLOAD_BYTES) break;
|
|
1891
|
+
steps.push(step);
|
|
1892
|
+
}
|
|
1893
|
+
return markdown?.trim() || steps.length > 0 ? {
|
|
1894
|
+
...markdown?.trim() ? { markdown } : {},
|
|
1895
|
+
steps
|
|
1896
|
+
} : void 0;
|
|
1897
|
+
}
|
|
1898
|
+
function serializePlan(plan) {
|
|
1899
|
+
return JSON.stringify({
|
|
1900
|
+
markdown: plan.markdown,
|
|
1901
|
+
plan: plan.steps
|
|
1902
|
+
});
|
|
1903
|
+
}
|
|
1904
|
+
function truncateUtf8(value, maxBytes) {
|
|
1905
|
+
if (Buffer$1.byteLength(value, "utf8") <= maxBytes) return value;
|
|
1906
|
+
return `${truncateUtf8Prefix(value, maxBytes - Buffer$1.byteLength(RESTORED_PLAN_TRUNCATION_SUFFIX, "utf8"))}${RESTORED_PLAN_TRUNCATION_SUFFIX}`;
|
|
1907
|
+
}
|
|
1908
|
+
function readPlanSteps(value) {
|
|
1909
|
+
if (!Array.isArray(value)) return [];
|
|
1910
|
+
return value.flatMap((entry) => {
|
|
1911
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return [];
|
|
1912
|
+
const { step, status } = entry;
|
|
1913
|
+
if (typeof step !== "string" || !isPlanStatus(status)) return [];
|
|
1914
|
+
return [{
|
|
1915
|
+
step,
|
|
1916
|
+
status
|
|
1917
|
+
}];
|
|
1918
|
+
});
|
|
1919
|
+
}
|
|
1920
|
+
function isPlanStatus(value) {
|
|
1921
|
+
return value === "pending" || value === "in_progress" || value === "completed";
|
|
1922
|
+
}
|
|
1923
|
+
//#endregion
|
|
1711
1924
|
//#region extensions/codex/src/app-server/user-input-bridge.ts
|
|
1712
|
-
/**
|
|
1925
|
+
/** Owns per-turn Codex request_user_input and ordinary MCP elicitation lifecycles. */
|
|
1713
1926
|
const DEFAULT_USER_INPUT_TIMEOUT_MS = 15 * 6e4;
|
|
1714
1927
|
const NONBLOCKING_USER_INPUT_TIMEOUT_MS = 12e4;
|
|
1715
|
-
|
|
1928
|
+
const MAX_USER_INPUT_QUESTIONS = 3;
|
|
1929
|
+
const MAX_USER_INPUT_OPTIONS = 4;
|
|
1930
|
+
const MAX_USER_INPUT_ID = 256;
|
|
1931
|
+
const MAX_USER_INPUT_HEADER = 64;
|
|
1932
|
+
const MAX_USER_INPUT_TEXT = 4096;
|
|
1933
|
+
/** Creates the single per-turn owner for Codex operator input. */
|
|
1716
1934
|
function createCodexUserInputBridge(params) {
|
|
1717
|
-
let sensitiveInput;
|
|
1718
|
-
let pendingGateway;
|
|
1719
1935
|
const gatewayCall = params.gatewayCall ?? callGatewayTool;
|
|
1720
|
-
const
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1936
|
+
const jobs = [];
|
|
1937
|
+
let activeCompletion;
|
|
1938
|
+
const inputSessionKey = params.paramsForRun.sessionKey ?? params.paramsForRun.sessionId;
|
|
1939
|
+
const pump = () => {
|
|
1940
|
+
const job = jobs[0];
|
|
1941
|
+
if (activeCompletion || !job) return;
|
|
1942
|
+
activeCompletion = job.run(job.abort.signal).catch((error) => {
|
|
1943
|
+
embeddedAgentLog.warn("failed to bridge codex operator input", { error });
|
|
1944
|
+
return job.abort.signal.aborted ? job.cancelValue : job.failureValue;
|
|
1945
|
+
}).then((value) => {
|
|
1946
|
+
job.resolve(job.abort.signal.aborted ? job.cancelValue : value ?? job.failureValue);
|
|
1947
|
+
}).finally(() => {
|
|
1948
|
+
if (jobs[0] === job) jobs.shift();
|
|
1949
|
+
activeCompletion = void 0;
|
|
1950
|
+
pump();
|
|
1951
|
+
});
|
|
1731
1952
|
};
|
|
1732
|
-
const
|
|
1733
|
-
|
|
1953
|
+
const enqueue = (definition) => {
|
|
1954
|
+
if (params.signal?.aborted) return Promise.resolve(definition.cancelValue);
|
|
1955
|
+
return new Promise((resolve) => {
|
|
1956
|
+
jobs.push({
|
|
1957
|
+
...definition,
|
|
1958
|
+
resolve
|
|
1959
|
+
});
|
|
1960
|
+
pump();
|
|
1961
|
+
});
|
|
1734
1962
|
};
|
|
1963
|
+
const cancelJob = (job) => {
|
|
1964
|
+
const index = jobs.indexOf(job);
|
|
1965
|
+
if (index < 0) return;
|
|
1966
|
+
if (index === 0) {
|
|
1967
|
+
job.abort.abort(/* @__PURE__ */ new Error("Codex operator input request cancelled"));
|
|
1968
|
+
return;
|
|
1969
|
+
}
|
|
1970
|
+
jobs.splice(index, 1);
|
|
1971
|
+
job.resolve(job.cancelValue);
|
|
1972
|
+
};
|
|
1973
|
+
const cancelPending = async () => {
|
|
1974
|
+
const pendingCompletion = activeCompletion;
|
|
1975
|
+
const queuedJobs = jobs.splice(1);
|
|
1976
|
+
for (const job of queuedJobs) job.resolve(job.cancelValue);
|
|
1977
|
+
jobs[0]?.abort.abort(/* @__PURE__ */ new Error("Codex operator input request cancelled"));
|
|
1978
|
+
await pendingCompletion;
|
|
1979
|
+
};
|
|
1980
|
+
const execute = (input, timeoutMs, signal) => agentHarnessStructuredInput.run({
|
|
1981
|
+
input,
|
|
1982
|
+
sessionKey: inputSessionKey,
|
|
1983
|
+
agentId: params.paramsForRun.agentId,
|
|
1984
|
+
runId: params.paramsForRun.runId,
|
|
1985
|
+
timeoutMs,
|
|
1986
|
+
gatewayCall,
|
|
1987
|
+
delivery: params.paramsForRun,
|
|
1988
|
+
signal,
|
|
1989
|
+
promptOptions: {
|
|
1990
|
+
formatText: formatCodexDisplayText,
|
|
1991
|
+
unsupportedIntro: "Codex input request could not be shown:",
|
|
1992
|
+
urlIntro: "Codex needs confirmation:"
|
|
1993
|
+
}
|
|
1994
|
+
});
|
|
1995
|
+
params.signal?.addEventListener("abort", () => void cancelPending(), { once: true });
|
|
1735
1996
|
return {
|
|
1736
1997
|
async handleRequest(request) {
|
|
1737
1998
|
const requestParams = readUserInputParams(request.params);
|
|
1738
|
-
if (!requestParams) return;
|
|
1739
|
-
if (requestParams.threadId !== params.threadId || requestParams.turnId !== params.turnId) return;
|
|
1999
|
+
if (!requestParams || requestParams.threadId !== params.threadId || requestParams.turnId !== params.turnId) return;
|
|
1740
2000
|
if (requestParams.questions.length === 0) return emptyUserInputResponse();
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
requestId: request.id,
|
|
1753
|
-
threadId: requestParams.threadId,
|
|
1754
|
-
questions: requestParams.questions,
|
|
1755
|
-
claimed: false,
|
|
1756
|
-
resolve,
|
|
1757
|
-
cleanup
|
|
1758
|
-
};
|
|
1759
|
-
sensitiveInput = current;
|
|
1760
|
-
params.signal?.addEventListener("abort", abortListener, { once: true });
|
|
1761
|
-
if (params.signal?.aborted) {
|
|
1762
|
-
resolveSecret(emptyUserInputResponse());
|
|
1763
|
-
return;
|
|
2001
|
+
const timeoutMs = requestParams.isBlocking ? params.paramsForRun.timeoutMs ?? DEFAULT_USER_INPUT_TIMEOUT_MS : NONBLOCKING_USER_INPUT_TIMEOUT_MS;
|
|
2002
|
+
const input = compileUserInputQuestions(requestParams.questions);
|
|
2003
|
+
const cancelValue = emptyUserInputResponse();
|
|
2004
|
+
return await enqueue({
|
|
2005
|
+
requestId: request.id,
|
|
2006
|
+
abort: new AbortController(),
|
|
2007
|
+
cancelValue,
|
|
2008
|
+
failureValue: cancelValue,
|
|
2009
|
+
run: async (signal) => {
|
|
2010
|
+
const result = await execute(input, timeoutMs, signal);
|
|
2011
|
+
return result.status === "answered" ? gatewayAnswersToCodexResponse(result.answers) : cancelValue;
|
|
1764
2012
|
}
|
|
1765
|
-
deliverAgentHarnessUserInputPrompt(params.paramsForRun, requestParams.questions, {
|
|
1766
|
-
formatText: formatCodexDisplayText,
|
|
1767
|
-
intro: "Codex needs input:"
|
|
1768
|
-
}).catch((error) => {
|
|
1769
|
-
embeddedAgentLog.warn("failed to deliver secret codex user input prompt", { error });
|
|
1770
|
-
resolveSecretIfCurrent(current, emptyUserInputResponse());
|
|
1771
|
-
});
|
|
1772
2013
|
});
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
params
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
promptOptions: {
|
|
1792
|
-
formatText: formatCodexDisplayText,
|
|
1793
|
-
intro: "Codex needs input:"
|
|
1794
|
-
},
|
|
1795
|
-
signal: abort.signal
|
|
2014
|
+
},
|
|
2015
|
+
async handleElicitationRequest(request) {
|
|
2016
|
+
if (readRawOwnString(request.params, "threadId") !== params.threadId) return;
|
|
2017
|
+
const requestSnapshot = agentHarnessStructuredInput.snapshot(request.params);
|
|
2018
|
+
if (requestSnapshot === void 0) {
|
|
2019
|
+
const cancelValue = createCodexElicitationResponse("cancel");
|
|
2020
|
+
return await enqueue({
|
|
2021
|
+
requestId: request.id,
|
|
2022
|
+
abort: new AbortController(),
|
|
2023
|
+
cancelValue,
|
|
2024
|
+
failureValue: declineElicitation("OpenClaw could not handle this elicitation."),
|
|
2025
|
+
run: async (signal) => {
|
|
2026
|
+
const result = await execute({
|
|
2027
|
+
kind: "unsupported",
|
|
2028
|
+
message: "OpenClaw declined a malformed or over-limit MCP elicitation request."
|
|
2029
|
+
}, params.paramsForRun.timeoutMs ?? DEFAULT_USER_INPUT_TIMEOUT_MS, signal);
|
|
2030
|
+
return result.status === "unsupported" ? declineElicitation(result.message) : cancelValue;
|
|
2031
|
+
}
|
|
1796
2032
|
});
|
|
1797
|
-
return result.status === "answered" ? gatewayAnswersToCodexResponse(result.answers.answers) : emptyUserInputResponse();
|
|
1798
|
-
} catch (error) {
|
|
1799
|
-
embeddedAgentLog.warn("failed to bridge codex user input through gateway", { error });
|
|
1800
|
-
return emptyUserInputResponse();
|
|
1801
|
-
} finally {
|
|
1802
|
-
params.signal?.removeEventListener("abort", abortFromRun);
|
|
1803
|
-
if (pendingGateway?.abort === abort) pendingGateway = void 0;
|
|
1804
2033
|
}
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
2034
|
+
const { compileCodexOrdinaryElicitation } = await import("./elicitation-input-DMkeki8d.js");
|
|
2035
|
+
const compiled = compileCodexOrdinaryElicitation({
|
|
2036
|
+
value: requestSnapshot,
|
|
2037
|
+
threadId: params.threadId,
|
|
2038
|
+
turnId: params.turnId
|
|
2039
|
+
});
|
|
2040
|
+
if (compiled.kind === "ignored") return;
|
|
2041
|
+
const cancelValue = createCodexElicitationResponse("cancel");
|
|
2042
|
+
const timeoutMs = params.paramsForRun.timeoutMs ?? DEFAULT_USER_INPUT_TIMEOUT_MS;
|
|
2043
|
+
return await enqueue({
|
|
2044
|
+
requestId: request.id,
|
|
2045
|
+
abort: new AbortController(),
|
|
2046
|
+
cancelValue,
|
|
2047
|
+
failureValue: declineElicitation("OpenClaw could not handle this elicitation."),
|
|
2048
|
+
run: async (signal) => {
|
|
2049
|
+
const result = await execute(compiled.input, timeoutMs, signal);
|
|
2050
|
+
if (result.status === "answered") return createCodexElicitationResponse("accept", compiled.input.kind === "ready" && compiled.input.plan.kind === "url" ? null : result.content);
|
|
2051
|
+
if (result.status === "declined") return declineElicitation(result.message);
|
|
2052
|
+
if (result.status === "unsupported") return declineElicitation(result.message);
|
|
2053
|
+
return cancelValue;
|
|
2054
|
+
}
|
|
2055
|
+
});
|
|
1814
2056
|
},
|
|
1815
2057
|
handleNotification(notification) {
|
|
1816
|
-
if (notification.method !== "serverRequest/resolved") return;
|
|
1817
|
-
const
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
if (
|
|
1821
|
-
if (pendingGateway && readStringField(notificationParams, "threadId") === pendingGateway.threadId && String(requestId) === String(pendingGateway.requestId)) pendingGateway.abort.abort(/* @__PURE__ */ new Error("Codex server request resolved"));
|
|
2058
|
+
if (notification.method !== "serverRequest/resolved" || !isJsonObject(notification.params)) return;
|
|
2059
|
+
const requestId = readRequestId(notification.params);
|
|
2060
|
+
if (requestId === void 0 || readOwnString(notification.params, "threadId") !== params.threadId) return;
|
|
2061
|
+
const job = jobs.find((candidate) => typeof candidate.requestId === typeof requestId && candidate.requestId === requestId);
|
|
2062
|
+
if (job) cancelJob(job);
|
|
1822
2063
|
},
|
|
1823
|
-
cancelPending
|
|
1824
|
-
resolveSecret(emptyUserInputResponse());
|
|
1825
|
-
cancelGateway();
|
|
1826
|
-
}
|
|
2064
|
+
cancelPending
|
|
1827
2065
|
};
|
|
1828
2066
|
}
|
|
2067
|
+
function compileUserInputQuestions(questions) {
|
|
2068
|
+
return agentHarnessStructuredInput.compileQuestions({
|
|
2069
|
+
questions,
|
|
2070
|
+
intro: "Codex needs input:"
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
1829
2073
|
function readUserInputParams(value) {
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
const
|
|
1833
|
-
const
|
|
1834
|
-
const
|
|
1835
|
-
|
|
2074
|
+
const snapshot = agentHarnessStructuredInput.snapshot(value);
|
|
2075
|
+
if (!agentHarnessStructuredInput.isRecord(snapshot)) return;
|
|
2076
|
+
const threadId = readBoundedUserInputText(snapshot, "threadId", MAX_USER_INPUT_ID);
|
|
2077
|
+
const turnId = readBoundedUserInputText(snapshot, "turnId", MAX_USER_INPUT_ID);
|
|
2078
|
+
const itemId = readBoundedUserInputText(snapshot, "itemId", MAX_USER_INPUT_ID);
|
|
2079
|
+
const questions = readArray(snapshot, "questions", MAX_USER_INPUT_QUESTIONS);
|
|
2080
|
+
if (!threadId || !turnId || !itemId || !questions) return;
|
|
2081
|
+
const parsed = [];
|
|
2082
|
+
for (const questionValue of questions) {
|
|
2083
|
+
const question = readQuestion(questionValue);
|
|
2084
|
+
if (!question) return;
|
|
2085
|
+
parsed.push(question);
|
|
2086
|
+
}
|
|
1836
2087
|
return {
|
|
1837
2088
|
threadId,
|
|
1838
2089
|
turnId,
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
const question = readQuestion(rawQuestion);
|
|
1842
|
-
if (question && isJsonObject(rawQuestion) && rawQuestion.multiSelect === true) question.multiSelect = true;
|
|
1843
|
-
return question;
|
|
1844
|
-
}).filter((question) => Boolean(question)),
|
|
1845
|
-
isBlocking: value.isBlocking !== false
|
|
2090
|
+
questions: parsed,
|
|
2091
|
+
isBlocking: readValue(snapshot, "isBlocking") !== false
|
|
1846
2092
|
};
|
|
1847
2093
|
}
|
|
1848
2094
|
function readQuestion(value) {
|
|
1849
|
-
if (!
|
|
1850
|
-
const id =
|
|
1851
|
-
const header =
|
|
1852
|
-
const question =
|
|
2095
|
+
if (!agentHarnessStructuredInput.isRecord(value)) return;
|
|
2096
|
+
const id = readBoundedUserInputText(value, "id", MAX_USER_INPUT_ID);
|
|
2097
|
+
const header = readBoundedUserInputText(value, "header", MAX_USER_INPUT_HEADER);
|
|
2098
|
+
const question = readBoundedUserInputText(value, "question", MAX_USER_INPUT_TEXT);
|
|
1853
2099
|
if (!id || !header || !question) return;
|
|
2100
|
+
const options = readOptions(readValue(value, "options"));
|
|
2101
|
+
if (options === void 0) return;
|
|
1854
2102
|
return {
|
|
1855
2103
|
id,
|
|
1856
2104
|
header,
|
|
1857
2105
|
question,
|
|
1858
|
-
isOther: value
|
|
1859
|
-
isSecret: value
|
|
1860
|
-
|
|
2106
|
+
isOther: readValue(value, "isOther") === true,
|
|
2107
|
+
isSecret: readValue(value, "isSecret") === true,
|
|
2108
|
+
...readValue(value, "multiSelect") === true ? { multiSelect: true } : {},
|
|
2109
|
+
options
|
|
1861
2110
|
};
|
|
1862
2111
|
}
|
|
1863
2112
|
function readOptions(value) {
|
|
1864
|
-
if (
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
2113
|
+
if (value === void 0 || value === null) return null;
|
|
2114
|
+
if (!Array.isArray(value) || value.length > MAX_USER_INPUT_OPTIONS) return;
|
|
2115
|
+
const options = [];
|
|
2116
|
+
for (const entry of value) {
|
|
2117
|
+
if (!agentHarnessStructuredInput.isRecord(entry)) return;
|
|
2118
|
+
const label = readBoundedUserInputText(entry, "label", MAX_USER_INPUT_ID);
|
|
2119
|
+
const description = readBoundedUserInputText(entry, "description", MAX_USER_INPUT_TEXT, true);
|
|
2120
|
+
if (!label) return;
|
|
2121
|
+
options.push({
|
|
2122
|
+
label,
|
|
2123
|
+
...description ? { description } : {}
|
|
2124
|
+
});
|
|
2125
|
+
}
|
|
2126
|
+
return options;
|
|
2127
|
+
}
|
|
2128
|
+
function readValue(record, key) {
|
|
2129
|
+
return Object.hasOwn(record, key) ? record[key] : void 0;
|
|
2130
|
+
}
|
|
2131
|
+
function readBoundedUserInputText(record, key, maximum, allowEmpty = false) {
|
|
2132
|
+
const value = readValue(record, key);
|
|
2133
|
+
return typeof value === "string" && value.length <= maximum && (allowEmpty || value.length > 0) ? value : void 0;
|
|
1876
2134
|
}
|
|
1877
|
-
function
|
|
1878
|
-
|
|
2135
|
+
function readArray(record, key, maximum) {
|
|
2136
|
+
const value = readValue(record, key);
|
|
2137
|
+
return Array.isArray(value) && value.length <= maximum ? value : void 0;
|
|
2138
|
+
}
|
|
2139
|
+
function readOwnString(record, key) {
|
|
2140
|
+
const descriptor = Object.getOwnPropertyDescriptor(record, key);
|
|
2141
|
+
return descriptor && "value" in descriptor && typeof descriptor.value === "string" ? descriptor.value : void 0;
|
|
2142
|
+
}
|
|
2143
|
+
function readRawOwnString(value, key) {
|
|
2144
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
2145
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
2146
|
+
return descriptor && "value" in descriptor && typeof descriptor.value === "string" ? descriptor.value : void 0;
|
|
2147
|
+
}
|
|
2148
|
+
function readRequestId(record) {
|
|
2149
|
+
const descriptor = Object.getOwnPropertyDescriptor(record, "requestId");
|
|
2150
|
+
const value = descriptor && "value" in descriptor ? descriptor.value : void 0;
|
|
2151
|
+
return typeof value === "string" || typeof value === "number" ? value : void 0;
|
|
1879
2152
|
}
|
|
1880
2153
|
function gatewayAnswersToCodexResponse(answers) {
|
|
1881
2154
|
return { answers: Object.fromEntries(Object.entries(answers).map(([questionId, values]) => [questionId, { answers: values }])) };
|
|
1882
2155
|
}
|
|
1883
2156
|
function emptyUserInputResponse() {
|
|
1884
|
-
return emptyAgentHarnessUserInputAnswers();
|
|
2157
|
+
return { ...emptyAgentHarnessUserInputAnswers() };
|
|
1885
2158
|
}
|
|
1886
|
-
function
|
|
1887
|
-
|
|
1888
|
-
return typeof value === "string" || typeof value === "number" ? value : void 0;
|
|
2159
|
+
function declineElicitation(message) {
|
|
2160
|
+
return createCodexElicitationResponse("decline", null, message ? { message } : null);
|
|
1889
2161
|
}
|
|
1890
2162
|
//#endregion
|
|
1891
2163
|
//#region extensions/codex/src/app-server/run-attempt-active-turn.ts
|
|
@@ -1894,12 +2166,14 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
1894
2166
|
const { context, turnState } = prompt;
|
|
1895
2167
|
const { runtime, attemptTools } = context;
|
|
1896
2168
|
const { connection } = runtime;
|
|
1897
|
-
const { params, runAbortController, terminalState, abortExplicitly, abortFromUpstream, bindingStore, bindingIdentity, sessionAgentId, sandboxSessionKey, effectiveCwd } = connection;
|
|
1898
|
-
const { dynamicToolParams, computerContextEpoch, toolBridge } = attemptTools;
|
|
2169
|
+
const { params, runAbortController, terminalState, abortExplicitly, abortFromUpstream, bindingStore, bindingIdentity, sessionAgentId, sandboxSessionKey, contextSessionKey, effectiveCwd } = connection;
|
|
2170
|
+
const { dynamicToolParams, compactionPlanState, computerContextEpoch, toolBridge } = attemptTools;
|
|
1899
2171
|
const { state, userInputBridgeRef, steeringQueueRef, turnWatches, completeTurn, interruptTurn } = turnRuntime;
|
|
1900
2172
|
const { emitExecutionPhaseOnce, emitLifecycleStart, maybeAnnounceFastModeAutoOff } = lifecycle;
|
|
1901
2173
|
const { enqueueNotification } = notifications;
|
|
1902
2174
|
const activeTurnId = turn.turn.id;
|
|
2175
|
+
const progressCardTool = toolBridge.availableTools.find((tool) => tool.name === "progress_card");
|
|
2176
|
+
let nativePlanUpdateOrdinal = 0;
|
|
1903
2177
|
const prepareNativeMcpAppResultDetails = createCodexNativeMcpAppResultDetailsPreparer({
|
|
1904
2178
|
client: resourceState.client,
|
|
1905
2179
|
threadId: resourceState.thread.threadId,
|
|
@@ -1948,12 +2222,39 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
1948
2222
|
trajectoryRecorder,
|
|
1949
2223
|
resolveDynamicToolResultContentSource: toolBridge.resultContentSourceForTool,
|
|
1950
2224
|
onNativeToolResultRecorded: maybeAnnounceFastModeAutoOff,
|
|
2225
|
+
...progressCardTool ? { onNativePlanUpdate: async (update) => {
|
|
2226
|
+
nativePlanUpdateOrdinal += 1;
|
|
2227
|
+
try {
|
|
2228
|
+
const input = canonicalizeNativeProgressCardInput(update);
|
|
2229
|
+
await progressCardTool.execute(`codex-native-plan:${activeTurnId}:${nativePlanUpdateOrdinal}`, input, runAbortController.signal);
|
|
2230
|
+
} catch (error) {
|
|
2231
|
+
embeddedAgentLog.warn("failed to persist native Codex plan to progress card", {
|
|
2232
|
+
runId: params.runId,
|
|
2233
|
+
threadId: resourceState.thread.threadId,
|
|
2234
|
+
error: formatErrorMessage(error)
|
|
2235
|
+
});
|
|
2236
|
+
}
|
|
2237
|
+
} } : {},
|
|
1951
2238
|
...prepareNativeMcpAppResultDetails ? { prepareNativeMcpAppResultDetails } : {},
|
|
1952
2239
|
upstreamUserText: turnState.codexTurnPromptText,
|
|
1953
|
-
onContextCompacted: () => {
|
|
2240
|
+
onContextCompacted: async () => {
|
|
1954
2241
|
computerContextEpoch.value += 1;
|
|
1955
2242
|
delete computerContextEpoch.frameToolCallId;
|
|
1956
2243
|
delete computerContextEpoch.frameImageIdentity;
|
|
2244
|
+
try {
|
|
2245
|
+
await compactionPlanState.restore({
|
|
2246
|
+
client: resourceState.client,
|
|
2247
|
+
threadId: resourceState.thread.threadId,
|
|
2248
|
+
timeoutMs: connection.appServer.requestTimeoutMs,
|
|
2249
|
+
signal: runAbortController.signal
|
|
2250
|
+
});
|
|
2251
|
+
} catch (error) {
|
|
2252
|
+
embeddedAgentLog.warn("failed to restore Codex plan state after compaction", {
|
|
2253
|
+
runId: params.runId,
|
|
2254
|
+
threadId: resourceState.thread.threadId,
|
|
2255
|
+
error: formatErrorMessage(error)
|
|
2256
|
+
});
|
|
2257
|
+
}
|
|
1957
2258
|
}
|
|
1958
2259
|
});
|
|
1959
2260
|
if (isTerminalTurnStatus(turn.turn.status)) state.terminalTurnNotificationQueued = true;
|
|
@@ -1974,24 +2275,61 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
1974
2275
|
throw error;
|
|
1975
2276
|
}
|
|
1976
2277
|
}
|
|
1977
|
-
if (!state.completed && isTerminalTurnStatus(turn.turn.status))
|
|
1978
|
-
|
|
1979
|
-
|
|
2278
|
+
if (!state.completed && isTerminalTurnStatus(turn.turn.status)) {
|
|
2279
|
+
if (!isJsonObject(turn.turn)) throw new Error("Codex turn completion payload is not a JSON object");
|
|
2280
|
+
await enqueueNotification({
|
|
2281
|
+
method: "turn/completed",
|
|
2282
|
+
params: {
|
|
2283
|
+
threadId: resourceState.thread.threadId,
|
|
2284
|
+
turnId: activeTurnId,
|
|
2285
|
+
turn: turn.turn
|
|
2286
|
+
}
|
|
2287
|
+
}, {
|
|
1980
2288
|
threadId: resourceState.thread.threadId,
|
|
1981
|
-
turnId: activeTurnId
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
2289
|
+
turnId: activeTurnId
|
|
2290
|
+
});
|
|
2291
|
+
}
|
|
2292
|
+
const notifyUserMessagePersisted = createCodexAppServerUserMessagePersistenceNotifier(params);
|
|
2293
|
+
const promptMirrorPromise = mirrorPromptAtTurnStartBestEffort({
|
|
2294
|
+
params,
|
|
2295
|
+
agentId: sessionAgentId,
|
|
2296
|
+
notifyUserMessagePersisted,
|
|
2297
|
+
sessionKey: sandboxSessionKey,
|
|
2298
|
+
cwd: effectiveCwd,
|
|
1985
2299
|
threadId: resourceState.thread.threadId,
|
|
1986
|
-
turnId: activeTurnId
|
|
2300
|
+
turnId: activeTurnId,
|
|
2301
|
+
upstreamUserText: turnState.codexTurnPromptText
|
|
1987
2302
|
});
|
|
1988
2303
|
const activeSteeringQueue = createCodexSteeringQueue({
|
|
1989
2304
|
client: resourceState.client,
|
|
1990
2305
|
threadId: resourceState.thread.threadId,
|
|
1991
2306
|
turnId: activeTurnId,
|
|
1992
2307
|
requestTimeoutMs: connection.appServer.requestTimeoutMs,
|
|
1993
|
-
|
|
1994
|
-
|
|
2308
|
+
signal: runAbortController.signal,
|
|
2309
|
+
beforeConfirmConsumed: async (items) => {
|
|
2310
|
+
const inboundItems = items.filter((item) => item.isInboundUserMessage === true);
|
|
2311
|
+
if (inboundItems.length === 0) return;
|
|
2312
|
+
await promptMirrorPromise;
|
|
2313
|
+
const messages = activeProjector.buildSteeringTranscriptPrefix();
|
|
2314
|
+
if (params.sessionTarget && messages.length > 0) await codexTranscriptMirrorRuntime.mirror({
|
|
2315
|
+
agentId: sessionAgentId,
|
|
2316
|
+
sessionKey: contextSessionKey,
|
|
2317
|
+
sessionId: params.sessionId,
|
|
2318
|
+
storePath: params.sessionTarget.storePath,
|
|
2319
|
+
cwd: effectiveCwd,
|
|
2320
|
+
messages,
|
|
2321
|
+
idempotencyScope: `codex-app-server:${resourceState.thread.threadId}`,
|
|
2322
|
+
runId: params.runId,
|
|
2323
|
+
runMirrorIdentityPrefix: `${activeTurnId}:`,
|
|
2324
|
+
config: params.config
|
|
2325
|
+
});
|
|
2326
|
+
for (const item of inboundItems) {
|
|
2327
|
+
const recorder = item.userTurnTranscriptRecorder;
|
|
2328
|
+
if (!recorder) continue;
|
|
2329
|
+
await recorder.persistApproved();
|
|
2330
|
+
if (!recorder.hasPersisted()) throw new Error("Codex consumed steering before its user turn was persisted");
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
1995
2333
|
});
|
|
1996
2334
|
steeringQueueRef.current = activeSteeringQueue;
|
|
1997
2335
|
const claimPendingUserInputAnswer = async (text, optionsLocal) => {
|
|
@@ -2058,17 +2396,6 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2058
2396
|
terminalState.terminalOutcomeFrozen = true;
|
|
2059
2397
|
params.abortSignal?.removeEventListener("abort", abortFromUpstream);
|
|
2060
2398
|
};
|
|
2061
|
-
const notifyUserMessagePersisted = createCodexAppServerUserMessagePersistenceNotifier(params);
|
|
2062
|
-
mirrorPromptAtTurnStartBestEffort({
|
|
2063
|
-
params,
|
|
2064
|
-
agentId: sessionAgentId,
|
|
2065
|
-
notifyUserMessagePersisted,
|
|
2066
|
-
sessionKey: sandboxSessionKey,
|
|
2067
|
-
cwd: effectiveCwd,
|
|
2068
|
-
threadId: resourceState.thread.threadId,
|
|
2069
|
-
turnId: activeTurnId,
|
|
2070
|
-
upstreamUserText: turnState.codexTurnPromptText
|
|
2071
|
-
});
|
|
2072
2399
|
const abortListener = () => {
|
|
2073
2400
|
if (state.timedOut) {
|
|
2074
2401
|
(async () => {
|
|
@@ -2252,6 +2579,105 @@ async function runCodexAgentEndHook(params, hookParams) {
|
|
|
2252
2579
|
runAgentEndSideEffects(sideEffectParams);
|
|
2253
2580
|
}
|
|
2254
2581
|
//#endregion
|
|
2582
|
+
//#region extensions/codex/src/app-server/session-permission-policy.ts
|
|
2583
|
+
function tupleForMode(mode, canUseAutoReview) {
|
|
2584
|
+
switch (mode) {
|
|
2585
|
+
case "read-only": return {
|
|
2586
|
+
sandbox: "read-only",
|
|
2587
|
+
approvalPolicy: "on-request",
|
|
2588
|
+
approvalsReviewer: "user"
|
|
2589
|
+
};
|
|
2590
|
+
case "guarded": return {
|
|
2591
|
+
sandbox: "workspace-write",
|
|
2592
|
+
approvalPolicy: "on-request",
|
|
2593
|
+
approvalsReviewer: "user"
|
|
2594
|
+
};
|
|
2595
|
+
case "workspace": return {
|
|
2596
|
+
sandbox: "workspace-write",
|
|
2597
|
+
approvalPolicy: "on-request",
|
|
2598
|
+
approvalsReviewer: canUseAutoReview ? "auto_review" : "user"
|
|
2599
|
+
};
|
|
2600
|
+
case "full": return {
|
|
2601
|
+
sandbox: "danger-full-access",
|
|
2602
|
+
approvalPolicy: "never",
|
|
2603
|
+
approvalsReviewer: "user"
|
|
2604
|
+
};
|
|
2605
|
+
}
|
|
2606
|
+
return mode;
|
|
2607
|
+
}
|
|
2608
|
+
function requirementsAllowTuple(tuple, allowed) {
|
|
2609
|
+
return (allowed.sandboxes === void 0 || allowed.sandboxes.has(tuple.sandbox)) && (allowed.approvalPolicies === void 0 || allowed.approvalPolicies.has(tuple.approvalPolicy)) && (allowed.reviewers === void 0 || allowed.reviewers.has(tuple.approvalsReviewer));
|
|
2610
|
+
}
|
|
2611
|
+
function tightenTupleForExecMode(tuple, execMode) {
|
|
2612
|
+
switch (execMode) {
|
|
2613
|
+
case "deny":
|
|
2614
|
+
case "allowlist": return {
|
|
2615
|
+
sandbox: "read-only",
|
|
2616
|
+
approvalPolicy: "on-request",
|
|
2617
|
+
approvalsReviewer: "user"
|
|
2618
|
+
};
|
|
2619
|
+
case "ask": return {
|
|
2620
|
+
...tuple,
|
|
2621
|
+
approvalPolicy: "on-request",
|
|
2622
|
+
approvalsReviewer: "user"
|
|
2623
|
+
};
|
|
2624
|
+
case "auto":
|
|
2625
|
+
case "full":
|
|
2626
|
+
case void 0: return tuple;
|
|
2627
|
+
}
|
|
2628
|
+
return execMode;
|
|
2629
|
+
}
|
|
2630
|
+
function clampSessionPermissionTuple(params) {
|
|
2631
|
+
if (!params.requirementsToml) return params.requested;
|
|
2632
|
+
const allowed = {
|
|
2633
|
+
sandboxes: parseAllowedSandboxModesFromCodexRequirements(params.requirementsToml, params.hostName ?? hostname()),
|
|
2634
|
+
approvalPolicies: parseAllowedApprovalPoliciesFromCodexRequirements(params.requirementsToml),
|
|
2635
|
+
reviewers: parseAllowedApprovalsReviewersFromCodexRequirements(params.requirementsToml)
|
|
2636
|
+
};
|
|
2637
|
+
if (requirementsAllowTuple(params.requested, allowed)) return params.requested;
|
|
2638
|
+
const userReviewRequired = params.mode === "read-only" || params.mode === "guarded" || params.mode === "workspace" && !params.canUseAutoReview;
|
|
2639
|
+
return {
|
|
2640
|
+
sandbox: selectGuardianSandbox(allowed.sandboxes),
|
|
2641
|
+
approvalPolicy: selectGuardianApprovalPolicy(allowed.approvalPolicies, userReviewRequired ? "ask" : "auto"),
|
|
2642
|
+
approvalsReviewer: userReviewRequired ? selectUserApprovalsReviewer(allowed.reviewers) : selectGuardianApprovalsReviewer(allowed.reviewers, "auto")
|
|
2643
|
+
};
|
|
2644
|
+
}
|
|
2645
|
+
/** Applies one complete session-mode tuple without mixing requirements-clamped fields. */
|
|
2646
|
+
function applyCodexSessionPermissionPolicy(params) {
|
|
2647
|
+
if (!params.permissionMode) return params.appServer;
|
|
2648
|
+
const sessionRoot = params.sessionRoot?.trim();
|
|
2649
|
+
if (!sessionRoot) throw new Error("Codex session permission mode requires a recorded session root");
|
|
2650
|
+
if (params.policyLocked) return {
|
|
2651
|
+
...params.appServer,
|
|
2652
|
+
sessionRoot
|
|
2653
|
+
};
|
|
2654
|
+
const requested = tightenTupleForExecMode(tupleForMode(params.permissionMode, params.canUseAutoReview), params.execMode);
|
|
2655
|
+
const tuple = params.appServer.start.transport === "stdio" ? clampSessionPermissionTuple({
|
|
2656
|
+
mode: params.permissionMode,
|
|
2657
|
+
requested,
|
|
2658
|
+
requirementsToml: params.requirementsToml,
|
|
2659
|
+
hostName: params.hostName,
|
|
2660
|
+
canUseAutoReview: params.canUseAutoReview
|
|
2661
|
+
}) : requested;
|
|
2662
|
+
const networkProxy = params.appServer.networkProxy ? resolveCodexAppServerNetworkProxy(params.pluginConfig.appServer?.networkProxy, tuple.sandbox).networkProxy : void 0;
|
|
2663
|
+
const resolved = {
|
|
2664
|
+
...params.appServer,
|
|
2665
|
+
...tuple,
|
|
2666
|
+
sessionRoot
|
|
2667
|
+
};
|
|
2668
|
+
if (networkProxy) resolved.networkProxy = networkProxy;
|
|
2669
|
+
else delete resolved.networkProxy;
|
|
2670
|
+
return resolved;
|
|
2671
|
+
}
|
|
2672
|
+
/** Keeps relative execution inside the prepared root without filesystem rediscovery. */
|
|
2673
|
+
function resolveCodexSessionPermissionCwd(params) {
|
|
2674
|
+
if (!params.permissionMode) return params.requestedCwd ?? params.fallbackCwd;
|
|
2675
|
+
const sessionRoot = params.sessionRoot?.trim();
|
|
2676
|
+
if (!sessionRoot) throw new Error("Codex session permission mode requires a recorded session root");
|
|
2677
|
+
const requestedCwd = params.requestedCwd?.trim();
|
|
2678
|
+
return requestedCwd && isPathInside(sessionRoot, requestedCwd) ? requestedCwd : sessionRoot;
|
|
2679
|
+
}
|
|
2680
|
+
//#endregion
|
|
2255
2681
|
//#region extensions/codex/src/app-server/startup-binding.ts
|
|
2256
2682
|
const CODEX_APP_SERVER_NATIVE_THREAD_FALLBACK_MAX_TOKENS = 3e5;
|
|
2257
2683
|
const CODEX_APP_SERVER_NATIVE_THREAD_DEFAULT_RESERVE_TOKENS = 2e4;
|
|
@@ -2295,10 +2721,7 @@ async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codex
|
|
|
2295
2721
|
path.join(resolvedAgentDir, "agent", "codex-home", "sessions"),
|
|
2296
2722
|
path.join(path.dirname(resolvedAgentDir), "codex-home", "sessions")
|
|
2297
2723
|
];
|
|
2298
|
-
const rolloutRoot = rolloutPath ? roots.find((root) =>
|
|
2299
|
-
const relativePath = path.relative(root, rolloutPath);
|
|
2300
|
-
return relativePath !== "" && relativePath !== ".." && !relativePath.startsWith(`..${path.sep}`) && !path.isAbsolute(relativePath);
|
|
2301
|
-
}) : void 0;
|
|
2724
|
+
const rolloutRoot = rolloutPath ? roots.find((root) => isPathStrictlyInside(root, rolloutPath)) : void 0;
|
|
2302
2725
|
if (rolloutPath && rolloutRoot && path.isAbsolute(rolloutPath) && path.extname(rolloutPath) === ".jsonl" && path.basename(rolloutPath).includes(threadId)) try {
|
|
2303
2726
|
const opened = await (await root(rolloutRoot, {
|
|
2304
2727
|
hardlinks: "reject",
|
|
@@ -2555,14 +2978,6 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
2555
2978
|
}
|
|
2556
2979
|
//#endregion
|
|
2557
2980
|
//#region extensions/codex/src/app-server/run-attempt-connection.ts
|
|
2558
|
-
function applyStoredBindingPermissions(params) {
|
|
2559
|
-
if (params.execPolicyTouched || params.binding?.connectionScope === "supervision") return params.appServer;
|
|
2560
|
-
return {
|
|
2561
|
-
...params.appServer,
|
|
2562
|
-
approvalPolicy: params.binding?.approvalPolicy ?? params.appServer.approvalPolicy,
|
|
2563
|
-
sandbox: params.binding?.sandbox ?? params.appServer.sandbox
|
|
2564
|
-
};
|
|
2565
|
-
}
|
|
2566
2981
|
async function prepareCodexAttemptConnection({ params, options }) {
|
|
2567
2982
|
const attemptStartedAt = Date.now();
|
|
2568
2983
|
const profilerEnabled = isCodexAppServerProfilerEnabled(params.config);
|
|
@@ -2575,16 +2990,15 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2575
2990
|
resetAnnounced: false
|
|
2576
2991
|
};
|
|
2577
2992
|
const preDynamicStartupStages = createCodexDynamicToolBuildStageTracker({ enabled: profilerEnabled });
|
|
2578
|
-
const attemptClientFactory = options.clientFactory ?? getLeasedSharedCodexAppServerClient;
|
|
2579
2993
|
const runtimeArtifactRequest = params.captureRuntimeArtifact || params.expectedRuntimeArtifact ? params.expectedRuntimeArtifact ? { expected: params.expectedRuntimeArtifact } : {} : void 0;
|
|
2580
2994
|
const pluginConfig = readCodexPluginConfig(options.pluginConfig);
|
|
2995
|
+
const requirementsToml = readCodexRequirementsToml({});
|
|
2581
2996
|
const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig });
|
|
2582
2997
|
const { sessionAgentId } = resolveSessionAgentIds({
|
|
2583
2998
|
sessionKey: params.sessionKey,
|
|
2584
2999
|
config: params.config,
|
|
2585
3000
|
agentId: params.agentId
|
|
2586
3001
|
});
|
|
2587
|
-
const beforeToolCallPolicy = getBeforeToolCallPolicyDiagnosticState();
|
|
2588
3002
|
preDynamicStartupStages.mark("config");
|
|
2589
3003
|
const resolvedWorkspace = resolveUserPath(params.workspaceDir);
|
|
2590
3004
|
await ensureCodexWorkspaceDirOnce(resolvedWorkspace);
|
|
@@ -2596,14 +3010,36 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2596
3010
|
sessionKey: sandboxSessionKey,
|
|
2597
3011
|
workspaceDir: resolvedWorkspace
|
|
2598
3012
|
});
|
|
3013
|
+
const attemptClientFactory = options.clientFactory ?? (isCodexPairedNodeRemoteExecPlacementSandbox(sandbox) ? createIsolatedCodexAppServerClient : getLeasedSharedCodexAppServerClient);
|
|
2599
3014
|
preDynamicStartupStages.mark("sandbox");
|
|
2600
3015
|
const execPolicy = resolveOpenClawExecPolicyForCodexAppServer({
|
|
3016
|
+
permissionMode: params.permissionMode,
|
|
2601
3017
|
execOverrides: params.execOverrides,
|
|
2602
|
-
approvals: loadExecApprovals(),
|
|
3018
|
+
approvals: params.permissionMode === "full" ? void 0 : loadExecApprovals(),
|
|
2603
3019
|
config: params.config,
|
|
2604
3020
|
agentId: sessionAgentId
|
|
2605
3021
|
});
|
|
2606
3022
|
const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId);
|
|
3023
|
+
const preparedEnvironment = params.hostCapabilities.preparedEnvironment?.();
|
|
3024
|
+
const remoteExec = isCodexRemoteExecPlacementSandbox(sandbox);
|
|
3025
|
+
const preparedShellEnvironment = preparedEnvironment ? {
|
|
3026
|
+
...preparedEnvironment.credentialScrubEnv,
|
|
3027
|
+
...!remoteExec ? preparedEnvironment.localIdentityEnv : void 0
|
|
3028
|
+
} : void 0;
|
|
3029
|
+
const shellEnvironment = preparedShellEnvironment && Object.keys(preparedShellEnvironment).length > 0 ? preparedShellEnvironment : void 0;
|
|
3030
|
+
const disableLoginShell = remoteExec || preparedEnvironment?.managedLocalIdentity === true || preparedEnvironment !== void 0 && Object.keys(preparedEnvironment.credentialScrubEnv).length > 0;
|
|
3031
|
+
const withPreparedProcessEnv = (appServer) => {
|
|
3032
|
+
return shellEnvironment ? {
|
|
3033
|
+
...appServer,
|
|
3034
|
+
start: {
|
|
3035
|
+
...appServer.start,
|
|
3036
|
+
env: {
|
|
3037
|
+
...appServer.start.env,
|
|
3038
|
+
...shellEnvironment
|
|
3039
|
+
}
|
|
3040
|
+
}
|
|
3041
|
+
} : appServer;
|
|
3042
|
+
};
|
|
2607
3043
|
let bindingIdentity = sessionBindingIdentity({
|
|
2608
3044
|
sessionId: params.sessionId,
|
|
2609
3045
|
sessionKey: params.sessionKey,
|
|
@@ -2650,21 +3086,20 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2650
3086
|
const usesSupervisionConnection = startupBinding?.connectionScope === "supervision";
|
|
2651
3087
|
if (usesSupervisionConnection) activeContextEngine = void 0;
|
|
2652
3088
|
if (usesSupervisionConnection && pluginConfig.supervision?.enabled !== true) throw new Error("Codex supervision is disabled; refusing to open a native user-home supervised session");
|
|
2653
|
-
const resolveRuntimeOptionsForBinding = (selection) =>
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
execPolicyTouched: execPolicy.touched
|
|
2666
|
-
});
|
|
3089
|
+
const resolveRuntimeOptionsForBinding = (binding, selection) => resolveCodexBindingAppServerConnection({
|
|
3090
|
+
binding,
|
|
3091
|
+
pluginConfig,
|
|
3092
|
+
execPolicy,
|
|
3093
|
+
modelProvider: selection.modelProvider,
|
|
3094
|
+
model: selection.model,
|
|
3095
|
+
config: params.config,
|
|
3096
|
+
agentDir,
|
|
3097
|
+
requirementsToml,
|
|
3098
|
+
openClawSandboxActive: sandbox?.enabled === true,
|
|
3099
|
+
sessionPermissionMode: params.permissionMode
|
|
3100
|
+
}).appServer;
|
|
2667
3101
|
const initialStartupBindingHadInactiveThreadBootstrap = isInactiveThreadBootstrapBinding(startupBinding);
|
|
3102
|
+
const appServerHomeScope = resolveCodexAppServerHomeScope({ appServer: pluginConfig.appServer });
|
|
2668
3103
|
const preparedAuthRoute = usesSupervisionConnection ? void 0 : params.runtimePlan?.auth.modelRoute;
|
|
2669
3104
|
const startupAuthProfileCandidate = usesSupervisionConnection ? void 0 : preparedAuthRoute ? params.runtimePlan?.auth.forwardedAuthProfileId : params.runtimePlan?.auth.forwardedAuthProfileId ?? params.authProfileId ?? startupBinding?.authProfileId;
|
|
2670
3105
|
const resolvedStartupAuthProfileId = usesSupervisionConnection ? void 0 : preparedAuthRoute ? startupAuthProfileCandidate : params.authProfileStore ? resolveCodexAppServerAuthProfileId({
|
|
@@ -2686,13 +3121,13 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2686
3121
|
authProfileId: resolvedStartupAuthProfileId,
|
|
2687
3122
|
authProfileStore: params.authProfileStore,
|
|
2688
3123
|
agentDir,
|
|
2689
|
-
homeScope:
|
|
3124
|
+
homeScope: appServerHomeScope,
|
|
2690
3125
|
requirePreparedAuth: isCodexRemoteExecPlacementSandbox(sandbox),
|
|
2691
3126
|
config: params.config,
|
|
2692
3127
|
subscriptionProfileRequiredError: "Prepared Codex subscription route requires a forwarded OpenAI OAuth or token profile.",
|
|
2693
3128
|
subscriptionProfileUnusableError: "Prepared Codex subscription auth profile is unusable."
|
|
2694
3129
|
});
|
|
2695
|
-
const startupClientAuthProfileId = usesSupervisionConnection || startupPreparedAuth?.kind === "api-key" ? null : startupAuthProfileId;
|
|
3130
|
+
const startupClientAuthProfileId = usesSupervisionConnection || appServerHomeScope === "user" || startupPreparedAuth?.kind === "api-key" ? null : startupAuthProfileId;
|
|
2696
3131
|
const resolveReviewerPolicyContext = (binding) => {
|
|
2697
3132
|
const nativeModelOwned = binding?.preserveNativeModel === true;
|
|
2698
3133
|
return resolveCodexModelBackedReviewerPolicyContext({
|
|
@@ -2705,41 +3140,56 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2705
3140
|
};
|
|
2706
3141
|
let reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
|
|
2707
3142
|
preDynamicStartupStages.mark("auth-profile");
|
|
2708
|
-
let configuredAppServer = resolveRuntimeOptionsForBinding({
|
|
3143
|
+
let configuredAppServer = resolveRuntimeOptionsForBinding(startupBinding, {
|
|
2709
3144
|
modelProvider: reviewerPolicyContext.modelProvider,
|
|
2710
3145
|
model: reviewerPolicyContext.model
|
|
2711
3146
|
});
|
|
2712
3147
|
const effectiveWorkspace = sandbox?.enabled ? sandbox.workspaceAccess === "rw" ? resolvedWorkspace : sandbox.workspaceDir : resolvedWorkspace;
|
|
2713
3148
|
const requestedCwd = params.cwd ? resolveUserPath(params.cwd) : void 0;
|
|
2714
3149
|
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");
|
|
2715
|
-
const
|
|
3150
|
+
const sessionPermissionCwd = resolveCodexSessionPermissionCwd({
|
|
3151
|
+
permissionMode: params.permissionMode,
|
|
3152
|
+
sessionRoot: params.sessionRoot,
|
|
3153
|
+
requestedCwd,
|
|
3154
|
+
fallbackCwd: effectiveWorkspace
|
|
3155
|
+
});
|
|
3156
|
+
const effectiveCwd = sandbox?.enabled ? effectiveWorkspace : sessionPermissionCwd;
|
|
2716
3157
|
if (effectiveWorkspace !== resolvedWorkspace) await ensureCodexWorkspaceDirOnce(effectiveWorkspace);
|
|
2717
3158
|
preDynamicStartupStages.mark("effective-workspace");
|
|
2718
|
-
const
|
|
2719
|
-
|
|
2720
|
-
|
|
3159
|
+
const applySessionPermissionPolicy = (appServer, selection) => applyCodexSessionPermissionPolicy({
|
|
3160
|
+
appServer,
|
|
3161
|
+
permissionMode: params.permissionMode,
|
|
3162
|
+
sessionRoot: params.sessionRoot,
|
|
2721
3163
|
pluginConfig,
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
env: process.env,
|
|
2734
|
-
agentDir
|
|
2735
|
-
});
|
|
2736
|
-
let approvalPolicyPromotedForOpenClawToolPolicy = configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted";
|
|
2737
|
-
if (approvalPolicyPromotedForOpenClawToolPolicy) embeddedAgentLog.info("codex app-server approval policy promoted for OpenClaw tool policy", {
|
|
2738
|
-
from: "never",
|
|
2739
|
-
to: "untrusted",
|
|
2740
|
-
beforeToolCallHook: beforeToolCallPolicy.hasBeforeToolCallHook,
|
|
2741
|
-
trustedToolPolicies: beforeToolCallPolicy.trustedToolPolicies
|
|
3164
|
+
canUseAutoReview: canUseCodexModelBackedApprovalsReviewerForModel({
|
|
3165
|
+
modelProvider: selection.modelProvider,
|
|
3166
|
+
model: selection.model,
|
|
3167
|
+
config: params.config,
|
|
3168
|
+
env: process.env,
|
|
3169
|
+
agentDir,
|
|
3170
|
+
homeScope: appServer.start.homeScope
|
|
3171
|
+
}),
|
|
3172
|
+
requirementsToml,
|
|
3173
|
+
policyLocked: startupBinding?.connectionScope === "supervision",
|
|
3174
|
+
execMode: execPolicy.mode
|
|
2742
3175
|
});
|
|
3176
|
+
const resolveFinalAppServer = (configured, selection) => {
|
|
3177
|
+
const session = applySessionPermissionPolicy(configured, selection);
|
|
3178
|
+
const trusted = resolveCodexAppServerForModelProvider({
|
|
3179
|
+
appServer: session,
|
|
3180
|
+
provider: selection.modelProvider,
|
|
3181
|
+
model: selection.model,
|
|
3182
|
+
config: params.config,
|
|
3183
|
+
env: process.env,
|
|
3184
|
+
agentDir
|
|
3185
|
+
});
|
|
3186
|
+
return {
|
|
3187
|
+
session,
|
|
3188
|
+
appServer: withPreparedProcessEnv(trusted)
|
|
3189
|
+
};
|
|
3190
|
+
};
|
|
3191
|
+
let resolvedAppServer = resolveFinalAppServer(configuredAppServer, reviewerPolicyContext);
|
|
3192
|
+
let appServer = resolvedAppServer.appServer;
|
|
2743
3193
|
preDynamicStartupStages.mark("app-server-policy");
|
|
2744
3194
|
preDynamicStartupStages.mark("native-hook-relay");
|
|
2745
3195
|
const terminalState = {
|
|
@@ -2787,20 +3237,12 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2787
3237
|
preDynamicStartupStages.mark("rotate-binding");
|
|
2788
3238
|
if (startupBinding !== startupBindingBeforeRotation) {
|
|
2789
3239
|
reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
|
|
2790
|
-
configuredAppServer = resolveRuntimeOptionsForBinding({
|
|
3240
|
+
configuredAppServer = resolveRuntimeOptionsForBinding(startupBinding, {
|
|
2791
3241
|
modelProvider: reviewerPolicyContext.modelProvider,
|
|
2792
3242
|
model: reviewerPolicyContext.model
|
|
2793
3243
|
});
|
|
2794
|
-
|
|
2795
|
-
appServer =
|
|
2796
|
-
appServer: policyAppServer,
|
|
2797
|
-
provider: reviewerPolicyContext.modelProvider,
|
|
2798
|
-
model: reviewerPolicyContext.model,
|
|
2799
|
-
config: params.config,
|
|
2800
|
-
env: process.env,
|
|
2801
|
-
agentDir
|
|
2802
|
-
});
|
|
2803
|
-
approvalPolicyPromotedForOpenClawToolPolicy = configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted";
|
|
3244
|
+
resolvedAppServer = resolveFinalAppServer(configuredAppServer, reviewerPolicyContext);
|
|
3245
|
+
appServer = resolvedAppServer.appServer;
|
|
2804
3246
|
}
|
|
2805
3247
|
const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
|
|
2806
3248
|
configuredEvents: options.nativeHookRelay?.events,
|
|
@@ -2809,22 +3251,10 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2809
3251
|
const mutable = {
|
|
2810
3252
|
startupBinding,
|
|
2811
3253
|
startupContextTokens: startupBindingResolution.startupContextTokens,
|
|
2812
|
-
pluginAppServer: appServer
|
|
3254
|
+
pluginAppServer: appServer,
|
|
3255
|
+
continuityCalibration: startupBindingBeforeRotation?.continuityCalibration
|
|
2813
3256
|
};
|
|
2814
|
-
const resolveRuntimeOptionsForCurrentBinding = (selection) =>
|
|
2815
|
-
appServer: resolveCodexBindingAppServerConnection({
|
|
2816
|
-
binding: mutable.startupBinding,
|
|
2817
|
-
pluginConfig,
|
|
2818
|
-
execPolicy,
|
|
2819
|
-
modelProvider: selection.modelProvider,
|
|
2820
|
-
model: selection.model,
|
|
2821
|
-
config: params.config,
|
|
2822
|
-
agentDir,
|
|
2823
|
-
openClawSandboxActive: sandbox?.enabled === true
|
|
2824
|
-
}).appServer,
|
|
2825
|
-
binding: mutable.startupBinding,
|
|
2826
|
-
execPolicyTouched: execPolicy.touched
|
|
2827
|
-
});
|
|
3257
|
+
const resolveRuntimeOptionsForCurrentBinding = (selection) => resolveFinalAppServer(resolveRuntimeOptionsForBinding(mutable.startupBinding, selection), selection).appServer;
|
|
2828
3258
|
return {
|
|
2829
3259
|
params,
|
|
2830
3260
|
options,
|
|
@@ -2846,6 +3276,8 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2846
3276
|
contextSessionKey,
|
|
2847
3277
|
sandbox,
|
|
2848
3278
|
agentDir,
|
|
3279
|
+
shellEnvironment,
|
|
3280
|
+
disableLoginShell,
|
|
2849
3281
|
bindingIdentity,
|
|
2850
3282
|
bindingStore,
|
|
2851
3283
|
activeContextEngine,
|
|
@@ -2858,7 +3290,6 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2858
3290
|
effectiveWorkspace,
|
|
2859
3291
|
effectiveCwd,
|
|
2860
3292
|
appServer,
|
|
2861
|
-
approvalPolicyPromotedForOpenClawToolPolicy,
|
|
2862
3293
|
nativeHookRelayEvents,
|
|
2863
3294
|
runAbortController,
|
|
2864
3295
|
terminalState,
|
|
@@ -2951,10 +3382,12 @@ function resolveContextEngineBootstrapProjectionDecision(params) {
|
|
|
2951
3382
|
*/
|
|
2952
3383
|
async function buildCodexWorkspaceBootstrapContext(params) {
|
|
2953
3384
|
try {
|
|
3385
|
+
const inheritsAgentWorkspace = (params.executionWorkspace ?? params.resolvedWorkspace) !== params.resolvedWorkspace;
|
|
3386
|
+
const promptWorkspace = inheritsAgentWorkspace ? params.resolvedWorkspace : params.effectiveWorkspace;
|
|
2954
3387
|
const memoryToolsAvailable = params.memoryToolNames.length > 0 && canRouteCodexWorkspaceMemoryThroughTools({
|
|
2955
3388
|
config: params.params.config,
|
|
2956
3389
|
agentId: params.params.agentId ?? params.sessionAgentId,
|
|
2957
|
-
workspaceDir: params.effectiveWorkspace
|
|
3390
|
+
workspaceDir: inheritsAgentWorkspace ? params.resolvedWorkspace : params.effectiveWorkspace
|
|
2958
3391
|
});
|
|
2959
3392
|
const bootstrapFiles = await resolveBootstrapFilesForRun({
|
|
2960
3393
|
workspaceDir: params.resolvedWorkspace,
|
|
@@ -2974,7 +3407,7 @@ async function buildCodexWorkspaceBootstrapContext(params) {
|
|
|
2974
3407
|
const memoryReferenceFiles = memoryToolRoutedBootstrapFiles.map((file) => remapCodexContextFilePath({
|
|
2975
3408
|
file: toCodexEmbeddedContextFile(file),
|
|
2976
3409
|
sourceWorkspaceDir: params.resolvedWorkspace,
|
|
2977
|
-
targetWorkspaceDir:
|
|
3410
|
+
targetWorkspaceDir: promptWorkspace
|
|
2978
3411
|
}));
|
|
2979
3412
|
const contextFiles = buildBootstrapContextForFiles(memoryToolsAvailable ? bootstrapFiles.filter((file) => !isCodexWorkspaceRootMemoryBootstrapFile({
|
|
2980
3413
|
file,
|
|
@@ -2986,23 +3419,33 @@ async function buildCodexWorkspaceBootstrapContext(params) {
|
|
|
2986
3419
|
}).map((file) => remapCodexContextFilePath({
|
|
2987
3420
|
file,
|
|
2988
3421
|
sourceWorkspaceDir: params.resolvedWorkspace,
|
|
2989
|
-
targetWorkspaceDir:
|
|
3422
|
+
targetWorkspaceDir: promptWorkspace
|
|
2990
3423
|
}));
|
|
2991
3424
|
const promptContextFiles = selectCodexWorkspacePromptContextFiles(contextFiles, {
|
|
2992
3425
|
excludeMemory: memoryToolsAvailable,
|
|
2993
3426
|
memoryWorkspaceDir: params.effectiveWorkspace
|
|
2994
3427
|
});
|
|
2995
|
-
const
|
|
3428
|
+
const injectOpenClawContext = shouldInjectCodexOpenClawPromptContext(params.params);
|
|
3429
|
+
const restrictedProjectDocNeedsOpenClawCarrier = params.params.pluginHarnessToolPolicyRestricted === true && !params.params.disableTools && !isMessageOnlyCodexSourceReply(params.params) && params.params.bootstrapContextMode !== "lightweight";
|
|
3430
|
+
const threadDeveloperInstructionFiles = injectOpenClawContext && !params.ringZeroActive && (inheritsAgentWorkspace || restrictedProjectDocNeedsOpenClawCarrier) ? selectCodexWorkspaceAgentProjectInstructionFiles(contextFiles, params.resolvedWorkspace) : [];
|
|
3431
|
+
const turnScopedDeveloperInstructionFiles = injectOpenClawContext ? selectCodexWorkspaceTurnScopedDeveloperInstructionFiles(contextFiles) : [];
|
|
2996
3432
|
return {
|
|
2997
3433
|
bootstrapFiles,
|
|
2998
3434
|
contextFiles,
|
|
3435
|
+
inheritsAgentWorkspace,
|
|
2999
3436
|
promptContextFiles,
|
|
3437
|
+
threadDeveloperInstructionFiles,
|
|
3000
3438
|
turnScopedDeveloperInstructionFiles,
|
|
3001
3439
|
memoryReferenceFiles,
|
|
3002
3440
|
memoryToolRoutedBootstrapFiles,
|
|
3003
3441
|
memoryToolNames: [...params.memoryToolNames],
|
|
3004
3442
|
memoryToolRouted: memoryToolsAvailable,
|
|
3005
3443
|
promptContext: renderCodexWorkspaceBootstrapPromptContext(promptContextFiles),
|
|
3444
|
+
threadDeveloperInstructions: renderCodexWorkspaceDeveloperInstructions({
|
|
3445
|
+
files: threadDeveloperInstructionFiles,
|
|
3446
|
+
header: "## OpenClaw Agent Workspace Instructions",
|
|
3447
|
+
preamble: "OpenClaw loaded this bounded snapshot from the configured agent workspace."
|
|
3448
|
+
}),
|
|
3006
3449
|
turnScopedDeveloperInstructions: renderCodexWorkspaceCollaborationDeveloperInstructions(turnScopedDeveloperInstructionFiles),
|
|
3007
3450
|
memoryCollaborationInstructions: shouldInjectCodexOpenClawPromptContext(params.params) ? await renderCodexWorkspaceMemoryCollaborationInstructions({
|
|
3008
3451
|
files: memoryReferenceFiles,
|
|
@@ -3018,7 +3461,8 @@ async function buildCodexWorkspaceBootstrapContext(params) {
|
|
|
3018
3461
|
embeddedAgentLog.warn("failed to load codex workspace bootstrap instructions", { error });
|
|
3019
3462
|
return {
|
|
3020
3463
|
bootstrapFiles: [],
|
|
3021
|
-
contextFiles: []
|
|
3464
|
+
contextFiles: [],
|
|
3465
|
+
inheritsAgentWorkspace: false
|
|
3022
3466
|
};
|
|
3023
3467
|
}
|
|
3024
3468
|
}
|
|
@@ -3051,7 +3495,7 @@ function buildCodexSystemPromptReport(params) {
|
|
|
3051
3495
|
injectedWorkspaceFiles: buildCodexBootstrapInjectionStats({
|
|
3052
3496
|
bootstrapFiles: params.workspaceBootstrapContext.bootstrapFiles,
|
|
3053
3497
|
injectedFiles: params.workspaceBootstrapContext.promptContextFiles ?? [],
|
|
3054
|
-
developerInstructionFiles: params.workspaceBootstrapContext.turnScopedDeveloperInstructionFiles ?? [],
|
|
3498
|
+
developerInstructionFiles: [...params.workspaceBootstrapContext.threadDeveloperInstructionFiles ?? [], ...params.workspaceBootstrapContext.turnScopedDeveloperInstructionFiles ?? []],
|
|
3055
3499
|
memoryToolRoutedBootstrapFiles: params.workspaceBootstrapContext.memoryToolRoutedBootstrapFiles ?? [],
|
|
3056
3500
|
memoryToolRouted: params.workspaceBootstrapContext.memoryToolRouted === true
|
|
3057
3501
|
}),
|
|
@@ -3132,12 +3576,17 @@ function buildCodexBootstrapInjectionStats(params) {
|
|
|
3132
3576
|
const rawChars = file.missing ? 0 : (file.content ?? "").trimEnd().length;
|
|
3133
3577
|
const memoryToolRoutedFile = baseName === CODEX_MEMORY_CONTEXT_BASENAME && params.memoryToolRouted === true && memoryToolRoutedPaths.has(normalizeCodexContextFilePath(pathValue));
|
|
3134
3578
|
const injected = memoryToolRoutedFile ? void 0 : readCodexIndexedContextFileContent(injectedIndex, pathValue, fileName) ?? readCodexIndexedContextFileContent(developerInstructionIndex, pathValue, fileName);
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3579
|
+
if (!file.missing && injected === void 0 && CODEX_NATIVE_PROJECT_DOC_BASENAMES.has(baseName)) return {
|
|
3580
|
+
name: displayName,
|
|
3581
|
+
path: pathValue,
|
|
3582
|
+
missing: false,
|
|
3583
|
+
rawChars,
|
|
3584
|
+
injectionStatus: "native_unverified",
|
|
3585
|
+
injectedChars: null,
|
|
3586
|
+
truncated: null
|
|
3587
|
+
};
|
|
3588
|
+
const injectedChars = memoryToolRoutedFile ? 0 : injected?.length ?? 0;
|
|
3589
|
+
const truncated = memoryToolRoutedFile ? false : !file.missing && injectedChars < rawChars;
|
|
3141
3590
|
return {
|
|
3142
3591
|
name: displayName,
|
|
3143
3592
|
path: pathValue,
|
|
@@ -3272,7 +3721,7 @@ function renderCodexWorkspaceBootstrapPromptContext(contextFiles) {
|
|
|
3272
3721
|
const files = contextFiles;
|
|
3273
3722
|
if (files.length === 0) return;
|
|
3274
3723
|
const lines = [
|
|
3275
|
-
"OpenClaw loaded these user-editable workspace files for the current turn. Codex loads AGENTS.md natively. SOUL.md, IDENTITY.md, and USER.md
|
|
3724
|
+
"OpenClaw loaded these user-editable workspace files for the current turn. Codex loads project-local AGENTS.md natively. When execution uses another folder, OpenClaw supplies the agent workspace AGENTS.md as thread-level developer instructions. SOUL.md, IDENTITY.md, and USER.md remain turn-scoped collaboration instructions. Those files are not repeated here.",
|
|
3276
3725
|
"",
|
|
3277
3726
|
"# Project Context",
|
|
3278
3727
|
"",
|
|
@@ -3295,6 +3744,10 @@ function selectCodexWorkspacePromptContextFiles(contextFiles, options = {}) {
|
|
|
3295
3744
|
function selectCodexWorkspaceTurnScopedDeveloperInstructionFiles(contextFiles) {
|
|
3296
3745
|
return selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, CODEX_TURN_SCOPED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES);
|
|
3297
3746
|
}
|
|
3747
|
+
function selectCodexWorkspaceAgentProjectInstructionFiles(contextFiles, agentWorkspaceDir) {
|
|
3748
|
+
const agentProjectDocPath = path.join(path.resolve(agentWorkspaceDir), "AGENTS.md");
|
|
3749
|
+
return selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, CODEX_NATIVE_PROJECT_DOC_BASENAMES).filter((file) => path.resolve(file.path) === agentProjectDocPath);
|
|
3750
|
+
}
|
|
3298
3751
|
function selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, basenames) {
|
|
3299
3752
|
return contextFiles.filter((file) => {
|
|
3300
3753
|
const baseName = getCodexContextFileBasename(file.path);
|
|
@@ -3428,34 +3881,131 @@ function remapCodexContextFilePath(params) {
|
|
|
3428
3881
|
path: targetUsesPosixSeparators ? path.posix.join(params.targetWorkspaceDir, normalizedRelativePath) : path.win32.join(params.targetWorkspaceDir, normalizedRelativePath)
|
|
3429
3882
|
};
|
|
3430
3883
|
}
|
|
3431
|
-
function compareCodexContextFiles(left, right) {
|
|
3432
|
-
const leftPath = normalizeCodexContextFilePath(left.path);
|
|
3433
|
-
const rightPath = normalizeCodexContextFilePath(right.path);
|
|
3434
|
-
const leftBase = getCodexContextFileBasename(left.path);
|
|
3435
|
-
const rightBase = getCodexContextFileBasename(right.path);
|
|
3436
|
-
const leftOrder = CODEX_BOOTSTRAP_CONTEXT_ORDER.get(leftBase) ?? Number.MAX_SAFE_INTEGER;
|
|
3437
|
-
const rightOrder = CODEX_BOOTSTRAP_CONTEXT_ORDER.get(rightBase) ?? Number.MAX_SAFE_INTEGER;
|
|
3438
|
-
if (leftOrder !== rightOrder) return leftOrder - rightOrder;
|
|
3439
|
-
if (leftBase !== rightBase) return leftBase.localeCompare(rightBase);
|
|
3440
|
-
return leftPath.localeCompare(rightPath);
|
|
3884
|
+
function compareCodexContextFiles(left, right) {
|
|
3885
|
+
const leftPath = normalizeCodexContextFilePath(left.path);
|
|
3886
|
+
const rightPath = normalizeCodexContextFilePath(right.path);
|
|
3887
|
+
const leftBase = getCodexContextFileBasename(left.path);
|
|
3888
|
+
const rightBase = getCodexContextFileBasename(right.path);
|
|
3889
|
+
const leftOrder = CODEX_BOOTSTRAP_CONTEXT_ORDER.get(leftBase) ?? Number.MAX_SAFE_INTEGER;
|
|
3890
|
+
const rightOrder = CODEX_BOOTSTRAP_CONTEXT_ORDER.get(rightBase) ?? Number.MAX_SAFE_INTEGER;
|
|
3891
|
+
if (leftOrder !== rightOrder) return leftOrder - rightOrder;
|
|
3892
|
+
if (leftBase !== rightBase) return leftBase.localeCompare(rightBase);
|
|
3893
|
+
return leftPath.localeCompare(rightPath);
|
|
3894
|
+
}
|
|
3895
|
+
function compareCodexBootstrapFiles(left, right) {
|
|
3896
|
+
return compareCodexContextFiles(toCodexEmbeddedContextFile(left), toCodexEmbeddedContextFile(right));
|
|
3897
|
+
}
|
|
3898
|
+
function normalizeCodexContextFilePath(filePath) {
|
|
3899
|
+
return filePath.trim().replaceAll("\\", "/").toLowerCase();
|
|
3900
|
+
}
|
|
3901
|
+
function getCodexContextFileDisplayBasename(filePath) {
|
|
3902
|
+
return filePath.trim().replaceAll("\\", "/").split("/").pop()?.trim() ?? "";
|
|
3903
|
+
}
|
|
3904
|
+
function getCodexContextFileBasename(filePath) {
|
|
3905
|
+
return normalizeCodexContextFilePath(filePath).split("/").pop() ?? "";
|
|
3906
|
+
}
|
|
3907
|
+
function normalizeCodexDynamicToolName(name) {
|
|
3908
|
+
return name.trim().toLowerCase();
|
|
3909
|
+
}
|
|
3910
|
+
function isNonEmptyString$1(value) {
|
|
3911
|
+
return typeof value === "string" && value.length > 0;
|
|
3912
|
+
}
|
|
3913
|
+
//#endregion
|
|
3914
|
+
//#region extensions/codex/src/app-server/run-attempt-state.ts
|
|
3915
|
+
async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity, fields) {
|
|
3916
|
+
const currentBinding = await bindingStore.read(identity);
|
|
3917
|
+
const expectedThreadId = fields.threadId ?? currentBinding?.threadId;
|
|
3918
|
+
if (!expectedThreadId) return;
|
|
3919
|
+
if (currentBinding && currentBinding.threadId !== expectedThreadId) {
|
|
3920
|
+
embeddedAgentLog.warn("codex app-server image payload error detected for unbound thread; preserving thread binding", {
|
|
3921
|
+
...fields,
|
|
3922
|
+
boundThreadId: currentBinding.threadId
|
|
3923
|
+
});
|
|
3924
|
+
return;
|
|
3925
|
+
}
|
|
3926
|
+
if (currentBinding?.connectionScope === "supervision") {
|
|
3927
|
+
embeddedAgentLog.warn("codex app-server image payload error detected for supervised thread; preserving native binding", fields);
|
|
3928
|
+
return;
|
|
3929
|
+
}
|
|
3930
|
+
embeddedAgentLog.warn("codex app-server image payload error detected; clearing thread binding", fields);
|
|
3931
|
+
await bindingStore.mutate(identity, {
|
|
3932
|
+
kind: "clear",
|
|
3933
|
+
threadId: expectedThreadId
|
|
3934
|
+
});
|
|
3935
|
+
}
|
|
3936
|
+
async function markCodexAppServerBindingCoveredThroughTurn(params) {
|
|
3937
|
+
await params.bindingStore.mutate(params.identity, {
|
|
3938
|
+
kind: "patch",
|
|
3939
|
+
threadId: params.threadId,
|
|
3940
|
+
patch: {
|
|
3941
|
+
historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3942
|
+
...params.continuityCalibration ? { continuityCalibration: params.continuityCalibration } : {}
|
|
3943
|
+
}
|
|
3944
|
+
});
|
|
3945
|
+
}
|
|
3946
|
+
function isNonEmptyString(value) {
|
|
3947
|
+
return typeof value === "string" && value.length > 0;
|
|
3441
3948
|
}
|
|
3442
|
-
function
|
|
3443
|
-
|
|
3949
|
+
function shouldUseFreshCodexThreadAfterContextEngineOverflow(params) {
|
|
3950
|
+
if (!params.contextEngineActive || params.thread.lifecycle.action !== "resumed") return false;
|
|
3951
|
+
const message = formatErrorMessage(params.error);
|
|
3952
|
+
return /ran out of room in the model'?s context window/iu.test(message) || /context window/iu.test(message) || /context length/iu.test(message) || /maximum context/iu.test(message) || /too many tokens/iu.test(message);
|
|
3444
3953
|
}
|
|
3445
|
-
function
|
|
3446
|
-
|
|
3954
|
+
function isCodexActiveCompactTurnError(error) {
|
|
3955
|
+
if (!(error instanceof CodexAppServerRpcError)) return false;
|
|
3956
|
+
const data = isJsonObject(error.data) ? error.data : void 0;
|
|
3957
|
+
const codexErrorInfo = isJsonObject(data?.codexErrorInfo) ? data.codexErrorInfo : void 0;
|
|
3958
|
+
return (isJsonObject(codexErrorInfo?.activeTurnNotSteerable) ? codexErrorInfo.activeTurnNotSteerable : void 0)?.turnKind === "compact";
|
|
3447
3959
|
}
|
|
3448
|
-
function
|
|
3449
|
-
|
|
3960
|
+
function readCodexFinalizationHookNotification(notification, threadId, turnId) {
|
|
3961
|
+
if (notification.method !== "hook/started" && notification.method !== "hook/completed") return;
|
|
3962
|
+
const params = isJsonObject(notification.params) ? notification.params : void 0;
|
|
3963
|
+
const run = params && isJsonObject(params.run) ? params.run : void 0;
|
|
3964
|
+
if (params?.threadId !== threadId || params.turnId !== turnId || run?.eventName !== "stop" && run?.eventName !== "subagentStop" || typeof run.id !== "string" || !run.id) return;
|
|
3965
|
+
if (notification.method === "hook/started") return {
|
|
3966
|
+
phase: "started",
|
|
3967
|
+
runId: run.id
|
|
3968
|
+
};
|
|
3969
|
+
return {
|
|
3970
|
+
phase: "completed",
|
|
3971
|
+
runId: run.id,
|
|
3972
|
+
status: typeof run.status === "string" ? run.status : void 0
|
|
3973
|
+
};
|
|
3450
3974
|
}
|
|
3451
|
-
function
|
|
3452
|
-
return
|
|
3975
|
+
function joinPresentSections(...sections) {
|
|
3976
|
+
return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
|
|
3453
3977
|
}
|
|
3454
|
-
function
|
|
3455
|
-
|
|
3978
|
+
function prependCurrentInboundContext(prompt, context) {
|
|
3979
|
+
const text = context?.text.trim();
|
|
3980
|
+
return text ? [neutralizeCodexExplicitMentionSigils(text), prompt].filter(Boolean).join("\n\n") : prompt;
|
|
3456
3981
|
}
|
|
3457
|
-
function
|
|
3458
|
-
|
|
3982
|
+
function buildCodexAppServerTimeoutDiagnostics(params) {
|
|
3983
|
+
const readNonBlankDetailString = (key) => {
|
|
3984
|
+
const value = params.details?.[key];
|
|
3985
|
+
return hasNonEmptyString(value) ? value : void 0;
|
|
3986
|
+
};
|
|
3987
|
+
const activeAppServerTurnRequests = asFiniteNumber(params.details?.activeAppServerTurnRequests);
|
|
3988
|
+
const activeTurnItemCount = asFiniteNumber(params.details?.activeTurnItemCount);
|
|
3989
|
+
const terminalTurnNotificationQueued = asBoolean(params.details?.terminalTurnNotificationQueued);
|
|
3990
|
+
const completionIdleWatchArmed = asBoolean(params.details?.completionIdleWatchArmed);
|
|
3991
|
+
const assistantCompletionIdleWatchArmed = asBoolean(params.details?.assistantCompletionIdleWatchArmed);
|
|
3992
|
+
const terminalIdleWatchArmed = asBoolean(params.details?.terminalIdleWatchArmed);
|
|
3993
|
+
return {
|
|
3994
|
+
...params.idleMs !== void 0 ? { idleMs: params.idleMs } : {},
|
|
3995
|
+
...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
|
|
3996
|
+
...params.lastActivityReason ? { lastActivityReason: params.lastActivityReason } : {},
|
|
3997
|
+
...readNonBlankDetailString("lastNotificationMethod") ? { lastNotificationMethod: readNonBlankDetailString("lastNotificationMethod") } : {},
|
|
3998
|
+
...readNonBlankDetailString("lastNotificationItemId") ? { lastNotificationItemId: readNonBlankDetailString("lastNotificationItemId") } : {},
|
|
3999
|
+
...readNonBlankDetailString("lastNotificationItemType") ? { lastNotificationItemType: readNonBlankDetailString("lastNotificationItemType") } : {},
|
|
4000
|
+
...readNonBlankDetailString("lastNotificationItemRole") ? { lastNotificationItemRole: readNonBlankDetailString("lastNotificationItemRole") } : {},
|
|
4001
|
+
...readNonBlankDetailString("lastAssistantTextPreview") ? { lastAssistantTextPreview: readNonBlankDetailString("lastAssistantTextPreview") } : {},
|
|
4002
|
+
...activeAppServerTurnRequests !== void 0 ? { activeAppServerTurnRequests } : {},
|
|
4003
|
+
...activeTurnItemCount !== void 0 ? { activeTurnItemCount } : {},
|
|
4004
|
+
...terminalTurnNotificationQueued !== void 0 ? { terminalTurnNotificationQueued } : {},
|
|
4005
|
+
...completionIdleWatchArmed !== void 0 ? { completionIdleWatchArmed } : {},
|
|
4006
|
+
...assistantCompletionIdleWatchArmed !== void 0 ? { assistantCompletionIdleWatchArmed } : {},
|
|
4007
|
+
...terminalIdleWatchArmed !== void 0 ? { terminalIdleWatchArmed } : {}
|
|
4008
|
+
};
|
|
3459
4009
|
}
|
|
3460
4010
|
//#endregion
|
|
3461
4011
|
//#region extensions/codex/src/app-server/run-attempt-context.ts
|
|
@@ -3527,16 +4077,20 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
3527
4077
|
});
|
|
3528
4078
|
historyState.messages = await readFencedHistory() ?? historyState.messages;
|
|
3529
4079
|
}
|
|
4080
|
+
const memoryToolNames = getCodexWorkspaceMemoryToolNames(toolBridge.availableSpecs);
|
|
3530
4081
|
const workspaceBootstrapContext = await buildCodexWorkspaceBootstrapContext({
|
|
3531
4082
|
params: runtimeParams,
|
|
3532
|
-
resolvedWorkspace,
|
|
4083
|
+
resolvedWorkspace: runtimeParams.bootstrapWorkspaceDir ?? resolvedWorkspace,
|
|
4084
|
+
executionWorkspace: resolvedWorkspace,
|
|
3533
4085
|
effectiveWorkspace,
|
|
3534
4086
|
sessionKey: contextSessionKey,
|
|
3535
4087
|
sessionAgentId,
|
|
3536
|
-
memoryToolNames
|
|
4088
|
+
memoryToolNames,
|
|
4089
|
+
ringZeroActive: isHostScopedAgentToolActive("openclaw") && isSystemAgentOnlyCodexDynamicToolAllowlist(runtimeParams.toolsAllow),
|
|
3537
4090
|
sandboxed: sandbox?.enabled === true
|
|
3538
4091
|
});
|
|
3539
|
-
const
|
|
4092
|
+
const agentWorkspaceDeveloperInstructions = workspaceBootstrapContext.threadDeveloperInstructions ? connection.mutable.startupBinding?.agentWorkspaceDeveloperInstructions ?? workspaceBootstrapContext.threadDeveloperInstructions : void 0;
|
|
4093
|
+
const baseDeveloperInstructions = joinPresentSections(buildDeveloperInstructions(runtimeParams, { dynamicTools: toolBridge.availableSpecs }), agentWorkspaceDeveloperInstructions);
|
|
3540
4094
|
return {
|
|
3541
4095
|
runtime,
|
|
3542
4096
|
attemptTools,
|
|
@@ -3547,6 +4101,7 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
3547
4101
|
hookRunner,
|
|
3548
4102
|
buildActiveContextEngineRuntimeContext,
|
|
3549
4103
|
workspaceBootstrapContext,
|
|
4104
|
+
agentWorkspaceDeveloperInstructions,
|
|
3550
4105
|
baseDeveloperInstructions,
|
|
3551
4106
|
openClawPromptContext: buildCodexOpenClawPromptContext({
|
|
3552
4107
|
params: runtimeParams,
|
|
@@ -3570,11 +4125,16 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
3570
4125
|
contextEngineProjection: void 0,
|
|
3571
4126
|
precomputedStaleBindingContinuityProjectionApplied: false,
|
|
3572
4127
|
staleBindingContinuityForcedFreshStart: false,
|
|
4128
|
+
noEngineContinuityProjectionApplied: false,
|
|
3573
4129
|
inactiveThreadBootstrapBindingForcedFreshStart: initialInactiveThreadBootstrapBindingForcedFreshStart
|
|
3574
4130
|
},
|
|
3575
4131
|
codexContextProjectionMaxChars: resolveCodexContextEngineProjectionMaxChars({
|
|
3576
4132
|
contextTokenBudget: effectiveContextTokenBudget,
|
|
3577
4133
|
reserveTokens: resolveCodexContextEngineProjectionReserveTokens()
|
|
4134
|
+
}),
|
|
4135
|
+
codexContinuityProjectionMaxChars: resolveCodexContinuityProjectionMaxChars({
|
|
4136
|
+
contextTokenBudget: effectiveContextTokenBudget,
|
|
4137
|
+
calibration: connection.mutable.continuityCalibration
|
|
3578
4138
|
})
|
|
3579
4139
|
};
|
|
3580
4140
|
}
|
|
@@ -3785,105 +4345,6 @@ function isInvalidCodexImagePayloadError(message) {
|
|
|
3785
4345
|
return /\b(?:invalid|malformed)\b[\s\S]{0,120}\b(?:image|image url|base64)\b/iu.test(normalizedMessage) || /\b(?:image|image url|base64)\b[\s\S]{0,120}\b(?:invalid|malformed)\b/iu.test(normalizedMessage);
|
|
3786
4346
|
}
|
|
3787
4347
|
//#endregion
|
|
3788
|
-
//#region extensions/codex/src/app-server/run-attempt-state.ts
|
|
3789
|
-
async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity, fields) {
|
|
3790
|
-
const currentBinding = await bindingStore.read(identity);
|
|
3791
|
-
const expectedThreadId = fields.threadId ?? currentBinding?.threadId;
|
|
3792
|
-
if (!expectedThreadId) return;
|
|
3793
|
-
if (currentBinding && currentBinding.threadId !== expectedThreadId) {
|
|
3794
|
-
embeddedAgentLog.warn("codex app-server image payload error detected for unbound thread; preserving thread binding", {
|
|
3795
|
-
...fields,
|
|
3796
|
-
boundThreadId: currentBinding.threadId
|
|
3797
|
-
});
|
|
3798
|
-
return;
|
|
3799
|
-
}
|
|
3800
|
-
if (currentBinding?.connectionScope === "supervision") {
|
|
3801
|
-
embeddedAgentLog.warn("codex app-server image payload error detected for supervised thread; preserving native binding", fields);
|
|
3802
|
-
return;
|
|
3803
|
-
}
|
|
3804
|
-
embeddedAgentLog.warn("codex app-server image payload error detected; clearing thread binding", fields);
|
|
3805
|
-
await bindingStore.mutate(identity, {
|
|
3806
|
-
kind: "clear",
|
|
3807
|
-
threadId: expectedThreadId
|
|
3808
|
-
});
|
|
3809
|
-
}
|
|
3810
|
-
async function markCodexAppServerBindingCoveredThroughTurn(params) {
|
|
3811
|
-
await params.bindingStore.mutate(params.identity, {
|
|
3812
|
-
kind: "patch",
|
|
3813
|
-
threadId: params.threadId,
|
|
3814
|
-
patch: { historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString() }
|
|
3815
|
-
});
|
|
3816
|
-
}
|
|
3817
|
-
function isNonEmptyString(value) {
|
|
3818
|
-
return typeof value === "string" && value.length > 0;
|
|
3819
|
-
}
|
|
3820
|
-
function shouldUseFreshCodexThreadAfterContextEngineOverflow(params) {
|
|
3821
|
-
if (!params.contextEngineActive || params.thread.lifecycle.action !== "resumed") return false;
|
|
3822
|
-
const message = formatErrorMessage(params.error);
|
|
3823
|
-
return /ran out of room in the model'?s context window/iu.test(message) || /context window/iu.test(message) || /context length/iu.test(message) || /maximum context/iu.test(message) || /too many tokens/iu.test(message);
|
|
3824
|
-
}
|
|
3825
|
-
function isCodexActiveCompactTurnError(error) {
|
|
3826
|
-
if (!(error instanceof CodexAppServerRpcError)) return false;
|
|
3827
|
-
const data = isJsonObject(error.data) ? error.data : void 0;
|
|
3828
|
-
const codexErrorInfo = isJsonObject(data?.codexErrorInfo) ? data.codexErrorInfo : void 0;
|
|
3829
|
-
return (isJsonObject(codexErrorInfo?.activeTurnNotSteerable) ? codexErrorInfo.activeTurnNotSteerable : void 0)?.turnKind === "compact";
|
|
3830
|
-
}
|
|
3831
|
-
function readCodexFinalizationHookNotification(notification, threadId, turnId) {
|
|
3832
|
-
if (notification.method !== "hook/started" && notification.method !== "hook/completed") return;
|
|
3833
|
-
const params = isJsonObject(notification.params) ? notification.params : void 0;
|
|
3834
|
-
const run = params && isJsonObject(params.run) ? params.run : void 0;
|
|
3835
|
-
if (params?.threadId !== threadId || params.turnId !== turnId || run?.eventName !== "stop" && run?.eventName !== "subagentStop" || typeof run.id !== "string" || !run.id) return;
|
|
3836
|
-
if (notification.method === "hook/started") return {
|
|
3837
|
-
phase: "started",
|
|
3838
|
-
runId: run.id
|
|
3839
|
-
};
|
|
3840
|
-
return {
|
|
3841
|
-
phase: "completed",
|
|
3842
|
-
runId: run.id,
|
|
3843
|
-
status: typeof run.status === "string" ? run.status : void 0
|
|
3844
|
-
};
|
|
3845
|
-
}
|
|
3846
|
-
function joinPresentSections(...sections) {
|
|
3847
|
-
return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
|
|
3848
|
-
}
|
|
3849
|
-
function prependCurrentInboundContext(prompt, context) {
|
|
3850
|
-
const text = context?.text.trim();
|
|
3851
|
-
return text ? [neutralizeCodexExplicitMentionSigils(text), prompt].filter(Boolean).join("\n\n") : prompt;
|
|
3852
|
-
}
|
|
3853
|
-
function waitForCodexNotificationDispatchTurn() {
|
|
3854
|
-
return new Promise((resolve) => {
|
|
3855
|
-
setImmediate(resolve);
|
|
3856
|
-
});
|
|
3857
|
-
}
|
|
3858
|
-
function buildCodexAppServerTimeoutDiagnostics(params) {
|
|
3859
|
-
const readNonBlankDetailString = (key) => {
|
|
3860
|
-
const value = params.details?.[key];
|
|
3861
|
-
return hasNonEmptyString(value) ? value : void 0;
|
|
3862
|
-
};
|
|
3863
|
-
const activeAppServerTurnRequests = asFiniteNumber(params.details?.activeAppServerTurnRequests);
|
|
3864
|
-
const activeTurnItemCount = asFiniteNumber(params.details?.activeTurnItemCount);
|
|
3865
|
-
const terminalTurnNotificationQueued = asBoolean(params.details?.terminalTurnNotificationQueued);
|
|
3866
|
-
const completionIdleWatchArmed = asBoolean(params.details?.completionIdleWatchArmed);
|
|
3867
|
-
const assistantCompletionIdleWatchArmed = asBoolean(params.details?.assistantCompletionIdleWatchArmed);
|
|
3868
|
-
const terminalIdleWatchArmed = asBoolean(params.details?.terminalIdleWatchArmed);
|
|
3869
|
-
return {
|
|
3870
|
-
...params.idleMs !== void 0 ? { idleMs: params.idleMs } : {},
|
|
3871
|
-
...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
|
|
3872
|
-
...params.lastActivityReason ? { lastActivityReason: params.lastActivityReason } : {},
|
|
3873
|
-
...readNonBlankDetailString("lastNotificationMethod") ? { lastNotificationMethod: readNonBlankDetailString("lastNotificationMethod") } : {},
|
|
3874
|
-
...readNonBlankDetailString("lastNotificationItemId") ? { lastNotificationItemId: readNonBlankDetailString("lastNotificationItemId") } : {},
|
|
3875
|
-
...readNonBlankDetailString("lastNotificationItemType") ? { lastNotificationItemType: readNonBlankDetailString("lastNotificationItemType") } : {},
|
|
3876
|
-
...readNonBlankDetailString("lastNotificationItemRole") ? { lastNotificationItemRole: readNonBlankDetailString("lastNotificationItemRole") } : {},
|
|
3877
|
-
...readNonBlankDetailString("lastAssistantTextPreview") ? { lastAssistantTextPreview: readNonBlankDetailString("lastAssistantTextPreview") } : {},
|
|
3878
|
-
...activeAppServerTurnRequests !== void 0 ? { activeAppServerTurnRequests } : {},
|
|
3879
|
-
...activeTurnItemCount !== void 0 ? { activeTurnItemCount } : {},
|
|
3880
|
-
...terminalTurnNotificationQueued !== void 0 ? { terminalTurnNotificationQueued } : {},
|
|
3881
|
-
...completionIdleWatchArmed !== void 0 ? { completionIdleWatchArmed } : {},
|
|
3882
|
-
...assistantCompletionIdleWatchArmed !== void 0 ? { assistantCompletionIdleWatchArmed } : {},
|
|
3883
|
-
...terminalIdleWatchArmed !== void 0 ? { terminalIdleWatchArmed } : {}
|
|
3884
|
-
};
|
|
3885
|
-
}
|
|
3886
|
-
//#endregion
|
|
3887
4348
|
//#region extensions/codex/src/app-server/settled-turn-context.ts
|
|
3888
4349
|
function collectUniqueMessageIdentities(messages) {
|
|
3889
4350
|
const identities = /* @__PURE__ */ new Map();
|
|
@@ -3973,100 +4434,13 @@ async function captureCodexSettledTurnFinalizationContext(params) {
|
|
|
3973
4434
|
}
|
|
3974
4435
|
//#endregion
|
|
3975
4436
|
//#region extensions/codex/src/app-server/trajectory.ts
|
|
3976
|
-
|
|
3977
|
-
const PRIVATE_PAYLOAD_FIELD_RE = /(?:image|screenshot|attachment|fileData|dataUri)/iu;
|
|
3978
|
-
const AUTHORIZATION_VALUE_RE = /\b(Bearer|Basic)\s+[A-Za-z0-9+/._~=-]{8,}/giu;
|
|
3979
|
-
const JWT_VALUE_RE = /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/gu;
|
|
3980
|
-
const COOKIE_PAIR_RE = /\b([A-Za-z][A-Za-z0-9_.-]{1,64})=([A-Za-z0-9+/._~%=-]{16,})(?=;|\s|$)/gu;
|
|
3981
|
-
const TRAJECTORY_RUNTIME_EVENT_MAX_BYTES = 256 * 1024;
|
|
3982
|
-
const TRAJECTORY_RUNTIME_OVERSIZE_PRESERVED_DATA_KEYS = ["usage", "promptCache"];
|
|
3983
|
-
function boundedTrajectoryEvent(event) {
|
|
3984
|
-
const line = JSON.stringify(event);
|
|
3985
|
-
const bytes = Buffer.byteLength(line, "utf8");
|
|
3986
|
-
if (bytes <= TRAJECTORY_RUNTIME_EVENT_MAX_BYTES) return event;
|
|
3987
|
-
const originalData = event.data && typeof event.data === "object" && !Array.isArray(event.data) ? event.data : {};
|
|
3988
|
-
const originalDataKeys = Object.keys(originalData);
|
|
3989
|
-
const preservedDataKeys = /* @__PURE__ */ new Set();
|
|
3990
|
-
const baseData = {
|
|
3991
|
-
truncated: true,
|
|
3992
|
-
originalBytes: bytes,
|
|
3993
|
-
limitBytes: TRAJECTORY_RUNTIME_EVENT_MAX_BYTES,
|
|
3994
|
-
reason: "trajectory-event-size-limit"
|
|
3995
|
-
};
|
|
3996
|
-
const buildTruncatedEvent = (includeDroppedFields) => {
|
|
3997
|
-
const data = { ...baseData };
|
|
3998
|
-
for (const key of TRAJECTORY_RUNTIME_OVERSIZE_PRESERVED_DATA_KEYS) if (preservedDataKeys.has(key)) data[key] = originalData[key];
|
|
3999
|
-
if (includeDroppedFields) {
|
|
4000
|
-
const droppedFields = originalDataKeys.filter((key) => !preservedDataKeys.has(key));
|
|
4001
|
-
if (droppedFields.length > 0) data.droppedFields = droppedFields;
|
|
4002
|
-
}
|
|
4003
|
-
const truncatedEvent = {
|
|
4004
|
-
...event,
|
|
4005
|
-
data
|
|
4006
|
-
};
|
|
4007
|
-
const truncated = JSON.stringify(truncatedEvent);
|
|
4008
|
-
if (Buffer.byteLength(truncated, "utf8") <= TRAJECTORY_RUNTIME_EVENT_MAX_BYTES) return truncatedEvent;
|
|
4009
|
-
};
|
|
4010
|
-
let best = buildTruncatedEvent(true) ?? buildTruncatedEvent(false);
|
|
4011
|
-
if (!best) return;
|
|
4012
|
-
for (const key of TRAJECTORY_RUNTIME_OVERSIZE_PRESERVED_DATA_KEYS) {
|
|
4013
|
-
if (!Object.hasOwn(originalData, key)) continue;
|
|
4014
|
-
preservedDataKeys.add(key);
|
|
4015
|
-
const next = buildTruncatedEvent(true) ?? buildTruncatedEvent(false);
|
|
4016
|
-
if (next) {
|
|
4017
|
-
best = next;
|
|
4018
|
-
continue;
|
|
4019
|
-
}
|
|
4020
|
-
preservedDataKeys.delete(key);
|
|
4021
|
-
}
|
|
4022
|
-
return best;
|
|
4023
|
-
}
|
|
4024
|
-
function createCodexHostTrajectorySink(params) {
|
|
4025
|
-
return {
|
|
4026
|
-
write: (event) => {
|
|
4027
|
-
params.recorder.recordEvent(event.type, event.data);
|
|
4028
|
-
},
|
|
4029
|
-
flush: async () => {
|
|
4030
|
-
await params.recorder.flush();
|
|
4031
|
-
}
|
|
4032
|
-
};
|
|
4033
|
-
}
|
|
4034
|
-
/** Creates a trajectory recorder when trajectory capture is enabled for the environment. */
|
|
4437
|
+
/** Creates a trajectory recorder when the host exposes its capture capability. */
|
|
4035
4438
|
function createCodexTrajectoryRecorder(params) {
|
|
4036
|
-
if (!
|
|
4037
|
-
|
|
4038
|
-
params.warn?.("codex trajectory capture requires the SQLite host recorder", {
|
|
4039
|
-
sessionId: params.attempt.sessionId,
|
|
4040
|
-
reason: "sqlite-recorder-unavailable"
|
|
4041
|
-
});
|
|
4042
|
-
return null;
|
|
4043
|
-
}
|
|
4044
|
-
const sink = createCodexHostTrajectorySink({ recorder: params.trajectoryRecorder });
|
|
4045
|
-
let seq = 0;
|
|
4046
|
-
const attribution = resolveCodexLocalRuntimeAttribution(params.attempt);
|
|
4439
|
+
if (!params.trajectory) return null;
|
|
4440
|
+
const trajectory = params.trajectory;
|
|
4047
4441
|
return {
|
|
4048
|
-
recordEvent:
|
|
4049
|
-
|
|
4050
|
-
traceSchema: "openclaw-trajectory",
|
|
4051
|
-
schemaVersion: 1,
|
|
4052
|
-
traceId: params.attempt.sessionId,
|
|
4053
|
-
source: "runtime",
|
|
4054
|
-
type,
|
|
4055
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4056
|
-
seq: seq += 1,
|
|
4057
|
-
sourceSeq: seq,
|
|
4058
|
-
sessionId: params.attempt.sessionId,
|
|
4059
|
-
sessionKey: params.attempt.sessionKey,
|
|
4060
|
-
runId: params.attempt.runId,
|
|
4061
|
-
workspaceDir: params.cwd,
|
|
4062
|
-
provider: attribution.provider,
|
|
4063
|
-
modelId: params.attempt.modelId,
|
|
4064
|
-
modelApi: attribution.api,
|
|
4065
|
-
data: data ? sanitizeValue(data) : void 0
|
|
4066
|
-
});
|
|
4067
|
-
if (event) sink.write(event);
|
|
4068
|
-
},
|
|
4069
|
-
flush: sink.flush
|
|
4442
|
+
recordEvent: trajectory.recordEvent,
|
|
4443
|
+
flush: trajectory.flush
|
|
4070
4444
|
};
|
|
4071
4445
|
}
|
|
4072
4446
|
/** Records compiled prompt/tool context at the start of a Codex runtime attempt. */
|
|
@@ -4095,12 +4469,6 @@ function recordCodexTrajectoryCompletion(recorder, params) {
|
|
|
4095
4469
|
messagesSnapshot: params.result.messagesSnapshot
|
|
4096
4470
|
});
|
|
4097
4471
|
}
|
|
4098
|
-
function parseTrajectoryEnabled(env) {
|
|
4099
|
-
const value = env.OPENCLAW_TRAJECTORY?.trim().toLowerCase();
|
|
4100
|
-
if (value === "1" || value === "true" || value === "yes" || value === "on") return true;
|
|
4101
|
-
if (value === "0" || value === "false" || value === "no" || value === "off") return false;
|
|
4102
|
-
return true;
|
|
4103
|
-
}
|
|
4104
4472
|
function toTrajectoryToolDefinitions(tools) {
|
|
4105
4473
|
if (!tools || tools.length === 0) return;
|
|
4106
4474
|
return flattenCodexDynamicToolFunctions(tools).flatMap((tool) => {
|
|
@@ -4109,31 +4477,10 @@ function toTrajectoryToolDefinitions(tools) {
|
|
|
4109
4477
|
return [{
|
|
4110
4478
|
name,
|
|
4111
4479
|
description: tool.description,
|
|
4112
|
-
parameters:
|
|
4480
|
+
parameters: tool.inputSchema
|
|
4113
4481
|
}];
|
|
4114
4482
|
}).toSorted((left, right) => left.name.localeCompare(right.name));
|
|
4115
4483
|
}
|
|
4116
|
-
function sanitizeValue(value, depth = 0, key = "") {
|
|
4117
|
-
if (value == null || typeof value === "boolean" || typeof value === "number") return value;
|
|
4118
|
-
if (typeof value === "string") {
|
|
4119
|
-
if (SENSITIVE_FIELD_RE.test(key)) return "<redacted>";
|
|
4120
|
-
if (value.startsWith("data:") && value.length > 256) return `<redacted data-uri ${value.slice(0, value.indexOf(",")).length} chars>`;
|
|
4121
|
-
if (PRIVATE_PAYLOAD_FIELD_RE.test(key) && value.length > 256) return "<redacted payload>";
|
|
4122
|
-
const redacted = redactSensitiveString(value);
|
|
4123
|
-
return redacted.length > 2e4 ? `${truncateUtf16Safe(redacted, 2e4)}…` : redacted;
|
|
4124
|
-
}
|
|
4125
|
-
if (depth >= 6) return "<truncated>";
|
|
4126
|
-
if (Array.isArray(value)) return value.slice(0, 100).map((entry) => sanitizeValue(entry, depth + 1, key));
|
|
4127
|
-
if (typeof value === "object") {
|
|
4128
|
-
const next = {};
|
|
4129
|
-
for (const [keyLocal, child] of Object.entries(value).slice(0, 100)) next[keyLocal] = sanitizeValue(child, depth + 1, keyLocal);
|
|
4130
|
-
return next;
|
|
4131
|
-
}
|
|
4132
|
-
return JSON.stringify(value);
|
|
4133
|
-
}
|
|
4134
|
-
function redactSensitiveString(value) {
|
|
4135
|
-
return value.replace(AUTHORIZATION_VALUE_RE, "$1 <redacted>").replace(JWT_VALUE_RE, "<redacted-jwt>").replace(COOKIE_PAIR_RE, "$1=<redacted>");
|
|
4136
|
-
}
|
|
4137
4484
|
/** Converts arbitrary prompt errors into trajectory-safe text. */
|
|
4138
4485
|
function normalizeCodexTrajectoryError(value) {
|
|
4139
4486
|
if (!value) return null;
|
|
@@ -4186,9 +4533,9 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4186
4533
|
const projectedTerminal = attemptTerminal.project(result.terminal);
|
|
4187
4534
|
const effectiveTimedOut = state.timedOut && !recoveredTurnWatchTimeout;
|
|
4188
4535
|
const effectiveTurnCompletionIdleTimedOut = state.turnCompletionIdleTimedOut && !recoveredTurnWatchTimeout;
|
|
4189
|
-
const isFinalAborted = () =>
|
|
4536
|
+
const isFinalAborted = () => terminalState.explicitCancellationObserved || !resourceState.executionDisconnectError && (projectedTerminal.aborted || runAbortController.signal.aborted && !state.clientClosedAbort && !recoveredTurnWatchTimeout);
|
|
4190
4537
|
const clientClosedPromptErrorForFinal = state.clientClosedPromptError && hasRecoverableCompletedAssistant ? void 0 : state.clientClosedPromptError;
|
|
4191
|
-
let finalPromptError = clientClosedPromptErrorForFinal ?? (effectiveTurnCompletionIdleTimedOut ? state.turnCompletionIdleTimeoutMessage : effectiveTimedOut ? "codex app-server attempt timed out" : projectedTerminal.promptError);
|
|
4538
|
+
let finalPromptError = resourceState.executionDisconnectError ?? clientClosedPromptErrorForFinal ?? (effectiveTurnCompletionIdleTimedOut ? state.turnCompletionIdleTimeoutMessage : effectiveTimedOut ? "codex app-server attempt timed out" : projectedTerminal.promptError);
|
|
4192
4539
|
const finalPromptErrorMessage = typeof finalPromptError === "string" ? finalPromptError : finalPromptError instanceof Error ? finalPromptError.message : finalPromptError ? formatErrorMessage(finalPromptError) : void 0;
|
|
4193
4540
|
if (isInvalidCodexImagePayloadError(finalPromptErrorMessage)) await clearCodexBindingAfterInvalidImagePayload(bindingStore, bindingIdentity, {
|
|
4194
4541
|
phase: "turn_completed",
|
|
@@ -4229,6 +4576,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4229
4576
|
authProfileId: startupAuthProfileId,
|
|
4230
4577
|
rateLimits: readRecentCodexRateLimits(resourceState.client)
|
|
4231
4578
|
});
|
|
4579
|
+
finalPromptError = resourceState.executionDisconnectError ?? finalPromptError;
|
|
4232
4580
|
const finalPromptErrorSource = effectiveTimedOut || clientClosedPromptErrorForFinal ? "prompt" : projectedTerminal.promptErrorSource;
|
|
4233
4581
|
const codexAppServerFailureKind = clientClosedPromptErrorForFinal ? "client_closed_before_turn_completed" : effectiveTurnCompletionIdleTimedOut ? "turn_completion_idle_timeout" : void 0;
|
|
4234
4582
|
const replayBlockedReason = codexAppServerFailureKind ? resolveCodexAppServerReplayBlockedReason(result) : void 0;
|
|
@@ -4354,7 +4702,11 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4354
4702
|
await markCodexAppServerBindingCoveredThroughTurn({
|
|
4355
4703
|
bindingStore,
|
|
4356
4704
|
identity: bindingIdentity,
|
|
4357
|
-
threadId: resourceState.thread.threadId
|
|
4705
|
+
threadId: resourceState.thread.threadId,
|
|
4706
|
+
continuityCalibration: context.promptState.noEngineContinuityProjectionApplied ? buildCodexContinuityCalibration({
|
|
4707
|
+
promptChars: prompt.turnState.codexTurnPromptText.length,
|
|
4708
|
+
inputTokens: (result.attemptUsage?.input ?? 0) + (result.attemptUsage?.cacheRead ?? 0) + (result.attemptUsage?.cacheWrite ?? 0)
|
|
4709
|
+
}) : void 0
|
|
4358
4710
|
});
|
|
4359
4711
|
} catch (error) {
|
|
4360
4712
|
if (resourceState.thread.connectionScope === "supervision") throw error;
|
|
@@ -4407,6 +4759,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4407
4759
|
});
|
|
4408
4760
|
const finalizedResult = {
|
|
4409
4761
|
...result,
|
|
4762
|
+
...toolState.yieldAcknowledgment ? { yieldAcknowledgment: toolState.yieldAcknowledgment } : {},
|
|
4410
4763
|
terminal: attemptTerminal.normalize({
|
|
4411
4764
|
timedOut: effectiveTimedOut,
|
|
4412
4765
|
aborted: finalAborted,
|
|
@@ -4420,6 +4773,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4420
4773
|
...terminalAnchor ? { contextEngineTerminalAnchor: terminalAnchor } : {},
|
|
4421
4774
|
...settledTurnFinalizationContext ? { settledTurnFinalizationContext } : {},
|
|
4422
4775
|
...resourceState.runtimeArtifact ? { runtimeArtifact: resourceState.runtimeArtifact } : {},
|
|
4776
|
+
...resourceState.runtimeContinuationStarted ? { runtimeContinuationStarted: true } : {},
|
|
4423
4777
|
...!finalAborted && !effectiveTimedOut && !finalPromptError && preparedAuthBinding ? { authBindingFingerprint: preparedAuthBinding.fingerprint } : {},
|
|
4424
4778
|
systemPromptReport
|
|
4425
4779
|
};
|
|
@@ -4764,7 +5118,7 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
4764
5118
|
state.turnCrossedToolHandoff = notificationState.turnCrossedToolHandoff;
|
|
4765
5119
|
if (notificationState.isCurrentTurnNotification && notification.method === "item/completed") {
|
|
4766
5120
|
const item = readCodexNotificationItem(notification.params);
|
|
4767
|
-
if (item?.type === "userMessage" && typeof item.clientId === "string") steeringQueue?.confirmConsumed(item.clientId);
|
|
5121
|
+
if (item?.type === "userMessage" && typeof item.clientId === "string") await steeringQueue?.confirmConsumed(item.clientId);
|
|
4768
5122
|
}
|
|
4769
5123
|
if (notificationState.isTurnAbortMarker) state.sawCodexInterruptMarker = true;
|
|
4770
5124
|
const hookNotification = readCodexFinalizationHookNotification(notification, resourceState.thread.threadId, turnId);
|
|
@@ -4775,7 +5129,6 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
4775
5129
|
}
|
|
4776
5130
|
if (notificationState.isTurnTerminal) state.terminalTurnNotificationQueued = true;
|
|
4777
5131
|
try {
|
|
4778
|
-
await waitForCodexNotificationDispatchTurn();
|
|
4779
5132
|
await projector.handleNotification(notification);
|
|
4780
5133
|
const canRelease = isAssistantCompletionReleaseNotification(notification, state.turnCrossedToolHandoff) || notificationState.isCurrentTurnNotification && state.turnCrossedToolHandoff && notification.method === "rawResponseItem/completed" && projector.canReleaseLatestTerminalAssistantAfterToolHandoff();
|
|
4781
5134
|
if (notificationState.isCurrentTurnNotification && canRelease) {
|
|
@@ -4871,11 +5224,12 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
4871
5224
|
}
|
|
4872
5225
|
//#endregion
|
|
4873
5226
|
//#region extensions/codex/src/app-server/run-attempt-prompt.ts
|
|
5227
|
+
const CODEX_META_KEY = "__openclaw";
|
|
4874
5228
|
function isRestrictivePromptToolsAllow(toolsAllow) {
|
|
4875
5229
|
return toolsAllow !== void 0 && !toolsAllow.some((name) => name.trim() === "*");
|
|
4876
5230
|
}
|
|
4877
5231
|
async function prepareCodexAttemptPrompt(context) {
|
|
4878
|
-
const { runtime, attemptTools, historyState, hookContext, workspaceBootstrapContext, buildActiveContextEngineRuntimeContext, baseDeveloperInstructions, openClawPromptContext, skillsCollaborationInstructions, promptState, codexContextProjectionMaxChars } = context;
|
|
5232
|
+
const { runtime, attemptTools, historyState, hookContext, workspaceBootstrapContext, buildActiveContextEngineRuntimeContext, baseDeveloperInstructions, openClawPromptContext, skillsCollaborationInstructions, promptState, codexContextProjectionMaxChars, codexContinuityProjectionMaxChars } = context;
|
|
4879
5233
|
const { connection, buildActiveRunAttemptParams, effectiveContextTokenBudget, effectiveRuntimeModelId, effectiveRuntimeProviderId } = runtime;
|
|
4880
5234
|
const { params, activeContextEngine, usesSupervisionConnection, mutable, isInactiveThreadBootstrapBinding, bindingStore, bindingIdentity, agentDir, appServer, contextSessionKey, effectiveWorkspace, sandbox } = connection;
|
|
4881
5235
|
const { toolBridge } = attemptTools;
|
|
@@ -4884,11 +5238,12 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4884
5238
|
assembledMessages: historyState.messages,
|
|
4885
5239
|
originalHistoryMessages: historyState.messages,
|
|
4886
5240
|
prompt: params.prompt,
|
|
4887
|
-
maxRenderedContextChars:
|
|
5241
|
+
maxRenderedContextChars: codexContinuityProjectionMaxChars
|
|
4888
5242
|
});
|
|
4889
5243
|
promptState.promptText = projection.promptText;
|
|
4890
5244
|
promptState.promptContextRange = projection.promptContextRange;
|
|
4891
5245
|
promptState.prePromptMessageCount = projection.prePromptMessageCount;
|
|
5246
|
+
promptState.noEngineContinuityProjectionApplied = true;
|
|
4892
5247
|
};
|
|
4893
5248
|
const applyActiveContextEngineProjection = async (decisionStartupBinding) => {
|
|
4894
5249
|
if (!activeContextEngine) return;
|
|
@@ -4962,15 +5317,21 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4962
5317
|
}
|
|
4963
5318
|
const codexModelInputHistoryMessages = [];
|
|
4964
5319
|
const buildPromptFromCurrentInputs = async () => {
|
|
4965
|
-
|
|
5320
|
+
return await resolveAgentHarnessBeforePromptBuildResult({
|
|
4966
5321
|
prompt: prependCurrentInboundContext(promptState.promptText, params.currentInboundContext),
|
|
4967
|
-
developerInstructions:
|
|
5322
|
+
developerInstructions: { build: ({ toolsAllow }) => {
|
|
5323
|
+
if (isRestrictivePromptToolsAllow(toolsAllow)) throw new Error("Codex app-server cannot enforce before_prompt_build toolsAllow; use the embedded or Copilot runtime for turn-scoped tool policy.");
|
|
5324
|
+
return promptState.developerInstructions;
|
|
5325
|
+
} },
|
|
4968
5326
|
messages: structuredClone(historyState.messages),
|
|
4969
5327
|
ctx: hookContext,
|
|
4970
|
-
bootstrapContextRunKind: params.bootstrapContextRunKind
|
|
5328
|
+
bootstrapContextRunKind: params.bootstrapContextRunKind,
|
|
5329
|
+
toolAuthority: {
|
|
5330
|
+
fingerprint: params.toolAuthorityFingerprint,
|
|
5331
|
+
activeToolNames: () => flattenCodexDynamicToolFunctions(toolBridge.availableSpecs).map((tool) => tool.name).filter(isNonEmptyString),
|
|
5332
|
+
assertActive: params.hostCapabilities.assertActive
|
|
5333
|
+
}
|
|
4971
5334
|
});
|
|
4972
|
-
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.");
|
|
4973
|
-
return result;
|
|
4974
5335
|
};
|
|
4975
5336
|
const resolveShiftedPromptInputRange = (prompt, promptInputRange, turnPromptText) => {
|
|
4976
5337
|
if (!promptInputRange || promptInputRange.start < 0 || promptInputRange.end < promptInputRange.start || promptInputRange.end > prompt.length || !turnPromptText.endsWith(prompt)) return;
|
|
@@ -5040,12 +5401,11 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
5040
5401
|
const cutoff = Date.parse(binding.historyCoveredThrough ?? "");
|
|
5041
5402
|
return historyState.messages.filter((message) => {
|
|
5042
5403
|
if (message.role !== "user" && message.role !== "assistant") return false;
|
|
5043
|
-
const
|
|
5044
|
-
const meta = record["__openclaw"];
|
|
5404
|
+
const meta = CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0;
|
|
5045
5405
|
const mirrorIdentity = meta && typeof meta === "object" && !Array.isArray(meta) ? meta.mirrorIdentity : void 0;
|
|
5046
5406
|
const mirrorOrigin = meta && typeof meta === "object" && !Array.isArray(meta) ? meta.mirrorOrigin : void 0;
|
|
5047
5407
|
const timestamp = typeof message.timestamp === "number" ? message.timestamp : typeof message.timestamp === "string" ? Date.parse(message.timestamp) : NaN;
|
|
5048
|
-
return !(typeof
|
|
5408
|
+
return !("idempotencyKey" in message && typeof message.idempotencyKey === "string" && message.idempotencyKey.startsWith("codex-app-server:")) && mirrorOrigin !== "codex-app-server" && !(typeof mirrorIdentity === "string" && mirrorIdentity.startsWith("codex-app-server:")) && Number.isFinite(timestamp) && timestamp > (Number.isFinite(cutoff) ? cutoff : 0);
|
|
5049
5409
|
});
|
|
5050
5410
|
};
|
|
5051
5411
|
const applyResumeStaleBindingContinuityProjection = (binding) => {
|
|
@@ -5055,11 +5415,12 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
5055
5415
|
assembledMessages: newerVisibleMessages,
|
|
5056
5416
|
originalHistoryMessages: historyState.messages,
|
|
5057
5417
|
prompt: params.prompt,
|
|
5058
|
-
maxRenderedContextChars:
|
|
5418
|
+
maxRenderedContextChars: codexContinuityProjectionMaxChars
|
|
5059
5419
|
});
|
|
5060
5420
|
promptState.promptText = projection.promptText;
|
|
5061
5421
|
promptState.promptContextRange = projection.promptContextRange;
|
|
5062
5422
|
promptState.prePromptMessageCount = projection.prePromptMessageCount;
|
|
5423
|
+
promptState.noEngineContinuityProjectionApplied = true;
|
|
5063
5424
|
return true;
|
|
5064
5425
|
};
|
|
5065
5426
|
const precomputeNoContextEngineStaleBindingProjection = () => {
|
|
@@ -5171,15 +5532,13 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5171
5532
|
const { connection, hookChannelId } = runtime;
|
|
5172
5533
|
const { appServer, params, effectiveCwd, sessionAgentId, sandboxSessionKey, runAbortController, sandbox, options, nativeHookRelayEvents } = connection;
|
|
5173
5534
|
const { toolBridge } = attemptTools;
|
|
5174
|
-
const hostTrajectoryRecorder = params.trajectoryRecorder;
|
|
5175
5535
|
const trajectoryRecorder = createCodexTrajectoryRecorder({
|
|
5176
5536
|
attempt: params,
|
|
5177
5537
|
cwd: effectiveCwd,
|
|
5178
5538
|
developerInstructions: buildRenderedCodexDeveloperInstructions(),
|
|
5179
5539
|
prompt: turnState.codexTurnPromptText,
|
|
5180
|
-
|
|
5181
|
-
tools: toolBridge.availableSpecs
|
|
5182
|
-
warn: (message, fields) => embeddedAgentLog.warn(message, fields)
|
|
5540
|
+
trajectory: params.hostCapabilities.trajectory,
|
|
5541
|
+
tools: toolBridge.availableSpecs
|
|
5183
5542
|
});
|
|
5184
5543
|
const state = {
|
|
5185
5544
|
client: void 0,
|
|
@@ -5192,12 +5551,14 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5192
5551
|
trajectoryEndRecorded: false,
|
|
5193
5552
|
nativeHookRelay: void 0,
|
|
5194
5553
|
nativeSubagentMonitor: void 0,
|
|
5554
|
+
runtimeContinuationStarted: false,
|
|
5195
5555
|
nativePreToolUseFailureFallbackActive: false,
|
|
5196
5556
|
nativePreToolUseFailureFallbackTerminalReason: void 0,
|
|
5197
5557
|
releaseSharedClientLease: void 0,
|
|
5198
5558
|
startupClientUnsafe: false,
|
|
5199
5559
|
sharedCodexClientRetiredForOneShotCleanup: false,
|
|
5200
|
-
|
|
5560
|
+
sandboxExecEnvironment: void 0,
|
|
5561
|
+
executionDisconnectError: void 0,
|
|
5201
5562
|
codexEnvironmentSelection: void 0,
|
|
5202
5563
|
codexExecutionCwd: effectiveCwd,
|
|
5203
5564
|
codexSandboxPolicy: void 0,
|
|
@@ -5236,7 +5597,7 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5236
5597
|
if (params.cleanupBundleMcpOnRunEnd !== true || state.sharedCodexClientRetiredForOneShotCleanup) return;
|
|
5237
5598
|
state.sharedCodexClientRetiredForOneShotCleanup = true;
|
|
5238
5599
|
const retired = clearSharedCodexAppServerClientIfCurrentAndUnclaimed(state.client);
|
|
5239
|
-
embeddedAgentLog.
|
|
5600
|
+
embeddedAgentLog.debug("codex app-server one-shot cleanup checked shared client retirement", {
|
|
5240
5601
|
runId: params.runId,
|
|
5241
5602
|
sessionId: params.sessionId,
|
|
5242
5603
|
sessionKey: params.sessionKey,
|
|
@@ -5250,16 +5611,27 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5250
5611
|
forceKillDelayMs: 250
|
|
5251
5612
|
});
|
|
5252
5613
|
};
|
|
5614
|
+
const releaseSandboxExecEnvironment = async () => {
|
|
5615
|
+
if (state.sandboxExecEnvironment) {
|
|
5616
|
+
const environment = state.sandboxExecEnvironment;
|
|
5617
|
+
state.sandboxExecEnvironment = void 0;
|
|
5618
|
+
await releaseCodexSandboxExecServerEnvironment(sandbox, environment);
|
|
5619
|
+
}
|
|
5620
|
+
};
|
|
5253
5621
|
const releaseSharedClientLeaseAndRetireOneShotClient = async () => {
|
|
5622
|
+
if (connection.attemptClientFactory === createIsolatedCodexAppServerClient) {
|
|
5623
|
+
await releaseSandboxExecEnvironment();
|
|
5624
|
+
const ownedClient = state.releaseSharedClientLease ? state.client : void 0;
|
|
5625
|
+
releaseSharedClientLeaseOnce();
|
|
5626
|
+
await ownedClient?.closeAndWait({
|
|
5627
|
+
exitTimeoutMs: 2e3,
|
|
5628
|
+
forceKillDelayMs: 250
|
|
5629
|
+
});
|
|
5630
|
+
return;
|
|
5631
|
+
}
|
|
5254
5632
|
releaseSharedClientLeaseOnce();
|
|
5255
5633
|
await retireSharedCodexClientForOneShotCleanup();
|
|
5256
5634
|
};
|
|
5257
|
-
const releaseSandboxExecEnvironment = async () => {
|
|
5258
|
-
if (state.sandboxExecEnvironmentAcquired) {
|
|
5259
|
-
state.sandboxExecEnvironmentAcquired = false;
|
|
5260
|
-
await releaseCodexSandboxExecServerEnvironment(sandbox);
|
|
5261
|
-
}
|
|
5262
|
-
};
|
|
5263
5635
|
const runCleanupStep = (step, operation) => runAgentCleanupStep({
|
|
5264
5636
|
runId: params.runId,
|
|
5265
5637
|
sessionId: params.sessionId,
|
|
@@ -5284,7 +5656,10 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5284
5656
|
retainClient: () => retainSharedCodexAppServerClientIfCurrent(state.client),
|
|
5285
5657
|
retainParentThread: (protectedThreadId) => protectCodexAppServerLiveThread(state.client, protectedThreadId),
|
|
5286
5658
|
claimDirectChild: (childThreadId) => state.nativeHookRelay?.claimDirectChild(childThreadId),
|
|
5287
|
-
rejectPendingDirectChild: (childThreadId, reason) => state.nativeHookRelay?.rejectPendingDirectChild(childThreadId, reason)
|
|
5659
|
+
rejectPendingDirectChild: (childThreadId, reason) => state.nativeHookRelay?.rejectPendingDirectChild(childThreadId, reason),
|
|
5660
|
+
...params.sessionKey && params.agentHarnessTaskRuntimeScope ? { onDirectChildAccepted: () => {
|
|
5661
|
+
state.runtimeContinuationStarted = true;
|
|
5662
|
+
} } : {}
|
|
5288
5663
|
});
|
|
5289
5664
|
};
|
|
5290
5665
|
const releaseCurrentRoute = () => {
|
|
@@ -5347,8 +5722,7 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5347
5722
|
configPatch: state.nativeHookRelay ? buildCodexNativeHookRelayConfig({
|
|
5348
5723
|
relay: state.nativeHookRelay,
|
|
5349
5724
|
events: nativeHookRelayEvents,
|
|
5350
|
-
hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec
|
|
5351
|
-
loopDetectionPreToolUseRelay: appServer.loopDetectionPreToolUseRelay
|
|
5725
|
+
hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec
|
|
5352
5726
|
}) : options.nativeHookRelay?.enabled === false ? buildCodexNativeHookRelayDisabledConfig() : void 0,
|
|
5353
5727
|
nativeHookRelayGeneration: state.nativeHookRelay?.generation
|
|
5354
5728
|
};
|
|
@@ -5783,8 +6157,8 @@ async function prepareCodexAttemptRuntime(connection) {
|
|
|
5783
6157
|
const effectiveContextWindowInfo = usesSupervisionConnection ? void 0 : params.contextWindowInfo;
|
|
5784
6158
|
const effectiveContextTokenBudget = usesSupervisionConnection ? void 0 : params.contextTokenBudget;
|
|
5785
6159
|
const effectiveRuntimeProviderId = usesSupervisionConnection ? mutable.startupBinding?.modelProvider ?? "codex" : params.provider;
|
|
5786
|
-
const effectiveRuntimeModelId = usesSupervisionConnection ? mutable.startupBinding?.model ?? "codex-native" : params.modelId;
|
|
5787
|
-
const { authProfileId: _outerAuthProfileId, contextWindowInfo: _outerContextWindowInfo, contextTokenBudget: _outerContextTokenBudget, model: _outerModel, modelId: _outerModelId, provider: _outerProvider, runtimePlan: _outerRuntimePlan, requestedModelId: _outerRequestedModelId, fallbackReason: _outerFallbackReason, degradedReason: _outerDegradedReason, thinkLevel: _outerThinkLevel, fastMode: _outerFastMode, ...paramsWithoutOuterNativeOwnership } = params;
|
|
6160
|
+
const effectiveRuntimeModelId = usesSupervisionConnection ? mutable.startupBinding?.model ?? "codex-native" : connection.options.runtimeModelId ?? params.modelId;
|
|
6161
|
+
const { authProfileId: _outerAuthProfileId, authoredContextTokenCap: _outerAuthoredContextTokenCap, contextWindowInfo: _outerContextWindowInfo, contextTokenBudget: _outerContextTokenBudget, model: _outerModel, modelId: _outerModelId, provider: _outerProvider, runtimePlan: _outerRuntimePlan, requestedModelId: _outerRequestedModelId, fallbackReason: _outerFallbackReason, degradedReason: _outerDegradedReason, thinkLevel: _outerThinkLevel, fastMode: _outerFastMode, ...paramsWithoutOuterNativeOwnership } = params;
|
|
5788
6162
|
const supervisedRuntimeModel = {
|
|
5789
6163
|
id: effectiveRuntimeModelId,
|
|
5790
6164
|
name: effectiveRuntimeModelId,
|
|
@@ -6017,18 +6391,23 @@ function resolveCodexDynamicToolDirectNames(params, hostSystemAgentActive = fals
|
|
|
6017
6391
|
const names = [];
|
|
6018
6392
|
if (hostSystemAgentActive && isSystemAgentOnlyCodexDynamicToolAllowlist(params.toolsAllow)) names.push("openclaw");
|
|
6019
6393
|
if (params.sourceReplyDeliveryMode === "message_tool_only") names.push("message");
|
|
6020
|
-
|
|
6394
|
+
names.push("progress_card");
|
|
6021
6395
|
return names;
|
|
6022
6396
|
}
|
|
6023
6397
|
//#endregion
|
|
6024
6398
|
//#region extensions/codex/src/app-server/run-attempt-server-requests.ts
|
|
6399
|
+
const DYNAMIC_TOOL_TERMINAL_DIAGNOSTIC_TYPES = [
|
|
6400
|
+
"tool.execution.completed",
|
|
6401
|
+
"tool.execution.error",
|
|
6402
|
+
"tool.execution.blocked"
|
|
6403
|
+
];
|
|
6025
6404
|
function createCodexAttemptServerRequestController(resources, turnRuntime, lifecycle) {
|
|
6026
6405
|
const { prompt, state: resourceState, projectorRef, trajectoryRecorder } = resources;
|
|
6027
6406
|
const { context } = prompt;
|
|
6028
6407
|
const { runtime, attemptTools } = context;
|
|
6029
6408
|
const { connection } = runtime;
|
|
6030
|
-
const { params, computerUseConfig, runAbortController, appServer,
|
|
6031
|
-
const { toolBridge, toolOutcomeOrdinals, suppressedDynamicToolOutcomeOrdinals, allocateCodexToolOutcomeOrdinal } = attemptTools;
|
|
6409
|
+
const { params, computerUseConfig, runAbortController, appServer, sessionAgentId } = connection;
|
|
6410
|
+
const { compactionPlanState, toolBridge, toolOutcomeOrdinals, suppressedDynamicToolOutcomeOrdinals, allocateCodexToolOutcomeOrdinal } = attemptTools;
|
|
6032
6411
|
const { state, turnIdRef, userInputBridgeRef, openClawDynamicToolExecutions, pendingOpenClawDynamicToolCompletionIds, postToolRawAssistantCompletionIdleTimeoutMs, turnWatches } = turnRuntime;
|
|
6033
6412
|
const { emitExecutionPhaseOnce, scheduleTurnReleaseAfterTerminalDynamicTool, scheduleTerminalDynamicToolReleaseCheck } = lifecycle;
|
|
6034
6413
|
const handleServerRequest = async (request, scope, requestSignal = new AbortController().signal) => {
|
|
@@ -6054,7 +6433,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6054
6433
|
armCompletionWatchOnResponse = true;
|
|
6055
6434
|
markCurrentTurnRequestProgress();
|
|
6056
6435
|
}
|
|
6057
|
-
|
|
6436
|
+
const approvalResult = await routeCodexAppServerElicitationRequest({
|
|
6058
6437
|
requestParams: request.params,
|
|
6059
6438
|
paramsForRun: params,
|
|
6060
6439
|
threadId: resourceState.thread.threadId,
|
|
@@ -6063,6 +6442,11 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6063
6442
|
...computerUseConfig.enabled ? { computerUseMcpServerName: computerUseConfig.mcpServerName } : {},
|
|
6064
6443
|
signal
|
|
6065
6444
|
});
|
|
6445
|
+
if (approvalResult.kind === "handled") return approvalResult.response;
|
|
6446
|
+
return await userInputBridgeRef.current?.handleElicitationRequest({
|
|
6447
|
+
id: request.id,
|
|
6448
|
+
params: request.params
|
|
6449
|
+
});
|
|
6066
6450
|
}
|
|
6067
6451
|
if (request.method === "item/tool/requestUserInput") {
|
|
6068
6452
|
if (scope.turnId === turnId) {
|
|
@@ -6088,9 +6472,8 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6088
6472
|
turnId,
|
|
6089
6473
|
nativeHookRelay: resourceState.nativeHookRelay,
|
|
6090
6474
|
autoApprove: shouldAutoApproveCodexAppServerApprovals(appServer),
|
|
6091
|
-
autoApproveOpenClawToolPolicy: approvalPolicyPromotedForOpenClawToolPolicy,
|
|
6092
6475
|
signal,
|
|
6093
|
-
onNativeToolFailureDisposition: (itemId, disposition) => projector?.recordNativeToolApprovalFailure(itemId, disposition)
|
|
6476
|
+
onNativeToolFailureDisposition: (itemId, disposition, approvalKind) => projector?.recordNativeToolApprovalFailure(itemId, disposition, approvalKind)
|
|
6094
6477
|
});
|
|
6095
6478
|
}
|
|
6096
6479
|
return;
|
|
@@ -6126,13 +6509,6 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6126
6509
|
tool: call.tool,
|
|
6127
6510
|
toolCallId: call.callId
|
|
6128
6511
|
});
|
|
6129
|
-
emitDynamicToolStartedDiagnostic({
|
|
6130
|
-
call,
|
|
6131
|
-
agentId: sessionAgentId,
|
|
6132
|
-
runId: params.runId,
|
|
6133
|
-
sessionId: params.sessionId,
|
|
6134
|
-
sessionKey: params.sessionKey
|
|
6135
|
-
});
|
|
6136
6512
|
const toolMeta = inferCodexDynamicToolMeta(call, resolveCodexToolProgressDetailMode(params.toolProgressDetail));
|
|
6137
6513
|
const toolArgs = sanitizeCodexToolArguments(call.arguments);
|
|
6138
6514
|
const commandBearing = isCodexCommandBearingToolCall(call.tool, toolArgs);
|
|
@@ -6162,30 +6538,39 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6162
6538
|
sessionId: params.sessionId,
|
|
6163
6539
|
sessionKey: params.sessionKey
|
|
6164
6540
|
})) terminalDiagnosticObserved = true;
|
|
6165
|
-
});
|
|
6541
|
+
}, { include: DYNAMIC_TOOL_TERMINAL_DIAGNOSTIC_TYPES });
|
|
6166
6542
|
try {
|
|
6167
|
-
const { execution } = openClawDynamicToolExecutions.claim(call, () =>
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
}
|
|
6187
|
-
|
|
6188
|
-
|
|
6543
|
+
const { execution } = openClawDynamicToolExecutions.claim(call, () => {
|
|
6544
|
+
emitDynamicToolStartedDiagnostic({
|
|
6545
|
+
call,
|
|
6546
|
+
agentId: sessionAgentId,
|
|
6547
|
+
runId: params.runId,
|
|
6548
|
+
sessionId: params.sessionId,
|
|
6549
|
+
sessionKey: params.sessionKey
|
|
6550
|
+
});
|
|
6551
|
+
return handleDynamicToolCallWithTimeout({
|
|
6552
|
+
call,
|
|
6553
|
+
toolBridge,
|
|
6554
|
+
signal,
|
|
6555
|
+
timeoutMs: dynamicToolTimeoutMs,
|
|
6556
|
+
toolMeta,
|
|
6557
|
+
toolCallOrdinal,
|
|
6558
|
+
onAgentToolResult: params.onAgentToolResult,
|
|
6559
|
+
observeToolTerminal: params.observeToolTerminal,
|
|
6560
|
+
onFallbackSelected: () => {
|
|
6561
|
+
if (toolCallOrdinal !== void 0) suppressedDynamicToolOutcomeOrdinals.add(toolCallOrdinal);
|
|
6562
|
+
},
|
|
6563
|
+
onTimeout: () => {
|
|
6564
|
+
trajectoryRecorder?.recordEvent("tool.timeout", {
|
|
6565
|
+
threadId: call.threadId,
|
|
6566
|
+
turnId: call.turnId,
|
|
6567
|
+
toolCallId: call.callId,
|
|
6568
|
+
name: call.tool,
|
|
6569
|
+
timeoutMs: dynamicToolTimeoutMs
|
|
6570
|
+
});
|
|
6571
|
+
}
|
|
6572
|
+
});
|
|
6573
|
+
});
|
|
6189
6574
|
const response = await execution;
|
|
6190
6575
|
const protocolResponse = toCodexDynamicToolProtocolResponse(response);
|
|
6191
6576
|
if (!protocolResponse.success && toolCallOrdinal !== void 0) {
|
|
@@ -6209,7 +6594,11 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6209
6594
|
contentItems: protocolResponse.contentItems
|
|
6210
6595
|
});
|
|
6211
6596
|
recordCodexDynamicToolResult(projector, call, response, protocolResponse);
|
|
6212
|
-
if (protocolResponse.success && call.tool === "
|
|
6597
|
+
if (protocolResponse.success && call.tool === "progress_card") {
|
|
6598
|
+
const progressCardInput = response.executedArguments ?? call.arguments;
|
|
6599
|
+
await projector?.recordDynamicProgressCardUpdate(progressCardInput);
|
|
6600
|
+
compactionPlanState.recordProgressCardInput(progressCardInput);
|
|
6601
|
+
}
|
|
6213
6602
|
if (shouldEmitDynamicToolProgress) {
|
|
6214
6603
|
const progressResponse = toCodexDynamicToolProgressResponse(response, protocolResponse);
|
|
6215
6604
|
emitCodexAppServerEvent(params, {
|
|
@@ -6289,6 +6678,20 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6289
6678
|
return { handleServerRequest };
|
|
6290
6679
|
}
|
|
6291
6680
|
//#endregion
|
|
6681
|
+
//#region extensions/codex/src/app-server/attempt-runtime-artifact.ts
|
|
6682
|
+
async function verifyStartupArtifact(params) {
|
|
6683
|
+
if (!params.request) return;
|
|
6684
|
+
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-BvyT1uyd.js");
|
|
6685
|
+
const runtimeArtifact = readCodexAppServerClientRuntimeArtifact(params.client);
|
|
6686
|
+
const expected = params.request.expected;
|
|
6687
|
+
const matchesExpected = !expected || runtimeArtifact?.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint;
|
|
6688
|
+
if (!runtimeArtifact || !matchesExpected || !await validateCodexAppServerRuntimeArtifact(runtimeArtifact, params.signal)) {
|
|
6689
|
+
retireSharedCodexAppServerClientIfCurrent(params.client);
|
|
6690
|
+
throw new Error(expected ? "Codex app-server runtime artifact does not match verified inference" : "Codex app-server runtime artifact is unavailable or stale");
|
|
6691
|
+
}
|
|
6692
|
+
return runtimeArtifact;
|
|
6693
|
+
}
|
|
6694
|
+
//#endregion
|
|
6292
6695
|
//#region extensions/codex/src/app-server/computer-use-health.ts
|
|
6293
6696
|
const COMPUTER_USE_HEALTH_MONITOR_STATE = Symbol.for("openclaw.codexComputerUseHealthMonitorState");
|
|
6294
6697
|
function getComputerUseHealthMonitorState() {
|
|
@@ -6575,24 +6978,19 @@ async function startCodexAttemptThread(params) {
|
|
|
6575
6978
|
startupClientLease = () => {
|
|
6576
6979
|
if (startupClientLeaseReleased) return;
|
|
6577
6980
|
startupClientLeaseReleased = true;
|
|
6578
|
-
|
|
6981
|
+
if (params.attemptClientFactory === createIsolatedCodexAppServerClient) activeStartupClient.close();
|
|
6982
|
+
else releaseLeasedSharedCodexAppServerClient(activeStartupClient);
|
|
6579
6983
|
};
|
|
6580
6984
|
releaseSharedClientLease = startupClientLease;
|
|
6581
6985
|
attemptedClient = activeStartupClient;
|
|
6582
6986
|
startupClientForAbandonedRequestCleanup = activeStartupClient;
|
|
6583
6987
|
if (startupAbandoned) throw new CodexAppServerStartupError("timed_out");
|
|
6584
6988
|
if (startupAbandonController.signal.aborted) throw new CodexAppServerStartupError("aborted");
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
const matchesExpected = !expected || Boolean(runtimeArtifact && runtimeArtifact.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint);
|
|
6591
|
-
if (!runtimeArtifact || !matchesExpected || !await validateCodexAppServerRuntimeArtifact(runtimeArtifact, startupAbandonController.signal)) {
|
|
6592
|
-
retireSharedCodexAppServerClientIfCurrent(activeStartupClient);
|
|
6593
|
-
throw new Error(expected ? "Codex app-server runtime artifact does not match verified inference" : "Codex app-server runtime artifact is unavailable or stale");
|
|
6594
|
-
}
|
|
6595
|
-
}
|
|
6989
|
+
const runtimeArtifact = await verifyStartupArtifact({
|
|
6990
|
+
client: activeStartupClient,
|
|
6991
|
+
request: params.runtimeArtifactRequest,
|
|
6992
|
+
signal: startupAbandonController.signal
|
|
6993
|
+
});
|
|
6596
6994
|
ensureCodexAppServerClientRuntime(activeStartupClient, {
|
|
6597
6995
|
agentDir: params.agentDir,
|
|
6598
6996
|
authProfileId: startupRuntimeAuthProfileId,
|
|
@@ -6652,7 +7050,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6652
7050
|
const releaseStartupSandboxEnvironment = async () => {
|
|
6653
7051
|
if (startupSandboxEnvironmentAcquired) {
|
|
6654
7052
|
startupSandboxEnvironmentAcquired = false;
|
|
6655
|
-
await releaseCodexSandboxExecServerEnvironment(params.sandbox);
|
|
7053
|
+
await releaseCodexSandboxExecServerEnvironment(params.sandbox, startupSandboxEnvironment);
|
|
6656
7054
|
}
|
|
6657
7055
|
};
|
|
6658
7056
|
releaseStartupResourcesOnTimeout = releaseStartupSandboxEnvironment;
|
|
@@ -6665,9 +7063,11 @@ async function startCodexAttemptThread(params) {
|
|
|
6665
7063
|
startupSandboxEnvironment = sandboxEnvironmentRequired ? await ensureCodexSandboxExecServerEnvironment({
|
|
6666
7064
|
client: activeStartupClient,
|
|
6667
7065
|
sandbox: params.sandbox ?? null,
|
|
7066
|
+
runtime: params.runtime,
|
|
6668
7067
|
appServerStartOptions: params.appServer.start,
|
|
6669
7068
|
timeoutMs: params.appServer.requestTimeoutMs,
|
|
6670
|
-
signal: startupAbandonController.signal
|
|
7069
|
+
signal: AbortSignal.any([params.signal, startupAbandonController.signal]),
|
|
7070
|
+
onExecutionDisconnect: params.onExecutionDisconnect
|
|
6671
7071
|
}) : void 0;
|
|
6672
7072
|
startupSandboxEnvironmentAcquired = Boolean(startupSandboxEnvironment);
|
|
6673
7073
|
if (startupAbandonController.signal.aborted) {
|
|
@@ -6711,14 +7111,19 @@ async function startCodexAttemptThread(params) {
|
|
|
6711
7111
|
reserveResumeThread,
|
|
6712
7112
|
bindingStore: params.bindingStore,
|
|
6713
7113
|
params: params.buildAttemptParams(),
|
|
7114
|
+
runtimeModelId: params.runtimeModelId,
|
|
6714
7115
|
agentId: params.sessionAgentId,
|
|
7116
|
+
agentDir: params.agentDir,
|
|
6715
7117
|
cwd: startupExecutionCwd,
|
|
6716
7118
|
dynamicTools: params.dynamicTools,
|
|
6717
7119
|
persistentWebSearchAllowed: params.persistentWebSearchAllowed,
|
|
6718
7120
|
webSearchAllowed: params.webSearchAllowed,
|
|
6719
7121
|
appServer: pluginAppServer,
|
|
6720
7122
|
developerInstructions: params.developerInstructions,
|
|
7123
|
+
agentWorkspaceDeveloperInstructions: params.agentWorkspaceDeveloperInstructions,
|
|
6721
7124
|
config: threadConfig,
|
|
7125
|
+
shellEnvironment: params.shellEnvironment,
|
|
7126
|
+
disableLoginShell: params.disableLoginShell,
|
|
6722
7127
|
finalConfigPatch: params.finalConfigPatch,
|
|
6723
7128
|
buildFinalConfigPatch: params.buildFinalConfigPatch,
|
|
6724
7129
|
nativeHookRelayGeneration: params.nativeHookRelayGeneration,
|
|
@@ -6886,7 +7291,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6886
7291
|
const { prompt, state, trajectoryRecorder, activateNativePreToolUseFailureFallback, releaseSandboxExecEnvironment, releaseSharedClientLeaseAndRetireOneShotClient, releaseCurrentRoute, runCleanupStep, startupTimeoutMs, buildNativeHookRelayFinalConfigPatch } = resources;
|
|
6887
7292
|
const { context, turnState, buildRenderedCodexDeveloperInstructions, rebuildCodexTurnPromptTextFromCurrentProjection, applyNoContextEngineContinuityProjection } = prompt;
|
|
6888
7293
|
const { runtime, attemptTools, promptState } = context;
|
|
6889
|
-
const { connection, runtimeParams, preparedAuthBinding, buildActiveRunAttemptParams, startupAuthAccountCacheKey, startupEnvApiKeyCacheKey, bundleMcpThreadConfig, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, sandboxExecServerEnabled } = runtime;
|
|
7294
|
+
const { connection, runtimeParams, preparedAuthBinding, buildActiveRunAttemptParams, startupAuthAccountCacheKey, startupEnvApiKeyCacheKey, bundleMcpThreadConfig, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, effectiveRuntimeModelId, sandboxExecServerEnabled } = runtime;
|
|
6890
7295
|
const { toolBridge, toolState } = attemptTools;
|
|
6891
7296
|
const developerInstructions = joinPresentSections(turnState.promptBuild.developerInstructions, attemptTools.scheduledConfiguredMcp?.diagnosticNotice);
|
|
6892
7297
|
const { params, attemptClientFactory, bindingStore, appServer, pluginConfig, computerUseConfig, startupClientAuthProfileId, runtimeArtifactRequest, startupPreparedAuth, agentDir, sessionAgentId, effectiveWorkspace, effectiveCwd, sandbox, runAbortController, usesSupervisionConnection, resolveReviewerPolicyContext, resolveRuntimeOptionsForCurrentBinding, startupAuthProfileId, startupAuthRequirement, abortFromUpstream } = connection;
|
|
@@ -6899,6 +7304,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6899
7304
|
const startupResult = await startCodexAttemptThread({
|
|
6900
7305
|
attemptClientFactory,
|
|
6901
7306
|
bindingStore,
|
|
7307
|
+
runtime: connection.options.runtime,
|
|
6902
7308
|
appServer: pluginAppServer,
|
|
6903
7309
|
pluginConfig,
|
|
6904
7310
|
computerUseConfig,
|
|
@@ -6911,7 +7317,10 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6911
7317
|
startupEnvApiKeyCacheKey,
|
|
6912
7318
|
agentDir,
|
|
6913
7319
|
config: params.config,
|
|
7320
|
+
shellEnvironment: connection.shellEnvironment,
|
|
7321
|
+
disableLoginShell: connection.disableLoginShell,
|
|
6914
7322
|
buildAttemptParams: buildActiveRunAttemptParams,
|
|
7323
|
+
...effectiveRuntimeModelId !== runtimeParams.modelId ? { runtimeModelId: effectiveRuntimeModelId } : {},
|
|
6915
7324
|
sessionAgentId,
|
|
6916
7325
|
effectiveWorkspace,
|
|
6917
7326
|
effectiveCwd,
|
|
@@ -6919,6 +7328,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6919
7328
|
persistentWebSearchAllowed: toolState.persistentWebSearchAllowed,
|
|
6920
7329
|
webSearchAllowed: toolState.webSearchAllowed,
|
|
6921
7330
|
developerInstructions,
|
|
7331
|
+
agentWorkspaceDeveloperInstructions: context.agentWorkspaceDeveloperInstructions,
|
|
6922
7332
|
buildFinalConfigPatch: buildNativeHookRelayFinalConfigPatch,
|
|
6923
7333
|
bundleMcpThreadConfig,
|
|
6924
7334
|
configuredMcpOwnershipVersion: attemptTools.configuredMcpOwnershipVersion,
|
|
@@ -6930,6 +7340,11 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6930
7340
|
startupTimeoutMs,
|
|
6931
7341
|
signal: runAbortController.signal,
|
|
6932
7342
|
onStartupTimeout: () => runAbortController.abort("codex_startup_timeout"),
|
|
7343
|
+
onExecutionDisconnect: (error) => {
|
|
7344
|
+
state.executionDisconnectError = error;
|
|
7345
|
+
embeddedAgentLog.warn(error.message);
|
|
7346
|
+
runAbortController.abort("client_closed");
|
|
7347
|
+
},
|
|
6933
7348
|
spawnedBy: params.spawnedBy
|
|
6934
7349
|
});
|
|
6935
7350
|
state.client = startupResult.client;
|
|
@@ -6937,7 +7352,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6937
7352
|
state.runtimeArtifact = startupResult.runtimeArtifact;
|
|
6938
7353
|
state.turnRouter = startupResult.turnRouter;
|
|
6939
7354
|
state.turnRoute = startupResult.turnRoute;
|
|
6940
|
-
state.
|
|
7355
|
+
state.sandboxExecEnvironment = startupResult.sandboxEnvironment;
|
|
6941
7356
|
state.releaseSharedClientLease = startupResult.releaseSharedClientLease;
|
|
6942
7357
|
state.restartContextEngineCodexThread = startupResult.restartContextEngineCodexThread;
|
|
6943
7358
|
pluginAppServer = startupResult.pluginAppServer;
|
|
@@ -7011,7 +7426,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
7011
7426
|
await runCleanupStep("codex-start-failure-sandbox-release", releaseSandboxExecEnvironment);
|
|
7012
7427
|
await runCleanupStep("codex-start-failure-shared-client-release", releaseSharedClientLeaseAndRetireOneShotClient);
|
|
7013
7428
|
await runCleanupStep("codex-start-failure-abort-listener", () => params.abortSignal?.removeEventListener("abort", abortFromUpstream));
|
|
7014
|
-
throw error;
|
|
7429
|
+
throw state.executionDisconnectError ?? error;
|
|
7015
7430
|
}
|
|
7016
7431
|
}
|
|
7017
7432
|
//#endregion
|
|
@@ -7035,6 +7450,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7035
7450
|
});
|
|
7036
7451
|
const toolState = {
|
|
7037
7452
|
yieldDetected: false,
|
|
7453
|
+
yieldAcknowledgment: void 0,
|
|
7038
7454
|
persistentWebSearchAllowed: void 0,
|
|
7039
7455
|
webSearchAllowed: false
|
|
7040
7456
|
};
|
|
@@ -7052,11 +7468,16 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7052
7468
|
if (toolCallId) toolOutcomeOrdinals.set(toolCallId, ordinal);
|
|
7053
7469
|
return ordinal;
|
|
7054
7470
|
} : void 0;
|
|
7055
|
-
const
|
|
7471
|
+
const compactionPlanState = new CodexCompactionPlanState();
|
|
7472
|
+
const dynamicToolParams = {
|
|
7056
7473
|
...runtimeParams,
|
|
7474
|
+
onAgentEvent: (event) => {
|
|
7475
|
+
compactionPlanState.record(event);
|
|
7476
|
+
return runtimeParams.onAgentEvent?.(event);
|
|
7477
|
+
},
|
|
7057
7478
|
...allocateCodexToolOutcomeOrdinal ? { allocateToolOutcomeOrdinal: allocateCodexToolOutcomeOrdinal } : {},
|
|
7058
7479
|
...onCodexToolOutcome ? { onToolOutcome: onCodexToolOutcome } : {}
|
|
7059
|
-
}
|
|
7480
|
+
};
|
|
7060
7481
|
const computerContextEpoch = { value: 0 };
|
|
7061
7482
|
const cronCreatorToolAllowlist = [];
|
|
7062
7483
|
const cronCreatorToolAllowlistCaptureRef = {};
|
|
@@ -7080,6 +7501,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7080
7501
|
let toolBridge;
|
|
7081
7502
|
let creatorAuthorityPromise;
|
|
7082
7503
|
let resolveCreatorAuthorityImpl;
|
|
7504
|
+
const runtimeYieldCompletionClaim = {};
|
|
7083
7505
|
const commonToolParams = {
|
|
7084
7506
|
params: dynamicToolParams,
|
|
7085
7507
|
resolvedWorkspace,
|
|
@@ -7094,9 +7516,11 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7094
7516
|
pluginConfig,
|
|
7095
7517
|
profilerEnabled,
|
|
7096
7518
|
...params.cronCreatorAuthorityUnavailableReason === "queued-local-operator" && bundleMcpThreadConfig.staticServerNames.length > 0 ? { cronCreatorAuthorityUnavailableReason: "queued-local-operator-configured-mcp" } : {},
|
|
7097
|
-
onYieldDetected: () => {
|
|
7519
|
+
onYieldDetected: (acknowledgment) => {
|
|
7098
7520
|
toolState.yieldDetected = true;
|
|
7521
|
+
toolState.yieldAcknowledgment = acknowledgment;
|
|
7099
7522
|
},
|
|
7523
|
+
claimYieldCompletion: () => runtimeYieldCompletionClaim.current?.() ?? false,
|
|
7100
7524
|
onCodexAppServerEvent: (event) => {
|
|
7101
7525
|
emitCodexAppServerEvent(params, event);
|
|
7102
7526
|
},
|
|
@@ -7333,13 +7757,15 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7333
7757
|
cronCreatorToolAllowlistCaptureRef,
|
|
7334
7758
|
scheduledAppAuthoritySourceRef,
|
|
7335
7759
|
dynamicToolParams,
|
|
7760
|
+
compactionPlanState,
|
|
7336
7761
|
computerContextEpoch,
|
|
7337
7762
|
toolBridge,
|
|
7338
7763
|
toolState,
|
|
7339
7764
|
toolOutcomeOrdinals,
|
|
7340
7765
|
suppressedDynamicToolOutcomeOrdinals,
|
|
7341
7766
|
onCodexToolOutcome,
|
|
7342
|
-
allocateCodexToolOutcomeOrdinal
|
|
7767
|
+
allocateCodexToolOutcomeOrdinal,
|
|
7768
|
+
runtimeYieldCompletionClaim
|
|
7343
7769
|
};
|
|
7344
7770
|
} catch (error) {
|
|
7345
7771
|
await scopedMcpTools?.dispose();
|
|
@@ -7457,7 +7883,7 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
|
|
|
7457
7883
|
data: {
|
|
7458
7884
|
phase: "turn_starting",
|
|
7459
7885
|
threadId: resourceState.thread.threadId,
|
|
7460
|
-
model:
|
|
7886
|
+
model: params.modelId,
|
|
7461
7887
|
effort: turnStartParams.effort,
|
|
7462
7888
|
collaborationEffort: turnStartParams.collaborationMode?.settings.reasoning_effort,
|
|
7463
7889
|
serviceTier: turnStartParams.serviceTier
|
|
@@ -8179,11 +8605,14 @@ function createCodexAttemptTurnState(resources) {
|
|
|
8179
8605
|
//#endregion
|
|
8180
8606
|
//#region extensions/codex/src/app-server/run-attempt.ts
|
|
8181
8607
|
async function runCodexAppServerAttempt(params, options) {
|
|
8182
|
-
const
|
|
8608
|
+
const connection = await prepareCodexAttemptConnection({
|
|
8183
8609
|
params,
|
|
8184
8610
|
options
|
|
8185
|
-
})
|
|
8186
|
-
const
|
|
8611
|
+
});
|
|
8612
|
+
const runtime = await prepareCodexAttemptRuntime(connection);
|
|
8613
|
+
const attemptTools = await prepareCodexAttemptTools(runtime);
|
|
8614
|
+
const resources = prepareCodexAttemptResources(await prepareCodexAttemptPrompt(await prepareCodexAttemptContext(runtime, attemptTools)));
|
|
8615
|
+
attemptTools.runtimeYieldCompletionClaim.current = () => resources.state.nativeHookRelay?.hasClaimedDirectChild() ?? false;
|
|
8187
8616
|
await startCodexAttemptRuntime(resources);
|
|
8188
8617
|
const turnRuntime = createCodexAttemptTurnState(resources);
|
|
8189
8618
|
const lifecycle = createCodexAttemptLifecycleController(resources, turnRuntime);
|
|
@@ -8193,11 +8622,14 @@ async function runCodexAppServerAttempt(params, options) {
|
|
|
8193
8622
|
const turnStart = await startCodexAttemptTurn(resources, turnRuntime, notifications, turnRequest);
|
|
8194
8623
|
if ("result" in turnStart) return turnStart.result;
|
|
8195
8624
|
const activeTurn = await activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notifications, turnStart.turn);
|
|
8625
|
+
let finalizedResult;
|
|
8196
8626
|
try {
|
|
8197
|
-
|
|
8627
|
+
finalizedResult = await finalizeCodexAttempt(resources, turnRuntime, lifecycle, notifications, turnRequest, activeTurn);
|
|
8198
8628
|
} finally {
|
|
8199
8629
|
await cleanupCodexAttempt(resources, turnRuntime, lifecycle, turnRequest, activeTurn);
|
|
8200
8630
|
}
|
|
8631
|
+
if (resources.state.executionDisconnectError && !connection.terminalState.explicitCancellationObserved) throw resources.state.executionDisconnectError;
|
|
8632
|
+
return finalizedResult;
|
|
8201
8633
|
}
|
|
8202
8634
|
//#endregion
|
|
8203
8635
|
export { runCodexAppServerAttempt };
|