@openclaw/codex 2026.8.1-beta.2 → 2026.9.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +147 -0
- package/dist/{attempt-client-cleanup-DMLXUfa8.js → attempt-client-cleanup-bfsmcQ6m.js} +21 -2
- package/dist/{binding-connection-I5Bo-AsX.js → binding-connection-BMvPX73o.js} +15 -3
- package/dist/{bounded-turn-qgZmzy_4.js → bounded-turn-B7iBUcuP.js} +22 -16
- package/dist/{capabilities-CybGI1oz.js → capabilities-BRMh0aIq.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-B1AEz8ZA.js → command-formatters-DEsIufkt.js} +2 -2
- package/dist/{command-handlers-Db8pu_ds.js → command-handlers-D_-1_qRp.js} +65 -37
- package/dist/command-rpc-CCeCkf_v.js +90 -0
- package/dist/{compact-LspQaGfl.js → compact-BglNFZrQ.js} +35 -29
- package/dist/{session-binding-DPxIvMgE.js → config-giW8X0QA.js} +108 -914
- package/dist/context-compaction-activity-BOeJf7yo.js +58 -0
- package/dist/doctor-contract-api.js +23 -21
- package/dist/{dynamic-tools-BVdyWkUD.js → dynamic-tools-Dnlfa--w.js} +1345 -1424
- package/dist/{effective-mcp-catalog-DIIhAtOZ.js → effective-mcp-catalog-CTeGrnfO.js} +2 -2
- package/dist/elicitation-input-DMkeki8d.js +71 -0
- package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
- package/dist/{event-projector-usage-e5huIQWu.js → event-projector-usage-Bk1I90Bg.js} +18 -18
- package/dist/harness-Csz0F-DK.js +258 -0
- package/dist/harness.js +2 -226
- package/dist/index.js +262 -181
- package/dist/{isolated-completion-C58NbL40.js → isolated-completion-Cv6FqygM.js} +4 -4
- package/dist/managed-binary-DFYK4DWq.js +248 -0
- package/dist/media-understanding-provider.js +2 -2
- package/dist/model-catalog-i9rNBthX.js +48 -0
- package/dist/{models-BFlpn1Ex.js → models-TS3HBU-q.js} +4 -3
- package/dist/{native-subagent-monitor-DyTGmTUx.js → native-subagent-monitor-4Mfq2HDs.js} +354 -83
- package/dist/node-exec-server.runtime-BpWqJO1V.js +192 -0
- package/dist/{plugin-app-cache-key-C3H2CVp6.js → plugin-app-cache-key-C1CAdfcP.js} +19 -4
- package/dist/plugin-approval-roundtrip-bUm777tR.js +95 -0
- package/dist/{plugin-marketplace-discovery-CzrGJdCR.js → plugin-marketplace-discovery-B9DvaAG-.js} +59 -54
- package/dist/{plugin-metadata-cache-CNJPj4_b.js → plugin-metadata-cache-CTCT3w5L.js} +164 -134
- package/dist/{protocol-validators-B4F7L8Rf.js → protocol-validators-VeJxxJ0U.js} +80 -5
- package/dist/{rate-limits-DZXmOL8-.js → rate-limits-C5_D8Gmb.js} +1 -1
- package/dist/{request-BRl5_UfX.js → request-DXXGHko0.js} +2 -2
- package/dist/{run-attempt-P8BdxC1I.js → run-attempt-DYc0QCBF.js} +1276 -765
- package/dist/{runtime-artifact-BVSPdd6g.js → runtime-artifact-BvyT1uyd.js} +4 -7
- package/dist/{sandbox-guard-Cmwc9eIk.js → sandbox-guard-kuWTn9C5.js} +25 -19
- package/dist/session-binding-Bcynfd-_.js +874 -0
- package/dist/{session-catalog-xwNi_SDM.js → session-catalog-DaLKVtpH.js} +1534 -1288
- package/dist/session-catalog-home-id-BNwAJ9D7.js +18 -0
- package/dist/{session-cli-7hgXZDV7.js → session-cli-DMc4oS2w.js} +20 -7
- package/dist/session-permission-policy-BrNH1bjy.js +160 -0
- package/dist/{session-retirement-DoMMJFKm.js → session-retirement-CcNC3YSY.js} +3 -3
- package/dist/{session-upstream-marker-CrIFX06J.js → session-upstream-marker-BIkusb95.js} +1 -1
- package/dist/{settled-turn-finalizer-BRWBO4MO.js → settled-turn-finalizer-Dc3ApjU4.js} +24 -20
- package/dist/{shared-client-kIBbGjk4.js → shared-client-DKz23hHY.js} +1632 -372
- package/dist/{side-question-9HAL26l9.js → side-question-DjA_jsNe.js} +105 -54
- package/dist/{thread-lifecycle-Bu1BTDXr.js → thread-lifecycle-L7oEkTlq.js} +1147 -114
- package/dist/{thread-ownership-6kOQHlyC.js → thread-ownership-DZeuKH1j.js} +2 -2
- package/dist/{thread-resume-CPrJNQVM.js → thread-resume-BE9qNEW0.js} +3 -3
- package/dist/{transcript-mirror-B9gGgnJS.js → transcript-mirror-DsCMWBca.js} +137 -38
- 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-DlaHxSLC.js} +12 -6
- package/dist/{usage-CHlV0e-o.js → usage-ROIaW3wo.js} +3 -3
- package/dist/{web-search-provider.runtime-DRw2Vl42.js → web-search-provider.runtime-ClaNPV7N.js} +3 -3
- package/openclaw.plugin.json +49 -2
- package/package.json +9 -8
- package/dist/app-server-policy-zcBDc1JU.js +0 -49
|
@@ -1,42 +1,48 @@
|
|
|
1
|
-
import { C as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { l as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { C as resolveCodexModelBackedReviewerPolicyContext, D as readCodexRequirementsToml, d as withMcpElicitationsApprovalPolicy, f as isCodexPairedNodeRemoteExecPlacementSandbox, g as resolveCodexPluginsPolicy, h as readCodexPluginConfig, j as resolveOpenClawExecPolicyForCodexAppServer, m as isCodexSandboxExecServerEnabled, o as resolveCodexComputerUseConfig, p as isCodexRemoteExecPlacementSandbox, r as resolveCodexAppServerHomeScope, u as shouldAutoApproveCodexAppServerApprovals, x as canUseCodexModelBackedApprovalsReviewerForModel } from "./config-giW8X0QA.js";
|
|
2
|
+
import { A as resolveCodexTurnAssistantCompletionIdleTimeoutMs, E as isCodexAppServerStartupError, F as isCodexAppServerApprovalRequest, G as CodexAppServerRpcError, I as isCodexAppServerBrokenPipeError, K as createCodexElicitationResponse, L as isCodexAppServerConnectionClosedError, M as resolveCodexTurnTerminalIdleTimeoutMs, N as withCodexStartupTimeout, O as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, P as getCodexAppServerClientInstanceId, Q as protectCodexAppServerLiveThread, R as isCodexAppServerIndeterminateRequestCancellationError, T as CodexAppServerStartupError, U as resolveCodexAppServerClientInstanceId, V as isCodexAppServerRequestTimeoutError, Y as ensureCodexAppServerClientRuntime, _ as retireSharedCodexAppServerClientIfCurrent, _t as flattenCodexDynamicToolFunctions, a as createIsolatedCodexAppServerClient, at as readRecentCodexRateLimits, c as isCodexAppServerStartSelectionChangedError, ct as resolveCodexAppServerAuthAccountCacheKey, dt as resolveCodexAppServerFallbackApiKeyCacheKey, et as retainCodexAppServerLiveThread, ft as resolveCodexAppServerPreparedApiKeyCacheKey, g as retainSharedCodexAppServerClientIfCurrent, it as readCodexRateLimitsRevision, j as resolveCodexTurnCompletionIdleTimeoutMs, k as resolveCodexStartupTimeoutMs, lt as resolveCodexAppServerAuthProfileId, n as clearSharedCodexAppServerClientIfCurrent, nt as withAbortableTimeout, o as getLeasedSharedCodexAppServerClient, ot as rememberCodexRateLimitsRead, p as releaseLeasedSharedCodexAppServerClient, pt as resolveCodexAppServerPreparedAuthHandoff, r as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, s as getSharedCodexAppServerClient, u as readCodexAppServerClientDesktopGenerationFingerprint, ut as resolveCodexAppServerAuthProfileIdForAgent, vt as isJsonObject, w as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS, xt as resolveCodexAppServerHomeDir, z as isCodexAppServerIndeterminateTransportError } from "./shared-client-DKz23hHY.js";
|
|
3
|
+
import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, i as createCodexSessionGenerationSupersededError, l as resolveCodexRunSessionBindingAuthority, u as scopeCodexRunBindingStore } from "./session-binding-Bcynfd-_.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-bfsmcQ6m.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-Bk1I90Bg.js";
|
|
6
|
+
import { l as readCodexTurn, o as assertCodexTurnStartResponse, s as readCodexDynamicToolCallParams, u as readCodexTurnCompletedNotification } from "./protocol-validators-VeJxxJ0U.js";
|
|
7
|
+
import { n as buildCodexAppServerRuntimeFingerprint, o as defaultCodexAppInventoryCache, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-C1CAdfcP.js";
|
|
8
|
+
import { C as toCodexDynamicToolProgressResponse, Dt as resolveRecoverableCodexPluginConfigKeys, F as resolveCodexWebSearchPlan, I as buildDeveloperInstructions, J as areCodexDynamicToolFingerprintsCompatible, S as shouldReleaseTurnAfterTerminalDynamicTool, T as resolveCodexToolAbortTerminalReason, V as resolveCodexAppServerThreadModelSelection, X as codexLegacyDynamicToolsFingerprint, Y as codexDynamicToolsFingerprint, Z as filterCodexDynamicTools, _ as isDynamicToolTerminalDiagnosticEvent, _t as buildCodexPluginThreadConfigTimeoutFallback, a as isCodexAppServerProfilerEnabled, at as buildContextEngineBinding, b as resolveTerminalDynamicToolBatchAction, bt as mergeCodexThreadConfigs, c as buildCodexNativeHookRelayConfig, ct as fitCodexProjectedContextForTurnStart, d as emitCodexNativePreToolUseFailureDiagnostic, dt as resolveCodexContextEngineProjectionMaxChars, et as isMessageOnlyCodexSourceReply, f as resolveCodexNativeHookRelayEvents, ft as resolveCodexContextEngineProjectionReserveTokens, g as hasPendingDynamicToolTerminalDiagnostic, gt as buildCodexPluginThreadConfigInputFingerprint, h as handleDynamicToolCallWithTimeout, ht as buildCodexPluginThreadConfig, i as startOrResumeThread, it as resolveCodexDynamicToolsLoadingForRuntime, l as buildCodexNativeHookRelayDisabledConfig, lt as neutralizeCodexExplicitMentionSigils, m as scheduleCodexNativeHookRelayUnregister, mt as buildCodexPluginAppsConfigPatchFromPolicyContext, n as buildTurnStartParams, ot as isContextEngineBindingCompatible, p as resolveCodexNativeHookRelayTtlMs, pt as resolveCodexContinuityProjectionMaxChars, r as buildCodexUserInput, s as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, st as buildCodexContinuityCalibration, t as buildTurnCollaborationMode, tt as isSystemAgentOnlyCodexDynamicToolAllowlist, u as createCodexNativeHookRelay, ut as projectContextEngineAssemblyForCodex, v as isMatchingDynamicToolTerminalDiagnostic, w as toCodexDynamicToolProtocolResponse, x as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, xt as shouldBuildCodexPluginThreadConfig, y as resolveDynamicToolCallTimeoutMs, yt as buildPluginAppPolicyContext } from "./thread-lifecycle-L7oEkTlq.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 { n as
|
|
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-DsCMWBca.js";
|
|
12
|
+
import { t as CODEX_CONTROL_METHODS } from "./capabilities-BRMh0aIq.js";
|
|
13
|
+
import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-C5_D8Gmb.js";
|
|
14
|
+
import { r as formatCodexDisplayText } from "./command-formatters-DEsIufkt.js";
|
|
15
|
+
import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, r as resolveCodexEffectiveSessionPermissionPolicy } from "./session-permission-policy-BrNH1bjy.js";
|
|
16
|
+
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-BMvPX73o.js";
|
|
16
17
|
import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-B4FfbcCg.js";
|
|
17
|
-
import { t as
|
|
18
|
-
import { n as
|
|
19
|
-
import { a as
|
|
20
|
-
import {
|
|
21
|
-
import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse,
|
|
18
|
+
import { t as persistCodexContextCompactionActivity } from "./context-compaction-activity-BOeJf7yo.js";
|
|
19
|
+
import { i as createAssistantMirrorMessage, n as createAssistantCommentaryMessage, r as createAssistantMessage, t as createAssistantAsyncMessage } from "./event-projector-assistant-message-C5-Ds8mA.js";
|
|
20
|
+
import { a as readCodexMirroredSessionHistoryMessages, c as inferCodexDynamicToolMeta, d as sanitizeCodexToolArguments, f as sanitizeCodexToolResponse, i as CodexToolTranscriptProjection, l as isCodexCommandBearingToolCall, n as CodexEventProjection, o as CodexToolProgressProjection, r as emitCodexAgentEvent, s as shouldEmitTranscriptToolProgress, t as codexNativeSubagentMonitorRuntime, u as resolveCodexToolProgressDetailMode } from "./native-subagent-monitor-4Mfq2HDs.js";
|
|
21
|
+
import { C as shouldRequireCodexSandboxExecServerEnvironment, D as CodexNativeToolLifecycleProjector, E as readBoundedCodexRemoteWorkspaceFile, S as shouldEnableCodexAppServerNativeToolSurface, _ as resolveCodexAppServerHookChannelId, a as emitDynamicToolStartedDiagnostic, c as resolveCodexProviderWebSearchSupport, d as releaseCodexSandboxExecServerEnvironment, f as buildDynamicTools, g as resolveCodexAppServerExecutionCwd, h as formatCodexDynamicToolBuildStageSummary, i as emitDynamicToolErrorDiagnostic, m as disableCodexPluginThreadConfig, n as projectCodexExecutableDynamicTools, o as emitDynamicToolTerminalDiagnostic, p as createCodexDynamicToolBuildStageTracker, r as routeCodexAppServerElicitationRequest, s as handleCodexAppServerApprovalRequest, t as createCodexDynamicToolBridge, u as ensureCodexSandboxExecServerEnvironment, v as resolveCodexExternalSandboxPolicyForOpenClawSandbox, w as shouldWarnCodexDynamicToolBuildStageSummary, x as resolveCodexSandboxEnvironmentSelection, y as resolveCodexMessageToolProvider } from "./dynamic-tools-Dnlfa--w.js";
|
|
22
|
+
import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-CTCT3w5L.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, buildEmbeddedForegroundPromptContext, buildHarnessContextEngineRuntimeContext, buildWatchedSessionsHarnessContext, callGatewayTool, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, formatErrorMessage, formatFastModeAutoProgressText, getAgentHarnessHookRunner, hasBeforeToolCallPolicy, 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";
|
|
29
30
|
import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
31
|
+
import { resolveAgentConfig as resolveAgentConfig$1 } from "openclaw/plugin-sdk/agent-scope-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 { 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";
|
|
39
|
+
import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
35
40
|
import { prepareMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
|
|
41
|
+
import { isSilentReplyPayloadText } from "openclaw/plugin-sdk/reply-chunking";
|
|
36
42
|
import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
|
|
37
43
|
import { resolveGeneratedMediaMaxBytes } from "openclaw/plugin-sdk/media-generation-runtime";
|
|
38
44
|
import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
|
|
39
|
-
import {
|
|
45
|
+
import { stripInvisibleUnicode } from "openclaw/plugin-sdk/web-content-extractor";
|
|
40
46
|
import { MESSAGE_TOOL_DELIVERY_HINTS } from "openclaw/plugin-sdk/message-tool-delivery-hints";
|
|
41
47
|
//#region extensions/codex/src/app-server/attempt-steering.ts
|
|
42
48
|
/**
|
|
@@ -173,10 +179,12 @@ function createCodexSteeringQueue(params) {
|
|
|
173
179
|
acceptance: "open",
|
|
174
180
|
text,
|
|
175
181
|
images: options?.images,
|
|
182
|
+
isInboundUserMessage: options?.isInboundUserMessage,
|
|
176
183
|
onQueueAccepted: options?.onQueueAccepted,
|
|
177
184
|
resolve: resolveDelivery,
|
|
178
185
|
reject: rejectDelivery,
|
|
179
|
-
settled: false
|
|
186
|
+
settled: false,
|
|
187
|
+
userTurnTranscriptRecorder: options?.userTurnTranscriptRecorder
|
|
180
188
|
};
|
|
181
189
|
pendingMessages.add(item);
|
|
182
190
|
return {
|
|
@@ -193,19 +201,6 @@ function createCodexSteeringQueue(params) {
|
|
|
193
201
|
options?.onQueueAccepted?.(false);
|
|
194
202
|
throw unavailableError;
|
|
195
203
|
}
|
|
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
204
|
const { item, delivery } = createPendingMessage(text, options);
|
|
210
205
|
batchedMessages.push(item);
|
|
211
206
|
clearBatchTimer();
|
|
@@ -221,8 +216,21 @@ function createCodexSteeringQueue(params) {
|
|
|
221
216
|
const batch = dispatchedBatches.get(clientUserMessageId);
|
|
222
217
|
if (!batch) return false;
|
|
223
218
|
dispatchedBatches.delete(clientUserMessageId);
|
|
224
|
-
for (const item of batch.items)
|
|
225
|
-
|
|
219
|
+
for (const item of batch.items) reportItemAcceptance(item, true);
|
|
220
|
+
const resolveBatch = () => {
|
|
221
|
+
for (const item of batch.items) resolveItem(item);
|
|
222
|
+
return true;
|
|
223
|
+
};
|
|
224
|
+
const rejectBatch = (error) => {
|
|
225
|
+
for (const item of batch.items) rejectItem(item, error);
|
|
226
|
+
return true;
|
|
227
|
+
};
|
|
228
|
+
if (!params.beforeConfirmConsumed) return resolveBatch();
|
|
229
|
+
try {
|
|
230
|
+
return params.beforeConfirmConsumed(batch.items).then(resolveBatch, rejectBatch);
|
|
231
|
+
} catch (error) {
|
|
232
|
+
return rejectBatch(error);
|
|
233
|
+
}
|
|
226
234
|
},
|
|
227
235
|
sealAdmission: sealQueueAdmission,
|
|
228
236
|
cancel: cancelQueue
|
|
@@ -244,6 +252,7 @@ var CodexAssistantProjection = class {
|
|
|
244
252
|
this.assistantItemOrder = [];
|
|
245
253
|
this.assistantTimestampByItem = /* @__PURE__ */ new Map();
|
|
246
254
|
this.assistantPhaseByItem = /* @__PURE__ */ new Map();
|
|
255
|
+
this.assistantDeliveryByItem = /* @__PURE__ */ new Map();
|
|
247
256
|
this.latestTerminalAssistantCandidateSuperseded = false;
|
|
248
257
|
this.latestTerminalAssistantCandidateCanReleaseAfterToolHandoff = false;
|
|
249
258
|
this.terminalAssistantCandidateEarlierActiveItemIds = /* @__PURE__ */ new Set();
|
|
@@ -253,6 +262,9 @@ var CodexAssistantProjection = class {
|
|
|
253
262
|
this.rawPromotedAssistantItemIds = /* @__PURE__ */ new Set();
|
|
254
263
|
this.assistantStarted = false;
|
|
255
264
|
this.streamedPartialAssistantItemReplaceable = false;
|
|
265
|
+
this.persistableAssistantBarrier = 0;
|
|
266
|
+
this.persistedAssistantBoundary = false;
|
|
267
|
+
this.persistableAssistantBarrierItemIds = /* @__PURE__ */ new Set();
|
|
256
268
|
}
|
|
257
269
|
hasCompletedTerminalAssistantText(completedItemIds) {
|
|
258
270
|
const latestCompletedItemId = this.latestCompletedTerminalAssistantItemId;
|
|
@@ -284,7 +296,8 @@ var CodexAssistantProjection = class {
|
|
|
284
296
|
if (!delta) return;
|
|
285
297
|
if (itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
286
298
|
const isCommentary = this.isCommentaryAssistantItem(itemId);
|
|
287
|
-
|
|
299
|
+
const isAsync = this.isAsyncAssistantItem(itemId);
|
|
300
|
+
if (!isCommentary && !isAsync && itemId !== this.latestTerminalAssistantCandidateItemId) this.markTerminalAssistantCandidateSupersededBy();
|
|
288
301
|
if (!this.assistantStarted) {
|
|
289
302
|
this.assistantStarted = true;
|
|
290
303
|
await this.params.onAssistantMessageStart?.();
|
|
@@ -292,6 +305,7 @@ var CodexAssistantProjection = class {
|
|
|
292
305
|
this.rememberAssistantItem(itemId);
|
|
293
306
|
const text = `${this.assistantTextByItem.get(itemId) ?? ""}${delta}`;
|
|
294
307
|
this.assistantTextByItem.set(itemId, text);
|
|
308
|
+
if (isAsync) return;
|
|
295
309
|
if (isCommentary) {
|
|
296
310
|
this.emitCommentaryProgress({
|
|
297
311
|
itemId,
|
|
@@ -322,23 +336,25 @@ var CodexAssistantProjection = class {
|
|
|
322
336
|
if (knownFinalAnswer && !replaceable) await this.params.onPartialReply?.(streamPayload);
|
|
323
337
|
}
|
|
324
338
|
recordItemStarted(item, itemId) {
|
|
325
|
-
|
|
339
|
+
this.noteNativeWorkBarrier(item);
|
|
326
340
|
this.rememberAssistantPhase(item);
|
|
341
|
+
if (item?.type === "agentMessage" && itemId && !this.isNonTerminalAssistantItem(itemId) && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
327
342
|
if (item?.type === "agentMessage" && itemId) this.rememberAssistantItem(itemId);
|
|
328
|
-
if (itemId && itemId !== this.latestTerminalAssistantCandidateItemId) {
|
|
343
|
+
if (itemId && !this.isNonTerminalAssistantItem(itemId) && itemId !== this.latestTerminalAssistantCandidateItemId) {
|
|
329
344
|
this.markTerminalAssistantCandidateSupersededBy(itemId, { preserveEarlierActiveItem: true });
|
|
330
345
|
if (this.latestTerminalAssistantCandidateSuperseded) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
331
346
|
}
|
|
332
347
|
}
|
|
333
348
|
recordItemCompleted(item, itemId, activeItemIds) {
|
|
334
|
-
|
|
335
|
-
if (itemId) this.latestCompletedItemId = itemId;
|
|
349
|
+
this.noteNativeWorkBarrier(item);
|
|
336
350
|
this.rememberAssistantPhase(item);
|
|
337
|
-
if (item?.type === "agentMessage" && !this.
|
|
351
|
+
if (item?.type === "agentMessage" && itemId && !this.isNonTerminalAssistantItem(itemId) && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
352
|
+
if (itemId && !this.isNonTerminalAssistantItem(itemId)) this.latestCompletedItemId = itemId;
|
|
353
|
+
if (item?.type === "agentMessage" && !this.isNonTerminalAssistantItem(item.id)) {
|
|
338
354
|
this.latestCompletedTerminalAssistantItemId = item.id;
|
|
339
355
|
this.markLatestTerminalAssistantCandidate(item.id, activeItemIds);
|
|
340
356
|
this.pendingRawTerminalAssistantEchoItemId = item.id;
|
|
341
|
-
} else if (itemId) {
|
|
357
|
+
} else if (itemId && !this.isNonTerminalAssistantItem(itemId)) {
|
|
342
358
|
this.markTerminalAssistantCandidateSupersededBy(itemId, { preserveEarlierActiveItem: true });
|
|
343
359
|
if (this.latestTerminalAssistantCandidateSuperseded) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
344
360
|
}
|
|
@@ -351,7 +367,8 @@ var CodexAssistantProjection = class {
|
|
|
351
367
|
text: item.text
|
|
352
368
|
});
|
|
353
369
|
this.pendingRawCommentaryEchoes += 1;
|
|
354
|
-
} else if (item.text && this.isFinalAnswerAssistantItem(item.id)) this.emitAnswerCandidate(item.id, "candidate");
|
|
370
|
+
} else if (item.text && !this.isAsyncAssistantItem(item.id) && this.isFinalAnswerAssistantItem(item.id)) this.emitAnswerCandidate(item.id, "candidate");
|
|
371
|
+
return this.createAsyncDelivery(item.id);
|
|
355
372
|
}
|
|
356
373
|
}
|
|
357
374
|
recordSnapshotItem(item) {
|
|
@@ -359,6 +376,7 @@ var CodexAssistantProjection = class {
|
|
|
359
376
|
if (item.type === "agentMessage" && typeof item.text === "string") {
|
|
360
377
|
this.rememberAssistantItem(item.id);
|
|
361
378
|
this.assistantTextByItem.set(item.id, item.text);
|
|
379
|
+
return this.createAsyncDelivery(item.id);
|
|
362
380
|
}
|
|
363
381
|
}
|
|
364
382
|
handleRawResponseItemCompleted(item, activeItemIds) {
|
|
@@ -403,8 +421,15 @@ var CodexAssistantProjection = class {
|
|
|
403
421
|
else this.markLatestTerminalAssistantCandidate(itemId, activeItemIds, { canReleaseAfterToolHandoff: isIdlessTerminalAssistantAfterCompletedWork });
|
|
404
422
|
}
|
|
405
423
|
collectAssistantTexts() {
|
|
406
|
-
const
|
|
407
|
-
|
|
424
|
+
const afterHandoff = this.collectPersistableAssistantTexts(this.persistableAssistantBarrier);
|
|
425
|
+
const audibleAfterHandoff = afterHandoff.filter((text) => !isSilentReplyPayloadText(text));
|
|
426
|
+
if (audibleAfterHandoff.length > 0) return audibleAfterHandoff;
|
|
427
|
+
if (afterHandoff.length > 0) return afterHandoff.slice(-1);
|
|
428
|
+
if (this.persistedAssistantBoundary) return [];
|
|
429
|
+
const recoveredAudible = this.collectPersistableAssistantTexts(0).filter((text) => !isSilentReplyPayloadText(text));
|
|
430
|
+
if (recoveredAudible.length > 0) return recoveredAudible.slice(-1);
|
|
431
|
+
const recovered = this.resolveFinalAssistantTextItem()?.text;
|
|
432
|
+
return recovered ? [recovered] : [];
|
|
408
433
|
}
|
|
409
434
|
collectCommentaryMessages() {
|
|
410
435
|
return this.assistantItemOrder.flatMap((itemId) => {
|
|
@@ -418,6 +443,39 @@ var CodexAssistantProjection = class {
|
|
|
418
443
|
}];
|
|
419
444
|
});
|
|
420
445
|
}
|
|
446
|
+
collectAsyncMessages() {
|
|
447
|
+
return this.assistantItemOrder.flatMap((itemId) => {
|
|
448
|
+
if (!this.isAsyncAssistantItem(itemId)) return [];
|
|
449
|
+
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
450
|
+
const timestamp = this.assistantTimestampByItem.get(itemId);
|
|
451
|
+
if (!text || timestamp === void 0) return [];
|
|
452
|
+
return [{
|
|
453
|
+
itemId,
|
|
454
|
+
message: createAssistantAsyncMessage(this.params, text, itemId, timestamp)
|
|
455
|
+
}];
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
createCompletedAssistantBoundaryMessage(completedItemIds, options) {
|
|
459
|
+
const itemId = this.latestCompletedTerminalAssistantItemId;
|
|
460
|
+
const text = itemId ? this.assistantTextByItem.get(itemId)?.trim() : void 0;
|
|
461
|
+
const itemIndex = itemId ? this.assistantItemOrder.indexOf(itemId) : -1;
|
|
462
|
+
if (!itemId || !completedItemIds.has(itemId) || itemIndex < this.persistableAssistantBarrier || !text || isSilentReplyPayloadText(text) || this.isToolProgressEchoText(itemId, text)) return;
|
|
463
|
+
const message = this.createAssistantMessage(text, options);
|
|
464
|
+
return {
|
|
465
|
+
itemId,
|
|
466
|
+
message: {
|
|
467
|
+
...message,
|
|
468
|
+
timestamp: this.assistantTimestampByItem.get(itemId) ?? message.timestamp
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
markAssistantBoundaryPersisted(itemId) {
|
|
473
|
+
const index = this.assistantItemOrder.indexOf(itemId);
|
|
474
|
+
if (index >= 0) {
|
|
475
|
+
this.persistableAssistantBarrier = Math.max(this.persistableAssistantBarrier, index + 1);
|
|
476
|
+
this.persistedAssistantBoundary = true;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
421
479
|
finalizeAnswerCandidate(turn) {
|
|
422
480
|
if (turn.status !== "completed") {
|
|
423
481
|
this.supersedeVisibleAnswerCandidate();
|
|
@@ -427,7 +485,7 @@ var CodexAssistantProjection = class {
|
|
|
427
485
|
const authoritativeIndex = turnItems.findLastIndex((item) => {
|
|
428
486
|
if (item.type !== "agentMessage" || typeof item.text !== "string" || item.text.trim().length === 0) return false;
|
|
429
487
|
const phase = readItemString(item, "phase");
|
|
430
|
-
return phase === "final_answer" || phase === void 0;
|
|
488
|
+
return readItemString(item, "delivery") !== "async" && (phase === "final_answer" || phase === void 0);
|
|
431
489
|
});
|
|
432
490
|
const authoritative = authoritativeIndex >= 0 ? turnItems[authoritativeIndex] : void 0;
|
|
433
491
|
if (turnItems.slice(authoritativeIndex + 1).some(shouldClearTerminalPresentationForNativeItem) || authoritative?.id === this.latestTerminalAssistantCandidateItemId && this.latestTerminalAssistantCandidateSuperseded) {
|
|
@@ -445,7 +503,7 @@ var CodexAssistantProjection = class {
|
|
|
445
503
|
hasAssistantItemTextForSynthesis() {
|
|
446
504
|
for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
|
|
447
505
|
const itemId = this.assistantItemOrder[i];
|
|
448
|
-
if (!itemId || this.
|
|
506
|
+
if (!itemId || this.isNonTerminalAssistantItem(itemId)) continue;
|
|
449
507
|
const text = this.assistantTextByItem.get(itemId);
|
|
450
508
|
if (text && text.length > 0) return true;
|
|
451
509
|
}
|
|
@@ -454,7 +512,7 @@ var CodexAssistantProjection = class {
|
|
|
454
512
|
createCurrentAttemptAssistantMessage(options) {
|
|
455
513
|
for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
|
|
456
514
|
const itemId = this.assistantItemOrder[i];
|
|
457
|
-
if (!itemId || this.
|
|
515
|
+
if (!itemId || this.isNonTerminalAssistantItem(itemId) || !this.assistantTextByItem.has(itemId)) continue;
|
|
458
516
|
const text = this.assistantTextByItem.get(itemId) ?? "";
|
|
459
517
|
const normalizedText = text.trim();
|
|
460
518
|
if (normalizedText && this.isToolProgressEchoText(itemId, normalizedText)) continue;
|
|
@@ -475,10 +533,18 @@ var CodexAssistantProjection = class {
|
|
|
475
533
|
if (item?.type !== "agentMessage") return;
|
|
476
534
|
const phase = readItemString(item, "phase");
|
|
477
535
|
if (phase) this.assistantPhaseByItem.set(item.id, phase);
|
|
536
|
+
const delivery = readItemString(item, "delivery");
|
|
537
|
+
if (delivery) this.assistantDeliveryByItem.set(item.id, delivery);
|
|
478
538
|
}
|
|
479
539
|
isCommentaryAssistantItem(itemId) {
|
|
480
540
|
return this.assistantPhaseByItem.get(itemId) === "commentary";
|
|
481
541
|
}
|
|
542
|
+
isAsyncAssistantItem(itemId) {
|
|
543
|
+
return this.assistantDeliveryByItem.get(itemId) === "async";
|
|
544
|
+
}
|
|
545
|
+
isNonTerminalAssistantItem(itemId) {
|
|
546
|
+
return this.isCommentaryAssistantItem(itemId) || this.isAsyncAssistantItem(itemId);
|
|
547
|
+
}
|
|
482
548
|
isFinalAnswerAssistantItem(itemId) {
|
|
483
549
|
return this.assistantPhaseByItem.get(itemId) === "final_answer";
|
|
484
550
|
}
|
|
@@ -486,7 +552,7 @@ var CodexAssistantProjection = class {
|
|
|
486
552
|
return this.assistantPhaseByItem.get(itemId) === "final_answer";
|
|
487
553
|
}
|
|
488
554
|
emitCommentaryProgress(params) {
|
|
489
|
-
const progressText = params.text.
|
|
555
|
+
const progressText = params.text.trim();
|
|
490
556
|
if (!progressText || this.lastCommentaryProgressTextByItem.get(params.itemId) === progressText) return;
|
|
491
557
|
this.lastCommentaryProgressTextByItem.set(params.itemId, progressText);
|
|
492
558
|
this.emitAgentEvent({
|
|
@@ -553,22 +619,98 @@ var CodexAssistantProjection = class {
|
|
|
553
619
|
const itemId = this.assistantItemOrder[i];
|
|
554
620
|
if (!itemId) continue;
|
|
555
621
|
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
556
|
-
if (this.
|
|
622
|
+
if (this.isNonTerminalAssistantItem(itemId)) continue;
|
|
557
623
|
if (text && !this.isToolProgressEchoText(itemId, text)) return {
|
|
558
624
|
itemId,
|
|
559
625
|
text
|
|
560
626
|
};
|
|
561
627
|
}
|
|
562
628
|
}
|
|
629
|
+
collectPersistableAssistantTexts(minIndex) {
|
|
630
|
+
let texts = [];
|
|
631
|
+
let replaceable = false;
|
|
632
|
+
for (let index = minIndex; index < this.assistantItemOrder.length; index += 1) {
|
|
633
|
+
const itemId = this.assistantItemOrder[index];
|
|
634
|
+
if (!itemId || this.isNonTerminalAssistantItem(itemId)) continue;
|
|
635
|
+
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
636
|
+
if (!text || this.isToolProgressEchoText(itemId, text)) continue;
|
|
637
|
+
if (isSilentReplyPayloadText(text)) {
|
|
638
|
+
texts.push(text);
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
const isTerminalFinal = this.assistantPhaseByItem.get(itemId) === "final_answer";
|
|
642
|
+
if (!isTerminalFinal || replaceable) {
|
|
643
|
+
texts = [text];
|
|
644
|
+
replaceable = !isTerminalFinal;
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
texts.push(text);
|
|
648
|
+
}
|
|
649
|
+
return texts;
|
|
650
|
+
}
|
|
651
|
+
noteNativeWorkBarrier(item) {
|
|
652
|
+
if (!item || !shouldAdvancePersistableAssistantBarrier(item)) return;
|
|
653
|
+
if (item.id && this.persistableAssistantBarrierItemIds.has(item.id)) return;
|
|
654
|
+
if (item.id) this.persistableAssistantBarrierItemIds.add(item.id);
|
|
655
|
+
this.persistableAssistantBarrier = this.assistantItemOrder.length;
|
|
656
|
+
}
|
|
563
657
|
rememberAssistantItem(itemId) {
|
|
564
658
|
if (!itemId || this.assistantItemOrder.includes(itemId)) return;
|
|
565
659
|
this.assistantItemOrder.push(itemId);
|
|
566
660
|
this.assistantTimestampByItem.set(itemId, this.nextTranscriptTimestamp());
|
|
567
661
|
}
|
|
662
|
+
createAsyncDelivery(itemId) {
|
|
663
|
+
if (!this.isAsyncAssistantItem(itemId)) return;
|
|
664
|
+
const text = this.assistantTextByItem.get(itemId);
|
|
665
|
+
const timestamp = this.assistantTimestampByItem.get(itemId);
|
|
666
|
+
if (!text?.trim() || timestamp === void 0) return;
|
|
667
|
+
return {
|
|
668
|
+
itemId,
|
|
669
|
+
message: createAssistantAsyncMessage(this.params, text, itemId, timestamp),
|
|
670
|
+
text
|
|
671
|
+
};
|
|
672
|
+
}
|
|
568
673
|
isToolProgressEchoText(itemId, text) {
|
|
569
674
|
return this.rawPromotedAssistantItemIds.has(itemId) && this.matchesToolProgressEcho(text);
|
|
570
675
|
}
|
|
571
676
|
};
|
|
677
|
+
function shouldAdvancePersistableAssistantBarrier(item) {
|
|
678
|
+
return shouldClearTerminalPresentationForNativeItem(item) || item.type === "dynamicToolCall" || item.type === "sleep";
|
|
679
|
+
}
|
|
680
|
+
//#endregion
|
|
681
|
+
//#region extensions/codex/src/app-server/event-projector-async-delivery.ts
|
|
682
|
+
/** Owns authorization, exactly-once settlement, and terminal retry for async user messages. */
|
|
683
|
+
var CodexAsyncDeliveryProjection = class {
|
|
684
|
+
constructor(params, threadId, turnId, options) {
|
|
685
|
+
this.params = params;
|
|
686
|
+
this.threadId = threadId;
|
|
687
|
+
this.turnId = turnId;
|
|
688
|
+
this.options = options;
|
|
689
|
+
this.settledItemIds = /* @__PURE__ */ new Set();
|
|
690
|
+
this.pendingDeliveries = /* @__PURE__ */ new Map();
|
|
691
|
+
}
|
|
692
|
+
allows(item, reportUnauthorized = false) {
|
|
693
|
+
if (item?.type !== "agentMessage" || item.delivery !== "async") return true;
|
|
694
|
+
const allowed = this.params.disableTools !== true && (this.options.asyncUserMessageAllowed ?? (this.params.toolsAllow === void 0 || this.params.toolsAllow.some((name) => name === "*" || name === "message")));
|
|
695
|
+
if (!allowed && reportUnauthorized) embeddedAgentLog.warn("blocked unauthorized codex async user message", {
|
|
696
|
+
itemId: item.id,
|
|
697
|
+
threadId: this.threadId,
|
|
698
|
+
turnId: this.turnId
|
|
699
|
+
});
|
|
700
|
+
return allowed;
|
|
701
|
+
}
|
|
702
|
+
pending() {
|
|
703
|
+
return [...this.pendingDeliveries.values()];
|
|
704
|
+
}
|
|
705
|
+
async deliver(delivery) {
|
|
706
|
+
if (this.settledItemIds.has(delivery.itemId)) return;
|
|
707
|
+
const settlement = await this.options.onAsyncDelivery?.(delivery);
|
|
708
|
+
if (settlement === "settled") {
|
|
709
|
+
this.settledItemIds.add(delivery.itemId);
|
|
710
|
+
this.pendingDeliveries.delete(delivery.itemId);
|
|
711
|
+
} else if (settlement === "retry") this.pendingDeliveries.set(delivery.itemId, delivery);
|
|
712
|
+
}
|
|
713
|
+
};
|
|
572
714
|
//#endregion
|
|
573
715
|
//#region extensions/codex/src/app-server/event-projector-media.ts
|
|
574
716
|
const GENERATED_IMAGE_MEDIA_SUBDIR = "tool-image-generation";
|
|
@@ -739,9 +881,10 @@ function isBase64WhitespaceCode(code) {
|
|
|
739
881
|
//#endregion
|
|
740
882
|
//#region extensions/codex/src/app-server/event-projector-reasoning.ts
|
|
741
883
|
var CodexReasoningProjection = class {
|
|
742
|
-
constructor(params, emitAgentEvent) {
|
|
884
|
+
constructor(params, emitAgentEvent, onNativePlanUpdate) {
|
|
743
885
|
this.params = params;
|
|
744
886
|
this.emitAgentEvent = emitAgentEvent;
|
|
887
|
+
this.onNativePlanUpdate = onNativePlanUpdate;
|
|
745
888
|
this.reasoningTextByGroup = /* @__PURE__ */ new Map();
|
|
746
889
|
this.reasoningItemOrder = /* @__PURE__ */ new Map();
|
|
747
890
|
this.planTextByItem = /* @__PURE__ */ new Map();
|
|
@@ -782,7 +925,7 @@ var CodexReasoningProjection = class {
|
|
|
782
925
|
}))
|
|
783
926
|
});
|
|
784
927
|
}
|
|
785
|
-
handleTurnPlanUpdated(params, source = "codex-app-server") {
|
|
928
|
+
async handleTurnPlanUpdated(params, source = "codex-app-server") {
|
|
786
929
|
const explanation = readNullableString(params, "explanation");
|
|
787
930
|
const plan = Array.isArray(params.plan) ? params.plan.flatMap((entry) => {
|
|
788
931
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return [];
|
|
@@ -796,6 +939,10 @@ var CodexReasoningProjection = class {
|
|
|
796
939
|
}) : void 0;
|
|
797
940
|
const planText = [explanation, ...(plan ?? []).map(({ step, status }) => `- [${status}] ${step}`)].filter((part) => Boolean(part)).join("\n");
|
|
798
941
|
if (planText) this.turnPlanText = planText;
|
|
942
|
+
if (source === "codex-app-server" && plan) await this.onNativePlanUpdate?.({
|
|
943
|
+
...typeof explanation === "string" ? { markdown: explanation } : {},
|
|
944
|
+
steps: plan
|
|
945
|
+
});
|
|
799
946
|
this.emitPlanUpdate({
|
|
800
947
|
explanation,
|
|
801
948
|
steps: plan
|
|
@@ -825,7 +972,7 @@ var CodexReasoningProjection = class {
|
|
|
825
972
|
return this.turnPlanText ?? [...this.planTextByItem.values()].filter((text) => text.trim().length > 0).join("\n\n");
|
|
826
973
|
}
|
|
827
974
|
emitPlanUpdate(params, source = "codex-app-server") {
|
|
828
|
-
if (!params.explanation &&
|
|
975
|
+
if (!params.explanation && params.steps === void 0) return;
|
|
829
976
|
this.emitAgentEvent({
|
|
830
977
|
stream: "plan",
|
|
831
978
|
data: {
|
|
@@ -833,7 +980,7 @@ var CodexReasoningProjection = class {
|
|
|
833
980
|
title: "Plan updated",
|
|
834
981
|
source,
|
|
835
982
|
...params.explanation ? { explanation: params.explanation } : {},
|
|
836
|
-
...params.steps
|
|
983
|
+
...params.steps ? { steps: params.steps } : {}
|
|
837
984
|
}
|
|
838
985
|
});
|
|
839
986
|
}
|
|
@@ -858,9 +1005,9 @@ function reasoningMethodOrder(method) {
|
|
|
858
1005
|
const attemptTerminal = agentHarnessAttemptTerminal;
|
|
859
1006
|
//#endregion
|
|
860
1007
|
//#region extensions/codex/src/app-server/event-projector-snapshot.ts
|
|
1008
|
+
const CODEX_META_KEY$1 = "__openclaw";
|
|
861
1009
|
function readTurnTaintMetadata(message) {
|
|
862
|
-
|
|
863
|
-
return metadata && typeof metadata === "object" && !Array.isArray(metadata) ? metadata : void 0;
|
|
1010
|
+
return asOptionalRecord(CODEX_META_KEY$1 in message ? message[CODEX_META_KEY$1] : void 0);
|
|
864
1011
|
}
|
|
865
1012
|
function applyStickyTurnTaint(messages) {
|
|
866
1013
|
let tainted = false;
|
|
@@ -883,25 +1030,59 @@ function applyStickyTurnTaint(messages) {
|
|
|
883
1030
|
function buildCodexMessagesSnapshot(params) {
|
|
884
1031
|
const messages = promptSnapshot(params.runParams, params.turnId, params.upstreamUserText);
|
|
885
1032
|
if (params.reasoningText) messages.push(attachCodexMirrorIdentity(params.createAssistantMirrorMessage("Codex reasoning", params.reasoningText), `${params.turnId}:reasoning`));
|
|
886
|
-
|
|
887
|
-
const
|
|
1033
|
+
const commentaryMessages = params.runParams.config?.ui?.prefs?.chatPersistCommentary === false ? [] : params.commentaryMessages.map(({ itemId, message }) => attachCodexMirrorIdentity(message, `${params.turnId}:commentary:${itemId}`));
|
|
1034
|
+
const asyncMessages = params.asyncMessages.map(({ itemId, message }) => attachCodexMirrorIdentity(message, `${params.turnId}:async:${itemId}`));
|
|
1035
|
+
const visibleWorkMessages = [
|
|
1036
|
+
...commentaryMessages,
|
|
1037
|
+
...asyncMessages,
|
|
1038
|
+
...params.toolMessages
|
|
1039
|
+
].toSorted((left, right) => (asDateTimestampMs(left.timestamp) ?? 0) - (asDateTimestampMs(right.timestamp) ?? 0));
|
|
888
1040
|
messages.push(...visibleWorkMessages);
|
|
889
|
-
if (params.lastAssistant) messages.push(attachCodexMirrorIdentity(params.lastAssistant, `${params.turnId}:assistant`));
|
|
1041
|
+
if (params.lastAssistant) messages.push(attachCodexMirrorIdentity(params.lastAssistant, params.lastAssistantIdentity ?? `${params.turnId}:assistant`));
|
|
890
1042
|
return applyStickyTurnTaint(messages).map((message) => projectAgentHarnessTranscriptMessageForDisplay({
|
|
891
1043
|
hidden: params.runParams.trigger === "memory",
|
|
892
1044
|
message
|
|
893
1045
|
}));
|
|
894
1046
|
}
|
|
1047
|
+
function buildCodexSteeringMessagesSnapshot(params) {
|
|
1048
|
+
const asyncMessages = params.assistantProjection.collectAsyncMessages().filter(({ itemId }) => params.completedItemIds.has(itemId));
|
|
1049
|
+
const commentaryMessages = params.assistantProjection.collectCommentaryMessages().filter(({ itemId }) => params.completedItemIds.has(itemId));
|
|
1050
|
+
const assistantBoundary = params.assistantProjection.createCompletedAssistantBoundaryMessage(params.completedItemIds, {
|
|
1051
|
+
tokenUsage: void 0,
|
|
1052
|
+
aborted: false,
|
|
1053
|
+
promptError: void 0
|
|
1054
|
+
});
|
|
1055
|
+
return {
|
|
1056
|
+
messages: buildCodexMessagesSnapshot({
|
|
1057
|
+
runParams: params.runParams,
|
|
1058
|
+
turnId: params.turnId,
|
|
1059
|
+
upstreamUserText: params.upstreamUserText,
|
|
1060
|
+
reasoningText: void 0,
|
|
1061
|
+
asyncMessages,
|
|
1062
|
+
commentaryMessages,
|
|
1063
|
+
toolMessages: params.toolMessages,
|
|
1064
|
+
lastAssistant: assistantBoundary?.message,
|
|
1065
|
+
...assistantBoundary ? { lastAssistantIdentity: `${params.turnId}:assistant:${assistantBoundary.itemId}` } : {},
|
|
1066
|
+
createAssistantMirrorMessage: (title, text) => params.assistantProjection.createAssistantMirrorMessage(title, text)
|
|
1067
|
+
}).filter((message) => message.role !== "user"),
|
|
1068
|
+
...assistantBoundary ? { assistantBoundaryItemId: assistantBoundary.itemId } : {}
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
895
1071
|
//#endregion
|
|
896
1072
|
//#region extensions/codex/src/app-server/event-projector-result.ts
|
|
897
1073
|
function buildCodexAttemptResult(input) {
|
|
898
1074
|
input.nativeToolLifecycleProjection.finalizeActive();
|
|
899
1075
|
const assistantTexts = input.assistantProjection.collectAssistantTexts();
|
|
1076
|
+
const asyncMessages = input.assistantProjection.collectAsyncMessages();
|
|
900
1077
|
const commentaryMessages = input.assistantProjection.collectCommentaryMessages();
|
|
901
1078
|
const reasoningText = input.reasoningProjection.reasoningText();
|
|
902
1079
|
const planText = input.reasoningProjection.planText();
|
|
903
|
-
const
|
|
904
|
-
|
|
1080
|
+
const unavailableThreadUsage = input.tokenUsage ? {
|
|
1081
|
+
...input.tokenUsage,
|
|
1082
|
+
contextUsage: { state: "unavailable" }
|
|
1083
|
+
} : void 0;
|
|
1084
|
+
const completedUsage = input.responseCompletions.usage ?? (input.responseCompletions.modelIterations > 0 ? unavailableThreadUsage : input.tokenUsage);
|
|
1085
|
+
const projectedUsage = input.aborted ? unavailableThreadUsage : completedUsage;
|
|
905
1086
|
const hasAssistantItemText = input.assistantProjection.hasAssistantItemTextForSynthesis();
|
|
906
1087
|
const legacyFailClosed = !input.completedTurn || input.completedTurn.status !== "completed" || hasAssistantItemText;
|
|
907
1088
|
const hasDeliverableAssistantOnCompletedTurn = input.completedTurn?.status === "completed" && assistantTexts.some((text) => text.trim().length > 0);
|
|
@@ -927,7 +1108,7 @@ function buildCodexAttemptResult(input) {
|
|
|
927
1108
|
turnId: input.turnId,
|
|
928
1109
|
upstreamUserText: input.upstreamUserText,
|
|
929
1110
|
reasoningText,
|
|
930
|
-
|
|
1111
|
+
asyncMessages,
|
|
931
1112
|
commentaryMessages,
|
|
932
1113
|
toolMessages: input.toolTranscriptProjection.transcriptMessages,
|
|
933
1114
|
lastAssistant,
|
|
@@ -976,6 +1157,7 @@ function buildCodexAttemptResult(input) {
|
|
|
976
1157
|
acceptedSessionSpawns: input.toolTelemetry.acceptedSessionSpawns,
|
|
977
1158
|
cloudCodeAssistFormatError: false,
|
|
978
1159
|
contextTokens: input.contextTokens,
|
|
1160
|
+
contextTokensSource: input.contextTokensSource,
|
|
979
1161
|
attemptUsage: projectedUsage,
|
|
980
1162
|
...input.completedCompactionCount > 0 ? { compactionCount: input.completedCompactionCount } : {},
|
|
981
1163
|
replayMetadata: {
|
|
@@ -1147,7 +1329,9 @@ var CodexAppServerEventProjector = class {
|
|
|
1147
1329
|
this.responseCompletions = new CodexResponseCompletionProjection();
|
|
1148
1330
|
this.completedCompactionCount = 0;
|
|
1149
1331
|
this.lastTranscriptTimestamp = 0;
|
|
1332
|
+
this.asyncDeliveryProjection = new CodexAsyncDeliveryProjection(params, threadId, turnId, options);
|
|
1150
1333
|
this.contextTokens = options.initialContextTokens;
|
|
1334
|
+
this.contextTokensSource = options.initialContextTokens === void 0 ? void 0 : "resolved";
|
|
1151
1335
|
this.diagnostics = new CodexProjectionDiagnostics(threadId, turnId);
|
|
1152
1336
|
this.nativeToolLifecycleProjector = new CodexNativeToolLifecycleProjector(params, threadId, turnId, { runAbortSignal: options.runAbortSignal });
|
|
1153
1337
|
this.generatedMediaProjection = new CodexGeneratedMediaProjection(params.config, {
|
|
@@ -1164,7 +1348,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1164
1348
|
});
|
|
1165
1349
|
this.eventProjection = new CodexEventProjection(threadId, turnId, (event) => this.emitAgentEvent(event), this.toolProgressProjection, this.toolTranscriptProjection, options.onNativeToolResultRecorded);
|
|
1166
1350
|
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));
|
|
1351
|
+
this.reasoningProjection = new CodexReasoningProjection(params, (event) => this.emitAgentEvent(event), options.onNativePlanUpdate);
|
|
1168
1352
|
}
|
|
1169
1353
|
nextTranscriptTimestamp() {
|
|
1170
1354
|
this.lastTranscriptTimestamp = Math.max(Date.now(), this.lastTranscriptTimestamp + 1);
|
|
@@ -1173,6 +1357,25 @@ var CodexAppServerEventProjector = class {
|
|
|
1173
1357
|
getCompletedTurnStatus() {
|
|
1174
1358
|
return this.completedTurn?.status;
|
|
1175
1359
|
}
|
|
1360
|
+
buildSteeringTranscriptPrefix() {
|
|
1361
|
+
const snapshot = buildCodexSteeringMessagesSnapshot({
|
|
1362
|
+
runParams: this.params,
|
|
1363
|
+
turnId: this.turnId,
|
|
1364
|
+
upstreamUserText: this.options.upstreamUserText,
|
|
1365
|
+
completedItemIds: this.completedItemIds,
|
|
1366
|
+
assistantProjection: this.assistantProjection,
|
|
1367
|
+
toolMessages: this.toolTranscriptProjection.transcriptMessages
|
|
1368
|
+
});
|
|
1369
|
+
this.pendingSteeringAssistantBoundaryItemId = snapshot.assistantBoundaryItemId;
|
|
1370
|
+
return snapshot.messages;
|
|
1371
|
+
}
|
|
1372
|
+
markSteeringTranscriptPersisted() {
|
|
1373
|
+
const itemId = this.pendingSteeringAssistantBoundaryItemId;
|
|
1374
|
+
if (itemId) {
|
|
1375
|
+
this.assistantProjection.markAssistantBoundaryPersisted(itemId);
|
|
1376
|
+
this.pendingSteeringAssistantBoundaryItemId = void 0;
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1176
1379
|
hasCompletedTerminalAssistantText() {
|
|
1177
1380
|
return this.assistantProjection.hasCompletedTerminalAssistantText(this.completedItemIds);
|
|
1178
1381
|
}
|
|
@@ -1199,8 +1402,9 @@ var CodexAppServerEventProjector = class {
|
|
|
1199
1402
|
const ordinal = this.params.allocateToolOutcomeOrdinal?.(item.id);
|
|
1200
1403
|
if (ordinal !== void 0) this.nativeToolOutcomeOrdinals.set(item.id, ordinal);
|
|
1201
1404
|
}
|
|
1202
|
-
recordNativeToolApprovalFailure(toolCallId, disposition) {
|
|
1405
|
+
recordNativeToolApprovalFailure(toolCallId, disposition, approvalKind) {
|
|
1203
1406
|
this.nativeToolLifecycleProjector.recordApprovalFailureDisposition(toolCallId, disposition);
|
|
1407
|
+
if (disposition === "timed_out" && approvalKind) this.toolProgressProjection.approvalTimeoutKinds.set(toolCallId, approvalKind);
|
|
1204
1408
|
}
|
|
1205
1409
|
recordNativeToolPreToolUseFailure(failure) {
|
|
1206
1410
|
this.nativeToolLifecycleProjector.recordPreToolUseFailure(failure);
|
|
@@ -1210,9 +1414,11 @@ var CodexAppServerEventProjector = class {
|
|
|
1210
1414
|
if (!params) return;
|
|
1211
1415
|
if (notification.method === "hook/started" || notification.method === "hook/completed") {
|
|
1212
1416
|
if (!this.isHookNotificationForCurrentThread(params)) return;
|
|
1213
|
-
} else if (notification.method === "guardianWarning") {
|
|
1214
|
-
|
|
1417
|
+
} else if (notification.method === "guardianWarning" || notification.method === "warning" || notification.method === "configWarning") {
|
|
1418
|
+
const warningThreadId = readCodexNotificationThreadId(params);
|
|
1419
|
+
if (notification.method === "guardianWarning" && warningThreadId !== this.threadId || warningThreadId && warningThreadId !== this.threadId) return;
|
|
1215
1420
|
} else if (!isCodexNotificationForTurn(params, this.threadId, this.turnId)) return;
|
|
1421
|
+
if (notification.method !== "guardianWarning" && notification.method !== "item/autoApprovalReview/started" && notification.method !== "item/autoApprovalReview/completed") this.eventProjection.flushPendingGuardianWarning();
|
|
1216
1422
|
this.nativeToolLifecycleProjector.handleNotification(notification);
|
|
1217
1423
|
this.assistantProjection.handleNotification(notification.method, params);
|
|
1218
1424
|
switch (notification.method) {
|
|
@@ -1227,7 +1433,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1227
1433
|
this.reasoningProjection.handlePlanDelta(params);
|
|
1228
1434
|
break;
|
|
1229
1435
|
case "turn/plan/updated":
|
|
1230
|
-
this.reasoningProjection.handleTurnPlanUpdated(params);
|
|
1436
|
+
await this.reasoningProjection.handleTurnPlanUpdated(params);
|
|
1231
1437
|
break;
|
|
1232
1438
|
case "item/started":
|
|
1233
1439
|
await this.handleItemStarted(params);
|
|
@@ -1242,18 +1448,28 @@ var CodexAppServerEventProjector = class {
|
|
|
1242
1448
|
case "item/autoApprovalReview/completed":
|
|
1243
1449
|
this.eventProjection.handleGuardianReview(notification.method, params);
|
|
1244
1450
|
break;
|
|
1451
|
+
case "autoApprovalReview/strictReviewRequired":
|
|
1452
|
+
this.eventProjection.handleStrictReviewRequired(params);
|
|
1453
|
+
break;
|
|
1245
1454
|
case "guardianWarning":
|
|
1246
1455
|
this.eventProjection.handleGuardianWarning(params);
|
|
1247
1456
|
break;
|
|
1457
|
+
case "warning":
|
|
1458
|
+
case "configWarning":
|
|
1459
|
+
this.eventProjection.handleWarning(params);
|
|
1460
|
+
break;
|
|
1248
1461
|
case "hook/started":
|
|
1249
1462
|
case "hook/completed":
|
|
1250
1463
|
this.eventProjection.handleHook(notification.method, params);
|
|
1251
1464
|
break;
|
|
1252
1465
|
case "thread/tokenUsage/updated":
|
|
1253
1466
|
projectCodexThreadUsageUpdate(params, this.tokenUsage, (usage) => this.tokenUsage = usage, (data) => {
|
|
1254
|
-
|
|
1467
|
+
if (data.modelContextWindow !== void 0) {
|
|
1468
|
+
this.contextTokens = data.modelContextWindow;
|
|
1469
|
+
this.contextTokensSource = this.params.authoredContextTokenCap === void 0 ? "runtime" : "runtime-configured";
|
|
1470
|
+
}
|
|
1255
1471
|
this.emitAgentEvent({
|
|
1256
|
-
stream: "
|
|
1472
|
+
stream: "usage",
|
|
1257
1473
|
data
|
|
1258
1474
|
});
|
|
1259
1475
|
});
|
|
@@ -1267,13 +1483,19 @@ var CodexAppServerEventProjector = class {
|
|
|
1267
1483
|
case "rawResponseItem/completed":
|
|
1268
1484
|
await this.handleRawResponseItemCompleted(params);
|
|
1269
1485
|
break;
|
|
1270
|
-
case "
|
|
1486
|
+
case "model/rerouted":
|
|
1487
|
+
this.eventProjection.handleModelRerouted(params);
|
|
1488
|
+
break;
|
|
1489
|
+
case "error": {
|
|
1271
1490
|
this.responseCompletions.clear();
|
|
1272
1491
|
if (params.willRetry === true) break;
|
|
1273
|
-
|
|
1492
|
+
const codexErrorInfo = isJsonObject(params.error) ? params.error.codexErrorInfo : void 0;
|
|
1493
|
+
const compactionFailure = codexErrorInfo === "other" && this.isCompacting();
|
|
1494
|
+
this.settledTurnFailureFinalizationAllowed = codexErrorInfo === "serverOverloaded" || compactionFailure;
|
|
1274
1495
|
this.promptError = this.formatCodexErrorMessage(params) ?? "codex app-server error";
|
|
1275
|
-
this.promptErrorSource = "prompt";
|
|
1496
|
+
this.promptErrorSource = compactionFailure ? "compaction" : "prompt";
|
|
1276
1497
|
break;
|
|
1498
|
+
}
|
|
1277
1499
|
case "thread/compacted":
|
|
1278
1500
|
case "turn/started":
|
|
1279
1501
|
case "turn/diff/updated":
|
|
@@ -1282,7 +1504,6 @@ var CodexAppServerEventProjector = class {
|
|
|
1282
1504
|
case "item/fileChange/outputDelta":
|
|
1283
1505
|
case "item/fileChange/patchUpdated":
|
|
1284
1506
|
case "item/mcpToolCall/progress":
|
|
1285
|
-
case "model/rerouted":
|
|
1286
1507
|
case "model/verification":
|
|
1287
1508
|
case "turn/moderationMetadata":
|
|
1288
1509
|
case "model/safetyBuffering/updated": break;
|
|
@@ -1292,6 +1513,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1292
1513
|
}
|
|
1293
1514
|
}
|
|
1294
1515
|
buildResult(toolTelemetry, options) {
|
|
1516
|
+
this.eventProjection.flushPendingGuardianWarning();
|
|
1295
1517
|
return buildCodexAttemptResult({
|
|
1296
1518
|
runParams: this.params,
|
|
1297
1519
|
turnId: this.turnId,
|
|
@@ -1307,6 +1529,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1307
1529
|
aborted: this.aborted,
|
|
1308
1530
|
tokenUsage: this.tokenUsage,
|
|
1309
1531
|
contextTokens: this.contextTokens,
|
|
1532
|
+
contextTokensSource: this.contextTokensSource,
|
|
1310
1533
|
completedCompactionCount: this.completedCompactionCount,
|
|
1311
1534
|
activeItemCount: this.activeItemIds.size,
|
|
1312
1535
|
completedItemCount: this.completedItemIds.size,
|
|
@@ -1325,9 +1548,12 @@ var CodexAppServerEventProjector = class {
|
|
|
1325
1548
|
recordDynamicToolCall(params) {
|
|
1326
1549
|
this.toolTranscriptProjection.recordDynamicToolCall(params);
|
|
1327
1550
|
}
|
|
1328
|
-
/** Projects a successful OpenClaw
|
|
1329
|
-
|
|
1330
|
-
if (isJsonObject(params))
|
|
1551
|
+
/** Projects a successful OpenClaw progress_card call through the native plan stream. */
|
|
1552
|
+
async recordDynamicProgressCardUpdate(params) {
|
|
1553
|
+
if (isJsonObject(params)) {
|
|
1554
|
+
const projected = { plan: Array.isArray(params.plan) ? params.plan : [] };
|
|
1555
|
+
await this.reasoningProjection.handleTurnPlanUpdated(projected, "openclaw");
|
|
1556
|
+
}
|
|
1331
1557
|
}
|
|
1332
1558
|
recordDynamicToolResult(params) {
|
|
1333
1559
|
this.toolProgressProjection.recordDynamicToolResult(params);
|
|
@@ -1409,13 +1635,15 @@ var CodexAppServerEventProjector = class {
|
|
|
1409
1635
|
this.activeItemIds.delete(itemId);
|
|
1410
1636
|
this.completedItemIds.add(itemId);
|
|
1411
1637
|
}
|
|
1412
|
-
this.
|
|
1638
|
+
if (!this.asyncDeliveryProjection.allows(item, true)) return;
|
|
1639
|
+
const asyncMessage = this.assistantProjection.recordItemCompleted(item, itemId, this.activeItemIds);
|
|
1640
|
+
if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
|
|
1413
1641
|
this.reasoningProjection.recordItem(item);
|
|
1414
1642
|
await this.generatedMediaProjection.recordNative(item);
|
|
1415
1643
|
if (item?.type === "contextCompaction" && itemId) {
|
|
1416
1644
|
this.activeCompactionItemIds.delete(itemId);
|
|
1417
1645
|
this.completedCompactionCount += 1;
|
|
1418
|
-
this.options.onContextCompacted?.();
|
|
1646
|
+
await this.options.onContextCompacted?.();
|
|
1419
1647
|
await runAgentHarnessAfterCompactionHook({
|
|
1420
1648
|
sessionFile: this.params.sessionFile,
|
|
1421
1649
|
messages: await this.toolTranscriptProjection.readMirroredSessionMessages(),
|
|
@@ -1431,17 +1659,17 @@ var CodexAppServerEventProjector = class {
|
|
|
1431
1659
|
channelId: this.params.messageChannel ?? this.params.messageProvider ?? void 0
|
|
1432
1660
|
}
|
|
1433
1661
|
});
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
}
|
|
1662
|
+
await persistCodexContextCompactionActivity({
|
|
1663
|
+
sessionTarget: this.params.sessionTarget,
|
|
1664
|
+
config: this.params.config,
|
|
1665
|
+
cwd: this.params.workspaceDir,
|
|
1666
|
+
runId: this.params.runId,
|
|
1667
|
+
threadId: this.threadId,
|
|
1668
|
+
turnId: this.turnId,
|
|
1669
|
+
itemId,
|
|
1670
|
+
timestamp: this.nextTranscriptTimestamp()
|
|
1444
1671
|
});
|
|
1672
|
+
this.eventProjection.emitCompactionEnd(itemId, true);
|
|
1445
1673
|
}
|
|
1446
1674
|
this.toolProgressProjection.recordToolMeta(item);
|
|
1447
1675
|
this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
|
|
@@ -1470,7 +1698,8 @@ var CodexAppServerEventProjector = class {
|
|
|
1470
1698
|
const turn = readCodexTurn(params.turn);
|
|
1471
1699
|
if (!turn || turn.id !== this.turnId) return;
|
|
1472
1700
|
this.completedTurn = turn;
|
|
1473
|
-
|
|
1701
|
+
const compactionFailure = turn.status === "failed" && (this.promptErrorSource === "compaction" || turn.error?.codexErrorInfo === "other" && this.isCompacting());
|
|
1702
|
+
this.settledTurnFailureFinalizationAllowed = turn.status === "failed" && (turn.error?.codexErrorInfo === "serverOverloaded" || compactionFailure);
|
|
1474
1703
|
if (turn.status !== "completed") this.responseCompletions.clear();
|
|
1475
1704
|
if (turn.status === "failed") {
|
|
1476
1705
|
const usageLimitMessage = formatCodexUsageLimitErrorMessage({
|
|
@@ -1479,9 +1708,18 @@ var CodexAppServerEventProjector = class {
|
|
|
1479
1708
|
rateLimits: this.options.readRecentRateLimits?.()
|
|
1480
1709
|
});
|
|
1481
1710
|
this.promptError = usageLimitMessage ? createCodexUsageLimitPromptError(usageLimitMessage) : turn.error?.message ?? "codex app-server turn failed";
|
|
1482
|
-
this.promptErrorSource = "prompt";
|
|
1711
|
+
this.promptErrorSource = compactionFailure ? "compaction" : "prompt";
|
|
1712
|
+
}
|
|
1713
|
+
if (compactionFailure) {
|
|
1714
|
+
const failedCompactionItemIds = [...this.activeCompactionItemIds];
|
|
1715
|
+
for (const itemId of failedCompactionItemIds) {
|
|
1716
|
+
this.activeItemIds.delete(itemId);
|
|
1717
|
+
this.activeCompactionItemIds.delete(itemId);
|
|
1718
|
+
this.eventProjection.emitCompactionEnd(itemId, false);
|
|
1719
|
+
}
|
|
1483
1720
|
}
|
|
1484
1721
|
const turnItems = turn.items ?? [];
|
|
1722
|
+
const unsettledAsyncDeliveries = this.asyncDeliveryProjection.pending();
|
|
1485
1723
|
for (let index = turnItems.length - 1; index >= 0; index -= 1) {
|
|
1486
1724
|
const item = turnItems[index];
|
|
1487
1725
|
if (!item || !this.isCurrentTurnSnapshotItem(item)) continue;
|
|
@@ -1492,8 +1730,10 @@ var CodexAppServerEventProjector = class {
|
|
|
1492
1730
|
}
|
|
1493
1731
|
}
|
|
1494
1732
|
for (const item of turnItems) {
|
|
1733
|
+
if (!this.asyncDeliveryProjection.allows(item)) continue;
|
|
1495
1734
|
this.diagnostics.warnUnknownItemStatus(item);
|
|
1496
|
-
this.assistantProjection.recordSnapshotItem(item);
|
|
1735
|
+
const asyncMessage = this.assistantProjection.recordSnapshotItem(item);
|
|
1736
|
+
if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
|
|
1497
1737
|
this.reasoningProjection.recordItem(item);
|
|
1498
1738
|
await this.generatedMediaProjection.recordNative(item);
|
|
1499
1739
|
this.toolProgressProjection.recordToolMeta(item);
|
|
@@ -1505,6 +1745,8 @@ var CodexAppServerEventProjector = class {
|
|
|
1505
1745
|
this.toolProgressProjection.emitToolResultSummary(item);
|
|
1506
1746
|
this.toolProgressProjection.emitToolResultOutput(item);
|
|
1507
1747
|
}
|
|
1748
|
+
this.toolProgressProjection.approvalTimeoutKinds.clear();
|
|
1749
|
+
for (const delivery of unsettledAsyncDeliveries) await this.asyncDeliveryProjection.deliver(delivery);
|
|
1508
1750
|
this.assistantProjection.finalizeAnswerCandidate(turn);
|
|
1509
1751
|
this.activeCompactionItemIds.clear();
|
|
1510
1752
|
await this.reasoningProjection.maybeEndReasoning();
|
|
@@ -1566,24 +1808,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1566
1808
|
return usageLimitMessage ? createCodexUsageLimitPromptError(usageLimitMessage) : readCodexErrorNotificationMessage(params);
|
|
1567
1809
|
}
|
|
1568
1810
|
emitAgentEvent(event) {
|
|
1569
|
-
|
|
1570
|
-
emitAgentEvent({
|
|
1571
|
-
runId: this.params.runId,
|
|
1572
|
-
stream: event.stream,
|
|
1573
|
-
data: event.data,
|
|
1574
|
-
...this.params.sessionKey ? { sessionKey: this.params.sessionKey } : {}
|
|
1575
|
-
});
|
|
1576
|
-
} catch (error) {
|
|
1577
|
-
embeddedAgentLog.debug("codex app-server global agent event emit failed", { error });
|
|
1578
|
-
}
|
|
1579
|
-
try {
|
|
1580
|
-
const maybePromise = this.params.onAgentEvent?.(event);
|
|
1581
|
-
Promise.resolve(maybePromise).catch((error) => {
|
|
1582
|
-
embeddedAgentLog.debug("codex app-server agent event handler rejected", { error });
|
|
1583
|
-
});
|
|
1584
|
-
} catch (error) {
|
|
1585
|
-
embeddedAgentLog.debug("codex app-server agent event handler threw", { error });
|
|
1586
|
-
}
|
|
1811
|
+
emitCodexAgentEvent(this.params, event);
|
|
1587
1812
|
}
|
|
1588
1813
|
isHookNotificationForCurrentThread(params) {
|
|
1589
1814
|
const threadId = readStringField(params, "threadId");
|
|
@@ -1592,11 +1817,28 @@ var CodexAppServerEventProjector = class {
|
|
|
1592
1817
|
}
|
|
1593
1818
|
};
|
|
1594
1819
|
//#endregion
|
|
1820
|
+
//#region extensions/codex/src/app-server/mcp-tool-metadata.ts
|
|
1821
|
+
/** Hosted app ownership is authoritative only on metadata supplied by Codex. */
|
|
1822
|
+
function readCodexMcpToolConnectorId(tool) {
|
|
1823
|
+
const metadata = asOptionalRecord(asOptionalRecord(tool)?.["_meta"]);
|
|
1824
|
+
return normalizeOptionalString(metadata?.connector_id) ?? normalizeOptionalString(metadata?.connectorId);
|
|
1825
|
+
}
|
|
1826
|
+
/** Preserve MCP App visibility so model-only tools cannot become widget authority. */
|
|
1827
|
+
function readCodexMcpToolUiVisibility(tool) {
|
|
1828
|
+
const visibility = asOptionalRecord(asOptionalRecord(asOptionalRecord(tool)?.["_meta"])?.ui)?.visibility;
|
|
1829
|
+
if (!Array.isArray(visibility)) return;
|
|
1830
|
+
return [...new Set(visibility.filter((value) => value === "app" || value === "model"))].toSorted();
|
|
1831
|
+
}
|
|
1832
|
+
//#endregion
|
|
1595
1833
|
//#region extensions/codex/src/app-server/native-mcp-app.ts
|
|
1834
|
+
const CODEX_APPS_MCP_SERVER$1 = "codex_apps";
|
|
1596
1835
|
function readMcpAppResourceUri(item) {
|
|
1597
1836
|
const uri = normalizeOptionalString(asOptionalRecord(item.appContext)?.resourceUri) ?? normalizeOptionalString(item.mcpAppResourceUri);
|
|
1598
1837
|
return uri?.startsWith("ui://") ? uri : void 0;
|
|
1599
1838
|
}
|
|
1839
|
+
function readMcpAppConnectorId(item) {
|
|
1840
|
+
return normalizeOptionalString(asOptionalRecord(item.appContext)?.connectorId);
|
|
1841
|
+
}
|
|
1600
1842
|
function readMcpToolResult(item) {
|
|
1601
1843
|
const result = asOptionalRecord(item.result);
|
|
1602
1844
|
if (!result || !Array.isArray(result.content)) return;
|
|
@@ -1634,13 +1876,16 @@ function createNativeMcpRuntime(params) {
|
|
|
1634
1876
|
launchSummary: "Codex native MCP connection",
|
|
1635
1877
|
toolCount: Object.keys(status.tools).length
|
|
1636
1878
|
}])),
|
|
1637
|
-
tools: loaded.flatMap((status) => statusTools(status).map((tool) =>
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1879
|
+
tools: loaded.flatMap((status) => statusTools(status).map((tool) => {
|
|
1880
|
+
const uiVisibility = readCodexMcpToolUiVisibility(tool);
|
|
1881
|
+
return Object.assign({
|
|
1882
|
+
serverName: status.name,
|
|
1883
|
+
safeServerName: status.name,
|
|
1884
|
+
toolName: String(tool.name),
|
|
1885
|
+
inputSchema: asOptionalRecord(tool.inputSchema) ?? { type: "object" },
|
|
1886
|
+
fallbackDescription: normalizeOptionalString(tool.description) ?? String(tool.name)
|
|
1887
|
+
}, uiVisibility ? { uiVisibility } : {});
|
|
1888
|
+
}))
|
|
1644
1889
|
};
|
|
1645
1890
|
return catalog;
|
|
1646
1891
|
};
|
|
@@ -1668,11 +1913,18 @@ function createNativeMcpRuntime(params) {
|
|
|
1668
1913
|
const status = (await loadStatuses()).find((entry) => entry.name === serverName);
|
|
1669
1914
|
return { tools: status ? statusTools(status) : [] };
|
|
1670
1915
|
},
|
|
1671
|
-
readResource: async (serverName, uri) =>
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1916
|
+
readResource: async (serverName, uri) => {
|
|
1917
|
+
const isCodexAppsServer = serverName === CODEX_APPS_MCP_SERVER$1;
|
|
1918
|
+
const response = await params.client.request("mcpServer/resource/read", {
|
|
1919
|
+
threadId: params.threadId,
|
|
1920
|
+
...isCodexAppsServer ? { originCallId: params.originCallId } : {},
|
|
1921
|
+
server: serverName,
|
|
1922
|
+
uri,
|
|
1923
|
+
...params.connectorId ? { connectorId: params.connectorId } : {}
|
|
1924
|
+
});
|
|
1925
|
+
if (isCodexAppsServer && response.originCallId !== params.originCallId) throw new Error(`Codex MCP resource response originCallId mismatch: expected ${params.originCallId}, received ${response.originCallId}`);
|
|
1926
|
+
return response;
|
|
1927
|
+
},
|
|
1676
1928
|
listResources: async (serverName) => {
|
|
1677
1929
|
return { resources: (await loadStatuses()).find((entry) => entry.name === serverName)?.resources ?? [] };
|
|
1678
1930
|
},
|
|
@@ -1685,15 +1937,25 @@ function createNativeMcpRuntime(params) {
|
|
|
1685
1937
|
}
|
|
1686
1938
|
function createCodexNativeMcpAppResultDetailsPreparer(params) {
|
|
1687
1939
|
if (params.attempt.config?.mcp?.apps?.enabled !== true) return;
|
|
1688
|
-
const runtime = createNativeMcpRuntime(params);
|
|
1689
1940
|
return async (item) => {
|
|
1690
1941
|
const serverName = normalizeOptionalString(item.server);
|
|
1691
1942
|
const toolName = normalizeOptionalString(item.tool);
|
|
1692
1943
|
const uiResourceUri = readMcpAppResourceUri(item);
|
|
1944
|
+
const connectorId = readMcpAppConnectorId(item);
|
|
1693
1945
|
const toolResult = readMcpToolResult(item);
|
|
1694
1946
|
if (!serverName || !toolName || !uiResourceUri || !toolResult) return;
|
|
1695
|
-
|
|
1696
|
-
|
|
1947
|
+
if (serverName === CODEX_APPS_MCP_SERVER$1 && !connectorId) return;
|
|
1948
|
+
const runtime = createNativeMcpRuntime({
|
|
1949
|
+
...params,
|
|
1950
|
+
originCallId: item.id,
|
|
1951
|
+
...connectorId ? { connectorId } : {}
|
|
1952
|
+
});
|
|
1953
|
+
const tools = (await runtime.listTools?.(serverName))?.tools ?? [];
|
|
1954
|
+
const allowedAppToolNames = new Set(tools.filter((tool) => {
|
|
1955
|
+
const uiVisibility = readCodexMcpToolUiVisibility(tool);
|
|
1956
|
+
return (uiVisibility === void 0 || uiVisibility.includes("app")) && (serverName !== CODEX_APPS_MCP_SERVER$1 || readCodexMcpToolConnectorId(tool) === connectorId);
|
|
1957
|
+
}).map((tool) => tool.name));
|
|
1958
|
+
if (!allowedAppToolNames.has(toolName)) return;
|
|
1697
1959
|
return await prepareHarnessNativeMcpAppPreview({
|
|
1698
1960
|
runtime,
|
|
1699
1961
|
serverName,
|
|
@@ -1708,184 +1970,347 @@ function createCodexNativeMcpAppResultDetailsPreparer(params) {
|
|
|
1708
1970
|
};
|
|
1709
1971
|
}
|
|
1710
1972
|
//#endregion
|
|
1973
|
+
//#region extensions/codex/src/app-server/plan-compaction-state.ts
|
|
1974
|
+
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.";
|
|
1975
|
+
const PROGRESS_CARD_MAX_STEPS = 50;
|
|
1976
|
+
const PROGRESS_CARD_MAX_STEP_UTF8_BYTES = 512;
|
|
1977
|
+
const PROGRESS_CARD_MAX_UTF8_BYTES = 8 * 1024;
|
|
1978
|
+
const RESTORED_PLAN_MAX_MARKDOWN_BYTES = 2 * 1024;
|
|
1979
|
+
const RESTORED_PLAN_MAX_PAYLOAD_BYTES = 32 * 1024;
|
|
1980
|
+
const RESTORED_PLAN_TRUNCATION_SUFFIX = "…";
|
|
1981
|
+
function canonicalizeNativeProgressCardInput(input) {
|
|
1982
|
+
const markdown = input.markdown === void 0 ? void 0 : truncateUtf8(stripInvisibleUnicode(input.markdown), PROGRESS_CARD_MAX_UTF8_BYTES);
|
|
1983
|
+
const plan = [];
|
|
1984
|
+
let hasInProgressStep = false;
|
|
1985
|
+
for (const step of input.steps.slice(0, PROGRESS_CARD_MAX_STEPS)) {
|
|
1986
|
+
const text = truncateUtf8(stripInvisibleUnicode(step.step), PROGRESS_CARD_MAX_STEP_UTF8_BYTES);
|
|
1987
|
+
if (!text.trim()) continue;
|
|
1988
|
+
let status = step.status;
|
|
1989
|
+
if (status === "in_progress") if (hasInProgressStep) status = "pending";
|
|
1990
|
+
else hasInProgressStep = true;
|
|
1991
|
+
plan.push({
|
|
1992
|
+
step: text,
|
|
1993
|
+
status
|
|
1994
|
+
});
|
|
1995
|
+
}
|
|
1996
|
+
return {
|
|
1997
|
+
...markdown !== void 0 ? { markdown } : {},
|
|
1998
|
+
plan
|
|
1999
|
+
};
|
|
2000
|
+
}
|
|
2001
|
+
/** Retains the latest projected plan so Codex compaction cannot discard it. */
|
|
2002
|
+
var CodexCompactionPlanState = class {
|
|
2003
|
+
record(event) {
|
|
2004
|
+
if (event.stream !== "plan") return;
|
|
2005
|
+
const plan = readBoundedPlan(event.data.explanation, event.data.steps);
|
|
2006
|
+
this.latestPlan = plan;
|
|
2007
|
+
}
|
|
2008
|
+
/** Retains markdown that migration-only plan events intentionally omit. */
|
|
2009
|
+
recordProgressCardInput(value) {
|
|
2010
|
+
if (!isJsonObject(value)) return;
|
|
2011
|
+
this.latestPlan = readBoundedPlan(value.markdown, value.plan);
|
|
2012
|
+
}
|
|
2013
|
+
async restore(params) {
|
|
2014
|
+
if (!this.latestPlan) return;
|
|
2015
|
+
await params.client.request("thread/inject_items", {
|
|
2016
|
+
threadId: params.threadId,
|
|
2017
|
+
items: [{
|
|
2018
|
+
type: "message",
|
|
2019
|
+
role: "user",
|
|
2020
|
+
content: [{
|
|
2021
|
+
type: "input_text",
|
|
2022
|
+
text: `${RESTORED_PLAN_PREAMBLE}\n${serializePlan(this.latestPlan)}`
|
|
2023
|
+
}]
|
|
2024
|
+
}]
|
|
2025
|
+
}, {
|
|
2026
|
+
timeoutMs: params.timeoutMs,
|
|
2027
|
+
signal: params.signal
|
|
2028
|
+
});
|
|
2029
|
+
}
|
|
2030
|
+
};
|
|
2031
|
+
function readBoundedPlan(markdownValue, stepsValue) {
|
|
2032
|
+
const canonical = canonicalizeNativeProgressCardInput({
|
|
2033
|
+
...typeof markdownValue === "string" ? { markdown: markdownValue } : {},
|
|
2034
|
+
steps: readPlanSteps(stepsValue)
|
|
2035
|
+
});
|
|
2036
|
+
const markdown = canonical.markdown === void 0 ? void 0 : truncateUtf8(canonical.markdown, RESTORED_PLAN_MAX_MARKDOWN_BYTES);
|
|
2037
|
+
const steps = [];
|
|
2038
|
+
for (const step of canonical.plan) {
|
|
2039
|
+
const candidate = {
|
|
2040
|
+
...markdown?.trim() ? { markdown } : {},
|
|
2041
|
+
steps: [...steps, step]
|
|
2042
|
+
};
|
|
2043
|
+
if (Buffer$1.byteLength(serializePlan(candidate), "utf8") > RESTORED_PLAN_MAX_PAYLOAD_BYTES) break;
|
|
2044
|
+
steps.push(step);
|
|
2045
|
+
}
|
|
2046
|
+
return markdown?.trim() || steps.length > 0 ? {
|
|
2047
|
+
...markdown?.trim() ? { markdown } : {},
|
|
2048
|
+
steps
|
|
2049
|
+
} : void 0;
|
|
2050
|
+
}
|
|
2051
|
+
function serializePlan(plan) {
|
|
2052
|
+
return JSON.stringify({
|
|
2053
|
+
markdown: plan.markdown,
|
|
2054
|
+
plan: plan.steps
|
|
2055
|
+
});
|
|
2056
|
+
}
|
|
2057
|
+
function truncateUtf8(value, maxBytes) {
|
|
2058
|
+
if (Buffer$1.byteLength(value, "utf8") <= maxBytes) return value;
|
|
2059
|
+
return `${truncateUtf8Prefix(value, maxBytes - Buffer$1.byteLength(RESTORED_PLAN_TRUNCATION_SUFFIX, "utf8"))}${RESTORED_PLAN_TRUNCATION_SUFFIX}`;
|
|
2060
|
+
}
|
|
2061
|
+
function readPlanSteps(value) {
|
|
2062
|
+
if (!Array.isArray(value)) return [];
|
|
2063
|
+
return value.flatMap((entry) => {
|
|
2064
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return [];
|
|
2065
|
+
const { step, status } = entry;
|
|
2066
|
+
if (typeof step !== "string" || !isPlanStatus(status)) return [];
|
|
2067
|
+
return [{
|
|
2068
|
+
step,
|
|
2069
|
+
status
|
|
2070
|
+
}];
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
2073
|
+
function isPlanStatus(value) {
|
|
2074
|
+
return value === "pending" || value === "in_progress" || value === "completed";
|
|
2075
|
+
}
|
|
2076
|
+
//#endregion
|
|
1711
2077
|
//#region extensions/codex/src/app-server/user-input-bridge.ts
|
|
1712
|
-
/**
|
|
2078
|
+
/** Owns per-turn Codex request_user_input and ordinary MCP elicitation lifecycles. */
|
|
1713
2079
|
const DEFAULT_USER_INPUT_TIMEOUT_MS = 15 * 6e4;
|
|
1714
2080
|
const NONBLOCKING_USER_INPUT_TIMEOUT_MS = 12e4;
|
|
1715
|
-
|
|
2081
|
+
const MAX_USER_INPUT_QUESTIONS = 3;
|
|
2082
|
+
const MAX_USER_INPUT_OPTIONS = 4;
|
|
2083
|
+
const MAX_USER_INPUT_ID = 256;
|
|
2084
|
+
const MAX_USER_INPUT_HEADER = 64;
|
|
2085
|
+
const MAX_USER_INPUT_TEXT = 4096;
|
|
2086
|
+
/** Creates the single per-turn owner for Codex operator input. */
|
|
1716
2087
|
function createCodexUserInputBridge(params) {
|
|
1717
|
-
let sensitiveInput;
|
|
1718
|
-
let pendingGateway;
|
|
1719
2088
|
const gatewayCall = params.gatewayCall ?? callGatewayTool;
|
|
1720
|
-
const
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
2089
|
+
const jobs = [];
|
|
2090
|
+
let activeCompletion;
|
|
2091
|
+
const inputSessionKey = params.paramsForRun.sessionKey ?? params.paramsForRun.sessionId;
|
|
2092
|
+
const pump = () => {
|
|
2093
|
+
const job = jobs[0];
|
|
2094
|
+
if (activeCompletion || !job) return;
|
|
2095
|
+
activeCompletion = job.run(job.abort.signal).catch((error) => {
|
|
2096
|
+
embeddedAgentLog.warn("failed to bridge codex operator input", { error });
|
|
2097
|
+
return job.abort.signal.aborted ? job.cancelValue : job.failureValue;
|
|
2098
|
+
}).then((value) => {
|
|
2099
|
+
job.resolve(job.abort.signal.aborted ? job.cancelValue : value ?? job.failureValue);
|
|
2100
|
+
}).finally(() => {
|
|
2101
|
+
if (jobs[0] === job) jobs.shift();
|
|
2102
|
+
activeCompletion = void 0;
|
|
2103
|
+
pump();
|
|
2104
|
+
});
|
|
1731
2105
|
};
|
|
1732
|
-
const
|
|
1733
|
-
|
|
2106
|
+
const enqueue = (definition) => {
|
|
2107
|
+
if (params.signal?.aborted) return Promise.resolve(definition.cancelValue);
|
|
2108
|
+
return new Promise((resolve) => {
|
|
2109
|
+
jobs.push({
|
|
2110
|
+
...definition,
|
|
2111
|
+
resolve
|
|
2112
|
+
});
|
|
2113
|
+
pump();
|
|
2114
|
+
});
|
|
1734
2115
|
};
|
|
2116
|
+
const cancelJob = (job) => {
|
|
2117
|
+
const index = jobs.indexOf(job);
|
|
2118
|
+
if (index < 0) return;
|
|
2119
|
+
if (index === 0) {
|
|
2120
|
+
job.abort.abort(/* @__PURE__ */ new Error("Codex operator input request cancelled"));
|
|
2121
|
+
return;
|
|
2122
|
+
}
|
|
2123
|
+
jobs.splice(index, 1);
|
|
2124
|
+
job.resolve(job.cancelValue);
|
|
2125
|
+
};
|
|
2126
|
+
const cancelPending = async () => {
|
|
2127
|
+
const pendingCompletion = activeCompletion;
|
|
2128
|
+
const queuedJobs = jobs.splice(1);
|
|
2129
|
+
for (const job of queuedJobs) job.resolve(job.cancelValue);
|
|
2130
|
+
jobs[0]?.abort.abort(/* @__PURE__ */ new Error("Codex operator input request cancelled"));
|
|
2131
|
+
await pendingCompletion;
|
|
2132
|
+
};
|
|
2133
|
+
const execute = (input, timeoutMs, signal) => agentHarnessStructuredInput.run({
|
|
2134
|
+
input,
|
|
2135
|
+
sessionKey: inputSessionKey,
|
|
2136
|
+
agentId: params.paramsForRun.agentId,
|
|
2137
|
+
runId: params.paramsForRun.runId,
|
|
2138
|
+
timeoutMs,
|
|
2139
|
+
gatewayCall,
|
|
2140
|
+
delivery: params.paramsForRun,
|
|
2141
|
+
signal,
|
|
2142
|
+
promptOptions: {
|
|
2143
|
+
formatText: formatCodexDisplayText,
|
|
2144
|
+
unsupportedIntro: "Codex input request could not be shown:",
|
|
2145
|
+
urlIntro: "Codex needs confirmation:"
|
|
2146
|
+
}
|
|
2147
|
+
});
|
|
2148
|
+
params.signal?.addEventListener("abort", () => void cancelPending(), { once: true });
|
|
1735
2149
|
return {
|
|
1736
2150
|
async handleRequest(request) {
|
|
1737
2151
|
const requestParams = readUserInputParams(request.params);
|
|
1738
|
-
if (!requestParams) return;
|
|
1739
|
-
if (requestParams.threadId !== params.threadId || requestParams.turnId !== params.turnId) return;
|
|
2152
|
+
if (!requestParams || requestParams.threadId !== params.threadId || requestParams.turnId !== params.turnId) return;
|
|
1740
2153
|
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;
|
|
2154
|
+
const timeoutMs = requestParams.isBlocking ? params.paramsForRun.timeoutMs ?? DEFAULT_USER_INPUT_TIMEOUT_MS : NONBLOCKING_USER_INPUT_TIMEOUT_MS;
|
|
2155
|
+
const input = compileUserInputQuestions(requestParams.questions);
|
|
2156
|
+
const cancelValue = emptyUserInputResponse();
|
|
2157
|
+
return await enqueue({
|
|
2158
|
+
requestId: request.id,
|
|
2159
|
+
abort: new AbortController(),
|
|
2160
|
+
cancelValue,
|
|
2161
|
+
failureValue: cancelValue,
|
|
2162
|
+
run: async (signal) => {
|
|
2163
|
+
const result = await execute(input, timeoutMs, signal);
|
|
2164
|
+
return result.status === "answered" ? gatewayAnswersToCodexResponse(result.answers) : cancelValue;
|
|
1764
2165
|
}
|
|
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
2166
|
});
|
|
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
|
|
2167
|
+
},
|
|
2168
|
+
async handleElicitationRequest(request) {
|
|
2169
|
+
if (readRawOwnString(request.params, "threadId") !== params.threadId) return;
|
|
2170
|
+
const requestSnapshot = agentHarnessStructuredInput.snapshot(request.params);
|
|
2171
|
+
if (requestSnapshot === void 0) {
|
|
2172
|
+
const cancelValue = createCodexElicitationResponse("cancel");
|
|
2173
|
+
return await enqueue({
|
|
2174
|
+
requestId: request.id,
|
|
2175
|
+
abort: new AbortController(),
|
|
2176
|
+
cancelValue,
|
|
2177
|
+
failureValue: declineElicitation("OpenClaw could not handle this elicitation."),
|
|
2178
|
+
run: async (signal) => {
|
|
2179
|
+
const result = await execute({
|
|
2180
|
+
kind: "unsupported",
|
|
2181
|
+
message: "OpenClaw declined a malformed or over-limit MCP elicitation request."
|
|
2182
|
+
}, params.paramsForRun.timeoutMs ?? DEFAULT_USER_INPUT_TIMEOUT_MS, signal);
|
|
2183
|
+
return result.status === "unsupported" ? declineElicitation(result.message) : cancelValue;
|
|
2184
|
+
}
|
|
1796
2185
|
});
|
|
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
2186
|
}
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
2187
|
+
const { compileCodexOrdinaryElicitation } = await import("./elicitation-input-DMkeki8d.js");
|
|
2188
|
+
const compiled = compileCodexOrdinaryElicitation({
|
|
2189
|
+
value: requestSnapshot,
|
|
2190
|
+
threadId: params.threadId,
|
|
2191
|
+
turnId: params.turnId
|
|
2192
|
+
});
|
|
2193
|
+
if (compiled.kind === "ignored") return;
|
|
2194
|
+
const cancelValue = createCodexElicitationResponse("cancel");
|
|
2195
|
+
const timeoutMs = params.paramsForRun.timeoutMs ?? DEFAULT_USER_INPUT_TIMEOUT_MS;
|
|
2196
|
+
return await enqueue({
|
|
2197
|
+
requestId: request.id,
|
|
2198
|
+
abort: new AbortController(),
|
|
2199
|
+
cancelValue,
|
|
2200
|
+
failureValue: declineElicitation("OpenClaw could not handle this elicitation."),
|
|
2201
|
+
run: async (signal) => {
|
|
2202
|
+
const result = await execute(compiled.input, timeoutMs, signal);
|
|
2203
|
+
if (result.status === "answered") return createCodexElicitationResponse("accept", compiled.input.kind === "ready" && compiled.input.plan.kind === "url" ? null : result.content);
|
|
2204
|
+
if (result.status === "declined") return declineElicitation(result.message);
|
|
2205
|
+
if (result.status === "unsupported") return declineElicitation(result.message);
|
|
2206
|
+
return cancelValue;
|
|
2207
|
+
}
|
|
2208
|
+
});
|
|
1814
2209
|
},
|
|
1815
2210
|
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"));
|
|
2211
|
+
if (notification.method !== "serverRequest/resolved" || !isJsonObject(notification.params)) return;
|
|
2212
|
+
const requestId = readRequestId(notification.params);
|
|
2213
|
+
if (requestId === void 0 || readOwnString(notification.params, "threadId") !== params.threadId) return;
|
|
2214
|
+
const job = jobs.find((candidate) => typeof candidate.requestId === typeof requestId && candidate.requestId === requestId);
|
|
2215
|
+
if (job) cancelJob(job);
|
|
1822
2216
|
},
|
|
1823
|
-
cancelPending
|
|
1824
|
-
resolveSecret(emptyUserInputResponse());
|
|
1825
|
-
cancelGateway();
|
|
1826
|
-
}
|
|
2217
|
+
cancelPending
|
|
1827
2218
|
};
|
|
1828
2219
|
}
|
|
2220
|
+
function compileUserInputQuestions(questions) {
|
|
2221
|
+
return agentHarnessStructuredInput.compileQuestions({
|
|
2222
|
+
questions,
|
|
2223
|
+
intro: "Codex needs input:"
|
|
2224
|
+
});
|
|
2225
|
+
}
|
|
1829
2226
|
function readUserInputParams(value) {
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
const
|
|
1833
|
-
const
|
|
1834
|
-
const
|
|
1835
|
-
|
|
2227
|
+
const snapshot = agentHarnessStructuredInput.snapshot(value);
|
|
2228
|
+
if (!agentHarnessStructuredInput.isRecord(snapshot)) return;
|
|
2229
|
+
const threadId = readBoundedUserInputText(snapshot, "threadId", MAX_USER_INPUT_ID);
|
|
2230
|
+
const turnId = readBoundedUserInputText(snapshot, "turnId", MAX_USER_INPUT_ID);
|
|
2231
|
+
const itemId = readBoundedUserInputText(snapshot, "itemId", MAX_USER_INPUT_ID);
|
|
2232
|
+
const questions = readArray(snapshot, "questions", MAX_USER_INPUT_QUESTIONS);
|
|
2233
|
+
if (!threadId || !turnId || !itemId || !questions) return;
|
|
2234
|
+
const parsed = [];
|
|
2235
|
+
for (const questionValue of questions) {
|
|
2236
|
+
const question = readQuestion(questionValue);
|
|
2237
|
+
if (!question) return;
|
|
2238
|
+
parsed.push(question);
|
|
2239
|
+
}
|
|
1836
2240
|
return {
|
|
1837
2241
|
threadId,
|
|
1838
2242
|
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
|
|
2243
|
+
questions: parsed,
|
|
2244
|
+
isBlocking: readValue(snapshot, "isBlocking") !== false
|
|
1846
2245
|
};
|
|
1847
2246
|
}
|
|
1848
2247
|
function readQuestion(value) {
|
|
1849
|
-
if (!
|
|
1850
|
-
const id =
|
|
1851
|
-
const header =
|
|
1852
|
-
const question =
|
|
2248
|
+
if (!agentHarnessStructuredInput.isRecord(value)) return;
|
|
2249
|
+
const id = readBoundedUserInputText(value, "id", MAX_USER_INPUT_ID);
|
|
2250
|
+
const header = readBoundedUserInputText(value, "header", MAX_USER_INPUT_HEADER);
|
|
2251
|
+
const question = readBoundedUserInputText(value, "question", MAX_USER_INPUT_TEXT);
|
|
1853
2252
|
if (!id || !header || !question) return;
|
|
2253
|
+
const options = readOptions(readValue(value, "options"));
|
|
2254
|
+
if (options === void 0) return;
|
|
1854
2255
|
return {
|
|
1855
2256
|
id,
|
|
1856
2257
|
header,
|
|
1857
2258
|
question,
|
|
1858
|
-
isOther: value
|
|
1859
|
-
isSecret: value
|
|
1860
|
-
|
|
2259
|
+
isOther: readValue(value, "isOther") === true,
|
|
2260
|
+
isSecret: readValue(value, "isSecret") === true,
|
|
2261
|
+
...readValue(value, "multiSelect") === true ? { multiSelect: true } : {},
|
|
2262
|
+
options
|
|
1861
2263
|
};
|
|
1862
2264
|
}
|
|
1863
2265
|
function readOptions(value) {
|
|
1864
|
-
if (
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
2266
|
+
if (value === void 0 || value === null) return null;
|
|
2267
|
+
if (!Array.isArray(value) || value.length > MAX_USER_INPUT_OPTIONS) return;
|
|
2268
|
+
const options = [];
|
|
2269
|
+
for (const entry of value) {
|
|
2270
|
+
if (!agentHarnessStructuredInput.isRecord(entry)) return;
|
|
2271
|
+
const label = readBoundedUserInputText(entry, "label", MAX_USER_INPUT_ID);
|
|
2272
|
+
const description = readBoundedUserInputText(entry, "description", MAX_USER_INPUT_TEXT, true);
|
|
2273
|
+
if (!label) return;
|
|
2274
|
+
options.push({
|
|
2275
|
+
label,
|
|
2276
|
+
...description ? { description } : {}
|
|
2277
|
+
});
|
|
2278
|
+
}
|
|
2279
|
+
return options;
|
|
2280
|
+
}
|
|
2281
|
+
function readValue(record, key) {
|
|
2282
|
+
return Object.hasOwn(record, key) ? record[key] : void 0;
|
|
2283
|
+
}
|
|
2284
|
+
function readBoundedUserInputText(record, key, maximum, allowEmpty = false) {
|
|
2285
|
+
const value = readValue(record, key);
|
|
2286
|
+
return typeof value === "string" && value.length <= maximum && (allowEmpty || value.length > 0) ? value : void 0;
|
|
2287
|
+
}
|
|
2288
|
+
function readArray(record, key, maximum) {
|
|
2289
|
+
const value = readValue(record, key);
|
|
2290
|
+
return Array.isArray(value) && value.length <= maximum ? value : void 0;
|
|
2291
|
+
}
|
|
2292
|
+
function readOwnString(record, key) {
|
|
2293
|
+
const descriptor = Object.getOwnPropertyDescriptor(record, key);
|
|
2294
|
+
return descriptor && "value" in descriptor && typeof descriptor.value === "string" ? descriptor.value : void 0;
|
|
1876
2295
|
}
|
|
1877
|
-
function
|
|
1878
|
-
|
|
2296
|
+
function readRawOwnString(value, key) {
|
|
2297
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
2298
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
2299
|
+
return descriptor && "value" in descriptor && typeof descriptor.value === "string" ? descriptor.value : void 0;
|
|
2300
|
+
}
|
|
2301
|
+
function readRequestId(record) {
|
|
2302
|
+
const descriptor = Object.getOwnPropertyDescriptor(record, "requestId");
|
|
2303
|
+
const value = descriptor && "value" in descriptor ? descriptor.value : void 0;
|
|
2304
|
+
return typeof value === "string" || typeof value === "number" ? value : void 0;
|
|
1879
2305
|
}
|
|
1880
2306
|
function gatewayAnswersToCodexResponse(answers) {
|
|
1881
2307
|
return { answers: Object.fromEntries(Object.entries(answers).map(([questionId, values]) => [questionId, { answers: values }])) };
|
|
1882
2308
|
}
|
|
1883
2309
|
function emptyUserInputResponse() {
|
|
1884
|
-
return emptyAgentHarnessUserInputAnswers();
|
|
2310
|
+
return { ...emptyAgentHarnessUserInputAnswers() };
|
|
1885
2311
|
}
|
|
1886
|
-
function
|
|
1887
|
-
|
|
1888
|
-
return typeof value === "string" || typeof value === "number" ? value : void 0;
|
|
2312
|
+
function declineElicitation(message) {
|
|
2313
|
+
return createCodexElicitationResponse("decline", null, message ? { message } : null);
|
|
1889
2314
|
}
|
|
1890
2315
|
//#endregion
|
|
1891
2316
|
//#region extensions/codex/src/app-server/run-attempt-active-turn.ts
|
|
@@ -1894,12 +2319,14 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
1894
2319
|
const { context, turnState } = prompt;
|
|
1895
2320
|
const { runtime, attemptTools } = context;
|
|
1896
2321
|
const { connection } = runtime;
|
|
1897
|
-
const { params, runAbortController, terminalState, abortExplicitly, abortFromUpstream, bindingStore, bindingIdentity, sessionAgentId, sandboxSessionKey, effectiveCwd } = connection;
|
|
1898
|
-
const { dynamicToolParams, computerContextEpoch, toolBridge } = attemptTools;
|
|
2322
|
+
const { params, runAbortController, terminalState, abortExplicitly, abortFromUpstream, bindingStore, bindingIdentity, sessionAgentId, sandboxSessionKey, contextSessionKey, effectiveCwd } = connection;
|
|
2323
|
+
const { dynamicToolParams, compactionPlanState, computerContextEpoch, toolBridge } = attemptTools;
|
|
1899
2324
|
const { state, userInputBridgeRef, steeringQueueRef, turnWatches, completeTurn, interruptTurn } = turnRuntime;
|
|
1900
2325
|
const { emitExecutionPhaseOnce, emitLifecycleStart, maybeAnnounceFastModeAutoOff } = lifecycle;
|
|
1901
2326
|
const { enqueueNotification } = notifications;
|
|
1902
2327
|
const activeTurnId = turn.turn.id;
|
|
2328
|
+
const progressCardTool = toolBridge.availableTools.find((tool) => tool.name === "progress_card");
|
|
2329
|
+
let nativePlanUpdateOrdinal = 0;
|
|
1903
2330
|
const prepareNativeMcpAppResultDetails = createCodexNativeMcpAppResultDetailsPreparer({
|
|
1904
2331
|
client: resourceState.client,
|
|
1905
2332
|
threadId: resourceState.thread.threadId,
|
|
@@ -1934,6 +2361,16 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
1934
2361
|
}, resourceState.thread.threadId, activeTurnId, {
|
|
1935
2362
|
initialContextTokens: connection.mutable.startupContextTokens,
|
|
1936
2363
|
nativePostToolUseRelayEnabled: resourceState.nativeHookRelay?.allowedEvents.includes("post_tool_use") === true && resourceState.nativeHookRelay.shouldRelayEvent("post_tool_use"),
|
|
2364
|
+
asyncUserMessageAllowed: params.disableTools !== true && (params.toolsAllow === void 0 || toolBridge.availableTools.some((tool) => tool.name === "message")),
|
|
2365
|
+
onAsyncDelivery: async (delivery) => {
|
|
2366
|
+
return await codexTranscriptMirrorRuntime.deliverAsyncMessageBestEffort({
|
|
2367
|
+
params: dynamicToolParams,
|
|
2368
|
+
cwd: effectiveCwd,
|
|
2369
|
+
threadId: resourceState.thread.threadId,
|
|
2370
|
+
turnId: activeTurnId,
|
|
2371
|
+
...delivery
|
|
2372
|
+
});
|
|
2373
|
+
},
|
|
1937
2374
|
readRecentRateLimits: () => readRecentCodexRateLimits(resourceState.client),
|
|
1938
2375
|
runAbortSignal: runAbortController.signal,
|
|
1939
2376
|
remoteWorkspaceRoot: connection.appServer.remoteWorkspaceRoot,
|
|
@@ -1948,12 +2385,39 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
1948
2385
|
trajectoryRecorder,
|
|
1949
2386
|
resolveDynamicToolResultContentSource: toolBridge.resultContentSourceForTool,
|
|
1950
2387
|
onNativeToolResultRecorded: maybeAnnounceFastModeAutoOff,
|
|
2388
|
+
...progressCardTool ? { onNativePlanUpdate: async (update) => {
|
|
2389
|
+
nativePlanUpdateOrdinal += 1;
|
|
2390
|
+
try {
|
|
2391
|
+
const input = canonicalizeNativeProgressCardInput(update);
|
|
2392
|
+
await progressCardTool.execute(`codex-native-plan:${activeTurnId}:${nativePlanUpdateOrdinal}`, input, runAbortController.signal);
|
|
2393
|
+
} catch (error) {
|
|
2394
|
+
embeddedAgentLog.warn("failed to persist native Codex plan to progress card", {
|
|
2395
|
+
runId: params.runId,
|
|
2396
|
+
threadId: resourceState.thread.threadId,
|
|
2397
|
+
error: formatErrorMessage(error)
|
|
2398
|
+
});
|
|
2399
|
+
}
|
|
2400
|
+
} } : {},
|
|
1951
2401
|
...prepareNativeMcpAppResultDetails ? { prepareNativeMcpAppResultDetails } : {},
|
|
1952
2402
|
upstreamUserText: turnState.codexTurnPromptText,
|
|
1953
|
-
onContextCompacted: () => {
|
|
2403
|
+
onContextCompacted: async () => {
|
|
1954
2404
|
computerContextEpoch.value += 1;
|
|
1955
2405
|
delete computerContextEpoch.frameToolCallId;
|
|
1956
2406
|
delete computerContextEpoch.frameImageIdentity;
|
|
2407
|
+
try {
|
|
2408
|
+
await compactionPlanState.restore({
|
|
2409
|
+
client: resourceState.client,
|
|
2410
|
+
threadId: resourceState.thread.threadId,
|
|
2411
|
+
timeoutMs: connection.appServer.requestTimeoutMs,
|
|
2412
|
+
signal: runAbortController.signal
|
|
2413
|
+
});
|
|
2414
|
+
} catch (error) {
|
|
2415
|
+
embeddedAgentLog.warn("failed to restore Codex plan state after compaction", {
|
|
2416
|
+
runId: params.runId,
|
|
2417
|
+
threadId: resourceState.thread.threadId,
|
|
2418
|
+
error: formatErrorMessage(error)
|
|
2419
|
+
});
|
|
2420
|
+
}
|
|
1957
2421
|
}
|
|
1958
2422
|
});
|
|
1959
2423
|
if (isTerminalTurnStatus(turn.turn.status)) state.terminalTurnNotificationQueued = true;
|
|
@@ -1964,6 +2428,18 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
1964
2428
|
turnWatches.armAttemptIdleWatch();
|
|
1965
2429
|
turnWatches.touchActivity("turn:start", { attemptProgress: true });
|
|
1966
2430
|
for (const failure of pendingNativePreToolUseFailures.splice(0)) activeProjector.recordNativeToolPreToolUseFailure(failure);
|
|
2431
|
+
const notifyUserMessagePersisted = createCodexAppServerUserMessagePersistenceNotifier(params);
|
|
2432
|
+
const promptMirrorPromise = mirrorPromptAtTurnStartBestEffort({
|
|
2433
|
+
params,
|
|
2434
|
+
agentId: sessionAgentId,
|
|
2435
|
+
notifyUserMessagePersisted,
|
|
2436
|
+
sessionKey: sandboxSessionKey,
|
|
2437
|
+
cwd: effectiveCwd,
|
|
2438
|
+
threadId: resourceState.thread.threadId,
|
|
2439
|
+
turnId: activeTurnId,
|
|
2440
|
+
upstreamUserText: turnState.codexTurnPromptText
|
|
2441
|
+
});
|
|
2442
|
+
await promptMirrorPromise;
|
|
1967
2443
|
if (resourceState.turnRoute) try {
|
|
1968
2444
|
await resourceState.turnRoute.bindTurn(activeTurnId);
|
|
1969
2445
|
} catch (error) {
|
|
@@ -1974,24 +2450,53 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
1974
2450
|
throw error;
|
|
1975
2451
|
}
|
|
1976
2452
|
}
|
|
1977
|
-
if (!state.completed && isTerminalTurnStatus(turn.turn.status))
|
|
1978
|
-
|
|
1979
|
-
|
|
2453
|
+
if (!state.completed && isTerminalTurnStatus(turn.turn.status)) {
|
|
2454
|
+
if (!isJsonObject(turn.turn)) throw new Error("Codex turn completion payload is not a JSON object");
|
|
2455
|
+
await enqueueNotification({
|
|
2456
|
+
method: "turn/completed",
|
|
2457
|
+
params: {
|
|
2458
|
+
threadId: resourceState.thread.threadId,
|
|
2459
|
+
turnId: activeTurnId,
|
|
2460
|
+
turn: turn.turn
|
|
2461
|
+
}
|
|
2462
|
+
}, {
|
|
1980
2463
|
threadId: resourceState.thread.threadId,
|
|
1981
|
-
turnId: activeTurnId
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
}, {
|
|
1985
|
-
threadId: resourceState.thread.threadId,
|
|
1986
|
-
turnId: activeTurnId
|
|
1987
|
-
});
|
|
2464
|
+
turnId: activeTurnId
|
|
2465
|
+
});
|
|
2466
|
+
}
|
|
1988
2467
|
const activeSteeringQueue = createCodexSteeringQueue({
|
|
1989
2468
|
client: resourceState.client,
|
|
1990
2469
|
threadId: resourceState.thread.threadId,
|
|
1991
2470
|
turnId: activeTurnId,
|
|
1992
2471
|
requestTimeoutMs: connection.appServer.requestTimeoutMs,
|
|
1993
|
-
|
|
1994
|
-
|
|
2472
|
+
signal: runAbortController.signal,
|
|
2473
|
+
beforeConfirmConsumed: async (items) => {
|
|
2474
|
+
const inboundItems = items.filter((item) => item.isInboundUserMessage === true);
|
|
2475
|
+
if (inboundItems.length === 0) return;
|
|
2476
|
+
await promptMirrorPromise;
|
|
2477
|
+
const messages = activeProjector.buildSteeringTranscriptPrefix();
|
|
2478
|
+
if (params.sessionTarget && messages.length > 0) {
|
|
2479
|
+
await codexTranscriptMirrorRuntime.mirror({
|
|
2480
|
+
agentId: sessionAgentId,
|
|
2481
|
+
sessionKey: contextSessionKey,
|
|
2482
|
+
sessionId: params.sessionId,
|
|
2483
|
+
storePath: params.sessionTarget.storePath,
|
|
2484
|
+
cwd: effectiveCwd,
|
|
2485
|
+
messages,
|
|
2486
|
+
idempotencyScope: `codex-app-server:${resourceState.thread.threadId}`,
|
|
2487
|
+
runId: params.runId,
|
|
2488
|
+
runMirrorIdentityPrefix: `${activeTurnId}:`,
|
|
2489
|
+
config: params.config
|
|
2490
|
+
});
|
|
2491
|
+
activeProjector.markSteeringTranscriptPersisted();
|
|
2492
|
+
}
|
|
2493
|
+
for (const item of inboundItems) {
|
|
2494
|
+
const recorder = item.userTurnTranscriptRecorder;
|
|
2495
|
+
if (!recorder) continue;
|
|
2496
|
+
await recorder.persistApproved();
|
|
2497
|
+
if (!recorder.hasPersisted()) throw new Error("Codex consumed steering before its user turn was persisted");
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
1995
2500
|
});
|
|
1996
2501
|
steeringQueueRef.current = activeSteeringQueue;
|
|
1997
2502
|
const claimPendingUserInputAnswer = async (text, optionsLocal) => {
|
|
@@ -2058,17 +2563,6 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2058
2563
|
terminalState.terminalOutcomeFrozen = true;
|
|
2059
2564
|
params.abortSignal?.removeEventListener("abort", abortFromUpstream);
|
|
2060
2565
|
};
|
|
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
2566
|
const abortListener = () => {
|
|
2073
2567
|
if (state.timedOut) {
|
|
2074
2568
|
(async () => {
|
|
@@ -2295,10 +2789,7 @@ async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codex
|
|
|
2295
2789
|
path.join(resolvedAgentDir, "agent", "codex-home", "sessions"),
|
|
2296
2790
|
path.join(path.dirname(resolvedAgentDir), "codex-home", "sessions")
|
|
2297
2791
|
];
|
|
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;
|
|
2792
|
+
const rolloutRoot = rolloutPath ? roots.find((root) => isPathStrictlyInside(root, rolloutPath)) : void 0;
|
|
2302
2793
|
if (rolloutPath && rolloutRoot && path.isAbsolute(rolloutPath) && path.extname(rolloutPath) === ".jsonl" && path.basename(rolloutPath).includes(threadId)) try {
|
|
2303
2794
|
const opened = await (await root(rolloutRoot, {
|
|
2304
2795
|
hardlinks: "reject",
|
|
@@ -2555,14 +3046,6 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
2555
3046
|
}
|
|
2556
3047
|
//#endregion
|
|
2557
3048
|
//#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
3049
|
async function prepareCodexAttemptConnection({ params, options }) {
|
|
2567
3050
|
const attemptStartedAt = Date.now();
|
|
2568
3051
|
const profilerEnabled = isCodexAppServerProfilerEnabled(params.config);
|
|
@@ -2575,16 +3058,15 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2575
3058
|
resetAnnounced: false
|
|
2576
3059
|
};
|
|
2577
3060
|
const preDynamicStartupStages = createCodexDynamicToolBuildStageTracker({ enabled: profilerEnabled });
|
|
2578
|
-
const attemptClientFactory = options.clientFactory ?? getLeasedSharedCodexAppServerClient;
|
|
2579
3061
|
const runtimeArtifactRequest = params.captureRuntimeArtifact || params.expectedRuntimeArtifact ? params.expectedRuntimeArtifact ? { expected: params.expectedRuntimeArtifact } : {} : void 0;
|
|
2580
3062
|
const pluginConfig = readCodexPluginConfig(options.pluginConfig);
|
|
3063
|
+
const requirementsToml = readCodexRequirementsToml({});
|
|
2581
3064
|
const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig });
|
|
2582
3065
|
const { sessionAgentId } = resolveSessionAgentIds({
|
|
2583
3066
|
sessionKey: params.sessionKey,
|
|
2584
3067
|
config: params.config,
|
|
2585
3068
|
agentId: params.agentId
|
|
2586
3069
|
});
|
|
2587
|
-
const beforeToolCallPolicy = getBeforeToolCallPolicyDiagnosticState();
|
|
2588
3070
|
preDynamicStartupStages.mark("config");
|
|
2589
3071
|
const resolvedWorkspace = resolveUserPath(params.workspaceDir);
|
|
2590
3072
|
await ensureCodexWorkspaceDirOnce(resolvedWorkspace);
|
|
@@ -2596,14 +3078,36 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2596
3078
|
sessionKey: sandboxSessionKey,
|
|
2597
3079
|
workspaceDir: resolvedWorkspace
|
|
2598
3080
|
});
|
|
3081
|
+
const attemptClientFactory = options.clientFactory ?? (isCodexPairedNodeRemoteExecPlacementSandbox(sandbox) ? createIsolatedCodexAppServerClient : getLeasedSharedCodexAppServerClient);
|
|
2599
3082
|
preDynamicStartupStages.mark("sandbox");
|
|
2600
3083
|
const execPolicy = resolveOpenClawExecPolicyForCodexAppServer({
|
|
3084
|
+
permissionMode: params.permissionMode,
|
|
2601
3085
|
execOverrides: params.execOverrides,
|
|
2602
|
-
approvals: loadExecApprovals(),
|
|
3086
|
+
approvals: params.permissionMode === "full" ? void 0 : loadExecApprovals(),
|
|
2603
3087
|
config: params.config,
|
|
2604
3088
|
agentId: sessionAgentId
|
|
2605
3089
|
});
|
|
2606
3090
|
const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId);
|
|
3091
|
+
const preparedEnvironment = params.hostCapabilities.preparedEnvironment?.();
|
|
3092
|
+
const remoteExec = isCodexRemoteExecPlacementSandbox(sandbox);
|
|
3093
|
+
const preparedShellEnvironment = preparedEnvironment ? {
|
|
3094
|
+
...preparedEnvironment.credentialScrubEnv,
|
|
3095
|
+
...!remoteExec ? preparedEnvironment.localIdentityEnv : void 0
|
|
3096
|
+
} : void 0;
|
|
3097
|
+
const shellEnvironment = preparedShellEnvironment && Object.keys(preparedShellEnvironment).length > 0 ? preparedShellEnvironment : void 0;
|
|
3098
|
+
const disableLoginShell = remoteExec || preparedEnvironment?.managedLocalIdentity === true || preparedEnvironment !== void 0 && Object.keys(preparedEnvironment.credentialScrubEnv).length > 0;
|
|
3099
|
+
const withPreparedProcessEnv = (appServer) => {
|
|
3100
|
+
return shellEnvironment ? {
|
|
3101
|
+
...appServer,
|
|
3102
|
+
start: {
|
|
3103
|
+
...appServer.start,
|
|
3104
|
+
env: {
|
|
3105
|
+
...appServer.start.env,
|
|
3106
|
+
...shellEnvironment
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
} : appServer;
|
|
3110
|
+
};
|
|
2607
3111
|
let bindingIdentity = sessionBindingIdentity({
|
|
2608
3112
|
sessionId: params.sessionId,
|
|
2609
3113
|
sessionKey: params.sessionKey,
|
|
@@ -2650,21 +3154,20 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2650
3154
|
const usesSupervisionConnection = startupBinding?.connectionScope === "supervision";
|
|
2651
3155
|
if (usesSupervisionConnection) activeContextEngine = void 0;
|
|
2652
3156
|
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
|
-
});
|
|
3157
|
+
const resolveRuntimeOptionsForBinding = (binding, selection) => resolveCodexBindingAppServerConnection({
|
|
3158
|
+
binding,
|
|
3159
|
+
pluginConfig,
|
|
3160
|
+
execPolicy,
|
|
3161
|
+
modelProvider: selection.modelProvider,
|
|
3162
|
+
model: selection.model,
|
|
3163
|
+
config: params.config,
|
|
3164
|
+
agentDir,
|
|
3165
|
+
requirementsToml,
|
|
3166
|
+
openClawSandboxActive: sandbox?.enabled === true,
|
|
3167
|
+
sessionPermissionMode: params.permissionMode
|
|
3168
|
+
}).appServer;
|
|
2667
3169
|
const initialStartupBindingHadInactiveThreadBootstrap = isInactiveThreadBootstrapBinding(startupBinding);
|
|
3170
|
+
const appServerHomeScope = resolveCodexAppServerHomeScope({ appServer: pluginConfig.appServer });
|
|
2668
3171
|
const preparedAuthRoute = usesSupervisionConnection ? void 0 : params.runtimePlan?.auth.modelRoute;
|
|
2669
3172
|
const startupAuthProfileCandidate = usesSupervisionConnection ? void 0 : preparedAuthRoute ? params.runtimePlan?.auth.forwardedAuthProfileId : params.runtimePlan?.auth.forwardedAuthProfileId ?? params.authProfileId ?? startupBinding?.authProfileId;
|
|
2670
3173
|
const resolvedStartupAuthProfileId = usesSupervisionConnection ? void 0 : preparedAuthRoute ? startupAuthProfileCandidate : params.authProfileStore ? resolveCodexAppServerAuthProfileId({
|
|
@@ -2686,13 +3189,13 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2686
3189
|
authProfileId: resolvedStartupAuthProfileId,
|
|
2687
3190
|
authProfileStore: params.authProfileStore,
|
|
2688
3191
|
agentDir,
|
|
2689
|
-
homeScope:
|
|
3192
|
+
homeScope: appServerHomeScope,
|
|
2690
3193
|
requirePreparedAuth: isCodexRemoteExecPlacementSandbox(sandbox),
|
|
2691
3194
|
config: params.config,
|
|
2692
3195
|
subscriptionProfileRequiredError: "Prepared Codex subscription route requires a forwarded OpenAI OAuth or token profile.",
|
|
2693
3196
|
subscriptionProfileUnusableError: "Prepared Codex subscription auth profile is unusable."
|
|
2694
3197
|
});
|
|
2695
|
-
const startupClientAuthProfileId = usesSupervisionConnection || startupPreparedAuth?.kind === "api-key" ? null : startupAuthProfileId;
|
|
3198
|
+
const startupClientAuthProfileId = usesSupervisionConnection || appServerHomeScope === "user" || startupPreparedAuth?.kind === "api-key" ? null : startupAuthProfileId;
|
|
2696
3199
|
const resolveReviewerPolicyContext = (binding) => {
|
|
2697
3200
|
const nativeModelOwned = binding?.preserveNativeModel === true;
|
|
2698
3201
|
return resolveCodexModelBackedReviewerPolicyContext({
|
|
@@ -2705,41 +3208,67 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2705
3208
|
};
|
|
2706
3209
|
let reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
|
|
2707
3210
|
preDynamicStartupStages.mark("auth-profile");
|
|
2708
|
-
let configuredAppServer = resolveRuntimeOptionsForBinding({
|
|
3211
|
+
let configuredAppServer = resolveRuntimeOptionsForBinding(startupBinding, {
|
|
2709
3212
|
modelProvider: reviewerPolicyContext.modelProvider,
|
|
2710
3213
|
model: reviewerPolicyContext.model
|
|
2711
3214
|
});
|
|
2712
3215
|
const effectiveWorkspace = sandbox?.enabled ? sandbox.workspaceAccess === "rw" ? resolvedWorkspace : sandbox.workspaceDir : resolvedWorkspace;
|
|
2713
3216
|
const requestedCwd = params.cwd ? resolveUserPath(params.cwd) : void 0;
|
|
2714
3217
|
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
|
|
3218
|
+
const sessionPermissionCwd = resolveCodexSessionPermissionCwd({
|
|
3219
|
+
permissionMode: params.permissionMode,
|
|
3220
|
+
sessionRoot: params.sessionRoot,
|
|
3221
|
+
defaultRoot: effectiveWorkspace,
|
|
3222
|
+
requestedCwd,
|
|
3223
|
+
fallbackCwd: effectiveWorkspace
|
|
3224
|
+
});
|
|
3225
|
+
const effectiveCwd = sandbox?.enabled ? effectiveWorkspace : sessionPermissionCwd;
|
|
2716
3226
|
if (effectiveWorkspace !== resolvedWorkspace) await ensureCodexWorkspaceDirOnce(effectiveWorkspace);
|
|
2717
3227
|
preDynamicStartupStages.mark("effective-workspace");
|
|
2718
|
-
const
|
|
2719
|
-
|
|
2720
|
-
|
|
3228
|
+
const applySessionPermissionPolicy = (appServer, selection) => applyCodexSessionPermissionPolicy({
|
|
3229
|
+
appServer,
|
|
3230
|
+
permissionMode: params.permissionMode,
|
|
3231
|
+
sessionRoot: params.sessionRoot,
|
|
3232
|
+
defaultRoot: effectiveWorkspace,
|
|
2721
3233
|
pluginConfig,
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
from: "never",
|
|
2739
|
-
to: "untrusted",
|
|
2740
|
-
beforeToolCallHook: beforeToolCallPolicy.hasBeforeToolCallHook,
|
|
2741
|
-
trustedToolPolicies: beforeToolCallPolicy.trustedToolPolicies
|
|
3234
|
+
canUseAutoReview: canUseCodexModelBackedApprovalsReviewerForModel({
|
|
3235
|
+
modelProvider: selection.modelProvider,
|
|
3236
|
+
model: selection.model,
|
|
3237
|
+
config: params.config,
|
|
3238
|
+
env: {
|
|
3239
|
+
...process.env,
|
|
3240
|
+
...appServer.start.env,
|
|
3241
|
+
...shellEnvironment
|
|
3242
|
+
},
|
|
3243
|
+
agentDir,
|
|
3244
|
+
homeScope: appServer.start.homeScope,
|
|
3245
|
+
codexArgs: appServer.start.args
|
|
3246
|
+
}),
|
|
3247
|
+
requirementsToml,
|
|
3248
|
+
policyLocked: startupBinding?.connectionScope === "supervision",
|
|
3249
|
+
execMode: execPolicy.mode
|
|
2742
3250
|
});
|
|
3251
|
+
const resolveFinalAppServer = (configured, selection) => {
|
|
3252
|
+
const session = applySessionPermissionPolicy(configured, selection);
|
|
3253
|
+
const trusted = resolveCodexAppServerForModelProvider({
|
|
3254
|
+
appServer: session,
|
|
3255
|
+
provider: selection.modelProvider,
|
|
3256
|
+
model: selection.model,
|
|
3257
|
+
config: params.config,
|
|
3258
|
+
env: {
|
|
3259
|
+
...process.env,
|
|
3260
|
+
...session.start.env,
|
|
3261
|
+
...shellEnvironment
|
|
3262
|
+
},
|
|
3263
|
+
agentDir
|
|
3264
|
+
});
|
|
3265
|
+
return {
|
|
3266
|
+
session,
|
|
3267
|
+
appServer: withPreparedProcessEnv(trusted)
|
|
3268
|
+
};
|
|
3269
|
+
};
|
|
3270
|
+
let resolvedAppServer = resolveFinalAppServer(configuredAppServer, reviewerPolicyContext);
|
|
3271
|
+
let appServer = resolvedAppServer.appServer;
|
|
2743
3272
|
preDynamicStartupStages.mark("app-server-policy");
|
|
2744
3273
|
preDynamicStartupStages.mark("native-hook-relay");
|
|
2745
3274
|
const terminalState = {
|
|
@@ -2787,20 +3316,23 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2787
3316
|
preDynamicStartupStages.mark("rotate-binding");
|
|
2788
3317
|
if (startupBinding !== startupBindingBeforeRotation) {
|
|
2789
3318
|
reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
|
|
2790
|
-
configuredAppServer = resolveRuntimeOptionsForBinding({
|
|
3319
|
+
configuredAppServer = resolveRuntimeOptionsForBinding(startupBinding, {
|
|
2791
3320
|
modelProvider: reviewerPolicyContext.modelProvider,
|
|
2792
3321
|
model: reviewerPolicyContext.model
|
|
2793
3322
|
});
|
|
2794
|
-
|
|
2795
|
-
appServer =
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
3323
|
+
resolvedAppServer = resolveFinalAppServer(configuredAppServer, reviewerPolicyContext);
|
|
3324
|
+
appServer = resolvedAppServer.appServer;
|
|
3325
|
+
}
|
|
3326
|
+
const sessionPermissionPolicy = resolveCodexEffectiveSessionPermissionPolicy({
|
|
3327
|
+
appServer,
|
|
3328
|
+
permissionMode: params.permissionMode,
|
|
3329
|
+
sessionRoot: params.sessionRoot,
|
|
3330
|
+
defaultRoot: effectiveWorkspace
|
|
3331
|
+
});
|
|
3332
|
+
if (sessionPermissionPolicy) {
|
|
3333
|
+
params.permissionMode = sessionPermissionPolicy.mode;
|
|
3334
|
+
params.sessionRoot = sessionPermissionPolicy.root;
|
|
3335
|
+
(params.execOverrides ??= {}).mode = sessionPermissionPolicy.execMode;
|
|
2804
3336
|
}
|
|
2805
3337
|
const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
|
|
2806
3338
|
configuredEvents: options.nativeHookRelay?.events,
|
|
@@ -2809,22 +3341,10 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2809
3341
|
const mutable = {
|
|
2810
3342
|
startupBinding,
|
|
2811
3343
|
startupContextTokens: startupBindingResolution.startupContextTokens,
|
|
2812
|
-
pluginAppServer: appServer
|
|
3344
|
+
pluginAppServer: appServer,
|
|
3345
|
+
continuityCalibration: startupBindingBeforeRotation?.continuityCalibration
|
|
2813
3346
|
};
|
|
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
|
-
});
|
|
3347
|
+
const resolveRuntimeOptionsForCurrentBinding = (selection) => resolveFinalAppServer(resolveRuntimeOptionsForBinding(mutable.startupBinding, selection), selection).appServer;
|
|
2828
3348
|
return {
|
|
2829
3349
|
params,
|
|
2830
3350
|
options,
|
|
@@ -2846,6 +3366,8 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2846
3366
|
contextSessionKey,
|
|
2847
3367
|
sandbox,
|
|
2848
3368
|
agentDir,
|
|
3369
|
+
shellEnvironment,
|
|
3370
|
+
disableLoginShell,
|
|
2849
3371
|
bindingIdentity,
|
|
2850
3372
|
bindingStore,
|
|
2851
3373
|
activeContextEngine,
|
|
@@ -2858,7 +3380,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2858
3380
|
effectiveWorkspace,
|
|
2859
3381
|
effectiveCwd,
|
|
2860
3382
|
appServer,
|
|
2861
|
-
|
|
3383
|
+
sessionPermissionPolicy,
|
|
2862
3384
|
nativeHookRelayEvents,
|
|
2863
3385
|
runAbortController,
|
|
2864
3386
|
terminalState,
|
|
@@ -2951,10 +3473,12 @@ function resolveContextEngineBootstrapProjectionDecision(params) {
|
|
|
2951
3473
|
*/
|
|
2952
3474
|
async function buildCodexWorkspaceBootstrapContext(params) {
|
|
2953
3475
|
try {
|
|
3476
|
+
const inheritsAgentWorkspace = (params.executionWorkspace ?? params.resolvedWorkspace) !== params.resolvedWorkspace;
|
|
3477
|
+
const promptWorkspace = inheritsAgentWorkspace ? params.resolvedWorkspace : params.effectiveWorkspace;
|
|
2954
3478
|
const memoryToolsAvailable = params.memoryToolNames.length > 0 && canRouteCodexWorkspaceMemoryThroughTools({
|
|
2955
3479
|
config: params.params.config,
|
|
2956
3480
|
agentId: params.params.agentId ?? params.sessionAgentId,
|
|
2957
|
-
workspaceDir: params.effectiveWorkspace
|
|
3481
|
+
workspaceDir: inheritsAgentWorkspace ? params.resolvedWorkspace : params.effectiveWorkspace
|
|
2958
3482
|
});
|
|
2959
3483
|
const bootstrapFiles = await resolveBootstrapFilesForRun({
|
|
2960
3484
|
workspaceDir: params.resolvedWorkspace,
|
|
@@ -2974,7 +3498,7 @@ async function buildCodexWorkspaceBootstrapContext(params) {
|
|
|
2974
3498
|
const memoryReferenceFiles = memoryToolRoutedBootstrapFiles.map((file) => remapCodexContextFilePath({
|
|
2975
3499
|
file: toCodexEmbeddedContextFile(file),
|
|
2976
3500
|
sourceWorkspaceDir: params.resolvedWorkspace,
|
|
2977
|
-
targetWorkspaceDir:
|
|
3501
|
+
targetWorkspaceDir: promptWorkspace
|
|
2978
3502
|
}));
|
|
2979
3503
|
const contextFiles = buildBootstrapContextForFiles(memoryToolsAvailable ? bootstrapFiles.filter((file) => !isCodexWorkspaceRootMemoryBootstrapFile({
|
|
2980
3504
|
file,
|
|
@@ -2986,23 +3510,33 @@ async function buildCodexWorkspaceBootstrapContext(params) {
|
|
|
2986
3510
|
}).map((file) => remapCodexContextFilePath({
|
|
2987
3511
|
file,
|
|
2988
3512
|
sourceWorkspaceDir: params.resolvedWorkspace,
|
|
2989
|
-
targetWorkspaceDir:
|
|
3513
|
+
targetWorkspaceDir: promptWorkspace
|
|
2990
3514
|
}));
|
|
2991
3515
|
const promptContextFiles = selectCodexWorkspacePromptContextFiles(contextFiles, {
|
|
2992
3516
|
excludeMemory: memoryToolsAvailable,
|
|
2993
3517
|
memoryWorkspaceDir: params.effectiveWorkspace
|
|
2994
3518
|
});
|
|
2995
|
-
const
|
|
3519
|
+
const injectOpenClawContext = shouldInjectCodexOpenClawPromptContext(params.params);
|
|
3520
|
+
const restrictedProjectDocNeedsOpenClawCarrier = params.params.pluginHarnessToolPolicyRestricted === true && !params.params.disableTools && !isMessageOnlyCodexSourceReply(params.params) && params.params.bootstrapContextMode !== "lightweight";
|
|
3521
|
+
const threadDeveloperInstructionFiles = injectOpenClawContext && !params.ringZeroActive && (inheritsAgentWorkspace || restrictedProjectDocNeedsOpenClawCarrier) ? selectCodexWorkspaceAgentProjectInstructionFiles(contextFiles, params.resolvedWorkspace) : [];
|
|
3522
|
+
const turnScopedDeveloperInstructionFiles = injectOpenClawContext ? selectCodexWorkspaceTurnScopedDeveloperInstructionFiles(contextFiles) : [];
|
|
2996
3523
|
return {
|
|
2997
3524
|
bootstrapFiles,
|
|
2998
3525
|
contextFiles,
|
|
3526
|
+
inheritsAgentWorkspace,
|
|
2999
3527
|
promptContextFiles,
|
|
3528
|
+
threadDeveloperInstructionFiles,
|
|
3000
3529
|
turnScopedDeveloperInstructionFiles,
|
|
3001
3530
|
memoryReferenceFiles,
|
|
3002
3531
|
memoryToolRoutedBootstrapFiles,
|
|
3003
3532
|
memoryToolNames: [...params.memoryToolNames],
|
|
3004
3533
|
memoryToolRouted: memoryToolsAvailable,
|
|
3005
3534
|
promptContext: renderCodexWorkspaceBootstrapPromptContext(promptContextFiles),
|
|
3535
|
+
threadDeveloperInstructions: renderCodexWorkspaceDeveloperInstructions({
|
|
3536
|
+
files: threadDeveloperInstructionFiles,
|
|
3537
|
+
header: "## OpenClaw Agent Workspace Instructions",
|
|
3538
|
+
preamble: "OpenClaw loaded this bounded snapshot from the configured agent workspace."
|
|
3539
|
+
}),
|
|
3006
3540
|
turnScopedDeveloperInstructions: renderCodexWorkspaceCollaborationDeveloperInstructions(turnScopedDeveloperInstructionFiles),
|
|
3007
3541
|
memoryCollaborationInstructions: shouldInjectCodexOpenClawPromptContext(params.params) ? await renderCodexWorkspaceMemoryCollaborationInstructions({
|
|
3008
3542
|
files: memoryReferenceFiles,
|
|
@@ -3018,7 +3552,8 @@ async function buildCodexWorkspaceBootstrapContext(params) {
|
|
|
3018
3552
|
embeddedAgentLog.warn("failed to load codex workspace bootstrap instructions", { error });
|
|
3019
3553
|
return {
|
|
3020
3554
|
bootstrapFiles: [],
|
|
3021
|
-
contextFiles: []
|
|
3555
|
+
contextFiles: [],
|
|
3556
|
+
inheritsAgentWorkspace: false
|
|
3022
3557
|
};
|
|
3023
3558
|
}
|
|
3024
3559
|
}
|
|
@@ -3051,7 +3586,7 @@ function buildCodexSystemPromptReport(params) {
|
|
|
3051
3586
|
injectedWorkspaceFiles: buildCodexBootstrapInjectionStats({
|
|
3052
3587
|
bootstrapFiles: params.workspaceBootstrapContext.bootstrapFiles,
|
|
3053
3588
|
injectedFiles: params.workspaceBootstrapContext.promptContextFiles ?? [],
|
|
3054
|
-
developerInstructionFiles: params.workspaceBootstrapContext.turnScopedDeveloperInstructionFiles ?? [],
|
|
3589
|
+
developerInstructionFiles: [...params.workspaceBootstrapContext.threadDeveloperInstructionFiles ?? [], ...params.workspaceBootstrapContext.turnScopedDeveloperInstructionFiles ?? []],
|
|
3055
3590
|
memoryToolRoutedBootstrapFiles: params.workspaceBootstrapContext.memoryToolRoutedBootstrapFiles ?? [],
|
|
3056
3591
|
memoryToolRouted: params.workspaceBootstrapContext.memoryToolRouted === true
|
|
3057
3592
|
}),
|
|
@@ -3132,12 +3667,17 @@ function buildCodexBootstrapInjectionStats(params) {
|
|
|
3132
3667
|
const rawChars = file.missing ? 0 : (file.content ?? "").trimEnd().length;
|
|
3133
3668
|
const memoryToolRoutedFile = baseName === CODEX_MEMORY_CONTEXT_BASENAME && params.memoryToolRouted === true && memoryToolRoutedPaths.has(normalizeCodexContextFilePath(pathValue));
|
|
3134
3669
|
const injected = memoryToolRoutedFile ? void 0 : readCodexIndexedContextFileContent(injectedIndex, pathValue, fileName) ?? readCodexIndexedContextFileContent(developerInstructionIndex, pathValue, fileName);
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3670
|
+
if (!file.missing && injected === void 0 && CODEX_NATIVE_PROJECT_DOC_BASENAMES.has(baseName)) return {
|
|
3671
|
+
name: displayName,
|
|
3672
|
+
path: pathValue,
|
|
3673
|
+
missing: false,
|
|
3674
|
+
rawChars,
|
|
3675
|
+
injectionStatus: "native_unverified",
|
|
3676
|
+
injectedChars: null,
|
|
3677
|
+
truncated: null
|
|
3678
|
+
};
|
|
3679
|
+
const injectedChars = memoryToolRoutedFile ? 0 : injected?.length ?? 0;
|
|
3680
|
+
const truncated = memoryToolRoutedFile ? false : !file.missing && injectedChars < rawChars;
|
|
3141
3681
|
return {
|
|
3142
3682
|
name: displayName,
|
|
3143
3683
|
path: pathValue,
|
|
@@ -3272,7 +3812,7 @@ function renderCodexWorkspaceBootstrapPromptContext(contextFiles) {
|
|
|
3272
3812
|
const files = contextFiles;
|
|
3273
3813
|
if (files.length === 0) return;
|
|
3274
3814
|
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
|
|
3815
|
+
"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
3816
|
"",
|
|
3277
3817
|
"# Project Context",
|
|
3278
3818
|
"",
|
|
@@ -3295,6 +3835,10 @@ function selectCodexWorkspacePromptContextFiles(contextFiles, options = {}) {
|
|
|
3295
3835
|
function selectCodexWorkspaceTurnScopedDeveloperInstructionFiles(contextFiles) {
|
|
3296
3836
|
return selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, CODEX_TURN_SCOPED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES);
|
|
3297
3837
|
}
|
|
3838
|
+
function selectCodexWorkspaceAgentProjectInstructionFiles(contextFiles, agentWorkspaceDir) {
|
|
3839
|
+
const agentProjectDocPath = path.join(path.resolve(agentWorkspaceDir), "AGENTS.md");
|
|
3840
|
+
return selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, CODEX_NATIVE_PROJECT_DOC_BASENAMES).filter((file) => path.resolve(file.path) === agentProjectDocPath);
|
|
3841
|
+
}
|
|
3298
3842
|
function selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, basenames) {
|
|
3299
3843
|
return contextFiles.filter((file) => {
|
|
3300
3844
|
const baseName = getCodexContextFileBasename(file.path);
|
|
@@ -3428,34 +3972,131 @@ function remapCodexContextFilePath(params) {
|
|
|
3428
3972
|
path: targetUsesPosixSeparators ? path.posix.join(params.targetWorkspaceDir, normalizedRelativePath) : path.win32.join(params.targetWorkspaceDir, normalizedRelativePath)
|
|
3429
3973
|
};
|
|
3430
3974
|
}
|
|
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);
|
|
3975
|
+
function compareCodexContextFiles(left, right) {
|
|
3976
|
+
const leftPath = normalizeCodexContextFilePath(left.path);
|
|
3977
|
+
const rightPath = normalizeCodexContextFilePath(right.path);
|
|
3978
|
+
const leftBase = getCodexContextFileBasename(left.path);
|
|
3979
|
+
const rightBase = getCodexContextFileBasename(right.path);
|
|
3980
|
+
const leftOrder = CODEX_BOOTSTRAP_CONTEXT_ORDER.get(leftBase) ?? Number.MAX_SAFE_INTEGER;
|
|
3981
|
+
const rightOrder = CODEX_BOOTSTRAP_CONTEXT_ORDER.get(rightBase) ?? Number.MAX_SAFE_INTEGER;
|
|
3982
|
+
if (leftOrder !== rightOrder) return leftOrder - rightOrder;
|
|
3983
|
+
if (leftBase !== rightBase) return leftBase.localeCompare(rightBase);
|
|
3984
|
+
return leftPath.localeCompare(rightPath);
|
|
3985
|
+
}
|
|
3986
|
+
function compareCodexBootstrapFiles(left, right) {
|
|
3987
|
+
return compareCodexContextFiles(toCodexEmbeddedContextFile(left), toCodexEmbeddedContextFile(right));
|
|
3988
|
+
}
|
|
3989
|
+
function normalizeCodexContextFilePath(filePath) {
|
|
3990
|
+
return filePath.trim().replaceAll("\\", "/").toLowerCase();
|
|
3991
|
+
}
|
|
3992
|
+
function getCodexContextFileDisplayBasename(filePath) {
|
|
3993
|
+
return filePath.trim().replaceAll("\\", "/").split("/").pop()?.trim() ?? "";
|
|
3994
|
+
}
|
|
3995
|
+
function getCodexContextFileBasename(filePath) {
|
|
3996
|
+
return normalizeCodexContextFilePath(filePath).split("/").pop() ?? "";
|
|
3997
|
+
}
|
|
3998
|
+
function normalizeCodexDynamicToolName(name) {
|
|
3999
|
+
return name.trim().toLowerCase();
|
|
4000
|
+
}
|
|
4001
|
+
function isNonEmptyString$1(value) {
|
|
4002
|
+
return typeof value === "string" && value.length > 0;
|
|
4003
|
+
}
|
|
4004
|
+
//#endregion
|
|
4005
|
+
//#region extensions/codex/src/app-server/run-attempt-state.ts
|
|
4006
|
+
async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity, fields) {
|
|
4007
|
+
const currentBinding = await bindingStore.read(identity);
|
|
4008
|
+
const expectedThreadId = fields.threadId ?? currentBinding?.threadId;
|
|
4009
|
+
if (!expectedThreadId) return;
|
|
4010
|
+
if (currentBinding && currentBinding.threadId !== expectedThreadId) {
|
|
4011
|
+
embeddedAgentLog.warn("codex app-server image payload error detected for unbound thread; preserving thread binding", {
|
|
4012
|
+
...fields,
|
|
4013
|
+
boundThreadId: currentBinding.threadId
|
|
4014
|
+
});
|
|
4015
|
+
return;
|
|
4016
|
+
}
|
|
4017
|
+
if (currentBinding?.connectionScope === "supervision") {
|
|
4018
|
+
embeddedAgentLog.warn("codex app-server image payload error detected for supervised thread; preserving native binding", fields);
|
|
4019
|
+
return;
|
|
4020
|
+
}
|
|
4021
|
+
embeddedAgentLog.warn("codex app-server image payload error detected; clearing thread binding", fields);
|
|
4022
|
+
await bindingStore.mutate(identity, {
|
|
4023
|
+
kind: "clear",
|
|
4024
|
+
threadId: expectedThreadId
|
|
4025
|
+
});
|
|
4026
|
+
}
|
|
4027
|
+
async function markCodexAppServerBindingCoveredThroughTurn(params) {
|
|
4028
|
+
await params.bindingStore.mutate(params.identity, {
|
|
4029
|
+
kind: "patch",
|
|
4030
|
+
threadId: params.threadId,
|
|
4031
|
+
patch: {
|
|
4032
|
+
historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4033
|
+
...params.continuityCalibration ? { continuityCalibration: params.continuityCalibration } : {}
|
|
4034
|
+
}
|
|
4035
|
+
});
|
|
4036
|
+
}
|
|
4037
|
+
function isNonEmptyString(value) {
|
|
4038
|
+
return typeof value === "string" && value.length > 0;
|
|
3441
4039
|
}
|
|
3442
|
-
function
|
|
3443
|
-
|
|
4040
|
+
function shouldUseFreshCodexThreadAfterContextEngineOverflow(params) {
|
|
4041
|
+
if (!params.contextEngineActive || params.thread.lifecycle.action !== "resumed") return false;
|
|
4042
|
+
const message = formatErrorMessage(params.error);
|
|
4043
|
+
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
4044
|
}
|
|
3445
|
-
function
|
|
3446
|
-
|
|
4045
|
+
function isCodexActiveCompactTurnError(error) {
|
|
4046
|
+
if (!(error instanceof CodexAppServerRpcError)) return false;
|
|
4047
|
+
const data = isJsonObject(error.data) ? error.data : void 0;
|
|
4048
|
+
const codexErrorInfo = isJsonObject(data?.codexErrorInfo) ? data.codexErrorInfo : void 0;
|
|
4049
|
+
return (isJsonObject(codexErrorInfo?.activeTurnNotSteerable) ? codexErrorInfo.activeTurnNotSteerable : void 0)?.turnKind === "compact";
|
|
3447
4050
|
}
|
|
3448
|
-
function
|
|
3449
|
-
|
|
4051
|
+
function readCodexFinalizationHookNotification(notification, threadId, turnId) {
|
|
4052
|
+
if (notification.method !== "hook/started" && notification.method !== "hook/completed") return;
|
|
4053
|
+
const params = isJsonObject(notification.params) ? notification.params : void 0;
|
|
4054
|
+
const run = params && isJsonObject(params.run) ? params.run : void 0;
|
|
4055
|
+
if (params?.threadId !== threadId || params.turnId !== turnId || run?.eventName !== "stop" && run?.eventName !== "subagentStop" || typeof run.id !== "string" || !run.id) return;
|
|
4056
|
+
if (notification.method === "hook/started") return {
|
|
4057
|
+
phase: "started",
|
|
4058
|
+
runId: run.id
|
|
4059
|
+
};
|
|
4060
|
+
return {
|
|
4061
|
+
phase: "completed",
|
|
4062
|
+
runId: run.id,
|
|
4063
|
+
status: typeof run.status === "string" ? run.status : void 0
|
|
4064
|
+
};
|
|
3450
4065
|
}
|
|
3451
|
-
function
|
|
3452
|
-
return
|
|
4066
|
+
function joinPresentSections(...sections) {
|
|
4067
|
+
return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
|
|
3453
4068
|
}
|
|
3454
|
-
function
|
|
3455
|
-
|
|
4069
|
+
function prependCurrentInboundContext(prompt, context) {
|
|
4070
|
+
const text = context?.text.trim();
|
|
4071
|
+
return text ? [neutralizeCodexExplicitMentionSigils(text), prompt].filter(Boolean).join("\n\n") : prompt;
|
|
3456
4072
|
}
|
|
3457
|
-
function
|
|
3458
|
-
|
|
4073
|
+
function buildCodexAppServerTimeoutDiagnostics(params) {
|
|
4074
|
+
const readNonBlankDetailString = (key) => {
|
|
4075
|
+
const value = params.details?.[key];
|
|
4076
|
+
return hasNonEmptyString(value) ? value : void 0;
|
|
4077
|
+
};
|
|
4078
|
+
const activeAppServerTurnRequests = asFiniteNumber(params.details?.activeAppServerTurnRequests);
|
|
4079
|
+
const activeTurnItemCount = asFiniteNumber(params.details?.activeTurnItemCount);
|
|
4080
|
+
const terminalTurnNotificationQueued = asBoolean(params.details?.terminalTurnNotificationQueued);
|
|
4081
|
+
const completionIdleWatchArmed = asBoolean(params.details?.completionIdleWatchArmed);
|
|
4082
|
+
const assistantCompletionIdleWatchArmed = asBoolean(params.details?.assistantCompletionIdleWatchArmed);
|
|
4083
|
+
const terminalIdleWatchArmed = asBoolean(params.details?.terminalIdleWatchArmed);
|
|
4084
|
+
return {
|
|
4085
|
+
...params.idleMs !== void 0 ? { idleMs: params.idleMs } : {},
|
|
4086
|
+
...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
|
|
4087
|
+
...params.lastActivityReason ? { lastActivityReason: params.lastActivityReason } : {},
|
|
4088
|
+
...readNonBlankDetailString("lastNotificationMethod") ? { lastNotificationMethod: readNonBlankDetailString("lastNotificationMethod") } : {},
|
|
4089
|
+
...readNonBlankDetailString("lastNotificationItemId") ? { lastNotificationItemId: readNonBlankDetailString("lastNotificationItemId") } : {},
|
|
4090
|
+
...readNonBlankDetailString("lastNotificationItemType") ? { lastNotificationItemType: readNonBlankDetailString("lastNotificationItemType") } : {},
|
|
4091
|
+
...readNonBlankDetailString("lastNotificationItemRole") ? { lastNotificationItemRole: readNonBlankDetailString("lastNotificationItemRole") } : {},
|
|
4092
|
+
...readNonBlankDetailString("lastAssistantTextPreview") ? { lastAssistantTextPreview: readNonBlankDetailString("lastAssistantTextPreview") } : {},
|
|
4093
|
+
...activeAppServerTurnRequests !== void 0 ? { activeAppServerTurnRequests } : {},
|
|
4094
|
+
...activeTurnItemCount !== void 0 ? { activeTurnItemCount } : {},
|
|
4095
|
+
...terminalTurnNotificationQueued !== void 0 ? { terminalTurnNotificationQueued } : {},
|
|
4096
|
+
...completionIdleWatchArmed !== void 0 ? { completionIdleWatchArmed } : {},
|
|
4097
|
+
...assistantCompletionIdleWatchArmed !== void 0 ? { assistantCompletionIdleWatchArmed } : {},
|
|
4098
|
+
...terminalIdleWatchArmed !== void 0 ? { terminalIdleWatchArmed } : {}
|
|
4099
|
+
};
|
|
3459
4100
|
}
|
|
3460
4101
|
//#endregion
|
|
3461
4102
|
//#region extensions/codex/src/app-server/run-attempt-context.ts
|
|
@@ -3527,16 +4168,20 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
3527
4168
|
});
|
|
3528
4169
|
historyState.messages = await readFencedHistory() ?? historyState.messages;
|
|
3529
4170
|
}
|
|
4171
|
+
const memoryToolNames = getCodexWorkspaceMemoryToolNames(toolBridge.availableSpecs);
|
|
3530
4172
|
const workspaceBootstrapContext = await buildCodexWorkspaceBootstrapContext({
|
|
3531
4173
|
params: runtimeParams,
|
|
3532
|
-
resolvedWorkspace,
|
|
4174
|
+
resolvedWorkspace: runtimeParams.bootstrapWorkspaceDir ?? resolvedWorkspace,
|
|
4175
|
+
executionWorkspace: resolvedWorkspace,
|
|
3533
4176
|
effectiveWorkspace,
|
|
3534
4177
|
sessionKey: contextSessionKey,
|
|
3535
4178
|
sessionAgentId,
|
|
3536
|
-
memoryToolNames
|
|
4179
|
+
memoryToolNames,
|
|
4180
|
+
ringZeroActive: isHostScopedAgentToolActive("openclaw") && isSystemAgentOnlyCodexDynamicToolAllowlist(runtimeParams.toolsAllow),
|
|
3537
4181
|
sandboxed: sandbox?.enabled === true
|
|
3538
4182
|
});
|
|
3539
|
-
const
|
|
4183
|
+
const agentWorkspaceDeveloperInstructions = workspaceBootstrapContext.threadDeveloperInstructions ? connection.mutable.startupBinding?.agentWorkspaceDeveloperInstructions ?? workspaceBootstrapContext.threadDeveloperInstructions : void 0;
|
|
4184
|
+
const baseDeveloperInstructions = joinPresentSections(buildDeveloperInstructions(runtimeParams, { dynamicTools: toolBridge.availableSpecs }), agentWorkspaceDeveloperInstructions);
|
|
3540
4185
|
return {
|
|
3541
4186
|
runtime,
|
|
3542
4187
|
attemptTools,
|
|
@@ -3547,6 +4192,7 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
3547
4192
|
hookRunner,
|
|
3548
4193
|
buildActiveContextEngineRuntimeContext,
|
|
3549
4194
|
workspaceBootstrapContext,
|
|
4195
|
+
agentWorkspaceDeveloperInstructions,
|
|
3550
4196
|
baseDeveloperInstructions,
|
|
3551
4197
|
openClawPromptContext: buildCodexOpenClawPromptContext({
|
|
3552
4198
|
params: runtimeParams,
|
|
@@ -3570,11 +4216,16 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
3570
4216
|
contextEngineProjection: void 0,
|
|
3571
4217
|
precomputedStaleBindingContinuityProjectionApplied: false,
|
|
3572
4218
|
staleBindingContinuityForcedFreshStart: false,
|
|
4219
|
+
noEngineContinuityProjectionApplied: false,
|
|
3573
4220
|
inactiveThreadBootstrapBindingForcedFreshStart: initialInactiveThreadBootstrapBindingForcedFreshStart
|
|
3574
4221
|
},
|
|
3575
4222
|
codexContextProjectionMaxChars: resolveCodexContextEngineProjectionMaxChars({
|
|
3576
4223
|
contextTokenBudget: effectiveContextTokenBudget,
|
|
3577
4224
|
reserveTokens: resolveCodexContextEngineProjectionReserveTokens()
|
|
4225
|
+
}),
|
|
4226
|
+
codexContinuityProjectionMaxChars: resolveCodexContinuityProjectionMaxChars({
|
|
4227
|
+
contextTokenBudget: effectiveContextTokenBudget,
|
|
4228
|
+
calibration: connection.mutable.continuityCalibration
|
|
3578
4229
|
})
|
|
3579
4230
|
};
|
|
3580
4231
|
}
|
|
@@ -3785,105 +4436,6 @@ function isInvalidCodexImagePayloadError(message) {
|
|
|
3785
4436
|
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
4437
|
}
|
|
3787
4438
|
//#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
4439
|
//#region extensions/codex/src/app-server/settled-turn-context.ts
|
|
3888
4440
|
function collectUniqueMessageIdentities(messages) {
|
|
3889
4441
|
const identities = /* @__PURE__ */ new Map();
|
|
@@ -3973,100 +4525,13 @@ async function captureCodexSettledTurnFinalizationContext(params) {
|
|
|
3973
4525
|
}
|
|
3974
4526
|
//#endregion
|
|
3975
4527
|
//#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. */
|
|
4528
|
+
/** Creates a trajectory recorder when the host exposes its capture capability. */
|
|
4035
4529
|
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);
|
|
4530
|
+
if (!params.trajectory) return null;
|
|
4531
|
+
const trajectory = params.trajectory;
|
|
4047
4532
|
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
|
|
4533
|
+
recordEvent: trajectory.recordEvent,
|
|
4534
|
+
flush: trajectory.flush
|
|
4070
4535
|
};
|
|
4071
4536
|
}
|
|
4072
4537
|
/** Records compiled prompt/tool context at the start of a Codex runtime attempt. */
|
|
@@ -4095,12 +4560,6 @@ function recordCodexTrajectoryCompletion(recorder, params) {
|
|
|
4095
4560
|
messagesSnapshot: params.result.messagesSnapshot
|
|
4096
4561
|
});
|
|
4097
4562
|
}
|
|
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
4563
|
function toTrajectoryToolDefinitions(tools) {
|
|
4105
4564
|
if (!tools || tools.length === 0) return;
|
|
4106
4565
|
return flattenCodexDynamicToolFunctions(tools).flatMap((tool) => {
|
|
@@ -4109,31 +4568,10 @@ function toTrajectoryToolDefinitions(tools) {
|
|
|
4109
4568
|
return [{
|
|
4110
4569
|
name,
|
|
4111
4570
|
description: tool.description,
|
|
4112
|
-
parameters:
|
|
4571
|
+
parameters: tool.inputSchema
|
|
4113
4572
|
}];
|
|
4114
4573
|
}).toSorted((left, right) => left.name.localeCompare(right.name));
|
|
4115
4574
|
}
|
|
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
4575
|
/** Converts arbitrary prompt errors into trajectory-safe text. */
|
|
4138
4576
|
function normalizeCodexTrajectoryError(value) {
|
|
4139
4577
|
if (!value) return null;
|
|
@@ -4154,7 +4592,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4154
4592
|
const { hookContextWindowFields, hookRunner } = context;
|
|
4155
4593
|
const { connection, preparedAuthBinding } = runtime;
|
|
4156
4594
|
const { effectiveRuntimeProviderId, effectiveRuntimeModelId } = runtime;
|
|
4157
|
-
const { params, terminalState, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, usesSupervisionConnection, sessionAgentId, contextSessionKey, effectiveCwd, attemptStartedAt, startupAuthProfileId } = connection;
|
|
4595
|
+
const { params, terminalState, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, usesSupervisionConnection, sessionAgentId, contextSessionKey, effectiveCwd, agentDir, attemptStartedAt, startupAuthProfileId } = connection;
|
|
4158
4596
|
const { toolBridge, toolState } = attemptTools;
|
|
4159
4597
|
const { state, completion, pendingOpenClawDynamicToolCompletionIds, activeTurnItemIds, activeCompletionBlockerItemIds, activeFinalizationHookRunIds, turnWatches } = turnRuntime;
|
|
4160
4598
|
const { emitLifecycleTerminal, buildLifecycleTerminalMeta } = lifecycle;
|
|
@@ -4186,9 +4624,9 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4186
4624
|
const projectedTerminal = attemptTerminal.project(result.terminal);
|
|
4187
4625
|
const effectiveTimedOut = state.timedOut && !recoveredTurnWatchTimeout;
|
|
4188
4626
|
const effectiveTurnCompletionIdleTimedOut = state.turnCompletionIdleTimedOut && !recoveredTurnWatchTimeout;
|
|
4189
|
-
const isFinalAborted = () =>
|
|
4627
|
+
const isFinalAborted = () => terminalState.explicitCancellationObserved || !resourceState.executionDisconnectError && (projectedTerminal.aborted || runAbortController.signal.aborted && !state.clientClosedAbort && !recoveredTurnWatchTimeout);
|
|
4190
4628
|
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);
|
|
4629
|
+
let finalPromptError = resourceState.executionDisconnectError ?? clientClosedPromptErrorForFinal ?? (effectiveTurnCompletionIdleTimedOut ? state.turnCompletionIdleTimeoutMessage : effectiveTimedOut ? "codex app-server attempt timed out" : projectedTerminal.promptError);
|
|
4192
4630
|
const finalPromptErrorMessage = typeof finalPromptError === "string" ? finalPromptError : finalPromptError instanceof Error ? finalPromptError.message : finalPromptError ? formatErrorMessage(finalPromptError) : void 0;
|
|
4193
4631
|
if (isInvalidCodexImagePayloadError(finalPromptErrorMessage)) await clearCodexBindingAfterInvalidImagePayload(bindingStore, bindingIdentity, {
|
|
4194
4632
|
phase: "turn_completed",
|
|
@@ -4229,6 +4667,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4229
4667
|
authProfileId: startupAuthProfileId,
|
|
4230
4668
|
rateLimits: readRecentCodexRateLimits(resourceState.client)
|
|
4231
4669
|
});
|
|
4670
|
+
finalPromptError = resourceState.executionDisconnectError ?? finalPromptError;
|
|
4232
4671
|
const finalPromptErrorSource = effectiveTimedOut || clientClosedPromptErrorForFinal ? "prompt" : projectedTerminal.promptErrorSource;
|
|
4233
4672
|
const codexAppServerFailureKind = clientClosedPromptErrorForFinal ? "client_closed_before_turn_completed" : effectiveTurnCompletionIdleTimedOut ? "turn_completion_idle_timeout" : void 0;
|
|
4234
4673
|
const replayBlockedReason = codexAppServerFailureKind ? resolveCodexAppServerReplayBlockedReason(result) : void 0;
|
|
@@ -4332,20 +4771,11 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4332
4771
|
modelIterations: result.modelIterations ?? 0,
|
|
4333
4772
|
skillWorkshopAvailable: flattenCodexDynamicToolFunctions(attemptTools.toolBridge.availableSpecs).some((tool) => tool.name === "skill_workshop"),
|
|
4334
4773
|
compacted: (result.compactionCount ?? 0) > 0,
|
|
4335
|
-
messageChannel: params.messageChannel,
|
|
4336
|
-
messageProvider: params.messageProvider,
|
|
4337
|
-
chatType: params.chatType,
|
|
4338
|
-
agentAccountId: params.agentAccountId,
|
|
4339
|
-
groupId: params.groupId,
|
|
4340
|
-
groupChannel: params.groupChannel,
|
|
4341
|
-
groupSpace: params.groupSpace,
|
|
4342
|
-
memberRoleIds: params.memberRoleIds,
|
|
4343
|
-
spawnedBy: params.spawnedBy,
|
|
4344
4774
|
senderId: params.senderId ?? void 0,
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4775
|
+
foregroundPromptContext: buildEmbeddedForegroundPromptContext({
|
|
4776
|
+
...params,
|
|
4777
|
+
agentId: sessionAgentId
|
|
4778
|
+
}, agentDir)
|
|
4349
4779
|
},
|
|
4350
4780
|
hookRunner
|
|
4351
4781
|
});
|
|
@@ -4354,7 +4784,11 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4354
4784
|
await markCodexAppServerBindingCoveredThroughTurn({
|
|
4355
4785
|
bindingStore,
|
|
4356
4786
|
identity: bindingIdentity,
|
|
4357
|
-
threadId: resourceState.thread.threadId
|
|
4787
|
+
threadId: resourceState.thread.threadId,
|
|
4788
|
+
continuityCalibration: context.promptState.noEngineContinuityProjectionApplied ? buildCodexContinuityCalibration({
|
|
4789
|
+
promptChars: prompt.turnState.codexTurnPromptText.length,
|
|
4790
|
+
inputTokens: (result.attemptUsage?.input ?? 0) + (result.attemptUsage?.cacheRead ?? 0) + (result.attemptUsage?.cacheWrite ?? 0)
|
|
4791
|
+
}) : void 0
|
|
4358
4792
|
});
|
|
4359
4793
|
} catch (error) {
|
|
4360
4794
|
if (resourceState.thread.connectionScope === "supervision") throw error;
|
|
@@ -4407,6 +4841,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4407
4841
|
});
|
|
4408
4842
|
const finalizedResult = {
|
|
4409
4843
|
...result,
|
|
4844
|
+
...toolState.yieldAcknowledgment ? { yieldAcknowledgment: toolState.yieldAcknowledgment } : {},
|
|
4410
4845
|
terminal: attemptTerminal.normalize({
|
|
4411
4846
|
timedOut: effectiveTimedOut,
|
|
4412
4847
|
aborted: finalAborted,
|
|
@@ -4420,6 +4855,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4420
4855
|
...terminalAnchor ? { contextEngineTerminalAnchor: terminalAnchor } : {},
|
|
4421
4856
|
...settledTurnFinalizationContext ? { settledTurnFinalizationContext } : {},
|
|
4422
4857
|
...resourceState.runtimeArtifact ? { runtimeArtifact: resourceState.runtimeArtifact } : {},
|
|
4858
|
+
...resourceState.runtimeContinuationStarted ? { runtimeContinuationStarted: true } : {},
|
|
4423
4859
|
...!finalAborted && !effectiveTimedOut && !finalPromptError && preparedAuthBinding ? { authBindingFingerprint: preparedAuthBinding.fingerprint } : {},
|
|
4424
4860
|
systemPromptReport
|
|
4425
4861
|
};
|
|
@@ -4764,7 +5200,7 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
4764
5200
|
state.turnCrossedToolHandoff = notificationState.turnCrossedToolHandoff;
|
|
4765
5201
|
if (notificationState.isCurrentTurnNotification && notification.method === "item/completed") {
|
|
4766
5202
|
const item = readCodexNotificationItem(notification.params);
|
|
4767
|
-
if (item?.type === "userMessage" && typeof item.clientId === "string") steeringQueue?.confirmConsumed(item.clientId);
|
|
5203
|
+
if (item?.type === "userMessage" && typeof item.clientId === "string") await steeringQueue?.confirmConsumed(item.clientId);
|
|
4768
5204
|
}
|
|
4769
5205
|
if (notificationState.isTurnAbortMarker) state.sawCodexInterruptMarker = true;
|
|
4770
5206
|
const hookNotification = readCodexFinalizationHookNotification(notification, resourceState.thread.threadId, turnId);
|
|
@@ -4775,7 +5211,6 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
4775
5211
|
}
|
|
4776
5212
|
if (notificationState.isTurnTerminal) state.terminalTurnNotificationQueued = true;
|
|
4777
5213
|
try {
|
|
4778
|
-
await waitForCodexNotificationDispatchTurn();
|
|
4779
5214
|
await projector.handleNotification(notification);
|
|
4780
5215
|
const canRelease = isAssistantCompletionReleaseNotification(notification, state.turnCrossedToolHandoff) || notificationState.isCurrentTurnNotification && state.turnCrossedToolHandoff && notification.method === "rawResponseItem/completed" && projector.canReleaseLatestTerminalAssistantAfterToolHandoff();
|
|
4781
5216
|
if (notificationState.isCurrentTurnNotification && canRelease) {
|
|
@@ -4871,11 +5306,12 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
4871
5306
|
}
|
|
4872
5307
|
//#endregion
|
|
4873
5308
|
//#region extensions/codex/src/app-server/run-attempt-prompt.ts
|
|
5309
|
+
const CODEX_META_KEY = "__openclaw";
|
|
4874
5310
|
function isRestrictivePromptToolsAllow(toolsAllow) {
|
|
4875
5311
|
return toolsAllow !== void 0 && !toolsAllow.some((name) => name.trim() === "*");
|
|
4876
5312
|
}
|
|
4877
5313
|
async function prepareCodexAttemptPrompt(context) {
|
|
4878
|
-
const { runtime, attemptTools, historyState, hookContext, workspaceBootstrapContext, buildActiveContextEngineRuntimeContext, baseDeveloperInstructions, openClawPromptContext, skillsCollaborationInstructions, promptState, codexContextProjectionMaxChars } = context;
|
|
5314
|
+
const { runtime, attemptTools, historyState, hookContext, workspaceBootstrapContext, buildActiveContextEngineRuntimeContext, baseDeveloperInstructions, openClawPromptContext, skillsCollaborationInstructions, promptState, codexContextProjectionMaxChars, codexContinuityProjectionMaxChars } = context;
|
|
4879
5315
|
const { connection, buildActiveRunAttemptParams, effectiveContextTokenBudget, effectiveRuntimeModelId, effectiveRuntimeProviderId } = runtime;
|
|
4880
5316
|
const { params, activeContextEngine, usesSupervisionConnection, mutable, isInactiveThreadBootstrapBinding, bindingStore, bindingIdentity, agentDir, appServer, contextSessionKey, effectiveWorkspace, sandbox } = connection;
|
|
4881
5317
|
const { toolBridge } = attemptTools;
|
|
@@ -4884,11 +5320,12 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4884
5320
|
assembledMessages: historyState.messages,
|
|
4885
5321
|
originalHistoryMessages: historyState.messages,
|
|
4886
5322
|
prompt: params.prompt,
|
|
4887
|
-
maxRenderedContextChars:
|
|
5323
|
+
maxRenderedContextChars: codexContinuityProjectionMaxChars
|
|
4888
5324
|
});
|
|
4889
5325
|
promptState.promptText = projection.promptText;
|
|
4890
5326
|
promptState.promptContextRange = projection.promptContextRange;
|
|
4891
5327
|
promptState.prePromptMessageCount = projection.prePromptMessageCount;
|
|
5328
|
+
promptState.noEngineContinuityProjectionApplied = true;
|
|
4892
5329
|
};
|
|
4893
5330
|
const applyActiveContextEngineProjection = async (decisionStartupBinding) => {
|
|
4894
5331
|
if (!activeContextEngine) return;
|
|
@@ -4962,15 +5399,21 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4962
5399
|
}
|
|
4963
5400
|
const codexModelInputHistoryMessages = [];
|
|
4964
5401
|
const buildPromptFromCurrentInputs = async () => {
|
|
4965
|
-
|
|
5402
|
+
return await resolveAgentHarnessBeforePromptBuildResult({
|
|
4966
5403
|
prompt: prependCurrentInboundContext(promptState.promptText, params.currentInboundContext),
|
|
4967
|
-
developerInstructions:
|
|
5404
|
+
developerInstructions: { build: ({ toolsAllow }) => {
|
|
5405
|
+
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.");
|
|
5406
|
+
return promptState.developerInstructions;
|
|
5407
|
+
} },
|
|
4968
5408
|
messages: structuredClone(historyState.messages),
|
|
4969
5409
|
ctx: hookContext,
|
|
4970
|
-
bootstrapContextRunKind: params.bootstrapContextRunKind
|
|
5410
|
+
bootstrapContextRunKind: params.bootstrapContextRunKind,
|
|
5411
|
+
toolAuthority: {
|
|
5412
|
+
fingerprint: params.toolAuthorityFingerprint,
|
|
5413
|
+
activeToolNames: () => flattenCodexDynamicToolFunctions(toolBridge.availableSpecs).map((tool) => tool.name).filter(isNonEmptyString),
|
|
5414
|
+
assertActive: params.hostCapabilities.assertActive
|
|
5415
|
+
}
|
|
4971
5416
|
});
|
|
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
5417
|
};
|
|
4975
5418
|
const resolveShiftedPromptInputRange = (prompt, promptInputRange, turnPromptText) => {
|
|
4976
5419
|
if (!promptInputRange || promptInputRange.start < 0 || promptInputRange.end < promptInputRange.start || promptInputRange.end > prompt.length || !turnPromptText.endsWith(prompt)) return;
|
|
@@ -5040,12 +5483,11 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
5040
5483
|
const cutoff = Date.parse(binding.historyCoveredThrough ?? "");
|
|
5041
5484
|
return historyState.messages.filter((message) => {
|
|
5042
5485
|
if (message.role !== "user" && message.role !== "assistant") return false;
|
|
5043
|
-
const
|
|
5044
|
-
const meta = record["__openclaw"];
|
|
5486
|
+
const meta = CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0;
|
|
5045
5487
|
const mirrorIdentity = meta && typeof meta === "object" && !Array.isArray(meta) ? meta.mirrorIdentity : void 0;
|
|
5046
5488
|
const mirrorOrigin = meta && typeof meta === "object" && !Array.isArray(meta) ? meta.mirrorOrigin : void 0;
|
|
5047
5489
|
const timestamp = typeof message.timestamp === "number" ? message.timestamp : typeof message.timestamp === "string" ? Date.parse(message.timestamp) : NaN;
|
|
5048
|
-
return !(typeof
|
|
5490
|
+
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
5491
|
});
|
|
5050
5492
|
};
|
|
5051
5493
|
const applyResumeStaleBindingContinuityProjection = (binding) => {
|
|
@@ -5055,11 +5497,12 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
5055
5497
|
assembledMessages: newerVisibleMessages,
|
|
5056
5498
|
originalHistoryMessages: historyState.messages,
|
|
5057
5499
|
prompt: params.prompt,
|
|
5058
|
-
maxRenderedContextChars:
|
|
5500
|
+
maxRenderedContextChars: codexContinuityProjectionMaxChars
|
|
5059
5501
|
});
|
|
5060
5502
|
promptState.promptText = projection.promptText;
|
|
5061
5503
|
promptState.promptContextRange = projection.promptContextRange;
|
|
5062
5504
|
promptState.prePromptMessageCount = projection.prePromptMessageCount;
|
|
5505
|
+
promptState.noEngineContinuityProjectionApplied = true;
|
|
5063
5506
|
return true;
|
|
5064
5507
|
};
|
|
5065
5508
|
const precomputeNoContextEngineStaleBindingProjection = () => {
|
|
@@ -5171,15 +5614,13 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5171
5614
|
const { connection, hookChannelId } = runtime;
|
|
5172
5615
|
const { appServer, params, effectiveCwd, sessionAgentId, sandboxSessionKey, runAbortController, sandbox, options, nativeHookRelayEvents } = connection;
|
|
5173
5616
|
const { toolBridge } = attemptTools;
|
|
5174
|
-
const hostTrajectoryRecorder = params.trajectoryRecorder;
|
|
5175
5617
|
const trajectoryRecorder = createCodexTrajectoryRecorder({
|
|
5176
5618
|
attempt: params,
|
|
5177
5619
|
cwd: effectiveCwd,
|
|
5178
5620
|
developerInstructions: buildRenderedCodexDeveloperInstructions(),
|
|
5179
5621
|
prompt: turnState.codexTurnPromptText,
|
|
5180
|
-
|
|
5181
|
-
tools: toolBridge.availableSpecs
|
|
5182
|
-
warn: (message, fields) => embeddedAgentLog.warn(message, fields)
|
|
5622
|
+
trajectory: params.hostCapabilities.trajectory,
|
|
5623
|
+
tools: toolBridge.availableSpecs
|
|
5183
5624
|
});
|
|
5184
5625
|
const state = {
|
|
5185
5626
|
client: void 0,
|
|
@@ -5192,12 +5633,14 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5192
5633
|
trajectoryEndRecorded: false,
|
|
5193
5634
|
nativeHookRelay: void 0,
|
|
5194
5635
|
nativeSubagentMonitor: void 0,
|
|
5636
|
+
runtimeContinuationStarted: false,
|
|
5195
5637
|
nativePreToolUseFailureFallbackActive: false,
|
|
5196
5638
|
nativePreToolUseFailureFallbackTerminalReason: void 0,
|
|
5197
5639
|
releaseSharedClientLease: void 0,
|
|
5198
5640
|
startupClientUnsafe: false,
|
|
5199
5641
|
sharedCodexClientRetiredForOneShotCleanup: false,
|
|
5200
|
-
|
|
5642
|
+
sandboxExecEnvironment: void 0,
|
|
5643
|
+
executionDisconnectError: void 0,
|
|
5201
5644
|
codexEnvironmentSelection: void 0,
|
|
5202
5645
|
codexExecutionCwd: effectiveCwd,
|
|
5203
5646
|
codexSandboxPolicy: void 0,
|
|
@@ -5236,7 +5679,7 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5236
5679
|
if (params.cleanupBundleMcpOnRunEnd !== true || state.sharedCodexClientRetiredForOneShotCleanup) return;
|
|
5237
5680
|
state.sharedCodexClientRetiredForOneShotCleanup = true;
|
|
5238
5681
|
const retired = clearSharedCodexAppServerClientIfCurrentAndUnclaimed(state.client);
|
|
5239
|
-
embeddedAgentLog.
|
|
5682
|
+
embeddedAgentLog.debug("codex app-server one-shot cleanup checked shared client retirement", {
|
|
5240
5683
|
runId: params.runId,
|
|
5241
5684
|
sessionId: params.sessionId,
|
|
5242
5685
|
sessionKey: params.sessionKey,
|
|
@@ -5250,16 +5693,27 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5250
5693
|
forceKillDelayMs: 250
|
|
5251
5694
|
});
|
|
5252
5695
|
};
|
|
5696
|
+
const releaseSandboxExecEnvironment = async () => {
|
|
5697
|
+
if (state.sandboxExecEnvironment) {
|
|
5698
|
+
const environment = state.sandboxExecEnvironment;
|
|
5699
|
+
state.sandboxExecEnvironment = void 0;
|
|
5700
|
+
await releaseCodexSandboxExecServerEnvironment(sandbox, environment);
|
|
5701
|
+
}
|
|
5702
|
+
};
|
|
5253
5703
|
const releaseSharedClientLeaseAndRetireOneShotClient = async () => {
|
|
5704
|
+
if (connection.attemptClientFactory === createIsolatedCodexAppServerClient) {
|
|
5705
|
+
await releaseSandboxExecEnvironment();
|
|
5706
|
+
const ownedClient = state.releaseSharedClientLease ? state.client : void 0;
|
|
5707
|
+
releaseSharedClientLeaseOnce();
|
|
5708
|
+
await ownedClient?.closeAndWait({
|
|
5709
|
+
exitTimeoutMs: 2e3,
|
|
5710
|
+
forceKillDelayMs: 250
|
|
5711
|
+
});
|
|
5712
|
+
return;
|
|
5713
|
+
}
|
|
5254
5714
|
releaseSharedClientLeaseOnce();
|
|
5255
5715
|
await retireSharedCodexClientForOneShotCleanup();
|
|
5256
5716
|
};
|
|
5257
|
-
const releaseSandboxExecEnvironment = async () => {
|
|
5258
|
-
if (state.sandboxExecEnvironmentAcquired) {
|
|
5259
|
-
state.sandboxExecEnvironmentAcquired = false;
|
|
5260
|
-
await releaseCodexSandboxExecServerEnvironment(sandbox);
|
|
5261
|
-
}
|
|
5262
|
-
};
|
|
5263
5717
|
const runCleanupStep = (step, operation) => runAgentCleanupStep({
|
|
5264
5718
|
runId: params.runId,
|
|
5265
5719
|
sessionId: params.sessionId,
|
|
@@ -5284,7 +5738,10 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5284
5738
|
retainClient: () => retainSharedCodexAppServerClientIfCurrent(state.client),
|
|
5285
5739
|
retainParentThread: (protectedThreadId) => protectCodexAppServerLiveThread(state.client, protectedThreadId),
|
|
5286
5740
|
claimDirectChild: (childThreadId) => state.nativeHookRelay?.claimDirectChild(childThreadId),
|
|
5287
|
-
rejectPendingDirectChild: (childThreadId, reason) => state.nativeHookRelay?.rejectPendingDirectChild(childThreadId, reason)
|
|
5741
|
+
rejectPendingDirectChild: (childThreadId, reason) => state.nativeHookRelay?.rejectPendingDirectChild(childThreadId, reason),
|
|
5742
|
+
...params.sessionKey && params.agentHarnessTaskRuntimeScope ? { onDirectChildAccepted: () => {
|
|
5743
|
+
state.runtimeContinuationStarted = true;
|
|
5744
|
+
} } : {}
|
|
5288
5745
|
});
|
|
5289
5746
|
};
|
|
5290
5747
|
const releaseCurrentRoute = () => {
|
|
@@ -5347,8 +5804,7 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5347
5804
|
configPatch: state.nativeHookRelay ? buildCodexNativeHookRelayConfig({
|
|
5348
5805
|
relay: state.nativeHookRelay,
|
|
5349
5806
|
events: nativeHookRelayEvents,
|
|
5350
|
-
hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec
|
|
5351
|
-
loopDetectionPreToolUseRelay: appServer.loopDetectionPreToolUseRelay
|
|
5807
|
+
hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec
|
|
5352
5808
|
}) : options.nativeHookRelay?.enabled === false ? buildCodexNativeHookRelayDisabledConfig() : void 0,
|
|
5353
5809
|
nativeHookRelayGeneration: state.nativeHookRelay?.generation
|
|
5354
5810
|
};
|
|
@@ -5480,10 +5936,6 @@ function resolveScheduledCodexAppCreatorCaptureDecision(params) {
|
|
|
5480
5936
|
...unavailableReason ? { unavailableReason } : {}
|
|
5481
5937
|
};
|
|
5482
5938
|
}
|
|
5483
|
-
function readConnectorId(tool) {
|
|
5484
|
-
const meta = asOptionalRecord(asOptionalRecord(tool)?.["_meta"]);
|
|
5485
|
-
return normalizeOptionalString(meta?.connector_id) ?? normalizeOptionalString(meta?.connectorId);
|
|
5486
|
-
}
|
|
5487
5939
|
function normalizeApprovalMode(value) {
|
|
5488
5940
|
return value === "allow" || value === "deny" || value === "auto" || value === "ask" ? value : void 0;
|
|
5489
5941
|
}
|
|
@@ -5550,7 +6002,7 @@ async function readCodexScheduledAppToolNamesByApp(params) {
|
|
|
5550
6002
|
if (!isJsonObject(status) || !isJsonObject(status.tools)) throw new Error("Codex scheduled app inventory contained an invalid server status");
|
|
5551
6003
|
if (status.name !== CODEX_APPS_MCP_SERVER) continue;
|
|
5552
6004
|
for (const [toolName, tool] of Object.entries(status.tools)) {
|
|
5553
|
-
const connectorId =
|
|
6005
|
+
const connectorId = readCodexMcpToolConnectorId(tool);
|
|
5554
6006
|
if (connectorId) {
|
|
5555
6007
|
const names = toolNamesByApp.get(connectorId) ?? /* @__PURE__ */ new Set();
|
|
5556
6008
|
names.add(toolName);
|
|
@@ -5783,8 +6235,8 @@ async function prepareCodexAttemptRuntime(connection) {
|
|
|
5783
6235
|
const effectiveContextWindowInfo = usesSupervisionConnection ? void 0 : params.contextWindowInfo;
|
|
5784
6236
|
const effectiveContextTokenBudget = usesSupervisionConnection ? void 0 : params.contextTokenBudget;
|
|
5785
6237
|
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;
|
|
6238
|
+
const effectiveRuntimeModelId = usesSupervisionConnection ? mutable.startupBinding?.model ?? "codex-native" : connection.options.runtimeModelId ?? params.modelId;
|
|
6239
|
+
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
6240
|
const supervisedRuntimeModel = {
|
|
5789
6241
|
id: effectiveRuntimeModelId,
|
|
5790
6242
|
name: effectiveRuntimeModelId,
|
|
@@ -6017,18 +6469,23 @@ function resolveCodexDynamicToolDirectNames(params, hostSystemAgentActive = fals
|
|
|
6017
6469
|
const names = [];
|
|
6018
6470
|
if (hostSystemAgentActive && isSystemAgentOnlyCodexDynamicToolAllowlist(params.toolsAllow)) names.push("openclaw");
|
|
6019
6471
|
if (params.sourceReplyDeliveryMode === "message_tool_only") names.push("message");
|
|
6020
|
-
|
|
6472
|
+
names.push("progress_card");
|
|
6021
6473
|
return names;
|
|
6022
6474
|
}
|
|
6023
6475
|
//#endregion
|
|
6024
6476
|
//#region extensions/codex/src/app-server/run-attempt-server-requests.ts
|
|
6477
|
+
const DYNAMIC_TOOL_TERMINAL_DIAGNOSTIC_TYPES = [
|
|
6478
|
+
"tool.execution.completed",
|
|
6479
|
+
"tool.execution.error",
|
|
6480
|
+
"tool.execution.blocked"
|
|
6481
|
+
];
|
|
6025
6482
|
function createCodexAttemptServerRequestController(resources, turnRuntime, lifecycle) {
|
|
6026
6483
|
const { prompt, state: resourceState, projectorRef, trajectoryRecorder } = resources;
|
|
6027
6484
|
const { context } = prompt;
|
|
6028
6485
|
const { runtime, attemptTools } = context;
|
|
6029
6486
|
const { connection } = runtime;
|
|
6030
|
-
const { params, computerUseConfig, runAbortController, appServer,
|
|
6031
|
-
const { toolBridge, toolOutcomeOrdinals, suppressedDynamicToolOutcomeOrdinals, allocateCodexToolOutcomeOrdinal } = attemptTools;
|
|
6487
|
+
const { params, computerUseConfig, runAbortController, appServer, sessionAgentId } = connection;
|
|
6488
|
+
const { compactionPlanState, toolBridge, toolOutcomeOrdinals, suppressedDynamicToolOutcomeOrdinals, allocateCodexToolOutcomeOrdinal } = attemptTools;
|
|
6032
6489
|
const { state, turnIdRef, userInputBridgeRef, openClawDynamicToolExecutions, pendingOpenClawDynamicToolCompletionIds, postToolRawAssistantCompletionIdleTimeoutMs, turnWatches } = turnRuntime;
|
|
6033
6490
|
const { emitExecutionPhaseOnce, scheduleTurnReleaseAfterTerminalDynamicTool, scheduleTerminalDynamicToolReleaseCheck } = lifecycle;
|
|
6034
6491
|
const handleServerRequest = async (request, scope, requestSignal = new AbortController().signal) => {
|
|
@@ -6054,7 +6511,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6054
6511
|
armCompletionWatchOnResponse = true;
|
|
6055
6512
|
markCurrentTurnRequestProgress();
|
|
6056
6513
|
}
|
|
6057
|
-
|
|
6514
|
+
const approvalResult = await routeCodexAppServerElicitationRequest({
|
|
6058
6515
|
requestParams: request.params,
|
|
6059
6516
|
paramsForRun: params,
|
|
6060
6517
|
threadId: resourceState.thread.threadId,
|
|
@@ -6063,6 +6520,11 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6063
6520
|
...computerUseConfig.enabled ? { computerUseMcpServerName: computerUseConfig.mcpServerName } : {},
|
|
6064
6521
|
signal
|
|
6065
6522
|
});
|
|
6523
|
+
if (approvalResult.kind === "handled") return approvalResult.response;
|
|
6524
|
+
return await userInputBridgeRef.current?.handleElicitationRequest({
|
|
6525
|
+
id: request.id,
|
|
6526
|
+
params: request.params
|
|
6527
|
+
});
|
|
6066
6528
|
}
|
|
6067
6529
|
if (request.method === "item/tool/requestUserInput") {
|
|
6068
6530
|
if (scope.turnId === turnId) {
|
|
@@ -6088,9 +6550,8 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6088
6550
|
turnId,
|
|
6089
6551
|
nativeHookRelay: resourceState.nativeHookRelay,
|
|
6090
6552
|
autoApprove: shouldAutoApproveCodexAppServerApprovals(appServer),
|
|
6091
|
-
autoApproveOpenClawToolPolicy: approvalPolicyPromotedForOpenClawToolPolicy,
|
|
6092
6553
|
signal,
|
|
6093
|
-
onNativeToolFailureDisposition: (itemId, disposition) => projector?.recordNativeToolApprovalFailure(itemId, disposition)
|
|
6554
|
+
onNativeToolFailureDisposition: (itemId, disposition, approvalKind) => projector?.recordNativeToolApprovalFailure(itemId, disposition, approvalKind)
|
|
6094
6555
|
});
|
|
6095
6556
|
}
|
|
6096
6557
|
return;
|
|
@@ -6126,13 +6587,6 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6126
6587
|
tool: call.tool,
|
|
6127
6588
|
toolCallId: call.callId
|
|
6128
6589
|
});
|
|
6129
|
-
emitDynamicToolStartedDiagnostic({
|
|
6130
|
-
call,
|
|
6131
|
-
agentId: sessionAgentId,
|
|
6132
|
-
runId: params.runId,
|
|
6133
|
-
sessionId: params.sessionId,
|
|
6134
|
-
sessionKey: params.sessionKey
|
|
6135
|
-
});
|
|
6136
6590
|
const toolMeta = inferCodexDynamicToolMeta(call, resolveCodexToolProgressDetailMode(params.toolProgressDetail));
|
|
6137
6591
|
const toolArgs = sanitizeCodexToolArguments(call.arguments);
|
|
6138
6592
|
const commandBearing = isCodexCommandBearingToolCall(call.tool, toolArgs);
|
|
@@ -6162,30 +6616,39 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6162
6616
|
sessionId: params.sessionId,
|
|
6163
6617
|
sessionKey: params.sessionKey
|
|
6164
6618
|
})) terminalDiagnosticObserved = true;
|
|
6165
|
-
});
|
|
6619
|
+
}, { include: DYNAMIC_TOOL_TERMINAL_DIAGNOSTIC_TYPES });
|
|
6166
6620
|
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
|
-
|
|
6621
|
+
const { execution } = openClawDynamicToolExecutions.claim(call, () => {
|
|
6622
|
+
emitDynamicToolStartedDiagnostic({
|
|
6623
|
+
call,
|
|
6624
|
+
agentId: sessionAgentId,
|
|
6625
|
+
runId: params.runId,
|
|
6626
|
+
sessionId: params.sessionId,
|
|
6627
|
+
sessionKey: params.sessionKey
|
|
6628
|
+
});
|
|
6629
|
+
return handleDynamicToolCallWithTimeout({
|
|
6630
|
+
call,
|
|
6631
|
+
toolBridge,
|
|
6632
|
+
signal,
|
|
6633
|
+
timeoutMs: dynamicToolTimeoutMs,
|
|
6634
|
+
toolMeta,
|
|
6635
|
+
toolCallOrdinal,
|
|
6636
|
+
onAgentToolResult: params.onAgentToolResult,
|
|
6637
|
+
observeToolTerminal: params.observeToolTerminal,
|
|
6638
|
+
onFallbackSelected: () => {
|
|
6639
|
+
if (toolCallOrdinal !== void 0) suppressedDynamicToolOutcomeOrdinals.add(toolCallOrdinal);
|
|
6640
|
+
},
|
|
6641
|
+
onTimeout: () => {
|
|
6642
|
+
trajectoryRecorder?.recordEvent("tool.timeout", {
|
|
6643
|
+
threadId: call.threadId,
|
|
6644
|
+
turnId: call.turnId,
|
|
6645
|
+
toolCallId: call.callId,
|
|
6646
|
+
name: call.tool,
|
|
6647
|
+
timeoutMs: dynamicToolTimeoutMs
|
|
6648
|
+
});
|
|
6649
|
+
}
|
|
6650
|
+
});
|
|
6651
|
+
});
|
|
6189
6652
|
const response = await execution;
|
|
6190
6653
|
const protocolResponse = toCodexDynamicToolProtocolResponse(response);
|
|
6191
6654
|
if (!protocolResponse.success && toolCallOrdinal !== void 0) {
|
|
@@ -6209,7 +6672,11 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6209
6672
|
contentItems: protocolResponse.contentItems
|
|
6210
6673
|
});
|
|
6211
6674
|
recordCodexDynamicToolResult(projector, call, response, protocolResponse);
|
|
6212
|
-
if (protocolResponse.success && call.tool === "
|
|
6675
|
+
if (protocolResponse.success && call.tool === "progress_card") {
|
|
6676
|
+
const progressCardInput = response.executedArguments ?? call.arguments;
|
|
6677
|
+
await projector?.recordDynamicProgressCardUpdate(progressCardInput);
|
|
6678
|
+
compactionPlanState.recordProgressCardInput(progressCardInput);
|
|
6679
|
+
}
|
|
6213
6680
|
if (shouldEmitDynamicToolProgress) {
|
|
6214
6681
|
const progressResponse = toCodexDynamicToolProgressResponse(response, protocolResponse);
|
|
6215
6682
|
emitCodexAppServerEvent(params, {
|
|
@@ -6289,6 +6756,20 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6289
6756
|
return { handleServerRequest };
|
|
6290
6757
|
}
|
|
6291
6758
|
//#endregion
|
|
6759
|
+
//#region extensions/codex/src/app-server/attempt-runtime-artifact.ts
|
|
6760
|
+
async function verifyStartupArtifact(params) {
|
|
6761
|
+
if (!params.request) return;
|
|
6762
|
+
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-BvyT1uyd.js");
|
|
6763
|
+
const runtimeArtifact = readCodexAppServerClientRuntimeArtifact(params.client);
|
|
6764
|
+
const expected = params.request.expected;
|
|
6765
|
+
const matchesExpected = !expected || runtimeArtifact?.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint;
|
|
6766
|
+
if (!runtimeArtifact || !matchesExpected || !await validateCodexAppServerRuntimeArtifact(runtimeArtifact, params.signal)) {
|
|
6767
|
+
retireSharedCodexAppServerClientIfCurrent(params.client);
|
|
6768
|
+
throw new Error(expected ? "Codex app-server runtime artifact does not match verified inference" : "Codex app-server runtime artifact is unavailable or stale");
|
|
6769
|
+
}
|
|
6770
|
+
return runtimeArtifact;
|
|
6771
|
+
}
|
|
6772
|
+
//#endregion
|
|
6292
6773
|
//#region extensions/codex/src/app-server/computer-use-health.ts
|
|
6293
6774
|
const COMPUTER_USE_HEALTH_MONITOR_STATE = Symbol.for("openclaw.codexComputerUseHealthMonitorState");
|
|
6294
6775
|
function getComputerUseHealthMonitorState() {
|
|
@@ -6308,19 +6789,17 @@ function startCodexComputerUseHealthMonitor(params) {
|
|
|
6308
6789
|
}
|
|
6309
6790
|
const fingerprint = buildComputerUseHealthMonitorFingerprint(params.config);
|
|
6310
6791
|
const intervalMs = params.config.healthCheckIntervalMinutes * 6e4;
|
|
6311
|
-
if (existing?.fingerprint === fingerprint
|
|
6792
|
+
if (existing?.fingerprint === fingerprint) return {
|
|
6312
6793
|
started: false,
|
|
6313
6794
|
intervalMs,
|
|
6314
6795
|
reason: "already_started"
|
|
6315
6796
|
};
|
|
6316
6797
|
if (existing) clearComputerUseHealthMonitor(params.client, existing);
|
|
6317
|
-
const repairComputerUseMcpChildren = params.repairComputerUseMcpChildren ?? (() => killStaleComputerUseMcpChildren({ ancestorPid: params.client.getTransportPid() }));
|
|
6318
6798
|
const monitor = {
|
|
6319
6799
|
fingerprint,
|
|
6320
6800
|
intervalMs,
|
|
6321
|
-
repairComputerUseMcpChildren: params.repairComputerUseMcpChildren,
|
|
6322
6801
|
timer: setInterval(() => {
|
|
6323
|
-
runCodexComputerUseHealthProbe(params.client, params.config, monitor
|
|
6802
|
+
runCodexComputerUseHealthProbe(params.client, params.config, monitor);
|
|
6324
6803
|
}, intervalMs),
|
|
6325
6804
|
disposeCloseHandler: () => void 0,
|
|
6326
6805
|
running: false
|
|
@@ -6345,13 +6824,12 @@ function buildComputerUseHealthMonitorFingerprint(config) {
|
|
|
6345
6824
|
toolCallTimeoutMs: config.toolCallTimeoutMs
|
|
6346
6825
|
});
|
|
6347
6826
|
}
|
|
6348
|
-
async function runCodexComputerUseHealthProbe(client, config, monitor
|
|
6827
|
+
async function runCodexComputerUseHealthProbe(client, config, monitor) {
|
|
6349
6828
|
if (monitor.running) return;
|
|
6350
6829
|
monitor.running = true;
|
|
6351
6830
|
try {
|
|
6352
6831
|
const { liveTest, repair } = await runCodexComputerUseLiveTest({
|
|
6353
6832
|
config,
|
|
6354
|
-
repairComputerUseMcpChildren: options.repairComputerUseMcpChildren,
|
|
6355
6833
|
request: async (method, requestParams, requestOptions) => await client.request(method, requestParams, { timeoutMs: requestOptions?.timeoutMs ?? config.liveTestTimeoutMs })
|
|
6356
6834
|
});
|
|
6357
6835
|
if (!liveTest.ok) {
|
|
@@ -6364,10 +6842,7 @@ async function runCodexComputerUseHealthProbe(client, config, monitor, options)
|
|
|
6364
6842
|
});
|
|
6365
6843
|
return;
|
|
6366
6844
|
}
|
|
6367
|
-
if (repair?.
|
|
6368
|
-
mcpServerName: config.mcpServerName,
|
|
6369
|
-
killedPids: repair.killedPids
|
|
6370
|
-
});
|
|
6845
|
+
if (repair?.attempted && repair.warnings.length === 0) embeddedAgentLog.info("codex computer-use periodic health reloaded MCP servers", { mcpServerName: config.mcpServerName });
|
|
6371
6846
|
} catch (error) {
|
|
6372
6847
|
embeddedAgentLog.warn("codex computer-use periodic health probe crashed", {
|
|
6373
6848
|
mcpServerName: config.mcpServerName,
|
|
@@ -6462,6 +6937,7 @@ function createCodexPluginThreadConfigStartupProvider(params) {
|
|
|
6462
6937
|
build: async (buildOptions) => {
|
|
6463
6938
|
const config = await buildCodexPluginThreadConfigWithinDeadline({
|
|
6464
6939
|
...buildParams,
|
|
6940
|
+
threadId: buildOptions?.threadId,
|
|
6465
6941
|
appCache: appCache ?? defaultCodexAppInventoryCache,
|
|
6466
6942
|
metadataCache,
|
|
6467
6943
|
failClosedOnTimeout: Boolean(params.scheduledRuntimeAuthority),
|
|
@@ -6494,7 +6970,7 @@ function isCodexPluginThreadConfigTimeoutError(error) {
|
|
|
6494
6970
|
* Startup orchestration for Codex app-server attempts, including shared-client
|
|
6495
6971
|
* leasing, plugin thread config, sandbox environment, and thread lifecycle binding.
|
|
6496
6972
|
*/
|
|
6497
|
-
const
|
|
6973
|
+
const CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS = 3;
|
|
6498
6974
|
const CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED = "CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED";
|
|
6499
6975
|
/** True when a pre-write context restart must replay on the newly selected owner. */
|
|
6500
6976
|
function isCodexContextRestartSelectionChangedError(error) {
|
|
@@ -6575,24 +7051,19 @@ async function startCodexAttemptThread(params) {
|
|
|
6575
7051
|
startupClientLease = () => {
|
|
6576
7052
|
if (startupClientLeaseReleased) return;
|
|
6577
7053
|
startupClientLeaseReleased = true;
|
|
6578
|
-
|
|
7054
|
+
if (params.attemptClientFactory === createIsolatedCodexAppServerClient) activeStartupClient.close();
|
|
7055
|
+
else releaseLeasedSharedCodexAppServerClient(activeStartupClient);
|
|
6579
7056
|
};
|
|
6580
7057
|
releaseSharedClientLease = startupClientLease;
|
|
6581
7058
|
attemptedClient = activeStartupClient;
|
|
6582
7059
|
startupClientForAbandonedRequestCleanup = activeStartupClient;
|
|
6583
7060
|
if (startupAbandoned) throw new CodexAppServerStartupError("timed_out");
|
|
6584
7061
|
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
|
-
}
|
|
7062
|
+
const runtimeArtifact = await verifyStartupArtifact({
|
|
7063
|
+
client: activeStartupClient,
|
|
7064
|
+
request: params.runtimeArtifactRequest,
|
|
7065
|
+
signal: startupAbandonController.signal
|
|
7066
|
+
});
|
|
6596
7067
|
ensureCodexAppServerClientRuntime(activeStartupClient, {
|
|
6597
7068
|
agentDir: params.agentDir,
|
|
6598
7069
|
authProfileId: startupRuntimeAuthProfileId,
|
|
@@ -6611,7 +7082,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6611
7082
|
signal: startupAbandonController.signal
|
|
6612
7083
|
});
|
|
6613
7084
|
} catch (error) {
|
|
6614
|
-
if (startupAbandonController.signal.aborted) throw error;
|
|
7085
|
+
if (startupAbandonController.signal.aborted || isCodexAppServerStartSelectionChangedError(error)) throw error;
|
|
6615
7086
|
throw new AgentHarnessPreflightError(`Codex Computer Use readiness failed: ${formatErrorMessage(error)}`, {
|
|
6616
7087
|
cause: error,
|
|
6617
7088
|
scope: "harness"
|
|
@@ -6625,7 +7096,8 @@ async function startCodexAttemptThread(params) {
|
|
|
6625
7096
|
accountId: params.startupAuthAccountCacheKey,
|
|
6626
7097
|
envApiKeyFingerprint: params.startupEnvApiKeyCacheKey,
|
|
6627
7098
|
appServerVersion: activeStartupClient.getServerVersion(),
|
|
6628
|
-
runtimeIdentity: startupRuntimeIdentity
|
|
7099
|
+
runtimeIdentity: startupRuntimeIdentity,
|
|
7100
|
+
desktopGenerationFingerprint: readCodexAppServerClientDesktopGenerationFingerprint(activeStartupClient)
|
|
6629
7101
|
});
|
|
6630
7102
|
const appServerRuntimeFingerprint = buildCodexAppServerRuntimeFingerprint({
|
|
6631
7103
|
appServer: params.appServer,
|
|
@@ -6652,7 +7124,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6652
7124
|
const releaseStartupSandboxEnvironment = async () => {
|
|
6653
7125
|
if (startupSandboxEnvironmentAcquired) {
|
|
6654
7126
|
startupSandboxEnvironmentAcquired = false;
|
|
6655
|
-
await releaseCodexSandboxExecServerEnvironment(params.sandbox);
|
|
7127
|
+
await releaseCodexSandboxExecServerEnvironment(params.sandbox, startupSandboxEnvironment);
|
|
6656
7128
|
}
|
|
6657
7129
|
};
|
|
6658
7130
|
releaseStartupResourcesOnTimeout = releaseStartupSandboxEnvironment;
|
|
@@ -6665,9 +7137,11 @@ async function startCodexAttemptThread(params) {
|
|
|
6665
7137
|
startupSandboxEnvironment = sandboxEnvironmentRequired ? await ensureCodexSandboxExecServerEnvironment({
|
|
6666
7138
|
client: activeStartupClient,
|
|
6667
7139
|
sandbox: params.sandbox ?? null,
|
|
7140
|
+
runtime: params.runtime,
|
|
6668
7141
|
appServerStartOptions: params.appServer.start,
|
|
6669
7142
|
timeoutMs: params.appServer.requestTimeoutMs,
|
|
6670
|
-
signal: startupAbandonController.signal
|
|
7143
|
+
signal: AbortSignal.any([params.signal, startupAbandonController.signal]),
|
|
7144
|
+
onExecutionDisconnect: params.onExecutionDisconnect
|
|
6671
7145
|
}) : void 0;
|
|
6672
7146
|
startupSandboxEnvironmentAcquired = Boolean(startupSandboxEnvironment);
|
|
6673
7147
|
if (startupAbandonController.signal.aborted) {
|
|
@@ -6711,17 +7185,23 @@ async function startCodexAttemptThread(params) {
|
|
|
6711
7185
|
reserveResumeThread,
|
|
6712
7186
|
bindingStore: params.bindingStore,
|
|
6713
7187
|
params: params.buildAttemptParams(),
|
|
7188
|
+
runtimeModelId: params.runtimeModelId,
|
|
6714
7189
|
agentId: params.sessionAgentId,
|
|
7190
|
+
agentDir: params.agentDir,
|
|
6715
7191
|
cwd: startupExecutionCwd,
|
|
6716
7192
|
dynamicTools: params.dynamicTools,
|
|
6717
7193
|
persistentWebSearchAllowed: params.persistentWebSearchAllowed,
|
|
6718
7194
|
webSearchAllowed: params.webSearchAllowed,
|
|
6719
7195
|
appServer: pluginAppServer,
|
|
6720
7196
|
developerInstructions: params.developerInstructions,
|
|
7197
|
+
agentWorkspaceDeveloperInstructions: params.agentWorkspaceDeveloperInstructions,
|
|
6721
7198
|
config: threadConfig,
|
|
7199
|
+
shellEnvironment: params.shellEnvironment,
|
|
7200
|
+
disableLoginShell: params.disableLoginShell,
|
|
6722
7201
|
finalConfigPatch: params.finalConfigPatch,
|
|
6723
7202
|
buildFinalConfigPatch: params.buildFinalConfigPatch,
|
|
6724
7203
|
nativeHookRelayGeneration: params.nativeHookRelayGeneration,
|
|
7204
|
+
nativeHookRelayRequired: params.nativeHookRelayRequired,
|
|
6725
7205
|
nativeCodeModeEnabled: params.nativeToolSurfaceEnabled,
|
|
6726
7206
|
nativeProviderWebSearchSupport: params.nativeProviderWebSearchSupport,
|
|
6727
7207
|
nativeCodeModeOnlyEnabled: params.appServer.codeModeOnly,
|
|
@@ -6816,30 +7296,31 @@ async function startCodexAttemptThread(params) {
|
|
|
6816
7296
|
}
|
|
6817
7297
|
}
|
|
6818
7298
|
};
|
|
6819
|
-
for (let attempt = 1; attempt <=
|
|
7299
|
+
for (let attempt = 1; attempt <= CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS; attempt += 1) try {
|
|
6820
7300
|
return await startupAttempt();
|
|
6821
7301
|
} catch (error) {
|
|
6822
7302
|
const selectionChanged = isCodexAppServerStartSelectionChangedError(error);
|
|
6823
7303
|
if (startupAbandoned || params.signal.aborted || !selectionChanged && !isCodexAppServerConnectionClosedError(error)) throw error;
|
|
6824
|
-
const
|
|
6825
|
-
|
|
6826
|
-
if (
|
|
6827
|
-
if (attempt >= CODEX_APP_SERVER_STARTUP_CONNECTION_CLOSE_MAX_ATTEMPTS) {
|
|
7304
|
+
const refreshedSharedClient = selectionChanged ? retireSharedCodexAppServerClientIfCurrent(attemptedClient) : clearSharedCodexAppServerClientIfCurrent(attemptedClient);
|
|
7305
|
+
if (startupClientForAbandonedRequestCleanup === attemptedClient) startupClientForAbandonedRequestCleanup = void 0;
|
|
7306
|
+
if (attempt >= CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS) {
|
|
6828
7307
|
embeddedAgentLog.warn(selectionChanged ? "codex app-server executable selection kept changing during startup; retries exhausted" : "codex app-server connection closed during startup; retries exhausted", {
|
|
6829
7308
|
attempt,
|
|
6830
|
-
maxAttempts:
|
|
7309
|
+
maxAttempts: CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS,
|
|
6831
7310
|
refreshedSharedClient,
|
|
6832
7311
|
error: formatErrorMessage(error)
|
|
6833
7312
|
});
|
|
6834
7313
|
throw error;
|
|
6835
7314
|
}
|
|
7315
|
+
const retryDelayMs = selectionChanged ? 0 : 1e3 * 2 ** (attempt - 1);
|
|
6836
7316
|
embeddedAgentLog.warn(selectionChanged ? "codex app-server executable selection changed during startup; restarting app-server and retrying" : "codex app-server connection closed during startup; restarting app-server and retrying", {
|
|
6837
7317
|
attempt,
|
|
6838
7318
|
nextAttempt: attempt + 1,
|
|
6839
|
-
maxAttempts:
|
|
7319
|
+
maxAttempts: CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS,
|
|
6840
7320
|
refreshedSharedClient,
|
|
6841
7321
|
error: formatErrorMessage(error)
|
|
6842
7322
|
});
|
|
7323
|
+
await sleepWithAbort(retryDelayMs, startupAbandonController.signal);
|
|
6843
7324
|
}
|
|
6844
7325
|
throw new Error("codex app-server startup retry loop exited unexpectedly");
|
|
6845
7326
|
}
|
|
@@ -6886,11 +7367,12 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6886
7367
|
const { prompt, state, trajectoryRecorder, activateNativePreToolUseFailureFallback, releaseSandboxExecEnvironment, releaseSharedClientLeaseAndRetireOneShotClient, releaseCurrentRoute, runCleanupStep, startupTimeoutMs, buildNativeHookRelayFinalConfigPatch } = resources;
|
|
6887
7368
|
const { context, turnState, buildRenderedCodexDeveloperInstructions, rebuildCodexTurnPromptTextFromCurrentProjection, applyNoContextEngineContinuityProjection } = prompt;
|
|
6888
7369
|
const { runtime, attemptTools, promptState } = context;
|
|
6889
|
-
const { connection, runtimeParams, preparedAuthBinding, buildActiveRunAttemptParams, startupAuthAccountCacheKey, startupEnvApiKeyCacheKey, bundleMcpThreadConfig, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, sandboxExecServerEnabled } = runtime;
|
|
7370
|
+
const { connection, runtimeParams, preparedAuthBinding, buildActiveRunAttemptParams, startupAuthAccountCacheKey, startupEnvApiKeyCacheKey, bundleMcpThreadConfig, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, effectiveRuntimeModelId, sandboxExecServerEnabled } = runtime;
|
|
6890
7371
|
const { toolBridge, toolState } = attemptTools;
|
|
6891
7372
|
const developerInstructions = joinPresentSections(turnState.promptBuild.developerInstructions, attemptTools.scheduledConfiguredMcp?.diagnosticNotice);
|
|
6892
7373
|
const { params, attemptClientFactory, bindingStore, appServer, pluginConfig, computerUseConfig, startupClientAuthProfileId, runtimeArtifactRequest, startupPreparedAuth, agentDir, sessionAgentId, effectiveWorkspace, effectiveCwd, sandbox, runAbortController, usesSupervisionConnection, resolveReviewerPolicyContext, resolveRuntimeOptionsForCurrentBinding, startupAuthProfileId, startupAuthRequirement, abortFromUpstream } = connection;
|
|
6893
7374
|
let pluginAppServer = withCodexAppServerFastModeServiceTier(appServer, runtimeParams);
|
|
7375
|
+
const loopDetectionEnabled = (sessionAgentId && params.config ? resolveAgentConfig$1(params.config, sessionAgentId)?.tools?.loopDetection?.enabled : void 0) ?? params.config?.tools?.loopDetection?.enabled ?? false;
|
|
6894
7376
|
try {
|
|
6895
7377
|
emitCodexAppServerEvent(params, {
|
|
6896
7378
|
stream: "codex_app_server.lifecycle",
|
|
@@ -6899,6 +7381,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6899
7381
|
const startupResult = await startCodexAttemptThread({
|
|
6900
7382
|
attemptClientFactory,
|
|
6901
7383
|
bindingStore,
|
|
7384
|
+
runtime: connection.options.runtime,
|
|
6902
7385
|
appServer: pluginAppServer,
|
|
6903
7386
|
pluginConfig,
|
|
6904
7387
|
computerUseConfig,
|
|
@@ -6911,7 +7394,10 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6911
7394
|
startupEnvApiKeyCacheKey,
|
|
6912
7395
|
agentDir,
|
|
6913
7396
|
config: params.config,
|
|
7397
|
+
shellEnvironment: connection.shellEnvironment,
|
|
7398
|
+
disableLoginShell: connection.disableLoginShell,
|
|
6914
7399
|
buildAttemptParams: buildActiveRunAttemptParams,
|
|
7400
|
+
...effectiveRuntimeModelId !== runtimeParams.modelId ? { runtimeModelId: effectiveRuntimeModelId } : {},
|
|
6915
7401
|
sessionAgentId,
|
|
6916
7402
|
effectiveWorkspace,
|
|
6917
7403
|
effectiveCwd,
|
|
@@ -6919,7 +7405,9 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6919
7405
|
persistentWebSearchAllowed: toolState.persistentWebSearchAllowed,
|
|
6920
7406
|
webSearchAllowed: toolState.webSearchAllowed,
|
|
6921
7407
|
developerInstructions,
|
|
7408
|
+
agentWorkspaceDeveloperInstructions: context.agentWorkspaceDeveloperInstructions,
|
|
6922
7409
|
buildFinalConfigPatch: buildNativeHookRelayFinalConfigPatch,
|
|
7410
|
+
nativeHookRelayRequired: connection.options.nativeHookRelay?.enabled !== false && params.pluginHarnessToolPolicyRestricted !== true && connection.nativeHookRelayEvents.includes("pre_tool_use") && (hasBeforeToolCallPolicy() || appServer.loopDetectionPreToolUseRelay && Boolean(connection.sandboxSessionKey) && loopDetectionEnabled),
|
|
6923
7411
|
bundleMcpThreadConfig,
|
|
6924
7412
|
configuredMcpOwnershipVersion: attemptTools.configuredMcpOwnershipVersion,
|
|
6925
7413
|
nativeToolSurfaceEnabled,
|
|
@@ -6930,6 +7418,11 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6930
7418
|
startupTimeoutMs,
|
|
6931
7419
|
signal: runAbortController.signal,
|
|
6932
7420
|
onStartupTimeout: () => runAbortController.abort("codex_startup_timeout"),
|
|
7421
|
+
onExecutionDisconnect: (error) => {
|
|
7422
|
+
state.executionDisconnectError = error;
|
|
7423
|
+
embeddedAgentLog.warn(error.message);
|
|
7424
|
+
runAbortController.abort("client_closed");
|
|
7425
|
+
},
|
|
6933
7426
|
spawnedBy: params.spawnedBy
|
|
6934
7427
|
});
|
|
6935
7428
|
state.client = startupResult.client;
|
|
@@ -6937,7 +7430,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6937
7430
|
state.runtimeArtifact = startupResult.runtimeArtifact;
|
|
6938
7431
|
state.turnRouter = startupResult.turnRouter;
|
|
6939
7432
|
state.turnRoute = startupResult.turnRoute;
|
|
6940
|
-
state.
|
|
7433
|
+
state.sandboxExecEnvironment = startupResult.sandboxEnvironment;
|
|
6941
7434
|
state.releaseSharedClientLease = startupResult.releaseSharedClientLease;
|
|
6942
7435
|
state.restartContextEngineCodexThread = startupResult.restartContextEngineCodexThread;
|
|
6943
7436
|
pluginAppServer = startupResult.pluginAppServer;
|
|
@@ -7011,7 +7504,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
7011
7504
|
await runCleanupStep("codex-start-failure-sandbox-release", releaseSandboxExecEnvironment);
|
|
7012
7505
|
await runCleanupStep("codex-start-failure-shared-client-release", releaseSharedClientLeaseAndRetireOneShotClient);
|
|
7013
7506
|
await runCleanupStep("codex-start-failure-abort-listener", () => params.abortSignal?.removeEventListener("abort", abortFromUpstream));
|
|
7014
|
-
throw error;
|
|
7507
|
+
throw state.executionDisconnectError ?? error;
|
|
7015
7508
|
}
|
|
7016
7509
|
}
|
|
7017
7510
|
//#endregion
|
|
@@ -7021,7 +7514,7 @@ function isAuthorityResolutionOperationAbort(error, signal) {
|
|
|
7021
7514
|
}
|
|
7022
7515
|
async function prepareCodexAttemptTools(runtime) {
|
|
7023
7516
|
const { connection, bundleMcpThreadConfig, bundleManifestRegistry, runtimeParams, effectiveRuntimeModelId, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, hookChannelId, codexMcpToolOverrides, authenticatedScheduledMode, ownsScheduledConfiguredMcpSurface, canResolveScheduledConfiguredMcpCreatorAuthority } = runtime;
|
|
7024
|
-
const { params, preDynamicStartupStages, mutable, startupAuthProfileId, resolvedWorkspace, effectiveWorkspace, effectiveCwd, sandboxSessionKey, sandbox, runAbortController, sessionAgentId, pluginConfig, profilerEnabled, agentDir } = connection;
|
|
7517
|
+
const { params, preDynamicStartupStages, mutable, startupAuthProfileId, resolvedWorkspace, effectiveWorkspace, effectiveCwd, sandboxSessionKey, sandbox, sessionPermissionPolicy, runAbortController, sessionAgentId, pluginConfig, profilerEnabled, agentDir } = connection;
|
|
7025
7518
|
const preDynamicSummary = preDynamicStartupStages.snapshot();
|
|
7026
7519
|
if (shouldWarnCodexDynamicToolBuildStageSummary(preDynamicSummary)) embeddedAgentLog.warn(`codex app-server pre-dynamic startup timings runId=${params.runId} sessionId=${params.sessionId} totalMs=${preDynamicSummary.totalMs} stages=${formatCodexDynamicToolBuildStageSummary(preDynamicSummary)}`, {
|
|
7027
7520
|
runId: params.runId,
|
|
@@ -7035,6 +7528,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7035
7528
|
});
|
|
7036
7529
|
const toolState = {
|
|
7037
7530
|
yieldDetected: false,
|
|
7531
|
+
yieldAcknowledgment: void 0,
|
|
7038
7532
|
persistentWebSearchAllowed: void 0,
|
|
7039
7533
|
webSearchAllowed: false
|
|
7040
7534
|
};
|
|
@@ -7052,11 +7546,16 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7052
7546
|
if (toolCallId) toolOutcomeOrdinals.set(toolCallId, ordinal);
|
|
7053
7547
|
return ordinal;
|
|
7054
7548
|
} : void 0;
|
|
7055
|
-
const
|
|
7549
|
+
const compactionPlanState = new CodexCompactionPlanState();
|
|
7550
|
+
const dynamicToolParams = {
|
|
7056
7551
|
...runtimeParams,
|
|
7552
|
+
onAgentEvent: (event) => {
|
|
7553
|
+
compactionPlanState.record(event);
|
|
7554
|
+
return runtimeParams.onAgentEvent?.(event);
|
|
7555
|
+
},
|
|
7057
7556
|
...allocateCodexToolOutcomeOrdinal ? { allocateToolOutcomeOrdinal: allocateCodexToolOutcomeOrdinal } : {},
|
|
7058
7557
|
...onCodexToolOutcome ? { onToolOutcome: onCodexToolOutcome } : {}
|
|
7059
|
-
}
|
|
7558
|
+
};
|
|
7060
7559
|
const computerContextEpoch = { value: 0 };
|
|
7061
7560
|
const cronCreatorToolAllowlist = [];
|
|
7062
7561
|
const cronCreatorToolAllowlistCaptureRef = {};
|
|
@@ -7080,6 +7579,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7080
7579
|
let toolBridge;
|
|
7081
7580
|
let creatorAuthorityPromise;
|
|
7082
7581
|
let resolveCreatorAuthorityImpl;
|
|
7582
|
+
const runtimeYieldCompletionClaim = {};
|
|
7083
7583
|
const commonToolParams = {
|
|
7084
7584
|
params: dynamicToolParams,
|
|
7085
7585
|
resolvedWorkspace,
|
|
@@ -7087,6 +7587,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7087
7587
|
effectiveCwd,
|
|
7088
7588
|
sandboxSessionKey,
|
|
7089
7589
|
sandbox,
|
|
7590
|
+
sessionPermissionPolicy,
|
|
7090
7591
|
nativeToolSurfaceEnabled,
|
|
7091
7592
|
nativeProviderWebSearchSupport,
|
|
7092
7593
|
runAbortController,
|
|
@@ -7094,9 +7595,11 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7094
7595
|
pluginConfig,
|
|
7095
7596
|
profilerEnabled,
|
|
7096
7597
|
...params.cronCreatorAuthorityUnavailableReason === "queued-local-operator" && bundleMcpThreadConfig.staticServerNames.length > 0 ? { cronCreatorAuthorityUnavailableReason: "queued-local-operator-configured-mcp" } : {},
|
|
7097
|
-
onYieldDetected: () => {
|
|
7598
|
+
onYieldDetected: (acknowledgment) => {
|
|
7098
7599
|
toolState.yieldDetected = true;
|
|
7600
|
+
toolState.yieldAcknowledgment = acknowledgment;
|
|
7099
7601
|
},
|
|
7602
|
+
claimYieldCompletion: () => runtimeYieldCompletionClaim.current?.() ?? false,
|
|
7100
7603
|
onCodexAppServerEvent: (event) => {
|
|
7101
7604
|
emitCodexAppServerEvent(params, event);
|
|
7102
7605
|
},
|
|
@@ -7333,13 +7836,15 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7333
7836
|
cronCreatorToolAllowlistCaptureRef,
|
|
7334
7837
|
scheduledAppAuthoritySourceRef,
|
|
7335
7838
|
dynamicToolParams,
|
|
7839
|
+
compactionPlanState,
|
|
7336
7840
|
computerContextEpoch,
|
|
7337
7841
|
toolBridge,
|
|
7338
7842
|
toolState,
|
|
7339
7843
|
toolOutcomeOrdinals,
|
|
7340
7844
|
suppressedDynamicToolOutcomeOrdinals,
|
|
7341
7845
|
onCodexToolOutcome,
|
|
7342
|
-
allocateCodexToolOutcomeOrdinal
|
|
7846
|
+
allocateCodexToolOutcomeOrdinal,
|
|
7847
|
+
runtimeYieldCompletionClaim
|
|
7343
7848
|
};
|
|
7344
7849
|
} catch (error) {
|
|
7345
7850
|
await scopedMcpTools?.dispose();
|
|
@@ -7457,7 +7962,7 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
|
|
|
7457
7962
|
data: {
|
|
7458
7963
|
phase: "turn_starting",
|
|
7459
7964
|
threadId: resourceState.thread.threadId,
|
|
7460
|
-
model:
|
|
7965
|
+
model: params.modelId,
|
|
7461
7966
|
effort: turnStartParams.effort,
|
|
7462
7967
|
collaborationEffort: turnStartParams.collaborationMode?.settings.reasoning_effort,
|
|
7463
7968
|
serviceTier: turnStartParams.serviceTier
|
|
@@ -8179,11 +8684,14 @@ function createCodexAttemptTurnState(resources) {
|
|
|
8179
8684
|
//#endregion
|
|
8180
8685
|
//#region extensions/codex/src/app-server/run-attempt.ts
|
|
8181
8686
|
async function runCodexAppServerAttempt(params, options) {
|
|
8182
|
-
const
|
|
8687
|
+
const connection = await prepareCodexAttemptConnection({
|
|
8183
8688
|
params,
|
|
8184
8689
|
options
|
|
8185
|
-
})
|
|
8186
|
-
const
|
|
8690
|
+
});
|
|
8691
|
+
const runtime = await prepareCodexAttemptRuntime(connection);
|
|
8692
|
+
const attemptTools = await prepareCodexAttemptTools(runtime);
|
|
8693
|
+
const resources = prepareCodexAttemptResources(await prepareCodexAttemptPrompt(await prepareCodexAttemptContext(runtime, attemptTools)));
|
|
8694
|
+
attemptTools.runtimeYieldCompletionClaim.current = () => resources.state.nativeHookRelay?.hasClaimedDirectChild() ?? false;
|
|
8187
8695
|
await startCodexAttemptRuntime(resources);
|
|
8188
8696
|
const turnRuntime = createCodexAttemptTurnState(resources);
|
|
8189
8697
|
const lifecycle = createCodexAttemptLifecycleController(resources, turnRuntime);
|
|
@@ -8193,11 +8701,14 @@ async function runCodexAppServerAttempt(params, options) {
|
|
|
8193
8701
|
const turnStart = await startCodexAttemptTurn(resources, turnRuntime, notifications, turnRequest);
|
|
8194
8702
|
if ("result" in turnStart) return turnStart.result;
|
|
8195
8703
|
const activeTurn = await activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notifications, turnStart.turn);
|
|
8704
|
+
let finalizedResult;
|
|
8196
8705
|
try {
|
|
8197
|
-
|
|
8706
|
+
finalizedResult = await finalizeCodexAttempt(resources, turnRuntime, lifecycle, notifications, turnRequest, activeTurn);
|
|
8198
8707
|
} finally {
|
|
8199
8708
|
await cleanupCodexAttempt(resources, turnRuntime, lifecycle, turnRequest, activeTurn);
|
|
8200
8709
|
}
|
|
8710
|
+
if (resources.state.executionDisconnectError && !connection.terminalState.explicitCancellationObserved) throw resources.state.executionDisconnectError;
|
|
8711
|
+
return finalizedResult;
|
|
8201
8712
|
}
|
|
8202
8713
|
//#endregion
|
|
8203
8714
|
export { runCodexAppServerAttempt };
|