@openclaw/codex 2026.8.1-beta.3 → 2026.8.2
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 +5 -6
- package/dist/{attempt-client-cleanup-URjUlCHg.js → attempt-client-cleanup-CpVfwctT.js} +47 -5
- package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
- package/dist/{binding-connection-DAvZwp96.js → binding-connection-CF7BmrDk.js} +2 -2
- package/dist/{bounded-turn-4BjrZEwW.js → bounded-turn-DRC3hcjm.js} +16 -20
- package/dist/{capabilities-CH3K57v4.js → capabilities-D6m_TdVy.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-D0nZ3qtd.js → command-formatters--UToCokS.js} +4 -3
- package/dist/{command-handlers-DC86lgT4.js → command-handlers-CLFx2Ypa.js} +114 -79
- package/dist/{compact-COqgBRny.js → compact-5xqW1oCh.js} +13 -12
- package/dist/{config-CpNeo5AE.js → config-CcYL77O6.js} +350 -288
- package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
- package/dist/doctor-contract-api.js +121 -16
- package/dist/{dynamic-tools-fJZhl4CE.js → dynamic-tools-BmeXjwNZ.js} +243 -1002
- package/dist/{effective-mcp-catalog-4YKn51aG.js → effective-mcp-catalog-XXQKgK1U.js} +2 -2
- package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
- package/dist/{event-projector-usage-CLwNEJqW.js → event-projector-usage-B2r5vhWH.js} +9 -14
- package/dist/{harness-DoKQcF8n.js → harness-BgeB7LnD.js} +42 -52
- package/dist/harness.js +1 -1
- package/dist/index.js +308 -306
- package/dist/{isolated-completion-DPMtlH9r.js → isolated-completion-CxTus3vZ.js} +4 -4
- package/dist/launch-args-sXOAg0SX.js +84 -0
- package/dist/{managed-binary-By4FZC6i.js → managed-binary-ZkGodW19.js} +43 -7
- package/dist/media-understanding-provider.js +1 -1
- package/dist/model-catalog-DULBcniB.js +101 -0
- package/dist/{models-CZw1wClT.js → models-DaWfETQk.js} +27 -29
- package/dist/{native-subagent-monitor-GGq3RnOo.js → native-subagent-monitor-vXYUZH37.js} +226 -129
- package/dist/{node-exec-server.runtime-Bsu1LdFZ.js → node-exec-server.runtime-DirKVZ5h.js} +9 -6
- package/dist/{plugin-approval-roundtrip-C75Yiiwc.js → plugin-approval-roundtrip-CCWQGlAI.js} +2 -1
- package/dist/{plugin-marketplace-discovery-CSWDkMrP.js → plugin-marketplace-discovery-BXjIFEiw.js} +38 -46
- package/dist/{plugin-metadata-cache-BXH5NF-4.js → plugin-metadata-cache-DQQm4gWT.js} +163 -136
- package/dist/{protocol-validators-VAVyEnDp.js → protocol-validators-Bg5rpNxk.js} +148 -5
- package/dist/{rate-limits-BI1dMHDG.js → rate-limits-BqHEHXQJ.js} +3 -2
- package/dist/{sandbox-guard-C1qEeZ5C.js → request-BWxweEdK.js} +183 -2
- package/dist/{run-attempt-BV3HzuCf.js → run-attempt-BVLE4Gbi.js} +706 -517
- package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-D9pYp4zL.js} +3 -3
- package/dist/{session-binding-BTrLf9Qm.js → session-binding-D0zinCP1.js} +195 -122
- package/dist/{session-catalog-ezP_UcRM.js → session-catalog-eMhVm0Ql.js} +448 -313
- package/dist/session-catalog-home-id-Dt2GiG5o.js +112 -0
- package/dist/{session-cli-B1hKvfkI.js → session-cli-B2lyjJA0.js} +1 -1
- package/dist/session-history-C5J1AKzG.js +87 -0
- package/dist/session-permission-policy-ScnAyG90.js +160 -0
- package/dist/session-retirement-CtUtUTr9.js +90 -0
- package/dist/{session-upstream-marker-D_2npHlA.js → session-upstream-marker-gqrYIRHk.js} +2 -3
- package/dist/settled-turn-context-Bk3IUwod.js +290 -0
- package/dist/settled-turn-finalizer-BXLN9PfJ.js +104 -0
- package/dist/{shared-client-Dw-rzii0.js → shared-client-B1tT5U6r.js} +1738 -806
- package/dist/{side-question-DbXkJZzg.js → side-question-CZ-mCw-t.js} +76 -43
- package/dist/{thread-lifecycle-DKdrnTMX.js → thread-lifecycle-CGGKP720.js} +991 -455
- package/dist/{thread-ownership-i2NBwDUL.js → thread-ownership-RkaoZCmQ.js} +18 -8
- package/dist/{plugin-app-cache-key-DMNQ8Zi8.js → thread-resume-BFt1-ZDa.js} +55 -8
- package/dist/{transcript-mirror-BU0_LKAL.js → transcript-mirror-1ep4XjzF.js} +124 -18
- package/dist/transport-stdio-NT_Dpd9V.js +724 -0
- package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
- package/dist/{upstream-session-fork-BDVJCLAD.js → upstream-session-fork-Dc8BFExw.js} +76 -90
- package/dist/{usage-9dKJCgcy.js → usage-DUhd58gI.js} +3 -3
- package/dist/{web-search-provider.runtime-DCdx4DGu.js → web-search-provider.runtime-BEmlE7ov.js} +3 -3
- package/openclaw.plugin.json +19 -1
- package/package.json +8 -8
- package/dist/app-server-policy-bg5QPSVP.js +0 -25
- package/dist/command-rpc-xUIIonsO.js +0 -90
- package/dist/incognito-session-ET_ufDH-.js +0 -2
- package/dist/model-catalog-CmGoqVKB.js +0 -48
- package/dist/request-DSK0W6YI.js +0 -157
- package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
- package/dist/session-retirement-CE4iMiLh.js +0 -36
- package/dist/settled-turn-finalizer-Dx1onIqg.js +0 -328
- package/dist/thread-resume-CdJk2Ehf.js +0 -30
- package/dist/transport-stdio-DhoGy33Z.js +0 -99
|
@@ -1,42 +1,48 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { $ as
|
|
3
|
-
import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, i as createCodexSessionGenerationSupersededError, l as resolveCodexRunSessionBindingAuthority, u as scopeCodexRunBindingStore } from "./session-binding-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { l as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { a as buildCodexUserPromptMessage,
|
|
12
|
-
import { t as CODEX_CONTROL_METHODS } from "./capabilities-
|
|
13
|
-
import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-
|
|
14
|
-
import { r as formatCodexDisplayText } from "./command-formatters
|
|
15
|
-
import {
|
|
16
|
-
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-
|
|
17
|
-
import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-
|
|
1
|
+
import { C as isCodexRemoteExecPlacementSandbox, D as resolveOpenClawExecPolicyForCodexAppServer, E as resolveCodexPluginsPolicy, P as resolveCodexAppServerHomeDir, S as isCodexPairedNodeRemoteExecPlacementSandbox, T as readCodexPluginConfig, d as withMcpElicitationsApprovalPolicy, m as resolveCodexModelBackedReviewerPolicyContext, o as resolveCodexComputerUseConfig, p as canUseCodexModelBackedApprovalsReviewerForModel, r as resolveCodexAppServerHomeScope, u as shouldAutoApproveCodexAppServerApprovals, v as readCodexRequirementsToml, w as isCodexSandboxExecServerEnabled } from "./config-CcYL77O6.js";
|
|
2
|
+
import { $ as CodexAppServerRpcError, A as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS, B as resolveCodexTurnTerminalIdleTimeoutMs, Dt as readCodexRateLimitsRevision, Ft as resolveCodexAppServerFallbackApiKeyCacheKey, G as isCodexAppServerConnectionClosedError, H as getCodexAppServerClientInstanceId, Ht as isJsonObject, I as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, It as resolveCodexAppServerPreparedApiKeyCacheKey, J as isCodexAppServerOverloadError, K as isCodexAppServerIndeterminateRequestCancellationError, L as resolveCodexStartupTimeoutMs, Lt as resolveCodexAppServerPreparedAuthHandoff, M as TURN_FINALIZE_DRAIN_ABORT_GRACE_MS, Mt as resolveCodexAppServerAuthProfileId, N as TURN_TERMINAL_SETTLEMENT_IDLE_TIMEOUT_MS, Nt as resolveCodexAppServerAuthProfileIdForAgent, Ot as readRecentCodexRateLimits, P as isCodexAppServerStartupError, Q as resolveCodexAppServerClientInstanceId, R as resolveCodexTurnAssistantCompletionIdleTimeoutMs, Tt as withAbortableTimeout, U as isCodexAppServerApprovalRequest, V as withCodexStartupTimeout, Vt as flattenCodexDynamicToolFunctions, W as isCodexAppServerBrokenPipeError, X as isCodexAppServerRequestTimeoutError, _t as ensureCodexAppServerClientRuntime, a as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, at as resolveDynamicToolCallTimeoutMs, c as getLeasedSharedCodexAppServerClient, ct as shouldReleaseTurnAfterTerminalDynamicTool, dt as resolveCodexToolAbortTerminalReason, et as createCodexElicitationResponse, f as readCodexAppServerClientDesktopGenerationFingerprint, h as releaseLeasedSharedCodexAppServerClient, i as clearSharedCodexAppServerClientIfCurrent, it as isMatchingDynamicToolTerminalDiagnostic, j as CodexAppServerStartupError, jt as resolveCodexAppServerAuthAccountCacheKey, kt as rememberCodexRateLimitsRead, l as getSharedCodexAppServerClient, lt as toCodexDynamicToolProgressResponse, nt as hasPendingDynamicToolTerminalDiagnostic, ot as resolveTerminalDynamicToolBatchAction, q as isCodexAppServerIndeterminateTransportError, rt as isDynamicToolTerminalDiagnosticEvent, s as createIsolatedCodexAppServerClient, st as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, tt as handleDynamicToolCallWithTimeout, u as isCodexAppServerStartSelectionChangedError, ut as toCodexDynamicToolProtocolResponse, v as retainSharedCodexAppServerClientIfCurrent, xt as protectCodexAppServerLiveThread, y as retireSharedCodexAppServerClientIfCurrent, z as resolveCodexTurnCompletionIdleTimeoutMs } from "./shared-client-B1tT5U6r.js";
|
|
3
|
+
import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, i as createCodexSessionGenerationSupersededError, l as resolveCodexRunSessionBindingAuthority, u as scopeCodexRunBindingStore } from "./session-binding-D0zinCP1.js";
|
|
4
|
+
import { c as assertCodexTurnStartResponse, d as readCodexTurn, f as readCodexTurnCompletedNotification, l as readCodexDynamicToolCallParams } from "./protocol-validators-Bg5rpNxk.js";
|
|
5
|
+
import { B as readNonNegativeInteger, D as itemStatus, E as itemName, H as splitPlanText, I as readItem, L as readItemString, M as extractRawAssistantText, P as readCodexErrorNotificationMessage, V as readNullableString, _ as readCodexNotificationThreadId, a as closeCodexStartupClientBestEffort, d as terminateCodexBackgroundTerminals, f as unsubscribeCodexThreadBestEffort, g as isCodexNotificationForTurn, h as CodexProjectionDiagnostics, j as shouldSynthesizeToolProgressForItem, k as shouldClearTerminalPresentationForNativeItem, l as retireCodexAppServerClientAfterTimedOutTurn, m as getCodexAppServerTurnRouter, o as interruptCodexTurnAndWaitBestEffort, p as CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS, r as CodexAppServerUnsafeSubscriptionError, t as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS, u as retireUnsafeCodexTurnClientBestEffort } from "./attempt-client-cleanup-CpVfwctT.js";
|
|
6
|
+
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-B2r5vhWH.js";
|
|
7
|
+
import { i as buildCodexPluginAppCacheKey, r as buildCodexAppServerRuntimeFingerprint, s as defaultCodexAppInventoryCache } from "./thread-resume-BFt1-ZDa.js";
|
|
8
|
+
import { $ as resolveCodexContinuityProjectionMaxChars, B as isMessageOnlyCodexSourceReply, D as resolveCodexAppServerThreadModelSelection, F as codexDynamicToolsFingerprint, G as buildContextEngineBinding, I as codexLegacyDynamicToolsFingerprint, J as fitCodexProjectedContextForTurnStart, K as isContextEngineBindingCompatible, L as filterCodexDynamicTools, P as areCodexDynamicToolFingerprintsCompatible, Q as resolveCodexContextEngineProjectionReserveTokens, S as buildDeveloperInstructions, V as isSystemAgentOnlyCodexDynamicToolAllowlist, W as resolveCodexDynamicToolsLoadingForRuntime, X as projectContextEngineAssemblyForCodex, Y as neutralizeCodexExplicitMentionSigils, Z as resolveCodexContextEngineProjectionMaxChars, a as isCodexAppServerProfilerEnabled, at as buildPluginAppPolicyContext, c as buildCodexNativeHookRelayConfig, d as emitCodexNativePreToolUseFailureDiagnostic, et as buildCodexPluginAppsConfigPatchFromPolicyContext, f as resolveCodexNativeHookRelayEvents, i as startOrResumeThread, l as buildCodexNativeHookRelayDisabledConfig, m as scheduleCodexNativeHookRelayUnregister, n as buildTurnStartParams, nt as buildCodexPluginThreadConfigInputFingerprint, ot as mergeCodexThreadConfigs, p as resolveCodexNativeHookRelayTtlMs, pt as resolveRecoverableCodexPluginConfigKeys, q as buildCodexContinuityCalibration, r as buildCodexUserInput, rt as buildCodexPluginThreadConfigTimeoutFallback, s as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, st as shouldBuildCodexPluginThreadConfig, t as buildTurnCollaborationMode, tt as buildCodexPluginThreadConfig, u as createCodexNativeHookRelay, x as resolveCodexWebSearchPlan } from "./thread-lifecycle-CGGKP720.js";
|
|
9
|
+
import { l as isIncognitoSessionKey, r as retainCodexAppServerBindingSubscription } from "./thread-ownership-RkaoZCmQ.js";
|
|
10
|
+
import { r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-LphB8slG.js";
|
|
11
|
+
import { a as buildCodexUserPromptMessage, i as mirrorPromptAtTurnStartBestEffort, l as hasCodexMirrorOrigin, n as createCodexAppServerUserMessagePersistenceNotifier, o as promptSnapshot, s as applyCodexTranscriptTaint, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-1ep4XjzF.js";
|
|
12
|
+
import { t as CODEX_CONTROL_METHODS } from "./capabilities-D6m_TdVy.js";
|
|
13
|
+
import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-BqHEHXQJ.js";
|
|
14
|
+
import { r as formatCodexDisplayText } from "./command-formatters--UToCokS.js";
|
|
15
|
+
import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, r as resolveCodexEffectiveSessionPermissionPolicy } from "./session-permission-policy-ScnAyG90.js";
|
|
16
|
+
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-CF7BmrDk.js";
|
|
17
|
+
import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-Ds_QVm-X.js";
|
|
18
18
|
import { t as persistCodexContextCompactionActivity } from "./context-compaction-activity-BOeJf7yo.js";
|
|
19
|
-
import { n as
|
|
20
|
-
import { a as CodexToolProgressProjection, c as isCodexCommandBearingToolCall, d as sanitizeCodexToolResponse, i as
|
|
21
|
-
import {
|
|
22
|
-
import { a as
|
|
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 CodexToolProgressProjection, c as isCodexCommandBearingToolCall, d as sanitizeCodexToolResponse, i as CodexToolTranscriptProjection, l as resolveCodexToolProgressDetailMode, n as CodexEventProjection, o as shouldEmitTranscriptToolProgress, r as emitCodexAgentEvent, s as inferCodexDynamicToolMeta, t as codexNativeSubagentMonitorRuntime, u as sanitizeCodexToolArguments } from "./native-subagent-monitor-vXYUZH37.js";
|
|
21
|
+
import { n as readCodexMirroredSessionHistoryMessages } from "./session-history-C5J1AKzG.js";
|
|
22
|
+
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-BmeXjwNZ.js";
|
|
23
|
+
import { n as captureCodexSettledTurnFinalizationContext } from "./settled-turn-context-Bk3IUwod.js";
|
|
24
|
+
import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-DQQm4gWT.js";
|
|
23
25
|
import { asBoolean, asFiniteNumber, asOptionalRecord, hasNonEmptyString, normalizeOptionalString, readNonBlankString, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
24
26
|
import fs from "node:fs/promises";
|
|
25
27
|
import path from "node:path";
|
|
26
28
|
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
27
29
|
import { asDateTimestampMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
28
|
-
import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, agentHarnessAttemptTerminal, agentHarnessStructuredInput, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine, buildBootstrapContextForFiles, buildHarnessContextEngineRuntimeContext, buildWatchedSessionsHarnessContext, callGatewayTool, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, formatErrorMessage, formatFastModeAutoProgressText, getAgentHarnessHookRunner, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, prepareHarnessNativeMcpAppPreview, projectAgentHarnessTranscriptMessageForDisplay, resolveAgentDir, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveBootstrapFilesForRun, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext,
|
|
30
|
+
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, detectAndLoadAgentHarnessPromptImages, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, formatErrorMessage, formatFastModeAutoProgressText, getAgentHarnessHookRunner, hasBeforeToolCallPolicy, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, prepareHarnessNativeMcpAppPreview, projectAgentHarnessTranscriptMessageForDisplay, resolveAgentDir, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveAttemptFsWorkspaceOnly, resolveBootstrapFilesForRun, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveUserPath, runAgentCleanupStep, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
29
31
|
import crypto, { createHash } from "node:crypto";
|
|
30
|
-
import { hostname } from "node:os";
|
|
31
32
|
import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
33
|
+
import { resolveAgentConfig as resolveAgentConfig$1, resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
32
34
|
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
33
35
|
import { parseSqliteSessionFileMarker } from "openclaw/plugin-sdk/session-store-runtime";
|
|
36
|
+
import { addAbortListener } from "node:events";
|
|
34
37
|
import { truncateUtf16Safe, truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
35
|
-
import { isPathInside, isPathStrictlyInside, root } from "openclaw/plugin-sdk/file-access-runtime";
|
|
36
|
-
import { captureFinalCodexCronCreatorToolAllowlist, materializeStaticMcpToolsForScheduledHarnessRun, resolveCodexMcpToolOverridesForAgent } from "openclaw/plugin-sdk/codex-mcp-projection";
|
|
37
38
|
import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
39
|
+
import { isPathStrictlyInside, root } from "openclaw/plugin-sdk/file-access-runtime";
|
|
40
|
+
import { captureFinalCodexCronCreatorToolAllowlist, materializeStaticMcpToolsForScheduledHarnessRun, resolveCodexMcpToolOverridesForAgent, resolveCodexTtsProvenanceTransfer } from "openclaw/plugin-sdk/codex-mcp-projection";
|
|
41
|
+
import { hasPromptImageInput } from "openclaw/plugin-sdk/session-transcript-runtime";
|
|
38
42
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
43
|
+
import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
39
44
|
import { prepareMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
|
|
45
|
+
import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-local-roots";
|
|
40
46
|
import { isSilentReplyPayloadText } from "openclaw/plugin-sdk/reply-chunking";
|
|
41
47
|
import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
|
|
42
48
|
import { resolveGeneratedMediaMaxBytes } from "openclaw/plugin-sdk/media-generation-runtime";
|
|
@@ -68,6 +74,12 @@ function createCodexSteeringQueue(params) {
|
|
|
68
74
|
let sendChain = Promise.resolve();
|
|
69
75
|
let sealedError;
|
|
70
76
|
let closedError;
|
|
77
|
+
const assertActive = () => {
|
|
78
|
+
const unavailableError = closedError ?? sealedError;
|
|
79
|
+
if (unavailableError) throw unavailableError;
|
|
80
|
+
params.signal.throwIfAborted();
|
|
81
|
+
params.assertActive();
|
|
82
|
+
};
|
|
71
83
|
const clearBatchTimer = () => {
|
|
72
84
|
if (batchTimer) {
|
|
73
85
|
clearTimeout(batchTimer);
|
|
@@ -120,19 +132,20 @@ function createCodexSteeringQueue(params) {
|
|
|
120
132
|
const sendBatch = async (items) => {
|
|
121
133
|
const liveItems = items.filter((item) => !item.settled);
|
|
122
134
|
if (liveItems.length === 0) return;
|
|
123
|
-
|
|
124
|
-
if (unavailableError) {
|
|
125
|
-
for (const item of liveItems) rejectItem(item, unavailableError);
|
|
126
|
-
throw unavailableError;
|
|
127
|
-
}
|
|
128
|
-
const clientUserMessageId = `openclaw:${params.turnId}:steer:${++batchSequence}`;
|
|
129
|
-
const batch = { items: liveItems };
|
|
130
|
-
dispatchedBatches.set(clientUserMessageId, batch);
|
|
135
|
+
let clientUserMessageId;
|
|
131
136
|
try {
|
|
137
|
+
assertActive();
|
|
138
|
+
const input = [];
|
|
139
|
+
for (const item of liveItems) {
|
|
140
|
+
input.push(...await params.prepareMessage(item.text, item));
|
|
141
|
+
assertActive();
|
|
142
|
+
}
|
|
143
|
+
clientUserMessageId = `openclaw:${params.turnId}:steer:${++batchSequence}`;
|
|
144
|
+
dispatchedBatches.set(clientUserMessageId, { items: liveItems });
|
|
132
145
|
await params.client.request("turn/steer", {
|
|
133
146
|
threadId: params.threadId,
|
|
134
147
|
expectedTurnId: params.turnId,
|
|
135
|
-
input
|
|
148
|
+
input,
|
|
136
149
|
clientUserMessageId
|
|
137
150
|
}, {
|
|
138
151
|
timeoutMs: params.requestTimeoutMs,
|
|
@@ -140,8 +153,8 @@ function createCodexSteeringQueue(params) {
|
|
|
140
153
|
});
|
|
141
154
|
for (const item of liveItems) reportItemAcceptance(item, true);
|
|
142
155
|
} catch (error) {
|
|
143
|
-
dispatchedBatches.delete(clientUserMessageId);
|
|
144
|
-
const acceptedUnconfirmed = isCodexAppServerIndeterminateRequestCancellationError(error) || isCodexAppServerIndeterminateTransportError(error);
|
|
156
|
+
if (clientUserMessageId) dispatchedBatches.delete(clientUserMessageId);
|
|
157
|
+
const acceptedUnconfirmed = clientUserMessageId !== void 0 && (isCodexAppServerIndeterminateRequestCancellationError(error) || isCodexAppServerIndeterminateTransportError(error));
|
|
145
158
|
for (const item of liveItems) {
|
|
146
159
|
if (acceptedUnconfirmed) reportItemAcceptance(item, true);
|
|
147
160
|
rejectItem(item, error);
|
|
@@ -175,15 +188,12 @@ function createCodexSteeringQueue(params) {
|
|
|
175
188
|
rejectDelivery = reject;
|
|
176
189
|
});
|
|
177
190
|
const item = {
|
|
191
|
+
...options,
|
|
178
192
|
acceptance: "open",
|
|
179
193
|
text,
|
|
180
|
-
images: options?.images,
|
|
181
|
-
isInboundUserMessage: options?.isInboundUserMessage,
|
|
182
|
-
onQueueAccepted: options?.onQueueAccepted,
|
|
183
194
|
resolve: resolveDelivery,
|
|
184
195
|
reject: rejectDelivery,
|
|
185
|
-
settled: false
|
|
186
|
-
userTurnTranscriptRecorder: options?.userTurnTranscriptRecorder
|
|
196
|
+
settled: false
|
|
187
197
|
};
|
|
188
198
|
pendingMessages.add(item);
|
|
189
199
|
return {
|
|
@@ -195,10 +205,11 @@ function createCodexSteeringQueue(params) {
|
|
|
195
205
|
if (params.signal.aborted) abortQueue();
|
|
196
206
|
return {
|
|
197
207
|
async queue(text, options) {
|
|
198
|
-
|
|
199
|
-
|
|
208
|
+
try {
|
|
209
|
+
assertActive();
|
|
210
|
+
} catch (error) {
|
|
200
211
|
options?.onQueueAccepted?.(false);
|
|
201
|
-
throw
|
|
212
|
+
throw error;
|
|
202
213
|
}
|
|
203
214
|
const { item, delivery } = createPendingMessage(text, options);
|
|
204
215
|
batchedMessages.push(item);
|
|
@@ -242,15 +253,17 @@ function normalizeCodexSteerDebounceMs(value) {
|
|
|
242
253
|
//#endregion
|
|
243
254
|
//#region extensions/codex/src/app-server/event-projector-assistant.ts
|
|
244
255
|
var CodexAssistantProjection = class {
|
|
245
|
-
constructor(params, emitAgentEvent, matchesToolProgressEcho, nextTranscriptTimestamp) {
|
|
256
|
+
constructor(params, emitAgentEvent, matchesToolProgressEcho, nextTranscriptTimestamp, checkpointCommentary) {
|
|
246
257
|
this.params = params;
|
|
247
258
|
this.emitAgentEvent = emitAgentEvent;
|
|
248
259
|
this.matchesToolProgressEcho = matchesToolProgressEcho;
|
|
249
260
|
this.nextTranscriptTimestamp = nextTranscriptTimestamp;
|
|
261
|
+
this.checkpointCommentary = checkpointCommentary;
|
|
250
262
|
this.assistantTextByItem = /* @__PURE__ */ new Map();
|
|
251
263
|
this.assistantItemOrder = [];
|
|
252
264
|
this.assistantTimestampByItem = /* @__PURE__ */ new Map();
|
|
253
265
|
this.assistantPhaseByItem = /* @__PURE__ */ new Map();
|
|
266
|
+
this.assistantDeliveryByItem = /* @__PURE__ */ new Map();
|
|
254
267
|
this.latestTerminalAssistantCandidateSuperseded = false;
|
|
255
268
|
this.latestTerminalAssistantCandidateCanReleaseAfterToolHandoff = false;
|
|
256
269
|
this.terminalAssistantCandidateEarlierActiveItemIds = /* @__PURE__ */ new Set();
|
|
@@ -261,7 +274,9 @@ var CodexAssistantProjection = class {
|
|
|
261
274
|
this.assistantStarted = false;
|
|
262
275
|
this.streamedPartialAssistantItemReplaceable = false;
|
|
263
276
|
this.persistableAssistantBarrier = 0;
|
|
277
|
+
this.persistedAssistantBoundary = false;
|
|
264
278
|
this.persistableAssistantBarrierItemIds = /* @__PURE__ */ new Set();
|
|
279
|
+
this.completedAssistantItemIds = /* @__PURE__ */ new Set();
|
|
265
280
|
}
|
|
266
281
|
hasCompletedTerminalAssistantText(completedItemIds) {
|
|
267
282
|
const latestCompletedItemId = this.latestCompletedTerminalAssistantItemId;
|
|
@@ -293,7 +308,8 @@ var CodexAssistantProjection = class {
|
|
|
293
308
|
if (!delta) return;
|
|
294
309
|
if (itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
295
310
|
const isCommentary = this.isCommentaryAssistantItem(itemId);
|
|
296
|
-
|
|
311
|
+
const isAsync = this.isAsyncAssistantItem(itemId);
|
|
312
|
+
if (!isCommentary && !isAsync && itemId !== this.latestTerminalAssistantCandidateItemId) this.markTerminalAssistantCandidateSupersededBy();
|
|
297
313
|
if (!this.assistantStarted) {
|
|
298
314
|
this.assistantStarted = true;
|
|
299
315
|
await this.params.onAssistantMessageStart?.();
|
|
@@ -301,6 +317,7 @@ var CodexAssistantProjection = class {
|
|
|
301
317
|
this.rememberAssistantItem(itemId);
|
|
302
318
|
const text = `${this.assistantTextByItem.get(itemId) ?? ""}${delta}`;
|
|
303
319
|
this.assistantTextByItem.set(itemId, text);
|
|
320
|
+
if (isAsync) return;
|
|
304
321
|
if (isCommentary) {
|
|
305
322
|
this.emitCommentaryProgress({
|
|
306
323
|
itemId,
|
|
@@ -332,24 +349,25 @@ var CodexAssistantProjection = class {
|
|
|
332
349
|
}
|
|
333
350
|
recordItemStarted(item, itemId) {
|
|
334
351
|
this.noteNativeWorkBarrier(item);
|
|
335
|
-
if (item?.type === "agentMessage" && itemId && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
336
352
|
this.rememberAssistantPhase(item);
|
|
353
|
+
if (item?.type === "agentMessage" && itemId && !this.isNonTerminalAssistantItem(itemId) && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
337
354
|
if (item?.type === "agentMessage" && itemId) this.rememberAssistantItem(itemId);
|
|
338
|
-
if (itemId && itemId !== this.latestTerminalAssistantCandidateItemId) {
|
|
355
|
+
if (itemId && !this.isNonTerminalAssistantItem(itemId) && itemId !== this.latestTerminalAssistantCandidateItemId) {
|
|
339
356
|
this.markTerminalAssistantCandidateSupersededBy(itemId, { preserveEarlierActiveItem: true });
|
|
340
357
|
if (this.latestTerminalAssistantCandidateSuperseded) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
341
358
|
}
|
|
342
359
|
}
|
|
343
360
|
recordItemCompleted(item, itemId, activeItemIds) {
|
|
361
|
+
if (itemId && item?.type === "agentMessage") this.completedAssistantItemIds.add(itemId);
|
|
344
362
|
this.noteNativeWorkBarrier(item);
|
|
345
|
-
if (item?.type === "agentMessage" && itemId && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
346
|
-
if (itemId) this.latestCompletedItemId = itemId;
|
|
347
363
|
this.rememberAssistantPhase(item);
|
|
348
|
-
if (item?.type === "agentMessage" && !this.
|
|
364
|
+
if (item?.type === "agentMessage" && itemId && !this.isNonTerminalAssistantItem(itemId) && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
365
|
+
if (itemId && !this.isNonTerminalAssistantItem(itemId)) this.latestCompletedItemId = itemId;
|
|
366
|
+
if (item?.type === "agentMessage" && !this.isNonTerminalAssistantItem(item.id)) {
|
|
349
367
|
this.latestCompletedTerminalAssistantItemId = item.id;
|
|
350
368
|
this.markLatestTerminalAssistantCandidate(item.id, activeItemIds);
|
|
351
369
|
this.pendingRawTerminalAssistantEchoItemId = item.id;
|
|
352
|
-
} else if (itemId) {
|
|
370
|
+
} else if (itemId && !this.isNonTerminalAssistantItem(itemId)) {
|
|
353
371
|
this.markTerminalAssistantCandidateSupersededBy(itemId, { preserveEarlierActiveItem: true });
|
|
354
372
|
if (this.latestTerminalAssistantCandidateSuperseded) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
355
373
|
}
|
|
@@ -362,14 +380,17 @@ var CodexAssistantProjection = class {
|
|
|
362
380
|
text: item.text
|
|
363
381
|
});
|
|
364
382
|
this.pendingRawCommentaryEchoes += 1;
|
|
365
|
-
} else if (item.text && this.isFinalAnswerAssistantItem(item.id)) this.emitAnswerCandidate(item.id, "candidate");
|
|
383
|
+
} else if (item.text && !this.isAsyncAssistantItem(item.id) && this.isFinalAnswerAssistantItem(item.id)) this.emitAnswerCandidate(item.id, "candidate");
|
|
384
|
+
return this.createAsyncDelivery(item.id);
|
|
366
385
|
}
|
|
367
386
|
}
|
|
368
387
|
recordSnapshotItem(item) {
|
|
388
|
+
if (item.type === "agentMessage") this.completedAssistantItemIds.add(item.id);
|
|
369
389
|
this.rememberAssistantPhase(item);
|
|
370
390
|
if (item.type === "agentMessage" && typeof item.text === "string") {
|
|
371
391
|
this.rememberAssistantItem(item.id);
|
|
372
392
|
this.assistantTextByItem.set(item.id, item.text);
|
|
393
|
+
return this.createAsyncDelivery(item.id);
|
|
373
394
|
}
|
|
374
395
|
}
|
|
375
396
|
handleRawResponseItemCompleted(item, activeItemIds) {
|
|
@@ -403,6 +424,7 @@ var CodexAssistantProjection = class {
|
|
|
403
424
|
const isIdlessTerminalAssistantAfterCompletedWork = candidateWasSupersededBeforeRaw && rawItemId === void 0 && pendingTerminalAssistantEchoItemId === void 0 && activeItemIds.size === 0;
|
|
404
425
|
if (text && phase !== "commentary" && candidateWasSupersededBeforeRaw && itemId !== this.streamedPartialAssistantItemId && !isIdlessTerminalAssistantAfterCompletedWork) return;
|
|
405
426
|
if (phase) this.assistantPhaseByItem.set(itemId, phase);
|
|
427
|
+
this.completedAssistantItemIds.add(itemId);
|
|
406
428
|
this.rememberAssistantItem(itemId);
|
|
407
429
|
this.assistantTextByItem.set(itemId, text);
|
|
408
430
|
if (!text) return;
|
|
@@ -418,6 +440,7 @@ var CodexAssistantProjection = class {
|
|
|
418
440
|
const audibleAfterHandoff = afterHandoff.filter((text) => !isSilentReplyPayloadText(text));
|
|
419
441
|
if (audibleAfterHandoff.length > 0) return audibleAfterHandoff;
|
|
420
442
|
if (afterHandoff.length > 0) return afterHandoff.slice(-1);
|
|
443
|
+
if (this.persistedAssistantBoundary) return [];
|
|
421
444
|
const recoveredAudible = this.collectPersistableAssistantTexts(0).filter((text) => !isSilentReplyPayloadText(text));
|
|
422
445
|
if (recoveredAudible.length > 0) return recoveredAudible.slice(-1);
|
|
423
446
|
const recovered = this.resolveFinalAssistantTextItem()?.text;
|
|
@@ -425,16 +448,52 @@ var CodexAssistantProjection = class {
|
|
|
425
448
|
}
|
|
426
449
|
collectCommentaryMessages() {
|
|
427
450
|
return this.assistantItemOrder.flatMap((itemId) => {
|
|
428
|
-
|
|
451
|
+
const message = this.readCommentaryMessage(itemId);
|
|
452
|
+
return message ? [{
|
|
453
|
+
itemId,
|
|
454
|
+
message
|
|
455
|
+
}] : [];
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
readCommentaryMessage(itemId) {
|
|
459
|
+
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
460
|
+
const timestamp = this.assistantTimestampByItem.get(itemId);
|
|
461
|
+
return this.isCommentaryAssistantItem(itemId) && text && timestamp !== void 0 ? createAssistantCommentaryMessage(this.params, text, itemId, timestamp) : void 0;
|
|
462
|
+
}
|
|
463
|
+
collectAsyncMessages() {
|
|
464
|
+
return this.assistantItemOrder.flatMap((itemId) => {
|
|
465
|
+
if (!this.isAsyncAssistantItem(itemId)) return [];
|
|
429
466
|
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
430
467
|
const timestamp = this.assistantTimestampByItem.get(itemId);
|
|
431
468
|
if (!text || timestamp === void 0) return [];
|
|
432
469
|
return [{
|
|
433
470
|
itemId,
|
|
434
|
-
message:
|
|
471
|
+
message: createAssistantAsyncMessage(this.params, text, itemId, timestamp)
|
|
435
472
|
}];
|
|
436
473
|
});
|
|
437
474
|
}
|
|
475
|
+
collectCompletedAssistantMessages(completedItemIds, options) {
|
|
476
|
+
return this.assistantItemOrder.flatMap((itemId) => {
|
|
477
|
+
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
478
|
+
if (!completedItemIds.has(itemId) || this.isNonTerminalAssistantItem(itemId) || !text || isSilentReplyPayloadText(text) || this.isToolProgressEchoText(itemId, text)) return [];
|
|
479
|
+
const message = this.createAssistantMessage(text, options);
|
|
480
|
+
const timestamp = this.assistantTimestampByItem.get(itemId) ?? message.timestamp;
|
|
481
|
+
return [{
|
|
482
|
+
itemId,
|
|
483
|
+
message: {
|
|
484
|
+
...message,
|
|
485
|
+
timestamp
|
|
486
|
+
}
|
|
487
|
+
}];
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
markAssistantBoundaryPersisted(itemId) {
|
|
491
|
+
const index = this.assistantItemOrder.indexOf(itemId);
|
|
492
|
+
if (index >= 0) {
|
|
493
|
+
this.persistableAssistantBarrier = Math.max(this.persistableAssistantBarrier, index + 1);
|
|
494
|
+
this.persistedAssistantBoundary = true;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
438
497
|
finalizeAnswerCandidate(turn) {
|
|
439
498
|
if (turn.status !== "completed") {
|
|
440
499
|
this.supersedeVisibleAnswerCandidate();
|
|
@@ -444,7 +503,7 @@ var CodexAssistantProjection = class {
|
|
|
444
503
|
const authoritativeIndex = turnItems.findLastIndex((item) => {
|
|
445
504
|
if (item.type !== "agentMessage" || typeof item.text !== "string" || item.text.trim().length === 0) return false;
|
|
446
505
|
const phase = readItemString(item, "phase");
|
|
447
|
-
return phase === "final_answer" || phase === void 0;
|
|
506
|
+
return readItemString(item, "delivery") !== "async" && (phase === "final_answer" || phase === void 0);
|
|
448
507
|
});
|
|
449
508
|
const authoritative = authoritativeIndex >= 0 ? turnItems[authoritativeIndex] : void 0;
|
|
450
509
|
if (turnItems.slice(authoritativeIndex + 1).some(shouldClearTerminalPresentationForNativeItem) || authoritative?.id === this.latestTerminalAssistantCandidateItemId && this.latestTerminalAssistantCandidateSuperseded) {
|
|
@@ -462,7 +521,7 @@ var CodexAssistantProjection = class {
|
|
|
462
521
|
hasAssistantItemTextForSynthesis() {
|
|
463
522
|
for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
|
|
464
523
|
const itemId = this.assistantItemOrder[i];
|
|
465
|
-
if (!itemId || this.
|
|
524
|
+
if (!itemId || this.isNonTerminalAssistantItem(itemId)) continue;
|
|
466
525
|
const text = this.assistantTextByItem.get(itemId);
|
|
467
526
|
if (text && text.length > 0) return true;
|
|
468
527
|
}
|
|
@@ -471,7 +530,7 @@ var CodexAssistantProjection = class {
|
|
|
471
530
|
createCurrentAttemptAssistantMessage(options) {
|
|
472
531
|
for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
|
|
473
532
|
const itemId = this.assistantItemOrder[i];
|
|
474
|
-
if (!itemId || this.
|
|
533
|
+
if (!itemId || this.isNonTerminalAssistantItem(itemId) || !this.assistantTextByItem.has(itemId)) continue;
|
|
475
534
|
const text = this.assistantTextByItem.get(itemId) ?? "";
|
|
476
535
|
const normalizedText = text.trim();
|
|
477
536
|
if (normalizedText && this.isToolProgressEchoText(itemId, normalizedText)) continue;
|
|
@@ -492,10 +551,18 @@ var CodexAssistantProjection = class {
|
|
|
492
551
|
if (item?.type !== "agentMessage") return;
|
|
493
552
|
const phase = readItemString(item, "phase");
|
|
494
553
|
if (phase) this.assistantPhaseByItem.set(item.id, phase);
|
|
554
|
+
const delivery = readItemString(item, "delivery");
|
|
555
|
+
if (delivery) this.assistantDeliveryByItem.set(item.id, delivery);
|
|
495
556
|
}
|
|
496
557
|
isCommentaryAssistantItem(itemId) {
|
|
497
558
|
return this.assistantPhaseByItem.get(itemId) === "commentary";
|
|
498
559
|
}
|
|
560
|
+
isAsyncAssistantItem(itemId) {
|
|
561
|
+
return this.assistantDeliveryByItem.get(itemId) === "async";
|
|
562
|
+
}
|
|
563
|
+
isNonTerminalAssistantItem(itemId) {
|
|
564
|
+
return this.isCommentaryAssistantItem(itemId) || this.isAsyncAssistantItem(itemId);
|
|
565
|
+
}
|
|
499
566
|
isFinalAnswerAssistantItem(itemId) {
|
|
500
567
|
return this.assistantPhaseByItem.get(itemId) === "final_answer";
|
|
501
568
|
}
|
|
@@ -503,7 +570,7 @@ var CodexAssistantProjection = class {
|
|
|
503
570
|
return this.assistantPhaseByItem.get(itemId) === "final_answer";
|
|
504
571
|
}
|
|
505
572
|
emitCommentaryProgress(params) {
|
|
506
|
-
const progressText = params.text.
|
|
573
|
+
const progressText = params.text.trim();
|
|
507
574
|
if (!progressText || this.lastCommentaryProgressTextByItem.get(params.itemId) === progressText) return;
|
|
508
575
|
this.lastCommentaryProgressTextByItem.set(params.itemId, progressText);
|
|
509
576
|
this.emitAgentEvent({
|
|
@@ -570,7 +637,7 @@ var CodexAssistantProjection = class {
|
|
|
570
637
|
const itemId = this.assistantItemOrder[i];
|
|
571
638
|
if (!itemId) continue;
|
|
572
639
|
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
573
|
-
if (this.
|
|
640
|
+
if (this.isNonTerminalAssistantItem(itemId)) continue;
|
|
574
641
|
if (text && !this.isToolProgressEchoText(itemId, text)) return {
|
|
575
642
|
itemId,
|
|
576
643
|
text
|
|
@@ -582,7 +649,7 @@ var CodexAssistantProjection = class {
|
|
|
582
649
|
let replaceable = false;
|
|
583
650
|
for (let index = minIndex; index < this.assistantItemOrder.length; index += 1) {
|
|
584
651
|
const itemId = this.assistantItemOrder[index];
|
|
585
|
-
if (!itemId || this.
|
|
652
|
+
if (!itemId || this.isNonTerminalAssistantItem(itemId)) continue;
|
|
586
653
|
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
587
654
|
if (!text || this.isToolProgressEchoText(itemId, text)) continue;
|
|
588
655
|
if (isSilentReplyPayloadText(text)) {
|
|
@@ -606,9 +673,26 @@ var CodexAssistantProjection = class {
|
|
|
606
673
|
this.persistableAssistantBarrier = this.assistantItemOrder.length;
|
|
607
674
|
}
|
|
608
675
|
rememberAssistantItem(itemId) {
|
|
609
|
-
if (!itemId
|
|
610
|
-
this.
|
|
611
|
-
|
|
676
|
+
if (!itemId) return;
|
|
677
|
+
if (!this.assistantTimestampByItem.has(itemId)) {
|
|
678
|
+
this.assistantItemOrder.push(itemId);
|
|
679
|
+
this.assistantTimestampByItem.set(itemId, this.nextTranscriptTimestamp());
|
|
680
|
+
}
|
|
681
|
+
if (this.isCommentaryAssistantItem(itemId)) this.checkpointCommentary?.(itemId, {
|
|
682
|
+
read: () => this.readCommentaryMessage(itemId),
|
|
683
|
+
ready: () => this.completedAssistantItemIds.has(itemId)
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
createAsyncDelivery(itemId) {
|
|
687
|
+
if (!this.isAsyncAssistantItem(itemId)) return;
|
|
688
|
+
const text = this.assistantTextByItem.get(itemId);
|
|
689
|
+
const timestamp = this.assistantTimestampByItem.get(itemId);
|
|
690
|
+
if (!text?.trim() || timestamp === void 0) return;
|
|
691
|
+
return {
|
|
692
|
+
itemId,
|
|
693
|
+
message: createAssistantAsyncMessage(this.params, text, itemId, timestamp),
|
|
694
|
+
text
|
|
695
|
+
};
|
|
612
696
|
}
|
|
613
697
|
isToolProgressEchoText(itemId, text) {
|
|
614
698
|
return this.rawPromotedAssistantItemIds.has(itemId) && this.matchesToolProgressEcho(text);
|
|
@@ -618,6 +702,40 @@ function shouldAdvancePersistableAssistantBarrier(item) {
|
|
|
618
702
|
return shouldClearTerminalPresentationForNativeItem(item) || item.type === "dynamicToolCall" || item.type === "sleep";
|
|
619
703
|
}
|
|
620
704
|
//#endregion
|
|
705
|
+
//#region extensions/codex/src/app-server/event-projector-async-delivery.ts
|
|
706
|
+
/** Owns authorization, exactly-once settlement, and terminal retry for async user messages. */
|
|
707
|
+
var CodexAsyncDeliveryProjection = class {
|
|
708
|
+
constructor(params, threadId, turnId, options) {
|
|
709
|
+
this.params = params;
|
|
710
|
+
this.threadId = threadId;
|
|
711
|
+
this.turnId = turnId;
|
|
712
|
+
this.options = options;
|
|
713
|
+
this.settledItemIds = /* @__PURE__ */ new Set();
|
|
714
|
+
this.pendingDeliveries = /* @__PURE__ */ new Map();
|
|
715
|
+
}
|
|
716
|
+
allows(item, reportUnauthorized = false) {
|
|
717
|
+
if (item?.type !== "agentMessage" || item.delivery !== "async") return true;
|
|
718
|
+
const allowed = this.params.disableTools !== true && (this.options.asyncUserMessageAllowed ?? (this.params.toolsAllow === void 0 || this.params.toolsAllow.some((name) => name === "*" || name === "message")));
|
|
719
|
+
if (!allowed && reportUnauthorized) embeddedAgentLog.warn("blocked unauthorized codex async user message", {
|
|
720
|
+
itemId: item.id,
|
|
721
|
+
threadId: this.threadId,
|
|
722
|
+
turnId: this.turnId
|
|
723
|
+
});
|
|
724
|
+
return allowed;
|
|
725
|
+
}
|
|
726
|
+
pending() {
|
|
727
|
+
return [...this.pendingDeliveries.values()];
|
|
728
|
+
}
|
|
729
|
+
async deliver(delivery) {
|
|
730
|
+
if (this.settledItemIds.has(delivery.itemId)) return;
|
|
731
|
+
const settlement = await this.options.onAsyncDelivery?.(delivery);
|
|
732
|
+
if (settlement === "settled") {
|
|
733
|
+
this.settledItemIds.add(delivery.itemId);
|
|
734
|
+
this.pendingDeliveries.delete(delivery.itemId);
|
|
735
|
+
} else if (settlement === "retry") this.pendingDeliveries.set(delivery.itemId, delivery);
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
//#endregion
|
|
621
739
|
//#region extensions/codex/src/app-server/event-projector-media.ts
|
|
622
740
|
const GENERATED_IMAGE_MEDIA_SUBDIR = "tool-image-generation";
|
|
623
741
|
var CodexGeneratedMediaProjection = class {
|
|
@@ -911,45 +1029,55 @@ function reasoningMethodOrder(method) {
|
|
|
911
1029
|
const attemptTerminal = agentHarnessAttemptTerminal;
|
|
912
1030
|
//#endregion
|
|
913
1031
|
//#region extensions/codex/src/app-server/event-projector-snapshot.ts
|
|
914
|
-
const CODEX_META_KEY$1 = "__openclaw";
|
|
915
|
-
function readTurnTaintMetadata(message) {
|
|
916
|
-
return asOptionalRecord(CODEX_META_KEY$1 in message ? message[CODEX_META_KEY$1] : void 0);
|
|
917
|
-
}
|
|
918
|
-
function applyStickyTurnTaint(messages) {
|
|
919
|
-
let tainted = false;
|
|
920
|
-
return messages.map((message) => {
|
|
921
|
-
if (message.role === "user") {
|
|
922
|
-
tainted = false;
|
|
923
|
-
return message;
|
|
924
|
-
}
|
|
925
|
-
const metadata = readTurnTaintMetadata(message);
|
|
926
|
-
tainted ||= metadata?.turnTainted === true || metadata?.resultContentSource === "network";
|
|
927
|
-
return message.role === "assistant" && tainted ? {
|
|
928
|
-
...message,
|
|
929
|
-
__openclaw: {
|
|
930
|
-
...metadata,
|
|
931
|
-
turnTainted: true
|
|
932
|
-
}
|
|
933
|
-
} : message;
|
|
934
|
-
});
|
|
935
|
-
}
|
|
936
1032
|
function buildCodexMessagesSnapshot(params) {
|
|
937
1033
|
const messages = promptSnapshot(params.runParams, params.turnId, params.upstreamUserText);
|
|
938
1034
|
if (params.reasoningText) messages.push(attachCodexMirrorIdentity(params.createAssistantMirrorMessage("Codex reasoning", params.reasoningText), `${params.turnId}:reasoning`));
|
|
939
|
-
|
|
940
|
-
const
|
|
1035
|
+
const commentaryMessages = params.runParams.config?.ui?.prefs?.chatPersistCommentary === false ? [] : params.commentaryMessages.map(({ itemId, message }) => attachCodexMirrorIdentity(message, `${params.turnId}:commentary:${itemId}`));
|
|
1036
|
+
const asyncMessages = params.asyncMessages.map(({ itemId, message }) => attachCodexMirrorIdentity(message, `${params.turnId}:async:${itemId}`));
|
|
1037
|
+
const visibleWorkMessages = [
|
|
1038
|
+
...commentaryMessages,
|
|
1039
|
+
...asyncMessages,
|
|
1040
|
+
...(params.assistantMessages ?? []).map(({ itemId, message }) => attachCodexMirrorIdentity(message, `${params.turnId}:assistant:${itemId}`)),
|
|
1041
|
+
...params.toolMessages
|
|
1042
|
+
].toSorted((left, right) => (asDateTimestampMs(left.timestamp) ?? 0) - (asDateTimestampMs(right.timestamp) ?? 0));
|
|
941
1043
|
messages.push(...visibleWorkMessages);
|
|
942
1044
|
if (params.lastAssistant) messages.push(attachCodexMirrorIdentity(params.lastAssistant, `${params.turnId}:assistant`));
|
|
943
|
-
|
|
1045
|
+
const taint = { tainted: false };
|
|
1046
|
+
return messages.map((message) => projectAgentHarnessTranscriptMessageForDisplay({
|
|
944
1047
|
hidden: params.runParams.trigger === "memory",
|
|
945
|
-
message
|
|
1048
|
+
message: applyCodexTranscriptTaint(message, taint)
|
|
946
1049
|
}));
|
|
947
1050
|
}
|
|
1051
|
+
function buildCodexSteeringMessagesSnapshot(params) {
|
|
1052
|
+
const asyncMessages = params.assistantProjection.collectAsyncMessages().filter(({ itemId }) => params.completedItemIds.has(itemId));
|
|
1053
|
+
const commentaryMessages = params.assistantProjection.collectCommentaryMessages().filter(({ itemId }) => params.completedItemIds.has(itemId));
|
|
1054
|
+
const assistantMessages = params.assistantProjection.collectCompletedAssistantMessages(params.completedItemIds, {
|
|
1055
|
+
tokenUsage: void 0,
|
|
1056
|
+
aborted: false,
|
|
1057
|
+
promptError: void 0
|
|
1058
|
+
});
|
|
1059
|
+
return {
|
|
1060
|
+
messages: buildCodexMessagesSnapshot({
|
|
1061
|
+
runParams: params.runParams,
|
|
1062
|
+
turnId: params.turnId,
|
|
1063
|
+
upstreamUserText: params.upstreamUserText,
|
|
1064
|
+
reasoningText: void 0,
|
|
1065
|
+
asyncMessages,
|
|
1066
|
+
commentaryMessages,
|
|
1067
|
+
assistantMessages,
|
|
1068
|
+
toolMessages: params.toolMessages,
|
|
1069
|
+
lastAssistant: void 0,
|
|
1070
|
+
createAssistantMirrorMessage: (title, text) => params.assistantProjection.createAssistantMirrorMessage(title, text)
|
|
1071
|
+
}).filter((message) => message.role !== "user"),
|
|
1072
|
+
assistantBoundaryItemId: assistantMessages.at(-1)?.itemId
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
948
1075
|
//#endregion
|
|
949
1076
|
//#region extensions/codex/src/app-server/event-projector-result.ts
|
|
950
1077
|
function buildCodexAttemptResult(input) {
|
|
951
1078
|
input.nativeToolLifecycleProjection.finalizeActive();
|
|
952
1079
|
const assistantTexts = input.assistantProjection.collectAssistantTexts();
|
|
1080
|
+
const asyncMessages = input.assistantProjection.collectAsyncMessages();
|
|
953
1081
|
const commentaryMessages = input.assistantProjection.collectCommentaryMessages();
|
|
954
1082
|
const reasoningText = input.reasoningProjection.reasoningText();
|
|
955
1083
|
const planText = input.reasoningProjection.planText();
|
|
@@ -984,7 +1112,7 @@ function buildCodexAttemptResult(input) {
|
|
|
984
1112
|
turnId: input.turnId,
|
|
985
1113
|
upstreamUserText: input.upstreamUserText,
|
|
986
1114
|
reasoningText,
|
|
987
|
-
|
|
1115
|
+
asyncMessages,
|
|
988
1116
|
commentaryMessages,
|
|
989
1117
|
toolMessages: input.toolTranscriptProjection.transcriptMessages,
|
|
990
1118
|
lastAssistant,
|
|
@@ -1001,7 +1129,9 @@ function buildCodexAttemptResult(input) {
|
|
|
1001
1129
|
});
|
|
1002
1130
|
const toolMetas = input.toolProgressProjection.toolMetas;
|
|
1003
1131
|
const hadPotentialSideEffects = input.toolTelemetry.didSendViaMessagingTool || Boolean(input.toolTelemetry.successfulCronAdds || input.toolTelemetry.acceptedSessionSpawns?.length) || input.generatedMediaProjection.hasGeneratedMedia() || input.toolProgressProjection.hasPotentialSideEffects;
|
|
1004
|
-
|
|
1132
|
+
const sentMediaUrls = new Set(input.toolTelemetry.messagingToolSentMediaUrls.map((url) => url.trim()));
|
|
1133
|
+
const toolAutoDeliveryMediaUrls = input.toolTelemetry.toolAutoDeliveryMediaUrls?.filter((url) => !sentMediaUrls.has(url.trim()));
|
|
1134
|
+
const result = {
|
|
1005
1135
|
terminal: attemptTerminal.normalize({
|
|
1006
1136
|
aborted: input.aborted,
|
|
1007
1137
|
promptError,
|
|
@@ -1048,8 +1178,83 @@ function buildCodexAttemptResult(input) {
|
|
|
1048
1178
|
yieldDetected: input.yieldDetected || false,
|
|
1049
1179
|
didSendDeterministicApprovalPrompt: input.guardianReviewCount > 0 ? false : void 0
|
|
1050
1180
|
};
|
|
1181
|
+
const transferTtsProvenance = resolveCodexTtsProvenanceTransfer(input.runParams.hostCapabilities);
|
|
1182
|
+
for (const toolResult of input.toolTelemetry.coreTtsToolResults ?? []) transferTtsProvenance?.(toolResult, result, toolAutoDeliveryMediaUrls ?? []);
|
|
1183
|
+
return result;
|
|
1051
1184
|
}
|
|
1052
1185
|
//#endregion
|
|
1186
|
+
//#region extensions/codex/src/app-server/transcript-checkpoint.ts
|
|
1187
|
+
/** Commits completed work in receipt order without waiting for the enclosing turn. */
|
|
1188
|
+
var CodexTranscriptCheckpoint = class {
|
|
1189
|
+
constructor(params, threadId, turnId) {
|
|
1190
|
+
this.params = params;
|
|
1191
|
+
this.threadId = threadId;
|
|
1192
|
+
this.turnId = turnId;
|
|
1193
|
+
this.pending = [];
|
|
1194
|
+
this.commentaryItemIds = /* @__PURE__ */ new Set();
|
|
1195
|
+
this.lastTimestamp = 0;
|
|
1196
|
+
this.writing = Promise.resolve();
|
|
1197
|
+
this.tainted = false;
|
|
1198
|
+
this.closed = false;
|
|
1199
|
+
this.nextTimestamp = () => {
|
|
1200
|
+
this.lastTimestamp = Math.max(Date.now(), this.lastTimestamp + 1);
|
|
1201
|
+
return this.lastTimestamp;
|
|
1202
|
+
};
|
|
1203
|
+
this.enqueueCommentary = (itemId, entry) => {
|
|
1204
|
+
if (this.params.config?.ui?.prefs?.chatPersistCommentary === false || this.commentaryItemIds.has(itemId)) return;
|
|
1205
|
+
this.commentaryItemIds.add(itemId);
|
|
1206
|
+
this.enqueue({
|
|
1207
|
+
...entry,
|
|
1208
|
+
read: () => {
|
|
1209
|
+
const message = entry.read();
|
|
1210
|
+
return message ? attachCodexMirrorIdentity(message, `${this.turnId}:commentary:${itemId}`) : void 0;
|
|
1211
|
+
}
|
|
1212
|
+
});
|
|
1213
|
+
};
|
|
1214
|
+
this.enqueue = (entry) => {
|
|
1215
|
+
if (this.params.sessionTarget && !this.closed) this.pending.push(entry);
|
|
1216
|
+
};
|
|
1217
|
+
}
|
|
1218
|
+
flush(close = false) {
|
|
1219
|
+
if (this.closed) return this.writing;
|
|
1220
|
+
this.closed = close;
|
|
1221
|
+
this.writing = this.writing.then(async () => {
|
|
1222
|
+
const blocked = close ? -1 : this.pending.findIndex((entry) => entry.ready?.() === false);
|
|
1223
|
+
const count = blocked < 0 ? this.pending.length : blocked;
|
|
1224
|
+
if (count === 0) return;
|
|
1225
|
+
const taint = { tainted: this.tainted };
|
|
1226
|
+
const messages = this.pending.slice(0, count).flatMap((entry) => {
|
|
1227
|
+
const message = entry.read();
|
|
1228
|
+
return message ? [projectAgentHarnessTranscriptMessageForDisplay({
|
|
1229
|
+
hidden: this.params.trigger === "memory",
|
|
1230
|
+
message: applyCodexTranscriptTaint(message, taint)
|
|
1231
|
+
})] : [];
|
|
1232
|
+
});
|
|
1233
|
+
try {
|
|
1234
|
+
await codexTranscriptMirrorRuntime.mirror({
|
|
1235
|
+
...this.params.sessionTarget,
|
|
1236
|
+
sessionId: this.params.sessionId,
|
|
1237
|
+
cwd: this.params.workspaceDir,
|
|
1238
|
+
messages,
|
|
1239
|
+
idempotencyScope: `codex-app-server:${this.threadId}`,
|
|
1240
|
+
runId: this.params.runId,
|
|
1241
|
+
runMirrorIdentityPrefix: `${this.turnId}:`,
|
|
1242
|
+
config: this.params.config
|
|
1243
|
+
});
|
|
1244
|
+
this.pending.splice(0, count);
|
|
1245
|
+
this.tainted = taint.tainted;
|
|
1246
|
+
} catch (error) {
|
|
1247
|
+
embeddedAgentLog.warn("failed to checkpoint codex app-server transcript", {
|
|
1248
|
+
runId: this.params.runId,
|
|
1249
|
+
sessionId: this.params.sessionId,
|
|
1250
|
+
error: formatErrorMessage(error)
|
|
1251
|
+
});
|
|
1252
|
+
}
|
|
1253
|
+
});
|
|
1254
|
+
return this.writing;
|
|
1255
|
+
}
|
|
1256
|
+
};
|
|
1257
|
+
//#endregion
|
|
1053
1258
|
//#region extensions/codex/src/app-server/usage-limit-error.ts
|
|
1054
1259
|
/**
|
|
1055
1260
|
* Enriches Codex usage-limit failures with current rate-limit information and
|
|
@@ -1204,7 +1409,8 @@ var CodexAppServerEventProjector = class {
|
|
|
1204
1409
|
this.aborted = false;
|
|
1205
1410
|
this.responseCompletions = new CodexResponseCompletionProjection();
|
|
1206
1411
|
this.completedCompactionCount = 0;
|
|
1207
|
-
this.
|
|
1412
|
+
this.transcriptCheckpoint = new CodexTranscriptCheckpoint(params, threadId, turnId);
|
|
1413
|
+
this.asyncDeliveryProjection = new CodexAsyncDeliveryProjection(params, threadId, turnId, options);
|
|
1208
1414
|
this.contextTokens = options.initialContextTokens;
|
|
1209
1415
|
this.contextTokensSource = options.initialContextTokens === void 0 ? void 0 : "resolved";
|
|
1210
1416
|
this.diagnostics = new CodexProjectionDiagnostics(threadId, turnId);
|
|
@@ -1216,35 +1422,37 @@ var CodexAppServerEventProjector = class {
|
|
|
1216
1422
|
signal: options.runAbortSignal
|
|
1217
1423
|
});
|
|
1218
1424
|
this.toolProgressProjection = new CodexToolProgressProjection(params);
|
|
1219
|
-
this.toolTranscriptProjection = new CodexToolTranscriptProjection(params, threadId, turnId, this.toolProgressProjection,
|
|
1425
|
+
this.toolTranscriptProjection = new CodexToolTranscriptProjection(params, threadId, turnId, this.toolProgressProjection, this.transcriptCheckpoint.nextTimestamp, {
|
|
1220
1426
|
nativePostToolUseRelayEnabled: options.nativePostToolUseRelayEnabled,
|
|
1221
1427
|
prepareNativeMcpAppResultDetails: options.prepareNativeMcpAppResultDetails,
|
|
1222
|
-
trajectoryRecorder: options.trajectoryRecorder
|
|
1428
|
+
trajectoryRecorder: options.trajectoryRecorder,
|
|
1429
|
+
checkpointMessage: this.transcriptCheckpoint.enqueue
|
|
1223
1430
|
});
|
|
1224
1431
|
this.eventProjection = new CodexEventProjection(threadId, turnId, (event) => this.emitAgentEvent(event), this.toolProgressProjection, this.toolTranscriptProjection, options.onNativeToolResultRecorded);
|
|
1225
|
-
this.assistantProjection = new CodexAssistantProjection(params, (event) => this.emitAgentEvent(event), (text) => this.toolProgressProjection.matchesEcho(text),
|
|
1432
|
+
this.assistantProjection = new CodexAssistantProjection(params, (event) => this.emitAgentEvent(event), (text) => this.toolProgressProjection.matchesEcho(text), this.transcriptCheckpoint.nextTimestamp, this.transcriptCheckpoint.enqueueCommentary);
|
|
1226
1433
|
this.reasoningProjection = new CodexReasoningProjection(params, (event) => this.emitAgentEvent(event), options.onNativePlanUpdate);
|
|
1227
1434
|
}
|
|
1228
|
-
nextTranscriptTimestamp() {
|
|
1229
|
-
this.lastTranscriptTimestamp = Math.max(Date.now(), this.lastTranscriptTimestamp + 1);
|
|
1230
|
-
return this.lastTranscriptTimestamp;
|
|
1231
|
-
}
|
|
1232
1435
|
getCompletedTurnStatus() {
|
|
1233
1436
|
return this.completedTurn?.status;
|
|
1234
1437
|
}
|
|
1235
1438
|
buildSteeringTranscriptPrefix() {
|
|
1236
|
-
const
|
|
1237
|
-
return buildCodexMessagesSnapshot({
|
|
1439
|
+
const snapshot = buildCodexSteeringMessagesSnapshot({
|
|
1238
1440
|
runParams: this.params,
|
|
1239
1441
|
turnId: this.turnId,
|
|
1240
1442
|
upstreamUserText: this.options.upstreamUserText,
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1443
|
+
completedItemIds: this.completedItemIds,
|
|
1444
|
+
assistantProjection: this.assistantProjection,
|
|
1445
|
+
toolMessages: this.toolTranscriptProjection.transcriptMessages
|
|
1446
|
+
});
|
|
1447
|
+
this.pendingSteeringAssistantBoundaryItemId = snapshot.assistantBoundaryItemId;
|
|
1448
|
+
return snapshot.messages;
|
|
1449
|
+
}
|
|
1450
|
+
markSteeringTranscriptPersisted() {
|
|
1451
|
+
const itemId = this.pendingSteeringAssistantBoundaryItemId;
|
|
1452
|
+
if (itemId) {
|
|
1453
|
+
this.assistantProjection.markAssistantBoundaryPersisted(itemId);
|
|
1454
|
+
this.pendingSteeringAssistantBoundaryItemId = void 0;
|
|
1455
|
+
}
|
|
1248
1456
|
}
|
|
1249
1457
|
hasCompletedTerminalAssistantText() {
|
|
1250
1458
|
return this.assistantProjection.hasCompletedTerminalAssistantText(this.completedItemIds);
|
|
@@ -1284,8 +1492,9 @@ var CodexAppServerEventProjector = class {
|
|
|
1284
1492
|
if (!params) return;
|
|
1285
1493
|
if (notification.method === "hook/started" || notification.method === "hook/completed") {
|
|
1286
1494
|
if (!this.isHookNotificationForCurrentThread(params)) return;
|
|
1287
|
-
} else if (notification.method === "guardianWarning") {
|
|
1288
|
-
|
|
1495
|
+
} else if (notification.method === "guardianWarning" || notification.method === "warning" || notification.method === "configWarning") {
|
|
1496
|
+
const warningThreadId = readCodexNotificationThreadId(params);
|
|
1497
|
+
if (notification.method === "guardianWarning" && warningThreadId !== this.threadId || warningThreadId && warningThreadId !== this.threadId) return;
|
|
1289
1498
|
} else if (!isCodexNotificationForTurn(params, this.threadId, this.turnId)) return;
|
|
1290
1499
|
if (notification.method !== "guardianWarning" && notification.method !== "item/autoApprovalReview/started" && notification.method !== "item/autoApprovalReview/completed") this.eventProjection.flushPendingGuardianWarning();
|
|
1291
1500
|
this.nativeToolLifecycleProjector.handleNotification(notification);
|
|
@@ -1306,9 +1515,11 @@ var CodexAppServerEventProjector = class {
|
|
|
1306
1515
|
break;
|
|
1307
1516
|
case "item/started":
|
|
1308
1517
|
await this.handleItemStarted(params);
|
|
1518
|
+
await this.transcriptCheckpoint.flush();
|
|
1309
1519
|
break;
|
|
1310
1520
|
case "item/completed":
|
|
1311
1521
|
await this.handleItemCompleted(params);
|
|
1522
|
+
await this.transcriptCheckpoint.flush();
|
|
1312
1523
|
break;
|
|
1313
1524
|
case "item/commandExecution/outputDelta":
|
|
1314
1525
|
this.toolProgressProjection.handleOutputDelta(params, "bash");
|
|
@@ -1317,9 +1528,16 @@ var CodexAppServerEventProjector = class {
|
|
|
1317
1528
|
case "item/autoApprovalReview/completed":
|
|
1318
1529
|
this.eventProjection.handleGuardianReview(notification.method, params);
|
|
1319
1530
|
break;
|
|
1531
|
+
case "autoApprovalReview/strictReviewRequired":
|
|
1532
|
+
this.eventProjection.handleStrictReviewRequired(params);
|
|
1533
|
+
break;
|
|
1320
1534
|
case "guardianWarning":
|
|
1321
1535
|
this.eventProjection.handleGuardianWarning(params);
|
|
1322
1536
|
break;
|
|
1537
|
+
case "warning":
|
|
1538
|
+
case "configWarning":
|
|
1539
|
+
this.eventProjection.handleWarning(params);
|
|
1540
|
+
break;
|
|
1323
1541
|
case "hook/started":
|
|
1324
1542
|
case "hook/completed":
|
|
1325
1543
|
this.eventProjection.handleHook(notification.method, params);
|
|
@@ -1331,7 +1549,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1331
1549
|
this.contextTokensSource = this.params.authoredContextTokenCap === void 0 ? "runtime" : "runtime-configured";
|
|
1332
1550
|
}
|
|
1333
1551
|
this.emitAgentEvent({
|
|
1334
|
-
stream: "
|
|
1552
|
+
stream: "usage",
|
|
1335
1553
|
data
|
|
1336
1554
|
});
|
|
1337
1555
|
});
|
|
@@ -1340,10 +1558,14 @@ var CodexAppServerEventProjector = class {
|
|
|
1340
1558
|
await this.handleTurnCompleted(params);
|
|
1341
1559
|
break;
|
|
1342
1560
|
case "rawResponse/completed":
|
|
1343
|
-
this.responseCompletions.record(params);
|
|
1561
|
+
this.responseCompletions.record(params, this.params.hostCapabilities.reportOutputTokens);
|
|
1344
1562
|
break;
|
|
1345
1563
|
case "rawResponseItem/completed":
|
|
1346
1564
|
await this.handleRawResponseItemCompleted(params);
|
|
1565
|
+
await this.transcriptCheckpoint.flush();
|
|
1566
|
+
break;
|
|
1567
|
+
case "model/rerouted":
|
|
1568
|
+
this.eventProjection.handleModelRerouted(params);
|
|
1347
1569
|
break;
|
|
1348
1570
|
case "error": {
|
|
1349
1571
|
this.responseCompletions.clear();
|
|
@@ -1363,13 +1585,10 @@ var CodexAppServerEventProjector = class {
|
|
|
1363
1585
|
case "item/fileChange/outputDelta":
|
|
1364
1586
|
case "item/fileChange/patchUpdated":
|
|
1365
1587
|
case "item/mcpToolCall/progress":
|
|
1366
|
-
case "model/rerouted":
|
|
1367
1588
|
case "model/verification":
|
|
1368
1589
|
case "turn/moderationMetadata":
|
|
1369
1590
|
case "model/safetyBuffering/updated": break;
|
|
1370
|
-
default:
|
|
1371
|
-
this.diagnostics.warnUnknownEvent(notification, params);
|
|
1372
|
-
break;
|
|
1591
|
+
default: this.diagnostics.warnUnknownEvent(notification, params);
|
|
1373
1592
|
}
|
|
1374
1593
|
}
|
|
1375
1594
|
buildResult(toolTelemetry, options) {
|
|
@@ -1495,7 +1714,9 @@ var CodexAppServerEventProjector = class {
|
|
|
1495
1714
|
this.activeItemIds.delete(itemId);
|
|
1496
1715
|
this.completedItemIds.add(itemId);
|
|
1497
1716
|
}
|
|
1498
|
-
this.
|
|
1717
|
+
if (!this.asyncDeliveryProjection.allows(item, true)) return;
|
|
1718
|
+
const asyncMessage = this.assistantProjection.recordItemCompleted(item, itemId, this.activeItemIds);
|
|
1719
|
+
if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
|
|
1499
1720
|
this.reasoningProjection.recordItem(item);
|
|
1500
1721
|
await this.generatedMediaProjection.recordNative(item);
|
|
1501
1722
|
if (item?.type === "contextCompaction" && itemId) {
|
|
@@ -1525,9 +1746,9 @@ var CodexAppServerEventProjector = class {
|
|
|
1525
1746
|
threadId: this.threadId,
|
|
1526
1747
|
turnId: this.turnId,
|
|
1527
1748
|
itemId,
|
|
1528
|
-
timestamp: this.
|
|
1749
|
+
timestamp: this.transcriptCheckpoint.nextTimestamp()
|
|
1529
1750
|
});
|
|
1530
|
-
this.emitCompactionEnd(itemId, true);
|
|
1751
|
+
this.eventProjection.emitCompactionEnd(itemId, true);
|
|
1531
1752
|
}
|
|
1532
1753
|
this.toolProgressProjection.recordToolMeta(item);
|
|
1533
1754
|
this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
|
|
@@ -1573,10 +1794,11 @@ var CodexAppServerEventProjector = class {
|
|
|
1573
1794
|
for (const itemId of failedCompactionItemIds) {
|
|
1574
1795
|
this.activeItemIds.delete(itemId);
|
|
1575
1796
|
this.activeCompactionItemIds.delete(itemId);
|
|
1576
|
-
this.emitCompactionEnd(itemId, false);
|
|
1797
|
+
this.eventProjection.emitCompactionEnd(itemId, false);
|
|
1577
1798
|
}
|
|
1578
1799
|
}
|
|
1579
1800
|
const turnItems = turn.items ?? [];
|
|
1801
|
+
const unsettledAsyncDeliveries = this.asyncDeliveryProjection.pending();
|
|
1580
1802
|
for (let index = turnItems.length - 1; index >= 0; index -= 1) {
|
|
1581
1803
|
const item = turnItems[index];
|
|
1582
1804
|
if (!item || !this.isCurrentTurnSnapshotItem(item)) continue;
|
|
@@ -1587,8 +1809,10 @@ var CodexAppServerEventProjector = class {
|
|
|
1587
1809
|
}
|
|
1588
1810
|
}
|
|
1589
1811
|
for (const item of turnItems) {
|
|
1812
|
+
if (!this.asyncDeliveryProjection.allows(item)) continue;
|
|
1590
1813
|
this.diagnostics.warnUnknownItemStatus(item);
|
|
1591
|
-
this.assistantProjection.recordSnapshotItem(item);
|
|
1814
|
+
const asyncMessage = this.assistantProjection.recordSnapshotItem(item);
|
|
1815
|
+
if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
|
|
1592
1816
|
this.reasoningProjection.recordItem(item);
|
|
1593
1817
|
await this.generatedMediaProjection.recordNative(item);
|
|
1594
1818
|
this.toolProgressProjection.recordToolMeta(item);
|
|
@@ -1601,23 +1825,11 @@ var CodexAppServerEventProjector = class {
|
|
|
1601
1825
|
this.toolProgressProjection.emitToolResultOutput(item);
|
|
1602
1826
|
}
|
|
1603
1827
|
this.toolProgressProjection.approvalTimeoutKinds.clear();
|
|
1828
|
+
for (const delivery of unsettledAsyncDeliveries) await this.asyncDeliveryProjection.deliver(delivery);
|
|
1604
1829
|
this.assistantProjection.finalizeAnswerCandidate(turn);
|
|
1605
1830
|
this.activeCompactionItemIds.clear();
|
|
1606
1831
|
await this.reasoningProjection.maybeEndReasoning();
|
|
1607
1832
|
}
|
|
1608
|
-
emitCompactionEnd(itemId, completed) {
|
|
1609
|
-
this.emitAgentEvent({
|
|
1610
|
-
stream: "compaction",
|
|
1611
|
-
data: {
|
|
1612
|
-
phase: "end",
|
|
1613
|
-
backend: "codex-app-server",
|
|
1614
|
-
completed,
|
|
1615
|
-
threadId: this.threadId,
|
|
1616
|
-
turnId: this.turnId,
|
|
1617
|
-
itemId
|
|
1618
|
-
}
|
|
1619
|
-
});
|
|
1620
|
-
}
|
|
1621
1833
|
async emitSnapshotOnlyNativeToolProgress(item) {
|
|
1622
1834
|
if (!shouldSynthesizeToolProgressForItem(item) || !this.isCurrentTurnSnapshotItem(item) || this.completedItemIds.has(item.id) || itemStatus(item) === "running") return;
|
|
1623
1835
|
if (!this.activeItemIds.has(item.id)) {
|
|
@@ -1675,24 +1887,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1675
1887
|
return usageLimitMessage ? createCodexUsageLimitPromptError(usageLimitMessage) : readCodexErrorNotificationMessage(params);
|
|
1676
1888
|
}
|
|
1677
1889
|
emitAgentEvent(event) {
|
|
1678
|
-
|
|
1679
|
-
emitAgentEvent({
|
|
1680
|
-
runId: this.params.runId,
|
|
1681
|
-
stream: event.stream,
|
|
1682
|
-
data: event.data,
|
|
1683
|
-
...this.params.sessionKey ? { sessionKey: this.params.sessionKey } : {}
|
|
1684
|
-
});
|
|
1685
|
-
} catch (error) {
|
|
1686
|
-
embeddedAgentLog.debug("codex app-server global agent event emit failed", { error });
|
|
1687
|
-
}
|
|
1688
|
-
try {
|
|
1689
|
-
const maybePromise = this.params.onAgentEvent?.(event);
|
|
1690
|
-
Promise.resolve(maybePromise).catch((error) => {
|
|
1691
|
-
embeddedAgentLog.debug("codex app-server agent event handler rejected", { error });
|
|
1692
|
-
});
|
|
1693
|
-
} catch (error) {
|
|
1694
|
-
embeddedAgentLog.debug("codex app-server agent event handler threw", { error });
|
|
1695
|
-
}
|
|
1890
|
+
emitCodexAgentEvent(this.params, event);
|
|
1696
1891
|
}
|
|
1697
1892
|
isHookNotificationForCurrentThread(params) {
|
|
1698
1893
|
const threadId = readStringField(params, "threadId");
|
|
@@ -1701,11 +1896,30 @@ var CodexAppServerEventProjector = class {
|
|
|
1701
1896
|
}
|
|
1702
1897
|
};
|
|
1703
1898
|
//#endregion
|
|
1899
|
+
//#region extensions/codex/src/app-server/mcp-tool-metadata.ts
|
|
1900
|
+
/** Hosted app ownership is authoritative only on metadata supplied by Codex. */
|
|
1901
|
+
function readCodexMcpToolConnectorId(tool) {
|
|
1902
|
+
const metadata = asOptionalRecord(asOptionalRecord(tool)?.["_meta"]);
|
|
1903
|
+
return normalizeOptionalString(metadata?.connector_id) ?? normalizeOptionalString(metadata?.connectorId);
|
|
1904
|
+
}
|
|
1905
|
+
/** Preserve MCP App visibility so model-only tools cannot become widget authority. */
|
|
1906
|
+
function readCodexMcpToolUiVisibility(tool) {
|
|
1907
|
+
const metadata = asOptionalRecord(asOptionalRecord(tool)?.["_meta"]);
|
|
1908
|
+
const visibility = asOptionalRecord(metadata?.ui)?.visibility;
|
|
1909
|
+
if (!Array.isArray(visibility)) return;
|
|
1910
|
+
return [...new Set(visibility.filter((value) => value === "app" || value === "model"))].toSorted();
|
|
1911
|
+
}
|
|
1912
|
+
//#endregion
|
|
1704
1913
|
//#region extensions/codex/src/app-server/native-mcp-app.ts
|
|
1914
|
+
const CODEX_APPS_MCP_SERVER$1 = "codex_apps";
|
|
1705
1915
|
function readMcpAppResourceUri(item) {
|
|
1706
|
-
const
|
|
1916
|
+
const appContext = asOptionalRecord(item.appContext);
|
|
1917
|
+
const uri = normalizeOptionalString(appContext?.resourceUri) ?? normalizeOptionalString(item.mcpAppResourceUri);
|
|
1707
1918
|
return uri?.startsWith("ui://") ? uri : void 0;
|
|
1708
1919
|
}
|
|
1920
|
+
function readMcpAppConnectorId(item) {
|
|
1921
|
+
return normalizeOptionalString(asOptionalRecord(item.appContext)?.connectorId);
|
|
1922
|
+
}
|
|
1709
1923
|
function readMcpToolResult(item) {
|
|
1710
1924
|
const result = asOptionalRecord(item.result);
|
|
1711
1925
|
if (!result || !Array.isArray(result.content)) return;
|
|
@@ -1743,13 +1957,16 @@ function createNativeMcpRuntime(params) {
|
|
|
1743
1957
|
launchSummary: "Codex native MCP connection",
|
|
1744
1958
|
toolCount: Object.keys(status.tools).length
|
|
1745
1959
|
}])),
|
|
1746
|
-
tools: loaded.flatMap((status) => statusTools(status).map((tool) =>
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1960
|
+
tools: loaded.flatMap((status) => statusTools(status).map((tool) => {
|
|
1961
|
+
const uiVisibility = readCodexMcpToolUiVisibility(tool);
|
|
1962
|
+
return Object.assign({
|
|
1963
|
+
serverName: status.name,
|
|
1964
|
+
safeServerName: status.name,
|
|
1965
|
+
toolName: String(tool.name),
|
|
1966
|
+
inputSchema: asOptionalRecord(tool.inputSchema) ?? { type: "object" },
|
|
1967
|
+
fallbackDescription: normalizeOptionalString(tool.description) ?? String(tool.name)
|
|
1968
|
+
}, uiVisibility ? { uiVisibility } : {});
|
|
1969
|
+
}))
|
|
1753
1970
|
};
|
|
1754
1971
|
return catalog;
|
|
1755
1972
|
};
|
|
@@ -1777,11 +1994,18 @@ function createNativeMcpRuntime(params) {
|
|
|
1777
1994
|
const status = (await loadStatuses()).find((entry) => entry.name === serverName);
|
|
1778
1995
|
return { tools: status ? statusTools(status) : [] };
|
|
1779
1996
|
},
|
|
1780
|
-
readResource: async (serverName, uri) =>
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1997
|
+
readResource: async (serverName, uri) => {
|
|
1998
|
+
const isCodexAppsServer = serverName === CODEX_APPS_MCP_SERVER$1;
|
|
1999
|
+
const response = await params.client.request("mcpServer/resource/read", {
|
|
2000
|
+
threadId: params.threadId,
|
|
2001
|
+
...isCodexAppsServer ? { originCallId: params.originCallId } : {},
|
|
2002
|
+
server: serverName,
|
|
2003
|
+
uri,
|
|
2004
|
+
...params.connectorId ? { connectorId: params.connectorId } : {}
|
|
2005
|
+
});
|
|
2006
|
+
if (isCodexAppsServer && response.originCallId !== params.originCallId) throw new Error(`Codex MCP resource response originCallId mismatch: expected ${params.originCallId}, received ${response.originCallId}`);
|
|
2007
|
+
return response;
|
|
2008
|
+
},
|
|
1785
2009
|
listResources: async (serverName) => {
|
|
1786
2010
|
return { resources: (await loadStatuses()).find((entry) => entry.name === serverName)?.resources ?? [] };
|
|
1787
2011
|
},
|
|
@@ -1794,15 +2018,25 @@ function createNativeMcpRuntime(params) {
|
|
|
1794
2018
|
}
|
|
1795
2019
|
function createCodexNativeMcpAppResultDetailsPreparer(params) {
|
|
1796
2020
|
if (params.attempt.config?.mcp?.apps?.enabled !== true) return;
|
|
1797
|
-
const runtime = createNativeMcpRuntime(params);
|
|
1798
2021
|
return async (item) => {
|
|
1799
2022
|
const serverName = normalizeOptionalString(item.server);
|
|
1800
2023
|
const toolName = normalizeOptionalString(item.tool);
|
|
1801
2024
|
const uiResourceUri = readMcpAppResourceUri(item);
|
|
2025
|
+
const connectorId = readMcpAppConnectorId(item);
|
|
1802
2026
|
const toolResult = readMcpToolResult(item);
|
|
1803
2027
|
if (!serverName || !toolName || !uiResourceUri || !toolResult) return;
|
|
1804
|
-
|
|
1805
|
-
|
|
2028
|
+
if (serverName === CODEX_APPS_MCP_SERVER$1 && !connectorId) return;
|
|
2029
|
+
const runtime = createNativeMcpRuntime({
|
|
2030
|
+
...params,
|
|
2031
|
+
originCallId: item.id,
|
|
2032
|
+
...connectorId ? { connectorId } : {}
|
|
2033
|
+
});
|
|
2034
|
+
const tools = (await runtime.listTools?.(serverName))?.tools ?? [];
|
|
2035
|
+
const allowedAppToolNames = new Set(tools.filter((tool) => {
|
|
2036
|
+
const uiVisibility = readCodexMcpToolUiVisibility(tool);
|
|
2037
|
+
return (uiVisibility === void 0 || uiVisibility.includes("app")) && (serverName !== CODEX_APPS_MCP_SERVER$1 || readCodexMcpToolConnectorId(tool) === connectorId);
|
|
2038
|
+
}).map((tool) => tool.name));
|
|
2039
|
+
if (!allowedAppToolNames.has(toolName)) return;
|
|
1806
2040
|
return await prepareHarnessNativeMcpAppPreview({
|
|
1807
2041
|
runtime,
|
|
1808
2042
|
serverName,
|
|
@@ -1821,9 +2055,9 @@ function createCodexNativeMcpAppResultDetailsPreparer(params) {
|
|
|
1821
2055
|
const RESTORED_PLAN_PREAMBLE = "OpenClaw restored the session progress card after context compaction. This is application state, not a new user request. Continue the current task and call progress_card whenever the status meaningfully changes.";
|
|
1822
2056
|
const PROGRESS_CARD_MAX_STEPS = 50;
|
|
1823
2057
|
const PROGRESS_CARD_MAX_STEP_UTF8_BYTES = 512;
|
|
1824
|
-
const PROGRESS_CARD_MAX_UTF8_BYTES =
|
|
1825
|
-
const RESTORED_PLAN_MAX_MARKDOWN_BYTES =
|
|
1826
|
-
const RESTORED_PLAN_MAX_PAYLOAD_BYTES =
|
|
2058
|
+
const PROGRESS_CARD_MAX_UTF8_BYTES = 8192;
|
|
2059
|
+
const RESTORED_PLAN_MAX_MARKDOWN_BYTES = 2048;
|
|
2060
|
+
const RESTORED_PLAN_MAX_PAYLOAD_BYTES = 32768;
|
|
1827
2061
|
const RESTORED_PLAN_TRUNCATION_SUFFIX = "…";
|
|
1828
2062
|
function canonicalizeNativeProgressCardInput(input) {
|
|
1829
2063
|
const markdown = input.markdown === void 0 ? void 0 : truncateUtf8(stripInvisibleUnicode(input.markdown), PROGRESS_CARD_MAX_UTF8_BYTES);
|
|
@@ -1833,8 +2067,10 @@ function canonicalizeNativeProgressCardInput(input) {
|
|
|
1833
2067
|
const text = truncateUtf8(stripInvisibleUnicode(step.step), PROGRESS_CARD_MAX_STEP_UTF8_BYTES);
|
|
1834
2068
|
if (!text.trim()) continue;
|
|
1835
2069
|
let status = step.status;
|
|
1836
|
-
if (status === "in_progress")
|
|
1837
|
-
|
|
2070
|
+
if (status === "in_progress") {
|
|
2071
|
+
if (hasInProgressStep) status = "pending";
|
|
2072
|
+
else hasInProgressStep = true;
|
|
2073
|
+
}
|
|
1838
2074
|
plan.push({
|
|
1839
2075
|
step: text,
|
|
1840
2076
|
status
|
|
@@ -1903,7 +2139,8 @@ function serializePlan(plan) {
|
|
|
1903
2139
|
}
|
|
1904
2140
|
function truncateUtf8(value, maxBytes) {
|
|
1905
2141
|
if (Buffer$1.byteLength(value, "utf8") <= maxBytes) return value;
|
|
1906
|
-
|
|
2142
|
+
const suffixBytes = Buffer$1.byteLength(RESTORED_PLAN_TRUNCATION_SUFFIX, "utf8");
|
|
2143
|
+
return `${truncateUtf8Prefix(value, maxBytes - suffixBytes)}${RESTORED_PLAN_TRUNCATION_SUFFIX}`;
|
|
1907
2144
|
}
|
|
1908
2145
|
function readPlanSteps(value) {
|
|
1909
2146
|
if (!Array.isArray(value)) return [];
|
|
@@ -1923,7 +2160,7 @@ function isPlanStatus(value) {
|
|
|
1923
2160
|
//#endregion
|
|
1924
2161
|
//#region extensions/codex/src/app-server/user-input-bridge.ts
|
|
1925
2162
|
/** Owns per-turn Codex request_user_input and ordinary MCP elicitation lifecycles. */
|
|
1926
|
-
const DEFAULT_USER_INPUT_TIMEOUT_MS =
|
|
2163
|
+
const DEFAULT_USER_INPUT_TIMEOUT_MS = 9e5;
|
|
1927
2164
|
const NONBLOCKING_USER_INPUT_TIMEOUT_MS = 12e4;
|
|
1928
2165
|
const MAX_USER_INPUT_QUESTIONS = 3;
|
|
1929
2166
|
const MAX_USER_INPUT_OPTIONS = 4;
|
|
@@ -2047,7 +2284,10 @@ function createCodexUserInputBridge(params) {
|
|
|
2047
2284
|
failureValue: declineElicitation("OpenClaw could not handle this elicitation."),
|
|
2048
2285
|
run: async (signal) => {
|
|
2049
2286
|
const result = await execute(compiled.input, timeoutMs, signal);
|
|
2050
|
-
if (result.status === "answered")
|
|
2287
|
+
if (result.status === "answered") {
|
|
2288
|
+
const content = compiled.input.kind === "ready" && compiled.input.plan.kind === "url" ? null : result.content;
|
|
2289
|
+
return createCodexElicitationResponse("accept", content);
|
|
2290
|
+
}
|
|
2051
2291
|
if (result.status === "declined") return declineElicitation(result.message);
|
|
2052
2292
|
if (result.status === "unsupported") return declineElicitation(result.message);
|
|
2053
2293
|
return cancelValue;
|
|
@@ -2166,7 +2406,7 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2166
2406
|
const { context, turnState } = prompt;
|
|
2167
2407
|
const { runtime, attemptTools } = context;
|
|
2168
2408
|
const { connection } = runtime;
|
|
2169
|
-
const { params, runAbortController, terminalState, abortExplicitly, abortFromUpstream, bindingStore, bindingIdentity, sessionAgentId,
|
|
2409
|
+
const { params, runAbortController, terminalState, abortExplicitly, abortFromUpstream, bindingStore, bindingIdentity, sessionAgentId, contextSessionKey, effectiveCwd } = connection;
|
|
2170
2410
|
const { dynamicToolParams, compactionPlanState, computerContextEpoch, toolBridge } = attemptTools;
|
|
2171
2411
|
const { state, userInputBridgeRef, steeringQueueRef, turnWatches, completeTurn, interruptTurn } = turnRuntime;
|
|
2172
2412
|
const { emitExecutionPhaseOnce, emitLifecycleStart, maybeAnnounceFastModeAutoOff } = lifecycle;
|
|
@@ -2208,6 +2448,16 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2208
2448
|
}, resourceState.thread.threadId, activeTurnId, {
|
|
2209
2449
|
initialContextTokens: connection.mutable.startupContextTokens,
|
|
2210
2450
|
nativePostToolUseRelayEnabled: resourceState.nativeHookRelay?.allowedEvents.includes("post_tool_use") === true && resourceState.nativeHookRelay.shouldRelayEvent("post_tool_use"),
|
|
2451
|
+
asyncUserMessageAllowed: params.disableTools !== true && (params.toolsAllow === void 0 || toolBridge.availableTools.some((tool) => tool.name === "message")),
|
|
2452
|
+
onAsyncDelivery: async (delivery) => {
|
|
2453
|
+
return await codexTranscriptMirrorRuntime.deliverAsyncMessageBestEffort({
|
|
2454
|
+
params: dynamicToolParams,
|
|
2455
|
+
cwd: effectiveCwd,
|
|
2456
|
+
threadId: resourceState.thread.threadId,
|
|
2457
|
+
turnId: activeTurnId,
|
|
2458
|
+
...delivery
|
|
2459
|
+
});
|
|
2460
|
+
},
|
|
2211
2461
|
readRecentRateLimits: () => readRecentCodexRateLimits(resourceState.client),
|
|
2212
2462
|
runAbortSignal: runAbortController.signal,
|
|
2213
2463
|
remoteWorkspaceRoot: connection.appServer.remoteWorkspaceRoot,
|
|
@@ -2265,6 +2515,18 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2265
2515
|
turnWatches.armAttemptIdleWatch();
|
|
2266
2516
|
turnWatches.touchActivity("turn:start", { attemptProgress: true });
|
|
2267
2517
|
for (const failure of pendingNativePreToolUseFailures.splice(0)) activeProjector.recordNativeToolPreToolUseFailure(failure);
|
|
2518
|
+
const notifyUserMessagePersisted = createCodexAppServerUserMessagePersistenceNotifier(params);
|
|
2519
|
+
const promptMirrorPromise = mirrorPromptAtTurnStartBestEffort({
|
|
2520
|
+
params,
|
|
2521
|
+
agentId: sessionAgentId,
|
|
2522
|
+
notifyUserMessagePersisted,
|
|
2523
|
+
sessionKey: contextSessionKey,
|
|
2524
|
+
cwd: effectiveCwd,
|
|
2525
|
+
threadId: resourceState.thread.threadId,
|
|
2526
|
+
turnId: activeTurnId,
|
|
2527
|
+
upstreamUserText: turnState.codexTurnPromptText
|
|
2528
|
+
});
|
|
2529
|
+
await promptMirrorPromise;
|
|
2268
2530
|
if (resourceState.turnRoute) try {
|
|
2269
2531
|
await resourceState.turnRoute.bindTurn(activeTurnId);
|
|
2270
2532
|
} catch (error) {
|
|
@@ -2289,41 +2551,66 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2289
2551
|
turnId: activeTurnId
|
|
2290
2552
|
});
|
|
2291
2553
|
}
|
|
2292
|
-
const
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
turnId: activeTurnId,
|
|
2301
|
-
upstreamUserText: turnState.codexTurnPromptText
|
|
2554
|
+
const assertSteeringActive = () => {
|
|
2555
|
+
params.hostCapabilities.assertActive();
|
|
2556
|
+
runAbortController.signal.throwIfAborted();
|
|
2557
|
+
if (state.completed || state.terminalTurnNotificationQueued || state.timedOut) throw new Error("codex app-server turn is no longer accepting steering");
|
|
2558
|
+
};
|
|
2559
|
+
const workspaceOnly = resolveAttemptFsWorkspaceOnly({
|
|
2560
|
+
config: params.config,
|
|
2561
|
+
sessionAgentId
|
|
2302
2562
|
});
|
|
2563
|
+
const imageContext = {
|
|
2564
|
+
workspaceDir: connection.effectiveWorkspace,
|
|
2565
|
+
model: params.model,
|
|
2566
|
+
config: params.config,
|
|
2567
|
+
workspaceOnly,
|
|
2568
|
+
localRoots: workspaceOnly ? void 0 : getAgentScopedMediaLocalRoots(params.config ?? {}, sessionAgentId),
|
|
2569
|
+
sandbox: connection.sandbox?.enabled && connection.sandbox.fsBridge ? {
|
|
2570
|
+
root: connection.sandbox.workspaceDir,
|
|
2571
|
+
bridge: connection.sandbox.fsBridge
|
|
2572
|
+
} : void 0
|
|
2573
|
+
};
|
|
2303
2574
|
const activeSteeringQueue = createCodexSteeringQueue({
|
|
2304
2575
|
client: resourceState.client,
|
|
2305
2576
|
threadId: resourceState.thread.threadId,
|
|
2306
2577
|
turnId: activeTurnId,
|
|
2307
2578
|
requestTimeoutMs: connection.appServer.requestTimeoutMs,
|
|
2308
2579
|
signal: runAbortController.signal,
|
|
2580
|
+
assertActive: assertSteeringActive,
|
|
2581
|
+
prepareMessage: async (text, options) => {
|
|
2582
|
+
const result = await detectAndLoadAgentHarnessPromptImages({
|
|
2583
|
+
...imageContext,
|
|
2584
|
+
prompt: text,
|
|
2585
|
+
existingImages: options.images,
|
|
2586
|
+
imageOrder: options.imageOrder,
|
|
2587
|
+
media: options.media,
|
|
2588
|
+
userTurnTranscriptRecorder: options.userTurnTranscriptRecorder
|
|
2589
|
+
});
|
|
2590
|
+
if (result.failedMediaCount) throw new Error(`failed to hydrate ${result.failedMediaCount} structured image attachment(s) for Codex steering`);
|
|
2591
|
+
return buildCodexUserInput(text, result.images);
|
|
2592
|
+
},
|
|
2309
2593
|
beforeConfirmConsumed: async (items) => {
|
|
2310
|
-
const
|
|
2311
|
-
if (
|
|
2594
|
+
const transcriptItems = items.filter((item) => item.isInboundUserMessage === true || item.userTurnTranscriptRecorder !== void 0);
|
|
2595
|
+
if (transcriptItems.length === 0) return;
|
|
2312
2596
|
await promptMirrorPromise;
|
|
2313
2597
|
const messages = activeProjector.buildSteeringTranscriptPrefix();
|
|
2314
|
-
if (params.sessionTarget && messages.length > 0)
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2598
|
+
if (params.sessionTarget && messages.length > 0) {
|
|
2599
|
+
await codexTranscriptMirrorRuntime.mirror({
|
|
2600
|
+
agentId: sessionAgentId,
|
|
2601
|
+
sessionKey: contextSessionKey,
|
|
2602
|
+
sessionId: params.sessionId,
|
|
2603
|
+
storePath: params.sessionTarget.storePath,
|
|
2604
|
+
cwd: effectiveCwd,
|
|
2605
|
+
messages,
|
|
2606
|
+
idempotencyScope: `codex-app-server:${resourceState.thread.threadId}`,
|
|
2607
|
+
runId: params.runId,
|
|
2608
|
+
runMirrorIdentityPrefix: `${activeTurnId}:`,
|
|
2609
|
+
config: params.config
|
|
2610
|
+
});
|
|
2611
|
+
activeProjector.markSteeringTranscriptPersisted();
|
|
2612
|
+
}
|
|
2613
|
+
for (const item of transcriptItems) {
|
|
2327
2614
|
const recorder = item.userTurnTranscriptRecorder;
|
|
2328
2615
|
if (!recorder) continue;
|
|
2329
2616
|
await recorder.persistApproved();
|
|
@@ -2333,7 +2620,8 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2333
2620
|
});
|
|
2334
2621
|
steeringQueueRef.current = activeSteeringQueue;
|
|
2335
2622
|
const claimPendingUserInputAnswer = async (text, optionsLocal) => {
|
|
2336
|
-
if (optionsLocal?.isInboundUserMessage !== true || optionsLocal
|
|
2623
|
+
if (optionsLocal?.isInboundUserMessage !== true || hasPromptImageInput(optionsLocal)) return false;
|
|
2624
|
+
assertSteeringActive();
|
|
2337
2625
|
return await claimPendingAgentQuestionAnswer({
|
|
2338
2626
|
sessionKey: params.sessionKey ?? params.sessionId,
|
|
2339
2627
|
text,
|
|
@@ -2347,14 +2635,17 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2347
2635
|
resolvedBy
|
|
2348
2636
|
});
|
|
2349
2637
|
const queueMessage = async (text, optionsLocal) => {
|
|
2350
|
-
const isInboundUserMessage = optionsLocal?.isInboundUserMessage === true;
|
|
2351
2638
|
if (await claimPendingUserInputAnswer(text, optionsLocal)) {
|
|
2352
2639
|
optionsLocal?.onQueueAccepted?.(true);
|
|
2353
2640
|
return;
|
|
2354
|
-
}
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2641
|
+
}
|
|
2642
|
+
if (optionsLocal?.isInboundUserMessage === true && hasPromptImageInput(optionsLocal)) {
|
|
2643
|
+
assertSteeringActive();
|
|
2644
|
+
try {
|
|
2645
|
+
await cancelPendingUserInput("image-reply");
|
|
2646
|
+
} catch (error) {
|
|
2647
|
+
embeddedAgentLog.warn("failed to cancel codex gateway question before image steering", { error });
|
|
2648
|
+
}
|
|
2358
2649
|
}
|
|
2359
2650
|
try {
|
|
2360
2651
|
await activeSteeringQueue.queue(text, optionsLocal);
|
|
@@ -2369,7 +2660,17 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2369
2660
|
const handle = {
|
|
2370
2661
|
kind: "embedded",
|
|
2371
2662
|
runId: params.runId,
|
|
2663
|
+
startedAtMs: params.startedAtMs,
|
|
2372
2664
|
toolAuthorityFingerprint: params.toolAuthorityFingerprint,
|
|
2665
|
+
permissionChangeOwner: params.permissionChange?.owner,
|
|
2666
|
+
applyPermissionMode: async (mode, revokeApprovals) => {
|
|
2667
|
+
if (!params.permissionChange || terminalState.terminalOutcomeFrozen || params.abortSignal?.aborted || !state.permissionChangeRestart && (state.completed || runAbortController.signal.aborted)) return false;
|
|
2668
|
+
const applied = params.permissionChange.request(mode);
|
|
2669
|
+
state.permissionChangeRestart ??= "requested";
|
|
2670
|
+
runAbortController.abort("permission-change");
|
|
2671
|
+
revokeApprovals();
|
|
2672
|
+
return await applied;
|
|
2673
|
+
},
|
|
2373
2674
|
claimPendingUserInputAnswer,
|
|
2374
2675
|
cancelPendingUserInput,
|
|
2375
2676
|
queueMessage,
|
|
@@ -2383,7 +2684,7 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2383
2684
|
isAbortable: () => !terminalState.terminalOutcomeFrozen || terminalState.sharedAbortAllowedAfterTerminalOutcome,
|
|
2384
2685
|
isCompacting: () => projectorRef.current?.isCompacting() ?? false,
|
|
2385
2686
|
supportsTranscriptCommitWait: true,
|
|
2386
|
-
supportsQueueMessageImages:
|
|
2687
|
+
supportsQueueMessageImages: params.model.input.includes("image"),
|
|
2387
2688
|
sourceReplyDeliveryMode: params.sourceReplyDeliveryMode,
|
|
2388
2689
|
taskSuggestionDeliveryMode: params.taskSuggestionDeliveryMode,
|
|
2389
2690
|
cancel: () => abortExplicitly("cancelled"),
|
|
@@ -2412,10 +2713,23 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2412
2713
|
})().finally(completeTurn);
|
|
2413
2714
|
return;
|
|
2414
2715
|
}
|
|
2415
|
-
interruptTurn(activeTurnId).
|
|
2716
|
+
state.abortCleanup = interruptTurn(activeTurnId).then(async (confirmed) => {
|
|
2717
|
+
if (!terminalState.explicitCancellationObserved && !state.permissionChangeRestart) return;
|
|
2718
|
+
if (!confirmed) throw new Error(state.permissionChangeRestart ? "Permission change could not confirm the previous Codex turn stopped." : "Codex cancellation could not confirm the turn stopped; background terminals may still be running.");
|
|
2719
|
+
await terminateCodexBackgroundTerminals(resourceState.client, resourceState.thread.threadId);
|
|
2720
|
+
if (state.permissionChangeRestart) state.permissionChangeRestart = "confirmed";
|
|
2721
|
+
});
|
|
2722
|
+
state.abortCleanup.then(completeTurn, (error) => {
|
|
2723
|
+
embeddedAgentLog.warn("codex app-server cancellation cleanup failed", { error });
|
|
2724
|
+
completeTurn();
|
|
2725
|
+
});
|
|
2416
2726
|
};
|
|
2417
2727
|
runAbortController.signal.addEventListener("abort", abortListener, { once: true });
|
|
2418
2728
|
if (runAbortController.signal.aborted) abortListener();
|
|
2729
|
+
else if (params.permissionChange && !params.permissionChange.applied()) {
|
|
2730
|
+
state.permissionChangeRestart = "requested";
|
|
2731
|
+
runAbortController.abort("permission-change");
|
|
2732
|
+
}
|
|
2419
2733
|
return {
|
|
2420
2734
|
activeTurnId,
|
|
2421
2735
|
activeProjector,
|
|
@@ -2437,6 +2751,8 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2437
2751
|
const { codexModelCallDiagnostics } = requestRuntime;
|
|
2438
2752
|
const { activeTurnId, abortListener, handle, freezeRunTerminalOutcome } = activeTurn;
|
|
2439
2753
|
prompt.context.attemptTools.scheduledAppAuthoritySourceRef.current = void 0;
|
|
2754
|
+
freezeRunTerminalOutcome();
|
|
2755
|
+
await state.abortCleanup.catch(() => void 0);
|
|
2440
2756
|
try {
|
|
2441
2757
|
steeringQueueRef.current?.cancel();
|
|
2442
2758
|
if (params.isFinalFallbackAttempt !== false) await maybeEmitFastModeAutoResetBestEffort();
|
|
@@ -2457,18 +2773,14 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2457
2773
|
aborted: runAbortController.signal.aborted && !state.clientClosedAbort
|
|
2458
2774
|
});
|
|
2459
2775
|
await runCleanupStep("codex-trajectory-flush", () => trajectoryRecorder?.flush());
|
|
2460
|
-
const retainLiveIncognitoThread = terminalState.turnSucceeded && isIncognitoSessionKey(params.sessionKey);
|
|
2776
|
+
const retainLiveIncognitoThread = (terminalState.turnSucceeded || state.permissionChangeRestart === "confirmed" && !params.abortSignal?.aborted) && isIncognitoSessionKey(params.sessionKey);
|
|
2461
2777
|
const retainedPersistentThread = terminalState.turnSucceeded && !isIncognitoSessionKey(params.sessionKey) && params.cleanupBundleMcpOnRunEnd !== true && resourceState.thread.liveThreadConfigFingerprint !== void 0 && resourceState.thread.clientId === resolveCodexAppServerClientInstanceId(resourceState.client) && resourceState.thread.preserveNativeModel !== true && resourceState.thread.connectionScope !== "supervision" && !resourceState.thread.ringZeroConfigFingerprint ? (await bindingStore.read(bindingIdentity))?.threadId === resourceState.thread.threadId && await bindingStore.withLease(bindingIdentity, async () => {
|
|
2462
2778
|
if ((await bindingStore.read(bindingIdentity))?.threadId !== resourceState.thread.threadId) return false;
|
|
2463
|
-
return await
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
await closeCodexStartupClientBestEffort(resourceState.client);
|
|
2469
|
-
throw new CodexAppServerUnsafeSubscriptionError(`Codex retained thread subscription could not be released: ${threadId}`);
|
|
2470
|
-
}
|
|
2471
|
-
}), resourceState.thread.liveThreadConfigFingerprint, connection.mutable.pluginAppServer.serviceTier);
|
|
2779
|
+
return await retainCodexAppServerBindingSubscription(resourceState.client, resourceState.thread.threadId, {
|
|
2780
|
+
release: resourceState.thread.liveThreadOwnership?.release,
|
|
2781
|
+
configFingerprint: resourceState.thread.liveThreadConfigFingerprint,
|
|
2782
|
+
serviceTier: connection.mutable.pluginAppServer.serviceTier
|
|
2783
|
+
});
|
|
2472
2784
|
}) : false;
|
|
2473
2785
|
const retainLiveThread = retainLiveIncognitoThread || retainedPersistentThread;
|
|
2474
2786
|
const bindingReleased = isIncognitoSessionKey(params.sessionKey) && !retainLiveIncognitoThread ? await bindingStore.mutate(bindingIdentity, {
|
|
@@ -2486,7 +2798,13 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2486
2798
|
} finally {
|
|
2487
2799
|
await runCleanupStep("codex-user-input-cancel", () => userInputBridgeRef.current?.cancelPending());
|
|
2488
2800
|
await runCleanupStep("codex-turn-watch-clear", () => turnWatches.clearAllTimers());
|
|
2801
|
+
await runCleanupStep("codex-dynamic-tool-cleanup", async () => {
|
|
2802
|
+
const cleanupReason = terminalState.turnSucceeded ? "completion" : state.timedOut ? "timeout" : runAbortController.signal.aborted ? "cancel" : "error";
|
|
2803
|
+
const cleanups = prompt.context.attemptTools.runCleanups.splice(0);
|
|
2804
|
+
await Promise.allSettled(cleanups.map(async (cleanup) => await cleanup(cleanupReason)));
|
|
2805
|
+
});
|
|
2489
2806
|
await runCleanupStep("codex-route-release", releaseCurrentRoute);
|
|
2807
|
+
await runCleanupStep("codex-transcript-checkpoint", () => activeTurn.activeProjector.transcriptCheckpoint.flush(true));
|
|
2490
2808
|
await runCleanupStep("codex-shared-client-release", releaseSharedClientLeaseAndRetireOneShotClient);
|
|
2491
2809
|
const nativeHookRelay = resourceState.nativeHookRelay;
|
|
2492
2810
|
resourceState.nativeHookRelay = void 0;
|
|
@@ -2505,12 +2823,12 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2505
2823
|
runAbortController.signal.removeEventListener("abort", abortListener);
|
|
2506
2824
|
});
|
|
2507
2825
|
await runCleanupStep("codex-steering-cancel", () => steeringQueueRef.current?.cancel());
|
|
2508
|
-
await runCleanupStep("codex-terminal-freeze", freezeRunTerminalOutcome);
|
|
2509
2826
|
await runCleanupStep("codex-reply-backend-detach", () => params.replyOperation?.detachBackend(handle));
|
|
2510
2827
|
await runCleanupStep("codex-active-run-clear", () => {
|
|
2511
2828
|
clearActiveEmbeddedRun(params.sessionId, handle, params.sessionKey, params.sessionFile);
|
|
2512
2829
|
});
|
|
2513
2830
|
}
|
|
2831
|
+
await state.abortCleanup;
|
|
2514
2832
|
}
|
|
2515
2833
|
//#endregion
|
|
2516
2834
|
//#region extensions/codex/src/app-server/workspace-dir-cache.ts
|
|
@@ -2579,125 +2897,26 @@ async function runCodexAgentEndHook(params, hookParams) {
|
|
|
2579
2897
|
runAgentEndSideEffects(sideEffectParams);
|
|
2580
2898
|
}
|
|
2581
2899
|
//#endregion
|
|
2582
|
-
//#region extensions/codex/src/app-server/session-permission-policy.ts
|
|
2583
|
-
function tupleForMode(mode, canUseAutoReview) {
|
|
2584
|
-
switch (mode) {
|
|
2585
|
-
case "read-only": return {
|
|
2586
|
-
sandbox: "read-only",
|
|
2587
|
-
approvalPolicy: "on-request",
|
|
2588
|
-
approvalsReviewer: "user"
|
|
2589
|
-
};
|
|
2590
|
-
case "guarded": return {
|
|
2591
|
-
sandbox: "workspace-write",
|
|
2592
|
-
approvalPolicy: "on-request",
|
|
2593
|
-
approvalsReviewer: "user"
|
|
2594
|
-
};
|
|
2595
|
-
case "workspace": return {
|
|
2596
|
-
sandbox: "workspace-write",
|
|
2597
|
-
approvalPolicy: "on-request",
|
|
2598
|
-
approvalsReviewer: canUseAutoReview ? "auto_review" : "user"
|
|
2599
|
-
};
|
|
2600
|
-
case "full": return {
|
|
2601
|
-
sandbox: "danger-full-access",
|
|
2602
|
-
approvalPolicy: "never",
|
|
2603
|
-
approvalsReviewer: "user"
|
|
2604
|
-
};
|
|
2605
|
-
}
|
|
2606
|
-
return mode;
|
|
2607
|
-
}
|
|
2608
|
-
function requirementsAllowTuple(tuple, allowed) {
|
|
2609
|
-
return (allowed.sandboxes === void 0 || allowed.sandboxes.has(tuple.sandbox)) && (allowed.approvalPolicies === void 0 || allowed.approvalPolicies.has(tuple.approvalPolicy)) && (allowed.reviewers === void 0 || allowed.reviewers.has(tuple.approvalsReviewer));
|
|
2610
|
-
}
|
|
2611
|
-
function tightenTupleForExecMode(tuple, execMode) {
|
|
2612
|
-
switch (execMode) {
|
|
2613
|
-
case "deny":
|
|
2614
|
-
case "allowlist": return {
|
|
2615
|
-
sandbox: "read-only",
|
|
2616
|
-
approvalPolicy: "on-request",
|
|
2617
|
-
approvalsReviewer: "user"
|
|
2618
|
-
};
|
|
2619
|
-
case "ask": return {
|
|
2620
|
-
...tuple,
|
|
2621
|
-
approvalPolicy: "on-request",
|
|
2622
|
-
approvalsReviewer: "user"
|
|
2623
|
-
};
|
|
2624
|
-
case "auto":
|
|
2625
|
-
case "full":
|
|
2626
|
-
case void 0: return tuple;
|
|
2627
|
-
}
|
|
2628
|
-
return execMode;
|
|
2629
|
-
}
|
|
2630
|
-
function clampSessionPermissionTuple(params) {
|
|
2631
|
-
if (!params.requirementsToml) return params.requested;
|
|
2632
|
-
const allowed = {
|
|
2633
|
-
sandboxes: parseAllowedSandboxModesFromCodexRequirements(params.requirementsToml, params.hostName ?? hostname()),
|
|
2634
|
-
approvalPolicies: parseAllowedApprovalPoliciesFromCodexRequirements(params.requirementsToml),
|
|
2635
|
-
reviewers: parseAllowedApprovalsReviewersFromCodexRequirements(params.requirementsToml)
|
|
2636
|
-
};
|
|
2637
|
-
if (requirementsAllowTuple(params.requested, allowed)) return params.requested;
|
|
2638
|
-
const userReviewRequired = params.mode === "read-only" || params.mode === "guarded" || params.mode === "workspace" && !params.canUseAutoReview;
|
|
2639
|
-
return {
|
|
2640
|
-
sandbox: selectGuardianSandbox(allowed.sandboxes),
|
|
2641
|
-
approvalPolicy: selectGuardianApprovalPolicy(allowed.approvalPolicies, userReviewRequired ? "ask" : "auto"),
|
|
2642
|
-
approvalsReviewer: userReviewRequired ? selectUserApprovalsReviewer(allowed.reviewers) : selectGuardianApprovalsReviewer(allowed.reviewers, "auto")
|
|
2643
|
-
};
|
|
2644
|
-
}
|
|
2645
|
-
/** Applies one complete session-mode tuple without mixing requirements-clamped fields. */
|
|
2646
|
-
function applyCodexSessionPermissionPolicy(params) {
|
|
2647
|
-
if (!params.permissionMode) return params.appServer;
|
|
2648
|
-
const sessionRoot = params.sessionRoot?.trim();
|
|
2649
|
-
if (!sessionRoot) throw new Error("Codex session permission mode requires a recorded session root");
|
|
2650
|
-
if (params.policyLocked) return {
|
|
2651
|
-
...params.appServer,
|
|
2652
|
-
sessionRoot
|
|
2653
|
-
};
|
|
2654
|
-
const requested = tightenTupleForExecMode(tupleForMode(params.permissionMode, params.canUseAutoReview), params.execMode);
|
|
2655
|
-
const tuple = params.appServer.start.transport === "stdio" ? clampSessionPermissionTuple({
|
|
2656
|
-
mode: params.permissionMode,
|
|
2657
|
-
requested,
|
|
2658
|
-
requirementsToml: params.requirementsToml,
|
|
2659
|
-
hostName: params.hostName,
|
|
2660
|
-
canUseAutoReview: params.canUseAutoReview
|
|
2661
|
-
}) : requested;
|
|
2662
|
-
const networkProxy = params.appServer.networkProxy ? resolveCodexAppServerNetworkProxy(params.pluginConfig.appServer?.networkProxy, tuple.sandbox).networkProxy : void 0;
|
|
2663
|
-
const resolved = {
|
|
2664
|
-
...params.appServer,
|
|
2665
|
-
...tuple,
|
|
2666
|
-
sessionRoot
|
|
2667
|
-
};
|
|
2668
|
-
if (networkProxy) resolved.networkProxy = networkProxy;
|
|
2669
|
-
else delete resolved.networkProxy;
|
|
2670
|
-
return resolved;
|
|
2671
|
-
}
|
|
2672
|
-
/** Keeps relative execution inside the prepared root without filesystem rediscovery. */
|
|
2673
|
-
function resolveCodexSessionPermissionCwd(params) {
|
|
2674
|
-
if (!params.permissionMode) return params.requestedCwd ?? params.fallbackCwd;
|
|
2675
|
-
const sessionRoot = params.sessionRoot?.trim();
|
|
2676
|
-
if (!sessionRoot) throw new Error("Codex session permission mode requires a recorded session root");
|
|
2677
|
-
const requestedCwd = params.requestedCwd?.trim();
|
|
2678
|
-
return requestedCwd && isPathInside(sessionRoot, requestedCwd) ? requestedCwd : sessionRoot;
|
|
2679
|
-
}
|
|
2680
|
-
//#endregion
|
|
2681
2900
|
//#region extensions/codex/src/app-server/startup-binding.ts
|
|
2682
2901
|
const CODEX_APP_SERVER_NATIVE_THREAD_FALLBACK_MAX_TOKENS = 3e5;
|
|
2683
2902
|
const CODEX_APP_SERVER_NATIVE_THREAD_DEFAULT_RESERVE_TOKENS = 2e4;
|
|
2684
2903
|
const CODEX_APP_SERVER_NATIVE_THREAD_MIN_PROMPT_BUDGET_TOKENS = 8e3;
|
|
2685
2904
|
const CODEX_APP_SERVER_NATIVE_THREAD_MIN_PROMPT_BUDGET_RATIO = .5;
|
|
2686
|
-
const CODEX_APP_SERVER_ROLLOUT_TAIL_READ_BYTES =
|
|
2905
|
+
const CODEX_APP_SERVER_ROLLOUT_TAIL_READ_BYTES = 65536;
|
|
2687
2906
|
const CODEX_APP_SERVER_BYTE_UNITS = {
|
|
2688
2907
|
b: 1,
|
|
2689
2908
|
k: 1024,
|
|
2690
2909
|
kb: 1024,
|
|
2691
2910
|
kib: 1024,
|
|
2692
|
-
m:
|
|
2693
|
-
mb:
|
|
2694
|
-
mib:
|
|
2695
|
-
g:
|
|
2696
|
-
gb:
|
|
2697
|
-
gib:
|
|
2698
|
-
t:
|
|
2699
|
-
tb:
|
|
2700
|
-
tib:
|
|
2911
|
+
m: 1048576,
|
|
2912
|
+
mb: 1048576,
|
|
2913
|
+
mib: 1048576,
|
|
2914
|
+
g: 1073741824,
|
|
2915
|
+
gb: 1073741824,
|
|
2916
|
+
gib: 1073741824,
|
|
2917
|
+
t: 1099511627776,
|
|
2918
|
+
tb: 1099511627776,
|
|
2919
|
+
tib: 1099511627776
|
|
2701
2920
|
};
|
|
2702
2921
|
const codexSessionRecordCache = /* @__PURE__ */ new Map();
|
|
2703
2922
|
function parseCodexAppServerByteLimit(value) {
|
|
@@ -2994,11 +3213,12 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2994
3213
|
const pluginConfig = readCodexPluginConfig(options.pluginConfig);
|
|
2995
3214
|
const requirementsToml = readCodexRequirementsToml({});
|
|
2996
3215
|
const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig });
|
|
2997
|
-
const { sessionAgentId } =
|
|
3216
|
+
const { sessionAgentId } = resolveSessionAgentIdsStrict({
|
|
2998
3217
|
sessionKey: params.sessionKey,
|
|
2999
3218
|
config: params.config,
|
|
3000
3219
|
agentId: params.agentId
|
|
3001
3220
|
});
|
|
3221
|
+
const policyAgentId = params.sandboxAgentId ?? sessionAgentId;
|
|
3002
3222
|
preDynamicStartupStages.mark("config");
|
|
3003
3223
|
const resolvedWorkspace = resolveUserPath(params.workspaceDir);
|
|
3004
3224
|
await ensureCodexWorkspaceDirOnce(resolvedWorkspace);
|
|
@@ -3007,6 +3227,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3007
3227
|
const contextSessionKey = params.sessionKey?.trim() || sandboxSessionKey;
|
|
3008
3228
|
const sandbox = params.sandbox !== void 0 ? params.sandbox : await resolveSandboxContext({
|
|
3009
3229
|
config: params.config,
|
|
3230
|
+
agentId: params.sandboxAgentId,
|
|
3010
3231
|
sessionKey: sandboxSessionKey,
|
|
3011
3232
|
workspaceDir: resolvedWorkspace
|
|
3012
3233
|
});
|
|
@@ -3017,18 +3238,24 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3017
3238
|
execOverrides: params.execOverrides,
|
|
3018
3239
|
approvals: params.permissionMode === "full" ? void 0 : loadExecApprovals(),
|
|
3019
3240
|
config: params.config,
|
|
3020
|
-
agentId:
|
|
3241
|
+
agentId: policyAgentId
|
|
3021
3242
|
});
|
|
3022
3243
|
const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId);
|
|
3023
3244
|
const preparedEnvironment = params.hostCapabilities.preparedEnvironment?.();
|
|
3024
3245
|
const remoteExec = isCodexRemoteExecPlacementSandbox(sandbox);
|
|
3246
|
+
const assertLocalTargetSupported = (unsupported) => {
|
|
3247
|
+
if (preparedEnvironment?.localProcessEnv && unsupported) throw new Error("This runtime cannot target the diagnosed local installation. Use the saved prompt with a suggested external or manual handoff on this machine.");
|
|
3248
|
+
};
|
|
3249
|
+
assertLocalTargetSupported(sandbox?.enabled === true || remoteExec);
|
|
3025
3250
|
const preparedShellEnvironment = preparedEnvironment ? {
|
|
3026
3251
|
...preparedEnvironment.credentialScrubEnv,
|
|
3027
|
-
...!remoteExec ? preparedEnvironment.localIdentityEnv : void 0
|
|
3252
|
+
...!remoteExec ? preparedEnvironment.localIdentityEnv : void 0,
|
|
3253
|
+
...preparedEnvironment.localProcessEnv
|
|
3028
3254
|
} : void 0;
|
|
3029
3255
|
const shellEnvironment = preparedShellEnvironment && Object.keys(preparedShellEnvironment).length > 0 ? preparedShellEnvironment : void 0;
|
|
3030
|
-
const disableLoginShell = remoteExec || preparedEnvironment?.managedLocalIdentity === true || preparedEnvironment !== void 0 && Object.keys(preparedEnvironment.credentialScrubEnv).length > 0;
|
|
3256
|
+
const disableLoginShell = remoteExec || preparedEnvironment?.localProcessEnv !== void 0 || preparedEnvironment?.managedLocalIdentity === true || preparedEnvironment !== void 0 && Object.keys(preparedEnvironment.credentialScrubEnv).length > 0;
|
|
3031
3257
|
const withPreparedProcessEnv = (appServer) => {
|
|
3258
|
+
assertLocalTargetSupported(appServer.start.transport === "websocket" || Boolean(appServer.remoteWorkspaceRoot));
|
|
3032
3259
|
return shellEnvironment ? {
|
|
3033
3260
|
...appServer,
|
|
3034
3261
|
start: {
|
|
@@ -3150,6 +3377,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3150
3377
|
const sessionPermissionCwd = resolveCodexSessionPermissionCwd({
|
|
3151
3378
|
permissionMode: params.permissionMode,
|
|
3152
3379
|
sessionRoot: params.sessionRoot,
|
|
3380
|
+
defaultRoot: effectiveWorkspace,
|
|
3153
3381
|
requestedCwd,
|
|
3154
3382
|
fallbackCwd: effectiveWorkspace
|
|
3155
3383
|
});
|
|
@@ -3160,14 +3388,20 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3160
3388
|
appServer,
|
|
3161
3389
|
permissionMode: params.permissionMode,
|
|
3162
3390
|
sessionRoot: params.sessionRoot,
|
|
3391
|
+
defaultRoot: effectiveWorkspace,
|
|
3163
3392
|
pluginConfig,
|
|
3164
3393
|
canUseAutoReview: canUseCodexModelBackedApprovalsReviewerForModel({
|
|
3165
3394
|
modelProvider: selection.modelProvider,
|
|
3166
3395
|
model: selection.model,
|
|
3167
3396
|
config: params.config,
|
|
3168
|
-
env:
|
|
3397
|
+
env: {
|
|
3398
|
+
...process.env,
|
|
3399
|
+
...appServer.start.env,
|
|
3400
|
+
...shellEnvironment
|
|
3401
|
+
},
|
|
3169
3402
|
agentDir,
|
|
3170
|
-
homeScope: appServer.start.homeScope
|
|
3403
|
+
homeScope: appServer.start.homeScope,
|
|
3404
|
+
codexArgs: appServer.start.args
|
|
3171
3405
|
}),
|
|
3172
3406
|
requirementsToml,
|
|
3173
3407
|
policyLocked: startupBinding?.connectionScope === "supervision",
|
|
@@ -3180,7 +3414,11 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3180
3414
|
provider: selection.modelProvider,
|
|
3181
3415
|
model: selection.model,
|
|
3182
3416
|
config: params.config,
|
|
3183
|
-
env:
|
|
3417
|
+
env: {
|
|
3418
|
+
...process.env,
|
|
3419
|
+
...session.start.env,
|
|
3420
|
+
...shellEnvironment
|
|
3421
|
+
},
|
|
3184
3422
|
agentDir
|
|
3185
3423
|
});
|
|
3186
3424
|
return {
|
|
@@ -3244,6 +3482,17 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3244
3482
|
resolvedAppServer = resolveFinalAppServer(configuredAppServer, reviewerPolicyContext);
|
|
3245
3483
|
appServer = resolvedAppServer.appServer;
|
|
3246
3484
|
}
|
|
3485
|
+
const sessionPermissionPolicy = resolveCodexEffectiveSessionPermissionPolicy({
|
|
3486
|
+
appServer,
|
|
3487
|
+
permissionMode: params.permissionMode,
|
|
3488
|
+
sessionRoot: params.sessionRoot,
|
|
3489
|
+
defaultRoot: effectiveWorkspace
|
|
3490
|
+
});
|
|
3491
|
+
if (sessionPermissionPolicy) {
|
|
3492
|
+
params.permissionMode = sessionPermissionPolicy.mode;
|
|
3493
|
+
params.sessionRoot = sessionPermissionPolicy.root;
|
|
3494
|
+
(params.execOverrides ??= {}).mode = sessionPermissionPolicy.execMode;
|
|
3495
|
+
}
|
|
3247
3496
|
const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
|
|
3248
3497
|
configuredEvents: options.nativeHookRelay?.events,
|
|
3249
3498
|
appServer
|
|
@@ -3271,6 +3520,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3271
3520
|
pluginConfig,
|
|
3272
3521
|
computerUseConfig,
|
|
3273
3522
|
sessionAgentId,
|
|
3523
|
+
policyAgentId,
|
|
3274
3524
|
resolvedWorkspace,
|
|
3275
3525
|
sandboxSessionKey,
|
|
3276
3526
|
contextSessionKey,
|
|
@@ -3290,6 +3540,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3290
3540
|
effectiveWorkspace,
|
|
3291
3541
|
effectiveCwd,
|
|
3292
3542
|
appServer,
|
|
3543
|
+
sessionPermissionPolicy,
|
|
3293
3544
|
nativeHookRelayEvents,
|
|
3294
3545
|
runAbortController,
|
|
3295
3546
|
terminalState,
|
|
@@ -3327,7 +3578,7 @@ const CODEX_BOOTSTRAP_CONTEXT_ORDER = /* @__PURE__ */ new Map([
|
|
|
3327
3578
|
/** Reads mirrored Codex session history for harness hooks. */
|
|
3328
3579
|
async function readMirroredSessionHistoryMessages(params) {
|
|
3329
3580
|
const { admission, ...target } = params;
|
|
3330
|
-
const messages = await readCodexMirroredSessionHistoryMessages(target, admission);
|
|
3581
|
+
const messages = await readCodexMirroredSessionHistoryMessages(target, admission, "model-context");
|
|
3331
3582
|
if (!messages) embeddedAgentLog.warn("failed to read mirrored session history for codex harness hooks", { sessionFile: params.sessionFile });
|
|
3332
3583
|
return messages;
|
|
3333
3584
|
}
|
|
@@ -3813,8 +4064,9 @@ async function renderCodexWorkspaceMemoryCollaborationInstructions(params) {
|
|
|
3813
4064
|
return sections.length > 0 ? sections.join("\n\n") : void 0;
|
|
3814
4065
|
}
|
|
3815
4066
|
async function renderCodexMemoryRecallInstructions(params) {
|
|
4067
|
+
const availableTools = new Set(params.toolNames);
|
|
3816
4068
|
const memoryPrompt = await prepareMemorySystemPromptAddition({
|
|
3817
|
-
availableTools
|
|
4069
|
+
availableTools,
|
|
3818
4070
|
citationsMode: params.citationsMode,
|
|
3819
4071
|
agentId: params.agentId,
|
|
3820
4072
|
agentSessionKey: params.agentSessionKey,
|
|
@@ -4011,7 +4263,7 @@ function buildCodexAppServerTimeoutDiagnostics(params) {
|
|
|
4011
4263
|
//#region extensions/codex/src/app-server/run-attempt-context.ts
|
|
4012
4264
|
async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
4013
4265
|
const { connection, runtimeParams, activeSessionId, activeSessionFile, buildActiveRunAttemptParams, effectiveContextWindowInfo, effectiveContextTokenBudget, effectiveRuntimeProviderId, effectiveRuntimeModelId, hookChannelId } = runtime;
|
|
4014
|
-
const { params, sessionAgentId, contextSessionKey, activeContextEngine, initialStartupBindingHadInactiveThreadBootstrap,
|
|
4266
|
+
const { params, sessionAgentId, contextSessionKey, activeContextEngine, initialStartupBindingHadInactiveThreadBootstrap, effectiveWorkspace, effectiveCwd, agentDir, usesSupervisionConnection, resolvedWorkspace, initialInactiveThreadBootstrapBindingForcedFreshStart, sandbox } = connection;
|
|
4015
4267
|
const { toolBridge } = attemptTools;
|
|
4016
4268
|
const activeTranscriptTarget = {
|
|
4017
4269
|
agentId: sessionAgentId,
|
|
@@ -4037,7 +4289,7 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
4037
4289
|
const hookContext = {
|
|
4038
4290
|
runId: params.runId,
|
|
4039
4291
|
agentId: sessionAgentId,
|
|
4040
|
-
sessionKey:
|
|
4292
|
+
sessionKey: contextSessionKey,
|
|
4041
4293
|
sessionId: params.sessionId,
|
|
4042
4294
|
workspaceDir: params.workspaceDir,
|
|
4043
4295
|
messageProvider: params.messageProvider ?? void 0,
|
|
@@ -4345,101 +4597,17 @@ function isInvalidCodexImagePayloadError(message) {
|
|
|
4345
4597
|
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);
|
|
4346
4598
|
}
|
|
4347
4599
|
//#endregion
|
|
4348
|
-
//#region extensions/codex/src/app-server/settled-turn-context.ts
|
|
4349
|
-
function collectUniqueMessageIdentities(messages) {
|
|
4350
|
-
const identities = /* @__PURE__ */ new Map();
|
|
4351
|
-
for (const [index, message] of messages.entries()) {
|
|
4352
|
-
const identity = readMirrorIdentity(message);
|
|
4353
|
-
if (!identity) continue;
|
|
4354
|
-
if (identities.has(identity)) return;
|
|
4355
|
-
identities.set(identity, index);
|
|
4356
|
-
}
|
|
4357
|
-
return identities;
|
|
4358
|
-
}
|
|
4359
|
-
function adoptPersistedHostPrompt(params) {
|
|
4360
|
-
const promptIdentity = `${params.turnId}:prompt`;
|
|
4361
|
-
if (params.mirroredMessages.some((message) => readMirrorIdentity(message) === promptIdentity)) return params;
|
|
4362
|
-
const sourcePrompt = params.settledMessages[0];
|
|
4363
|
-
const sourceKey = sourcePrompt?.idempotencyKey;
|
|
4364
|
-
if (sourcePrompt?.role !== "user" || readMirrorIdentity(sourcePrompt) !== promptIdentity || typeof sourceKey !== "string" || sourceKey.trim().length === 0) return params;
|
|
4365
|
-
const matches = params.historyMessages.flatMap((message, index) => message.role === "user" && message.idempotencyKey === sourceKey ? [{
|
|
4366
|
-
index,
|
|
4367
|
-
message
|
|
4368
|
-
}] : []);
|
|
4369
|
-
const persistedPrompt = matches.length === 1 ? matches[0] : void 0;
|
|
4370
|
-
const persistedMetadata = persistedPrompt?.message;
|
|
4371
|
-
if (!persistedPrompt || readMirrorIdentity(persistedPrompt.message) !== void 0 || readCodexMirrorSourceFingerprint(persistedPrompt.message) !== void 0 || persistedMetadata?.["__openclaw"]?.mirrorOrigin === "codex-app-server") return params;
|
|
4372
|
-
const sourceUpstreamText = readUpstreamUserText(sourcePrompt);
|
|
4373
|
-
const persistedUpstreamText = readUpstreamUserText(persistedPrompt.message);
|
|
4374
|
-
if (persistedUpstreamText !== void 0 && persistedUpstreamText !== sourceUpstreamText) return params;
|
|
4375
|
-
let logicalPrompt = attachCodexMirrorIdentity(persistedPrompt.message, promptIdentity);
|
|
4376
|
-
if (sourceUpstreamText !== void 0) logicalPrompt = attachUpstreamUserText(logicalPrompt, sourceUpstreamText);
|
|
4377
|
-
if (serializeCodexMirrorSourceEvidence(logicalPrompt) !== serializeCodexMirrorSourceEvidence(sourcePrompt)) return params;
|
|
4378
|
-
const historyMessages = [...params.historyMessages];
|
|
4379
|
-
historyMessages[persistedPrompt.index] = logicalPrompt;
|
|
4380
|
-
return {
|
|
4381
|
-
historyMessages,
|
|
4382
|
-
mirroredMessages: [logicalPrompt, ...params.mirroredMessages]
|
|
4383
|
-
};
|
|
4384
|
-
}
|
|
4385
|
-
/** Freezes one complete active transcript branch through the settled tool-result boundary. */
|
|
4386
|
-
function buildCodexSettledTurnFinalizationContext(params) {
|
|
4387
|
-
const { historyMessages, mirroredMessages } = adoptPersistedHostPrompt(params);
|
|
4388
|
-
const boundaryMessage = params.settledMessages.findLast((message) => message.role === "toolResult");
|
|
4389
|
-
const boundaryIdentity = boundaryMessage ? readMirrorIdentity(boundaryMessage) : void 0;
|
|
4390
|
-
if (!boundaryMessage || !boundaryIdentity || !boundaryIdentity.startsWith(`${params.turnId}:tool:`)) return;
|
|
4391
|
-
const settledBoundaryIndex = params.settledMessages.indexOf(boundaryMessage);
|
|
4392
|
-
const requiredIdentities = params.settledMessages.slice(0, settledBoundaryIndex + 1).map(readMirrorIdentity);
|
|
4393
|
-
if (requiredIdentities.length === 0 || requiredIdentities.some((identity) => !identity) || new Set(requiredIdentities).size !== requiredIdentities.length || !requiredIdentities.includes(`${params.turnId}:prompt`)) return;
|
|
4394
|
-
const historyIdentities = collectUniqueMessageIdentities(historyMessages);
|
|
4395
|
-
const mirroredIdentities = collectUniqueMessageIdentities(mirroredMessages);
|
|
4396
|
-
if (!historyIdentities || !mirroredIdentities) return;
|
|
4397
|
-
const mirroredBoundaryIndex = mirroredIdentities.get(boundaryIdentity);
|
|
4398
|
-
if (mirroredBoundaryIndex === void 0) return;
|
|
4399
|
-
const mirroredThroughBoundary = mirroredMessages.slice(0, mirroredBoundaryIndex + 1);
|
|
4400
|
-
if (mirroredThroughBoundary.length !== requiredIdentities.length || mirroredThroughBoundary.some((message, index) => readMirrorIdentity(message) !== requiredIdentities[index])) return;
|
|
4401
|
-
const historyBoundaryIndex = historyIdentities.get(boundaryIdentity);
|
|
4402
|
-
if (historyBoundaryIndex === void 0) return;
|
|
4403
|
-
let previousHistoryIndex = -1;
|
|
4404
|
-
for (const mirroredMessage of mirroredThroughBoundary) {
|
|
4405
|
-
const identity = readMirrorIdentity(mirroredMessage);
|
|
4406
|
-
const historyIndex = identity ? historyIdentities.get(identity) : void 0;
|
|
4407
|
-
const historyMessage = historyIndex === void 0 ? void 0 : historyMessages[historyIndex];
|
|
4408
|
-
if (historyIndex === void 0 || historyIndex <= previousHistoryIndex || historyIndex > historyBoundaryIndex || !historyMessage || serializeCodexMirrorSourceEvidence(historyMessage) !== serializeCodexMirrorSourceEvidence(mirroredMessage)) return;
|
|
4409
|
-
previousHistoryIndex = historyIndex;
|
|
4410
|
-
}
|
|
4411
|
-
return {
|
|
4412
|
-
source: "openclaw-transcript",
|
|
4413
|
-
messages: Object.freeze(structuredClone(params.historyMessages.slice(0, historyBoundaryIndex + 1)))
|
|
4414
|
-
};
|
|
4415
|
-
}
|
|
4416
|
-
/** Reads and freezes the current active transcript branch after mirroring has settled. */
|
|
4417
|
-
async function captureCodexSettledTurnFinalizationContext(params) {
|
|
4418
|
-
try {
|
|
4419
|
-
const historyMessages = await readCodexMirroredSessionHistoryMessages(params);
|
|
4420
|
-
if (!historyMessages) return;
|
|
4421
|
-
return buildCodexSettledTurnFinalizationContext({
|
|
4422
|
-
historyMessages,
|
|
4423
|
-
mirroredMessages: params.mirroredMessages,
|
|
4424
|
-
settledMessages: params.settledMessages,
|
|
4425
|
-
turnId: params.turnId
|
|
4426
|
-
});
|
|
4427
|
-
} catch (error) {
|
|
4428
|
-
embeddedAgentLog.warn("codex settled-turn finalization context capture failed", {
|
|
4429
|
-
error: formatErrorMessage(error),
|
|
4430
|
-
turnId: params.turnId
|
|
4431
|
-
});
|
|
4432
|
-
return;
|
|
4433
|
-
}
|
|
4434
|
-
}
|
|
4435
|
-
//#endregion
|
|
4436
4600
|
//#region extensions/codex/src/app-server/trajectory.ts
|
|
4437
4601
|
/** Creates a trajectory recorder when the host exposes its capture capability. */
|
|
4438
4602
|
function createCodexTrajectoryRecorder(params) {
|
|
4439
4603
|
if (!params.trajectory) return null;
|
|
4440
4604
|
const trajectory = params.trajectory;
|
|
4441
4605
|
return {
|
|
4442
|
-
recordEvent:
|
|
4606
|
+
recordEvent: (type, data) => {
|
|
4607
|
+
try {
|
|
4608
|
+
trajectory.recordEvent(type, data);
|
|
4609
|
+
} catch {}
|
|
4610
|
+
},
|
|
4443
4611
|
flush: trajectory.flush
|
|
4444
4612
|
};
|
|
4445
4613
|
}
|
|
@@ -4501,7 +4669,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4501
4669
|
const { hookContextWindowFields, hookRunner } = context;
|
|
4502
4670
|
const { connection, preparedAuthBinding } = runtime;
|
|
4503
4671
|
const { effectiveRuntimeProviderId, effectiveRuntimeModelId } = runtime;
|
|
4504
|
-
const { params, terminalState, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, usesSupervisionConnection, sessionAgentId, contextSessionKey, effectiveCwd, attemptStartedAt, startupAuthProfileId } = connection;
|
|
4672
|
+
const { params, terminalState, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, usesSupervisionConnection, sessionAgentId, contextSessionKey, effectiveCwd, agentDir, attemptStartedAt, startupAuthProfileId } = connection;
|
|
4505
4673
|
const { toolBridge, toolState } = attemptTools;
|
|
4506
4674
|
const { state, completion, pendingOpenClawDynamicToolCompletionIds, activeTurnItemIds, activeCompletionBlockerItemIds, activeFinalizationHookRunIds, turnWatches } = turnRuntime;
|
|
4507
4675
|
const { emitLifecycleTerminal, buildLifecycleTerminalMeta } = lifecycle;
|
|
@@ -4509,7 +4677,20 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4509
4677
|
const { codexModelCallDiagnostics } = requestRuntime;
|
|
4510
4678
|
const { activeTurnId, activeProjector, streamState, freezeRunTerminalOutcome, notifyUserMessagePersisted } = activeTurn;
|
|
4511
4679
|
await completion;
|
|
4512
|
-
await
|
|
4680
|
+
await state.abortCleanup;
|
|
4681
|
+
const drain = drainNotificationQueue();
|
|
4682
|
+
const abortGraceElapsed = createDeferred();
|
|
4683
|
+
let abortGraceTimer;
|
|
4684
|
+
const abortListener = addAbortListener(runAbortController.signal, () => {
|
|
4685
|
+
abortGraceTimer = setTimeout(() => abortGraceElapsed.resolve(), TURN_FINALIZE_DRAIN_ABORT_GRACE_MS);
|
|
4686
|
+
abortGraceTimer.unref?.();
|
|
4687
|
+
});
|
|
4688
|
+
try {
|
|
4689
|
+
await Promise.race([drain, abortGraceElapsed.promise]);
|
|
4690
|
+
} finally {
|
|
4691
|
+
abortListener[Symbol.dispose]();
|
|
4692
|
+
clearTimeout(abortGraceTimer);
|
|
4693
|
+
}
|
|
4513
4694
|
const hasQuiescentCompletedAssistant = activeProjector.hasCompletedTerminalAssistantText() && state.activeAppServerTurnRequests === 0 && activeTurnItemIds.size === 0 && activeCompletionBlockerItemIds.size === 0 && pendingOpenClawDynamicToolCompletionIds.size === 0 && activeFinalizationHookRunIds.size === 0 && state.unsettledFinalizationHookCount === 0 && state.rejectedFinalizationHookAssistant === void 0;
|
|
4514
4695
|
const hasRecoverableCompletedAssistant = !turnWatches.isCompletionIdleWatchPinnedByTerminalError() && turnWatches.isAssistantCompletionIdleWatchArmed() && hasQuiescentCompletedAssistant;
|
|
4515
4696
|
const recoveredTurnWatchTimeout = state.turnCompletionIdleTimedOut && !terminalState.explicitCancellationObserved && hasRecoverableCompletedAssistant && activeProjector.recoverCompletedTerminalAssistantAfterTurnWatchTimeout();
|
|
@@ -4638,14 +4819,13 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4638
4819
|
turnId: activeTurnId
|
|
4639
4820
|
});
|
|
4640
4821
|
const { assistantTranscriptOwned, assistantTranscriptIdempotencyKey, terminalAnchor } = mirrorOutcome;
|
|
4641
|
-
const
|
|
4642
|
-
const settledTurnFinalizationContext = shouldCaptureSettledTurnFinalizationContext ? await captureCodexSettledTurnFinalizationContext({
|
|
4822
|
+
const settledTurnFinalizationContext = result.assistantTexts.every((text) => !text.trim()) && result.messagesSnapshot.some((message) => message.role === "toolResult") && (!finalPromptError || activeProjector.settledTurnFailureFinalizationAllowed) ? await captureCodexSettledTurnFinalizationContext({
|
|
4643
4823
|
...activeTranscriptTarget,
|
|
4644
4824
|
mirroredMessages: mirrorOutcome.mirroredMessages,
|
|
4645
4825
|
settledMessages: result.messagesSnapshot,
|
|
4646
4826
|
turnId: activeTurnId
|
|
4647
|
-
}) : void 0;
|
|
4648
|
-
if (
|
|
4827
|
+
}) ?? Object.freeze({ source: "unavailable" }) : void 0;
|
|
4828
|
+
if (settledTurnFinalizationContext?.source === "unavailable") embeddedAgentLog.warn("codex settled-turn finalization context is unavailable", {
|
|
4649
4829
|
threadId: resourceState.thread.threadId,
|
|
4650
4830
|
turnId: activeTurnId
|
|
4651
4831
|
});
|
|
@@ -4680,20 +4860,11 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4680
4860
|
modelIterations: result.modelIterations ?? 0,
|
|
4681
4861
|
skillWorkshopAvailable: flattenCodexDynamicToolFunctions(attemptTools.toolBridge.availableSpecs).some((tool) => tool.name === "skill_workshop"),
|
|
4682
4862
|
compacted: (result.compactionCount ?? 0) > 0,
|
|
4683
|
-
messageChannel: params.messageChannel,
|
|
4684
|
-
messageProvider: params.messageProvider,
|
|
4685
|
-
chatType: params.chatType,
|
|
4686
|
-
agentAccountId: params.agentAccountId,
|
|
4687
|
-
groupId: params.groupId,
|
|
4688
|
-
groupChannel: params.groupChannel,
|
|
4689
|
-
groupSpace: params.groupSpace,
|
|
4690
|
-
memberRoleIds: params.memberRoleIds,
|
|
4691
|
-
spawnedBy: params.spawnedBy,
|
|
4692
4863
|
senderId: params.senderId ?? void 0,
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4864
|
+
foregroundPromptContext: buildEmbeddedForegroundPromptContext({
|
|
4865
|
+
...params,
|
|
4866
|
+
agentId: sessionAgentId
|
|
4867
|
+
}, agentDir)
|
|
4697
4868
|
},
|
|
4698
4869
|
hookRunner
|
|
4699
4870
|
});
|
|
@@ -4757,8 +4928,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4757
4928
|
yielded: toolState.yieldDetected
|
|
4758
4929
|
})
|
|
4759
4930
|
});
|
|
4760
|
-
const finalizedResult = {
|
|
4761
|
-
...result,
|
|
4931
|
+
const finalizedResult = Object.assign(result, {
|
|
4762
4932
|
...toolState.yieldAcknowledgment ? { yieldAcknowledgment: toolState.yieldAcknowledgment } : {},
|
|
4763
4933
|
terminal: attemptTerminal.normalize({
|
|
4764
4934
|
timedOut: effectiveTimedOut,
|
|
@@ -4776,7 +4946,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4776
4946
|
...resourceState.runtimeContinuationStarted ? { runtimeContinuationStarted: true } : {},
|
|
4777
4947
|
...!finalAborted && !effectiveTimedOut && !finalPromptError && preparedAuthBinding ? { authBindingFingerprint: preparedAuthBinding.fingerprint } : {},
|
|
4778
4948
|
systemPromptReport
|
|
4779
|
-
};
|
|
4949
|
+
});
|
|
4780
4950
|
if (turnSucceeded && toolState.yieldDetected && !runAbortController.signal.aborted) resourceState.nativeHookRelay?.authorizeRetentionAfterSuccessfulYield();
|
|
4781
4951
|
return finalizedResult;
|
|
4782
4952
|
}
|
|
@@ -4860,9 +5030,10 @@ function applyCodexTurnNotificationState(params) {
|
|
|
4860
5030
|
else if (shouldArmNoToolPostProgressReplyWatch || shouldArmNoToolPostRawProgressReplyWatch) armPostProgressReplyWatch();
|
|
4861
5031
|
else if (trackedDynamicToolCompletion) armPostToolContinuationWatch();
|
|
4862
5032
|
else if (unblockedAssistantCompletionRelease) turnWatches.armAssistantCompletionIdleWatch(describeNotificationActivity(notification));
|
|
4863
|
-
else if (shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem)
|
|
4864
|
-
|
|
4865
|
-
|
|
5033
|
+
else if (shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem) {
|
|
5034
|
+
if (shouldUsePostToolContinuationWatch) armPostToolContinuationWatch();
|
|
5035
|
+
else turnWatches.armCompletionIdleWatch();
|
|
5036
|
+
} else if (rawResponseItemCompletedWithNoActiveItems) turnWatches.armCompletionIdleWatch();
|
|
4866
5037
|
else if (isCurrentTurnNotification && rawToolOutputCompletion) armPostToolContinuationWatch();
|
|
4867
5038
|
else if (isCurrentTurnNotification && shouldDisarmAssistantCompletionIdleWatch(notification)) turnWatches.disarmAssistantCompletionIdleWatch();
|
|
4868
5039
|
if (turnWatches.isCompletionIdleWatchArmed() && !turnWatches.isCompletionIdleWatchPinnedByTerminalError() && notification.method !== "turn/completed" && isCurrentTurnNotification && !trackedDynamicToolCompletion && !rawToolOutputCompletion && !postToolProgressNeedsTerminalGuard && !postToolPatchUpdateNeedsTerminalGuard && !rawResponseItemCompletedWithNoActiveItems && !shouldArmNoToolPostProgressReplyWatch && !shouldArmNoToolPostRawProgressReplyWatch && !shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem) turnWatches.disarmCompletionIdleWatch();
|
|
@@ -4976,7 +5147,7 @@ function createCodexAttemptLifecycleController(resources, turnRuntime) {
|
|
|
4976
5147
|
state.lifecycleStarted = true;
|
|
4977
5148
|
};
|
|
4978
5149
|
const emitLifecycleTerminal = (data) => {
|
|
4979
|
-
if (!state.lifecycleStarted || state.lifecycleTerminalEmitted) return;
|
|
5150
|
+
if (!state.lifecycleStarted || state.lifecycleTerminalEmitted || state.permissionChangeRestart) return;
|
|
4980
5151
|
emitCodexAppServerEvent(params, {
|
|
4981
5152
|
stream: "lifecycle",
|
|
4982
5153
|
data: {
|
|
@@ -5224,7 +5395,6 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
5224
5395
|
}
|
|
5225
5396
|
//#endregion
|
|
5226
5397
|
//#region extensions/codex/src/app-server/run-attempt-prompt.ts
|
|
5227
|
-
const CODEX_META_KEY = "__openclaw";
|
|
5228
5398
|
function isRestrictivePromptToolsAllow(toolsAllow) {
|
|
5229
5399
|
return toolsAllow !== void 0 && !toolsAllow.some((name) => name.trim() === "*");
|
|
5230
5400
|
}
|
|
@@ -5323,7 +5493,7 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
5323
5493
|
if (isRestrictivePromptToolsAllow(toolsAllow)) throw new Error("Codex app-server cannot enforce before_prompt_build toolsAllow; use the embedded or Copilot runtime for turn-scoped tool policy.");
|
|
5324
5494
|
return promptState.developerInstructions;
|
|
5325
5495
|
} },
|
|
5326
|
-
messages:
|
|
5496
|
+
messages: historyState.messages,
|
|
5327
5497
|
ctx: hookContext,
|
|
5328
5498
|
bootstrapContextRunKind: params.bootstrapContextRunKind,
|
|
5329
5499
|
toolAuthority: {
|
|
@@ -5401,11 +5571,9 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
5401
5571
|
const cutoff = Date.parse(binding.historyCoveredThrough ?? "");
|
|
5402
5572
|
return historyState.messages.filter((message) => {
|
|
5403
5573
|
if (message.role !== "user" && message.role !== "assistant") return false;
|
|
5404
|
-
const
|
|
5405
|
-
const mirrorIdentity = meta && typeof meta === "object" && !Array.isArray(meta) ? meta.mirrorIdentity : void 0;
|
|
5406
|
-
const mirrorOrigin = meta && typeof meta === "object" && !Array.isArray(meta) ? meta.mirrorOrigin : void 0;
|
|
5574
|
+
const mirrorIdentity = readMirrorIdentity(message);
|
|
5407
5575
|
const timestamp = typeof message.timestamp === "number" ? message.timestamp : typeof message.timestamp === "string" ? Date.parse(message.timestamp) : NaN;
|
|
5408
|
-
return !("idempotencyKey" in message && typeof message.idempotencyKey === "string" && message.idempotencyKey.startsWith("codex-app-server:")) &&
|
|
5576
|
+
return !("idempotencyKey" in message && typeof message.idempotencyKey === "string" && message.idempotencyKey.startsWith("codex-app-server:")) && !hasCodexMirrorOrigin(message) && !mirrorIdentity?.startsWith("codex-app-server:") && Number.isFinite(timestamp) && timestamp > (Number.isFinite(cutoff) ? cutoff : 0);
|
|
5409
5577
|
});
|
|
5410
5578
|
};
|
|
5411
5579
|
const applyResumeStaleBindingContinuityProjection = (binding) => {
|
|
@@ -5437,7 +5605,8 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
5437
5605
|
return projected;
|
|
5438
5606
|
};
|
|
5439
5607
|
const applyNoContextEngineContinuityProjection = (action, binding) => {
|
|
5440
|
-
|
|
5608
|
+
const hasContinuity = historyState.messages.some((message) => message.role === "user" || action === "started" && (message.role === "compactionSummary" || message.role === "branchSummary"));
|
|
5609
|
+
if (activeContextEngine || !hasContinuity) return false;
|
|
5441
5610
|
if (action === "resumed" && promptState.precomputedStaleBindingContinuityProjectionApplied) return true;
|
|
5442
5611
|
if (action === "started" && promptState.staleBindingContinuityForcedFreshStart) return true;
|
|
5443
5612
|
if (action === "started" && promptState.inactiveThreadBootstrapBindingForcedFreshStart) return false;
|
|
@@ -5530,7 +5699,7 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5530
5699
|
const { context, turnState, buildRenderedCodexDeveloperInstructions } = prompt;
|
|
5531
5700
|
const { runtime, attemptTools } = context;
|
|
5532
5701
|
const { connection, hookChannelId } = runtime;
|
|
5533
|
-
const { appServer, params, effectiveCwd, sessionAgentId,
|
|
5702
|
+
const { appServer, params, effectiveCwd, sessionAgentId, contextSessionKey, runAbortController, sandbox, options, nativeHookRelayEvents } = connection;
|
|
5534
5703
|
const { toolBridge } = attemptTools;
|
|
5535
5704
|
const trajectoryRecorder = createCodexTrajectoryRecorder({
|
|
5536
5705
|
attempt: params,
|
|
@@ -5570,7 +5739,7 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5570
5739
|
emitCodexNativePreToolUseFailureDiagnostic({
|
|
5571
5740
|
agentId: sessionAgentId,
|
|
5572
5741
|
sessionId: params.sessionId,
|
|
5573
|
-
sessionKey:
|
|
5742
|
+
sessionKey: contextSessionKey,
|
|
5574
5743
|
runId: params.runId,
|
|
5575
5744
|
signal: runAbortController.signal,
|
|
5576
5745
|
failure,
|
|
@@ -5692,7 +5861,7 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5692
5861
|
events: nativeHookRelayEvents,
|
|
5693
5862
|
agentId: sessionAgentId,
|
|
5694
5863
|
sessionId: params.sessionId,
|
|
5695
|
-
sessionKey:
|
|
5864
|
+
sessionKey: contextSessionKey,
|
|
5696
5865
|
config: params.config,
|
|
5697
5866
|
runId: params.runId,
|
|
5698
5867
|
channelId: hookChannelId,
|
|
@@ -5854,10 +6023,6 @@ function resolveScheduledCodexAppCreatorCaptureDecision(params) {
|
|
|
5854
6023
|
...unavailableReason ? { unavailableReason } : {}
|
|
5855
6024
|
};
|
|
5856
6025
|
}
|
|
5857
|
-
function readConnectorId(tool) {
|
|
5858
|
-
const meta = asOptionalRecord(asOptionalRecord(tool)?.["_meta"]);
|
|
5859
|
-
return normalizeOptionalString(meta?.connector_id) ?? normalizeOptionalString(meta?.connectorId);
|
|
5860
|
-
}
|
|
5861
6026
|
function normalizeApprovalMode(value) {
|
|
5862
6027
|
return value === "allow" || value === "deny" || value === "auto" || value === "ask" ? value : void 0;
|
|
5863
6028
|
}
|
|
@@ -5924,7 +6089,7 @@ async function readCodexScheduledAppToolNamesByApp(params) {
|
|
|
5924
6089
|
if (!isJsonObject(status) || !isJsonObject(status.tools)) throw new Error("Codex scheduled app inventory contained an invalid server status");
|
|
5925
6090
|
if (status.name !== CODEX_APPS_MCP_SERVER) continue;
|
|
5926
6091
|
for (const [toolName, tool] of Object.entries(status.tools)) {
|
|
5927
|
-
const connectorId =
|
|
6092
|
+
const connectorId = readCodexMcpToolConnectorId(tool);
|
|
5928
6093
|
if (connectorId) {
|
|
5929
6094
|
const names = toolNamesByApp.get(connectorId) ?? /* @__PURE__ */ new Set();
|
|
5930
6095
|
names.add(toolName);
|
|
@@ -5953,7 +6118,8 @@ async function readCurrentCodexScheduledAppPolicy$1(params) {
|
|
|
5953
6118
|
};
|
|
5954
6119
|
}
|
|
5955
6120
|
function readToolApprovalMode(config, appId, toolName, fallback = "auto") {
|
|
5956
|
-
|
|
6121
|
+
const app = asOptionalRecord(asOptionalRecord(config.apps)?.[appId]);
|
|
6122
|
+
return normalizeAppToolApprovalMode(asOptionalRecord(asOptionalRecord(app?.tools)?.[toolName])?.approval_mode) ?? fallback;
|
|
5957
6123
|
}
|
|
5958
6124
|
/** Captures only apps callable on the exact active Codex client/thread. */
|
|
5959
6125
|
async function captureScheduledCodexAppAuthority(params) {
|
|
@@ -6071,7 +6237,8 @@ function intersectCodexPluginThreadConfigWithScheduledAuthority(config, authorit
|
|
|
6071
6237
|
destructiveApprovalMode: stricterApprovalMode(defaultApprovalMode(current), captured.destructiveApprovalMode)
|
|
6072
6238
|
};
|
|
6073
6239
|
}
|
|
6074
|
-
const
|
|
6240
|
+
const pluginAppIds = Object.fromEntries(Object.entries(config.policyContext.pluginAppIds).map(([key, ids]) => [key, ids.filter((id) => Object.hasOwn(apps, id))]).filter(([, ids]) => ids.length > 0));
|
|
6241
|
+
const policyContext = buildPluginAppPolicyContext(apps, pluginAppIds);
|
|
6075
6242
|
const configPatch = buildCodexPluginAppsConfigPatchFromPolicyContext(policyContext);
|
|
6076
6243
|
const appsPatch = asOptionalRecord(configPatch.apps);
|
|
6077
6244
|
for (const [appId, captured] of capturedById) {
|
|
@@ -6140,7 +6307,7 @@ function resolveCodexAttemptBundleManifestRegistry(preparedModelRuntime) {
|
|
|
6140
6307
|
return metadataSnapshot?.pluginIds === void 0 ? metadataSnapshot?.manifestRegistry : void 0;
|
|
6141
6308
|
}
|
|
6142
6309
|
async function prepareCodexAttemptRuntime(connection) {
|
|
6143
|
-
const { params, pluginConfig, usesSupervisionConnection, appServer, startupAuthProfileId, startupPreparedAuth, startupClientAuthProfileId, agentDir, preDynamicStartupStages, effectiveWorkspace, contextSessionKey, sandboxSessionKey, sessionAgentId, sandbox, attemptClientFactory, runAbortController, activeContextEngine, mutable } = connection;
|
|
6310
|
+
const { params, pluginConfig, usesSupervisionConnection, appServer, startupAuthProfileId, startupPreparedAuth, startupClientAuthProfileId, agentDir, preDynamicStartupStages, effectiveWorkspace, contextSessionKey, sandboxSessionKey, sessionAgentId, policyAgentId, sandbox, attemptClientFactory, runAbortController, activeContextEngine, mutable } = connection;
|
|
6144
6311
|
const preparedAuthBinding = !usesSupervisionConnection && appServer.start.homeScope !== "user" && startupAuthProfileId ? await prepareCodexAppServerAuthBinding({
|
|
6145
6312
|
authProfileId: startupAuthProfileId,
|
|
6146
6313
|
authProfileStore: params.authProfileStore,
|
|
@@ -6244,7 +6411,7 @@ async function prepareCodexAttemptRuntime(connection) {
|
|
|
6244
6411
|
preDynamicStartupStages.mark("bundle-mcp");
|
|
6245
6412
|
const sandboxExecServerEnabled = isCodexSandboxExecServerEnabled(pluginConfig, sandbox);
|
|
6246
6413
|
const nativeToolSurfaceEnabled = shouldEnableCodexAppServerNativeToolSurface(runtimeParams, sandbox, {
|
|
6247
|
-
agentId:
|
|
6414
|
+
agentId: policyAgentId,
|
|
6248
6415
|
runtimeSessionKey: sandboxSessionKey,
|
|
6249
6416
|
sandboxExecServerEnabled
|
|
6250
6417
|
});
|
|
@@ -6518,6 +6685,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6518
6685
|
data: {
|
|
6519
6686
|
phase: "start",
|
|
6520
6687
|
name: call.tool,
|
|
6688
|
+
itemId: call.callId,
|
|
6521
6689
|
toolCallId: call.callId,
|
|
6522
6690
|
...toolMeta ? { meta: toolMeta } : {},
|
|
6523
6691
|
...toolArgs ? { args: toolArgs } : {},
|
|
@@ -6540,7 +6708,8 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6540
6708
|
})) terminalDiagnosticObserved = true;
|
|
6541
6709
|
}, { include: DYNAMIC_TOOL_TERMINAL_DIAGNOSTIC_TYPES });
|
|
6542
6710
|
try {
|
|
6543
|
-
const { execution } = openClawDynamicToolExecutions.claim(call, () => {
|
|
6711
|
+
const { execution } = openClawDynamicToolExecutions.claim(call, async () => {
|
|
6712
|
+
await projector?.transcriptCheckpoint.flush();
|
|
6544
6713
|
emitDynamicToolStartedDiagnostic({
|
|
6545
6714
|
call,
|
|
6546
6715
|
agentId: sessionAgentId,
|
|
@@ -6548,7 +6717,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6548
6717
|
sessionId: params.sessionId,
|
|
6549
6718
|
sessionKey: params.sessionKey
|
|
6550
6719
|
});
|
|
6551
|
-
|
|
6720
|
+
const response = await handleDynamicToolCallWithTimeout({
|
|
6552
6721
|
call,
|
|
6553
6722
|
toolBridge,
|
|
6554
6723
|
signal,
|
|
@@ -6570,6 +6739,9 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6570
6739
|
});
|
|
6571
6740
|
}
|
|
6572
6741
|
});
|
|
6742
|
+
recordCodexDynamicToolResult(projector, call, response, toCodexDynamicToolProtocolResponse(response));
|
|
6743
|
+
await projector?.transcriptCheckpoint.flush();
|
|
6744
|
+
return response;
|
|
6573
6745
|
});
|
|
6574
6746
|
const response = await execution;
|
|
6575
6747
|
const protocolResponse = toCodexDynamicToolProtocolResponse(response);
|
|
@@ -6593,7 +6765,6 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6593
6765
|
success: protocolResponse.success,
|
|
6594
6766
|
contentItems: protocolResponse.contentItems
|
|
6595
6767
|
});
|
|
6596
|
-
recordCodexDynamicToolResult(projector, call, response, protocolResponse);
|
|
6597
6768
|
if (protocolResponse.success && call.tool === "progress_card") {
|
|
6598
6769
|
const progressCardInput = response.executedArguments ?? call.arguments;
|
|
6599
6770
|
await projector?.recordDynamicProgressCardUpdate(progressCardInput);
|
|
@@ -6606,6 +6777,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6606
6777
|
data: {
|
|
6607
6778
|
phase: "result",
|
|
6608
6779
|
name: call.tool,
|
|
6780
|
+
itemId: call.callId,
|
|
6609
6781
|
toolCallId: call.callId,
|
|
6610
6782
|
...toolMeta ? { meta: toolMeta } : {},
|
|
6611
6783
|
...commandBearing ? { commandBearing: true } : {},
|
|
@@ -6681,7 +6853,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6681
6853
|
//#region extensions/codex/src/app-server/attempt-runtime-artifact.ts
|
|
6682
6854
|
async function verifyStartupArtifact(params) {
|
|
6683
6855
|
if (!params.request) return;
|
|
6684
|
-
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-
|
|
6856
|
+
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-D9pYp4zL.js");
|
|
6685
6857
|
const runtimeArtifact = readCodexAppServerClientRuntimeArtifact(params.client);
|
|
6686
6858
|
const expected = params.request.expected;
|
|
6687
6859
|
const matchesExpected = !expected || runtimeArtifact?.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint;
|
|
@@ -6711,19 +6883,17 @@ function startCodexComputerUseHealthMonitor(params) {
|
|
|
6711
6883
|
}
|
|
6712
6884
|
const fingerprint = buildComputerUseHealthMonitorFingerprint(params.config);
|
|
6713
6885
|
const intervalMs = params.config.healthCheckIntervalMinutes * 6e4;
|
|
6714
|
-
if (existing?.fingerprint === fingerprint
|
|
6886
|
+
if (existing?.fingerprint === fingerprint) return {
|
|
6715
6887
|
started: false,
|
|
6716
6888
|
intervalMs,
|
|
6717
6889
|
reason: "already_started"
|
|
6718
6890
|
};
|
|
6719
6891
|
if (existing) clearComputerUseHealthMonitor(params.client, existing);
|
|
6720
|
-
const repairComputerUseMcpChildren = params.repairComputerUseMcpChildren ?? (() => killStaleComputerUseMcpChildren({ ancestorPid: params.client.getTransportPid() }));
|
|
6721
6892
|
const monitor = {
|
|
6722
6893
|
fingerprint,
|
|
6723
6894
|
intervalMs,
|
|
6724
|
-
repairComputerUseMcpChildren: params.repairComputerUseMcpChildren,
|
|
6725
6895
|
timer: setInterval(() => {
|
|
6726
|
-
runCodexComputerUseHealthProbe(params.client, params.config, monitor
|
|
6896
|
+
runCodexComputerUseHealthProbe(params.client, params.config, monitor);
|
|
6727
6897
|
}, intervalMs),
|
|
6728
6898
|
disposeCloseHandler: () => void 0,
|
|
6729
6899
|
running: false
|
|
@@ -6748,13 +6918,12 @@ function buildComputerUseHealthMonitorFingerprint(config) {
|
|
|
6748
6918
|
toolCallTimeoutMs: config.toolCallTimeoutMs
|
|
6749
6919
|
});
|
|
6750
6920
|
}
|
|
6751
|
-
async function runCodexComputerUseHealthProbe(client, config, monitor
|
|
6921
|
+
async function runCodexComputerUseHealthProbe(client, config, monitor) {
|
|
6752
6922
|
if (monitor.running) return;
|
|
6753
6923
|
monitor.running = true;
|
|
6754
6924
|
try {
|
|
6755
6925
|
const { liveTest, repair } = await runCodexComputerUseLiveTest({
|
|
6756
6926
|
config,
|
|
6757
|
-
repairComputerUseMcpChildren: options.repairComputerUseMcpChildren,
|
|
6758
6927
|
request: async (method, requestParams, requestOptions) => await client.request(method, requestParams, { timeoutMs: requestOptions?.timeoutMs ?? config.liveTestTimeoutMs })
|
|
6759
6928
|
});
|
|
6760
6929
|
if (!liveTest.ok) {
|
|
@@ -6767,10 +6936,7 @@ async function runCodexComputerUseHealthProbe(client, config, monitor, options)
|
|
|
6767
6936
|
});
|
|
6768
6937
|
return;
|
|
6769
6938
|
}
|
|
6770
|
-
if (repair?.
|
|
6771
|
-
mcpServerName: config.mcpServerName,
|
|
6772
|
-
killedPids: repair.killedPids
|
|
6773
|
-
});
|
|
6939
|
+
if (repair?.attempted && repair.warnings.length === 0) embeddedAgentLog.info("codex computer-use periodic health reloaded MCP servers", { mcpServerName: config.mcpServerName });
|
|
6774
6940
|
} catch (error) {
|
|
6775
6941
|
embeddedAgentLog.warn("codex computer-use periodic health probe crashed", {
|
|
6776
6942
|
mcpServerName: config.mcpServerName,
|
|
@@ -6865,6 +7031,7 @@ function createCodexPluginThreadConfigStartupProvider(params) {
|
|
|
6865
7031
|
build: async (buildOptions) => {
|
|
6866
7032
|
const config = await buildCodexPluginThreadConfigWithinDeadline({
|
|
6867
7033
|
...buildParams,
|
|
7034
|
+
threadId: buildOptions?.threadId,
|
|
6868
7035
|
appCache: appCache ?? defaultCodexAppInventoryCache,
|
|
6869
7036
|
metadataCache,
|
|
6870
7037
|
failClosedOnTimeout: Boolean(params.scheduledRuntimeAuthority),
|
|
@@ -6897,7 +7064,7 @@ function isCodexPluginThreadConfigTimeoutError(error) {
|
|
|
6897
7064
|
* Startup orchestration for Codex app-server attempts, including shared-client
|
|
6898
7065
|
* leasing, plugin thread config, sandbox environment, and thread lifecycle binding.
|
|
6899
7066
|
*/
|
|
6900
|
-
const
|
|
7067
|
+
const CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS = 3;
|
|
6901
7068
|
const CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED = "CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED";
|
|
6902
7069
|
/** True when a pre-write context restart must replay on the newly selected owner. */
|
|
6903
7070
|
function isCodexContextRestartSelectionChangedError(error) {
|
|
@@ -7009,7 +7176,7 @@ async function startCodexAttemptThread(params) {
|
|
|
7009
7176
|
signal: startupAbandonController.signal
|
|
7010
7177
|
});
|
|
7011
7178
|
} catch (error) {
|
|
7012
|
-
if (startupAbandonController.signal.aborted) throw error;
|
|
7179
|
+
if (startupAbandonController.signal.aborted || isCodexAppServerStartSelectionChangedError(error)) throw error;
|
|
7013
7180
|
throw new AgentHarnessPreflightError(`Codex Computer Use readiness failed: ${formatErrorMessage(error)}`, {
|
|
7014
7181
|
cause: error,
|
|
7015
7182
|
scope: "harness"
|
|
@@ -7023,7 +7190,8 @@ async function startCodexAttemptThread(params) {
|
|
|
7023
7190
|
accountId: params.startupAuthAccountCacheKey,
|
|
7024
7191
|
envApiKeyFingerprint: params.startupEnvApiKeyCacheKey,
|
|
7025
7192
|
appServerVersion: activeStartupClient.getServerVersion(),
|
|
7026
|
-
runtimeIdentity: startupRuntimeIdentity
|
|
7193
|
+
runtimeIdentity: startupRuntimeIdentity,
|
|
7194
|
+
desktopGenerationFingerprint: readCodexAppServerClientDesktopGenerationFingerprint(activeStartupClient)
|
|
7027
7195
|
});
|
|
7028
7196
|
const appServerRuntimeFingerprint = buildCodexAppServerRuntimeFingerprint({
|
|
7029
7197
|
appServer: params.appServer,
|
|
@@ -7127,6 +7295,7 @@ async function startCodexAttemptThread(params) {
|
|
|
7127
7295
|
finalConfigPatch: params.finalConfigPatch,
|
|
7128
7296
|
buildFinalConfigPatch: params.buildFinalConfigPatch,
|
|
7129
7297
|
nativeHookRelayGeneration: params.nativeHookRelayGeneration,
|
|
7298
|
+
nativeHookRelayRequired: params.nativeHookRelayRequired,
|
|
7130
7299
|
nativeCodeModeEnabled: params.nativeToolSurfaceEnabled,
|
|
7131
7300
|
nativeProviderWebSearchSupport: params.nativeProviderWebSearchSupport,
|
|
7132
7301
|
nativeCodeModeOnlyEnabled: params.appServer.codeModeOnly,
|
|
@@ -7221,30 +7390,31 @@ async function startCodexAttemptThread(params) {
|
|
|
7221
7390
|
}
|
|
7222
7391
|
}
|
|
7223
7392
|
};
|
|
7224
|
-
for (let attempt = 1; attempt <=
|
|
7393
|
+
for (let attempt = 1; attempt <= CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS; attempt += 1) try {
|
|
7225
7394
|
return await startupAttempt();
|
|
7226
7395
|
} catch (error) {
|
|
7227
7396
|
const selectionChanged = isCodexAppServerStartSelectionChangedError(error);
|
|
7228
7397
|
if (startupAbandoned || params.signal.aborted || !selectionChanged && !isCodexAppServerConnectionClosedError(error)) throw error;
|
|
7229
|
-
const
|
|
7230
|
-
|
|
7231
|
-
if (
|
|
7232
|
-
if (attempt >= CODEX_APP_SERVER_STARTUP_CONNECTION_CLOSE_MAX_ATTEMPTS) {
|
|
7398
|
+
const refreshedSharedClient = selectionChanged ? retireSharedCodexAppServerClientIfCurrent(attemptedClient) : clearSharedCodexAppServerClientIfCurrent(attemptedClient);
|
|
7399
|
+
if (startupClientForAbandonedRequestCleanup === attemptedClient) startupClientForAbandonedRequestCleanup = void 0;
|
|
7400
|
+
if (attempt >= CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS) {
|
|
7233
7401
|
embeddedAgentLog.warn(selectionChanged ? "codex app-server executable selection kept changing during startup; retries exhausted" : "codex app-server connection closed during startup; retries exhausted", {
|
|
7234
7402
|
attempt,
|
|
7235
|
-
maxAttempts:
|
|
7403
|
+
maxAttempts: CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS,
|
|
7236
7404
|
refreshedSharedClient,
|
|
7237
7405
|
error: formatErrorMessage(error)
|
|
7238
7406
|
});
|
|
7239
7407
|
throw error;
|
|
7240
7408
|
}
|
|
7409
|
+
const retryDelayMs = selectionChanged ? 0 : 1e3 * 2 ** (attempt - 1);
|
|
7241
7410
|
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", {
|
|
7242
7411
|
attempt,
|
|
7243
7412
|
nextAttempt: attempt + 1,
|
|
7244
|
-
maxAttempts:
|
|
7413
|
+
maxAttempts: CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS,
|
|
7245
7414
|
refreshedSharedClient,
|
|
7246
7415
|
error: formatErrorMessage(error)
|
|
7247
7416
|
});
|
|
7417
|
+
await sleepWithAbort(retryDelayMs, startupAbandonController.signal);
|
|
7248
7418
|
}
|
|
7249
7419
|
throw new Error("codex app-server startup retry loop exited unexpectedly");
|
|
7250
7420
|
}
|
|
@@ -7257,7 +7427,7 @@ async function startCodexAttemptThread(params) {
|
|
|
7257
7427
|
releaseSharedClientLease
|
|
7258
7428
|
};
|
|
7259
7429
|
} catch (error) {
|
|
7260
|
-
if (params.signal.aborted ||
|
|
7430
|
+
if (params.signal.aborted || isCodexAppServerStartupError(error)) {
|
|
7261
7431
|
releaseSharedClientLease?.();
|
|
7262
7432
|
releaseSharedClientLease = void 0;
|
|
7263
7433
|
await closeCodexStartupClientBestEffort(startupClientForAbandonedRequestCleanup);
|
|
@@ -7276,13 +7446,11 @@ async function startCodexAttemptThread(params) {
|
|
|
7276
7446
|
params.signal.removeEventListener("abort", abandonStartupAcquire);
|
|
7277
7447
|
}
|
|
7278
7448
|
}
|
|
7279
|
-
function shouldClearSharedClientAfterStartupAbandon(error) {
|
|
7280
|
-
return isCodexAppServerStartupError(error);
|
|
7281
|
-
}
|
|
7282
7449
|
function shouldClearSharedClientAfterStartupRace(error) {
|
|
7283
|
-
return
|
|
7450
|
+
return isCodexAppServerStartupError(error) || isCodexAppServerRequestTimeoutError(error);
|
|
7284
7451
|
}
|
|
7285
7452
|
function shouldClearSharedClientAfterStartupFailure(params) {
|
|
7453
|
+
if (isCodexAppServerOverloadError(params.error)) return false;
|
|
7286
7454
|
return isCodexAppServerBrokenPipeError(params.error) || !params.spawnedBy;
|
|
7287
7455
|
}
|
|
7288
7456
|
//#endregion
|
|
@@ -7296,6 +7464,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
7296
7464
|
const developerInstructions = joinPresentSections(turnState.promptBuild.developerInstructions, attemptTools.scheduledConfiguredMcp?.diagnosticNotice);
|
|
7297
7465
|
const { params, attemptClientFactory, bindingStore, appServer, pluginConfig, computerUseConfig, startupClientAuthProfileId, runtimeArtifactRequest, startupPreparedAuth, agentDir, sessionAgentId, effectiveWorkspace, effectiveCwd, sandbox, runAbortController, usesSupervisionConnection, resolveReviewerPolicyContext, resolveRuntimeOptionsForCurrentBinding, startupAuthProfileId, startupAuthRequirement, abortFromUpstream } = connection;
|
|
7298
7466
|
let pluginAppServer = withCodexAppServerFastModeServiceTier(appServer, runtimeParams);
|
|
7467
|
+
const loopDetectionEnabled = (sessionAgentId && params.config ? resolveAgentConfig$1(params.config, sessionAgentId)?.tools?.loopDetection?.enabled : void 0) ?? params.config?.tools?.loopDetection?.enabled ?? false;
|
|
7299
7468
|
try {
|
|
7300
7469
|
emitCodexAppServerEvent(params, {
|
|
7301
7470
|
stream: "codex_app_server.lifecycle",
|
|
@@ -7330,6 +7499,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
7330
7499
|
developerInstructions,
|
|
7331
7500
|
agentWorkspaceDeveloperInstructions: context.agentWorkspaceDeveloperInstructions,
|
|
7332
7501
|
buildFinalConfigPatch: buildNativeHookRelayFinalConfigPatch,
|
|
7502
|
+
nativeHookRelayRequired: connection.options.nativeHookRelay?.enabled !== false && params.pluginHarnessToolPolicyRestricted !== true && connection.nativeHookRelayEvents.includes("pre_tool_use") && (hasBeforeToolCallPolicy() || appServer.loopDetectionPreToolUseRelay && Boolean(connection.sandboxSessionKey) && loopDetectionEnabled),
|
|
7333
7503
|
bundleMcpThreadConfig,
|
|
7334
7504
|
configuredMcpOwnershipVersion: attemptTools.configuredMcpOwnershipVersion,
|
|
7335
7505
|
nativeToolSurfaceEnabled,
|
|
@@ -7367,11 +7537,12 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
7367
7537
|
if (usesSupervisionConnection && (state.thread.connectionScope !== "supervision" || state.thread.supervisionSourceThreadId !== connection.mutable.startupBinding?.supervisionSourceThreadId)) throw new Error("Codex supervised thread lost its private connection ownership");
|
|
7368
7538
|
if (state.thread.lifecycle.action === "started" || state.thread.lifecycle.action === "forked") {
|
|
7369
7539
|
const activePolicy = resolveReviewerPolicyContext(state.thread);
|
|
7540
|
+
const activeConfig = resolveRuntimeOptionsForCurrentBinding({
|
|
7541
|
+
modelProvider: activePolicy.modelProvider,
|
|
7542
|
+
model: activePolicy.model
|
|
7543
|
+
});
|
|
7370
7544
|
const activeAppServer = resolveCodexAppServerForModelProvider({
|
|
7371
|
-
appServer:
|
|
7372
|
-
modelProvider: activePolicy.modelProvider,
|
|
7373
|
-
model: activePolicy.model
|
|
7374
|
-
}),
|
|
7545
|
+
appServer: activeConfig,
|
|
7375
7546
|
provider: activePolicy.modelProvider,
|
|
7376
7547
|
model: activePolicy.model,
|
|
7377
7548
|
config: params.config,
|
|
@@ -7436,7 +7607,7 @@ function isAuthorityResolutionOperationAbort(error, signal) {
|
|
|
7436
7607
|
}
|
|
7437
7608
|
async function prepareCodexAttemptTools(runtime) {
|
|
7438
7609
|
const { connection, bundleMcpThreadConfig, bundleManifestRegistry, runtimeParams, effectiveRuntimeModelId, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, hookChannelId, codexMcpToolOverrides, authenticatedScheduledMode, ownsScheduledConfiguredMcpSurface, canResolveScheduledConfiguredMcpCreatorAuthority } = runtime;
|
|
7439
|
-
const { params, preDynamicStartupStages, mutable, startupAuthProfileId, resolvedWorkspace, effectiveWorkspace, effectiveCwd, sandboxSessionKey, sandbox, runAbortController, sessionAgentId, pluginConfig, profilerEnabled, agentDir } = connection;
|
|
7610
|
+
const { params, preDynamicStartupStages, mutable, startupAuthProfileId, resolvedWorkspace, effectiveWorkspace, effectiveCwd, sandboxSessionKey, contextSessionKey, sandbox, sessionPermissionPolicy, runAbortController, sessionAgentId, policyAgentId, pluginConfig, profilerEnabled, agentDir } = connection;
|
|
7440
7611
|
const preDynamicSummary = preDynamicStartupStages.snapshot();
|
|
7441
7612
|
if (shouldWarnCodexDynamicToolBuildStageSummary(preDynamicSummary)) embeddedAgentLog.warn(`codex app-server pre-dynamic startup timings runId=${params.runId} sessionId=${params.sessionId} totalMs=${preDynamicSummary.totalMs} stages=${formatCodexDynamicToolBuildStageSummary(preDynamicSummary)}`, {
|
|
7442
7613
|
runId: params.runId,
|
|
@@ -7479,6 +7650,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7479
7650
|
...onCodexToolOutcome ? { onToolOutcome: onCodexToolOutcome } : {}
|
|
7480
7651
|
};
|
|
7481
7652
|
const computerContextEpoch = { value: 0 };
|
|
7653
|
+
const runCleanups = [];
|
|
7482
7654
|
const cronCreatorToolAllowlist = [];
|
|
7483
7655
|
const cronCreatorToolAllowlistCaptureRef = {};
|
|
7484
7656
|
const scheduledAppAuthoritySourceRef = {};
|
|
@@ -7509,10 +7681,12 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7509
7681
|
effectiveCwd,
|
|
7510
7682
|
sandboxSessionKey,
|
|
7511
7683
|
sandbox,
|
|
7684
|
+
sessionPermissionPolicy,
|
|
7512
7685
|
nativeToolSurfaceEnabled,
|
|
7513
7686
|
nativeProviderWebSearchSupport,
|
|
7514
7687
|
runAbortController,
|
|
7515
7688
|
sessionAgentId,
|
|
7689
|
+
policyAgentId,
|
|
7516
7690
|
pluginConfig,
|
|
7517
7691
|
profilerEnabled,
|
|
7518
7692
|
...params.cronCreatorAuthorityUnavailableReason === "queued-local-operator" && bundleMcpThreadConfig.staticServerNames.length > 0 ? { cronCreatorAuthorityUnavailableReason: "queued-local-operator-configured-mcp" } : {},
|
|
@@ -7539,6 +7713,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7539
7713
|
};
|
|
7540
7714
|
const tools = await buildDynamicTools({
|
|
7541
7715
|
...commonToolParams,
|
|
7716
|
+
registerRunCleanup: (cleanup) => runCleanups.push(cleanup),
|
|
7542
7717
|
cronCreatorToolAllowlistRef: cronCreatorToolAllowlist,
|
|
7543
7718
|
cronCreatorToolAllowlistCaptureRef,
|
|
7544
7719
|
onPersistentWebSearchPolicyResolved: (allowed) => {
|
|
@@ -7560,7 +7735,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7560
7735
|
runSessionKey: params.sessionKey && params.sessionKey !== sandboxSessionKey ? params.sessionKey : void 0,
|
|
7561
7736
|
sessionId: params.sessionId,
|
|
7562
7737
|
runId: params.runId,
|
|
7563
|
-
agentId:
|
|
7738
|
+
agentId: policyAgentId,
|
|
7564
7739
|
agentDir: agentDir ?? resolveAgentDir(params.config ?? {}, sessionAgentId),
|
|
7565
7740
|
agentAccountId: params.agentAccountId,
|
|
7566
7741
|
messageProvider: params.messageProvider ?? params.messageChannel,
|
|
@@ -7650,7 +7825,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7650
7825
|
remoteWorkspaceRoot: connection.appServer.remoteWorkspaceRoot,
|
|
7651
7826
|
remoteWorkspaceRequestTimeoutMs: connection.appServer.requestTimeoutMs,
|
|
7652
7827
|
sessionId: params.sessionId,
|
|
7653
|
-
sessionKey:
|
|
7828
|
+
sessionKey: contextSessionKey,
|
|
7654
7829
|
runId: params.runId,
|
|
7655
7830
|
channelId: hookChannelId,
|
|
7656
7831
|
currentChannelProvider: resolveCodexMessageToolProvider(params),
|
|
@@ -7759,6 +7934,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7759
7934
|
dynamicToolParams,
|
|
7760
7935
|
compactionPlanState,
|
|
7761
7936
|
computerContextEpoch,
|
|
7937
|
+
runCleanups,
|
|
7762
7938
|
toolBridge,
|
|
7763
7939
|
toolState,
|
|
7764
7940
|
toolOutcomeOrdinals,
|
|
@@ -8240,8 +8416,10 @@ function createCodexAttemptTurnWatchController(params) {
|
|
|
8240
8416
|
function scheduleAttemptIdleWatch() {
|
|
8241
8417
|
scheduleWatch("attempt", fireAttemptIdleTimeout, attemptLastProgressAt, attemptIdleTimeoutOverrideMs ?? turnAttemptIdleTimeoutMs, attemptIdleWatchArmed && !shouldPauseAttemptIdleWatch());
|
|
8242
8418
|
}
|
|
8419
|
+
const terminalWorkIsActive = () => params.getActiveAppServerTurnRequests() > 0 || params.isTerminalTurnNotificationQueued() && params.getActiveFinalizationHookCount() > 0;
|
|
8420
|
+
const terminalIdleTimeoutMs = () => params.isTerminalTurnNotificationQueued() && !terminalWorkIsActive() ? Math.min(TURN_TERMINAL_SETTLEMENT_IDLE_TIMEOUT_MS, turnTerminalIdleTimeoutMs) : turnTerminalIdleTimeoutMs;
|
|
8243
8421
|
function scheduleTerminalIdleWatch() {
|
|
8244
|
-
scheduleWatch("terminal", fireTerminalIdleTimeout, completionLastActivityAt,
|
|
8422
|
+
scheduleWatch("terminal", fireTerminalIdleTimeout, completionLastActivityAt, terminalIdleTimeoutMs(), terminalIdleWatchArmed && (params.isTerminalTurnNotificationQueued() || params.getActiveAppServerTurnRequests() === 0));
|
|
8245
8423
|
}
|
|
8246
8424
|
function scheduleProgressWatches() {
|
|
8247
8425
|
scheduleAttemptIdleWatch();
|
|
@@ -8362,18 +8540,26 @@ function createCodexAttemptTurnWatchController(params) {
|
|
|
8362
8540
|
});
|
|
8363
8541
|
}
|
|
8364
8542
|
function fireTerminalIdleTimeout() {
|
|
8365
|
-
if (params.isCompleted() || params.
|
|
8543
|
+
if (params.isCompleted() || params.signal.aborted || !terminalIdleWatchArmed) return;
|
|
8544
|
+
if (!params.isTerminalTurnNotificationQueued() && params.getActiveAppServerTurnRequests() > 0) {
|
|
8545
|
+
scheduleTerminalIdleWatch();
|
|
8546
|
+
return;
|
|
8547
|
+
}
|
|
8548
|
+
const timeoutMs = terminalIdleTimeoutMs();
|
|
8366
8549
|
const idleMs = Math.max(0, Date.now() - completionLastActivityAt);
|
|
8367
|
-
if (idleMs <
|
|
8550
|
+
if (idleMs < timeoutMs) {
|
|
8368
8551
|
scheduleTerminalIdleWatch();
|
|
8369
8552
|
return;
|
|
8370
8553
|
}
|
|
8371
8554
|
reportTimeout({
|
|
8372
8555
|
kind: "terminal",
|
|
8373
8556
|
idleMs,
|
|
8374
|
-
timeoutMs
|
|
8557
|
+
timeoutMs,
|
|
8375
8558
|
lastActivityReason: completionLastActivityReason,
|
|
8376
|
-
details:
|
|
8559
|
+
details: {
|
|
8560
|
+
...completionLastActivityDetails,
|
|
8561
|
+
terminalTurnNotificationQueued: params.isTerminalTurnNotificationQueued()
|
|
8562
|
+
}
|
|
8377
8563
|
});
|
|
8378
8564
|
}
|
|
8379
8565
|
return {
|
|
@@ -8430,6 +8616,7 @@ function createCodexAttemptTurnWatchController(params) {
|
|
|
8430
8616
|
completionLastActivityReason = `notification:${method}`;
|
|
8431
8617
|
if (options?.details !== void 0) completionLastActivityDetails = options.details;
|
|
8432
8618
|
if (options?.attemptProgress) recordAttemptProgress(completionLastActivityReason, options);
|
|
8619
|
+
if (params.isTerminalTurnNotificationQueued()) scheduleTerminalIdleWatch();
|
|
8433
8620
|
},
|
|
8434
8621
|
extendAttemptIdleWatch: (timeoutMs) => {
|
|
8435
8622
|
attemptIdleTimeoutOverrideMs = resolveWatchTimeoutMs(timeoutMs);
|
|
@@ -8452,6 +8639,8 @@ function createCodexAttemptTurnState(resources) {
|
|
|
8452
8639
|
latestStartupErrorNotification: void 0,
|
|
8453
8640
|
rateLimitsRevisionBeforeLastTurnStart: void 0,
|
|
8454
8641
|
completed: false,
|
|
8642
|
+
abortCleanup: Promise.resolve(),
|
|
8643
|
+
permissionChangeRestart: void 0,
|
|
8455
8644
|
localCompletionRequested: false,
|
|
8456
8645
|
terminalTurnNotificationQueued: false,
|
|
8457
8646
|
sawCodexInterruptMarker: false,
|