@openclaw/codex 2026.8.1-beta.3 → 2026.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +4 -5
- package/dist/{attempt-client-cleanup-URjUlCHg.js → attempt-client-cleanup-CVPvp9dL.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-CCQFs8lf.js} +2 -2
- package/dist/{bounded-turn-4BjrZEwW.js → bounded-turn-rq5tiSXk.js} +13 -18
- package/dist/{capabilities-CH3K57v4.js → capabilities-CGm_94eL.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-D0nZ3qtd.js → command-formatters-C54Yg3eA.js} +2 -2
- package/dist/{command-handlers-DC86lgT4.js → command-handlers-BvOAHTrA.js} +89 -62
- package/dist/{compact-COqgBRny.js → compact-Hd7SAc0N.js} +8 -9
- package/dist/{config-CpNeo5AE.js → config-Cxw3Cl3k.js} +346 -286
- package/dist/doctor-contract-api.js +115 -14
- package/dist/{dynamic-tools-fJZhl4CE.js → dynamic-tools-BFoUcRdx.js} +147 -903
- package/dist/{effective-mcp-catalog-4YKn51aG.js → effective-mcp-catalog-BTJHnDSx.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-D3PHFFXh.js} +3 -3
- package/dist/{harness-DoKQcF8n.js → harness-DVfUQBlQ.js} +42 -52
- package/dist/harness.js +1 -1
- package/dist/index.js +278 -295
- package/dist/{isolated-completion-DPMtlH9r.js → isolated-completion-Cbbx_5Ed.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-o6Cgjoss.js +101 -0
- package/dist/{models-CZw1wClT.js → models-DgFWSuxA.js} +25 -28
- package/dist/{native-subagent-monitor-GGq3RnOo.js → native-subagent-monitor-CwFyoylz.js} +207 -30
- package/dist/{node-exec-server.runtime-Bsu1LdFZ.js → node-exec-server.runtime-DXrqpw1c.js} +8 -5
- package/dist/{plugin-approval-roundtrip-C75Yiiwc.js → plugin-approval-roundtrip-D80UZiJ_.js} +1 -1
- package/dist/{plugin-marketplace-discovery-CSWDkMrP.js → plugin-marketplace-discovery-mdmScYOj.js} +30 -39
- package/dist/{plugin-metadata-cache-BXH5NF-4.js → plugin-metadata-cache-CulOABwu.js} +162 -135
- package/dist/{protocol-validators-VAVyEnDp.js → protocol-validators-Bg5rpNxk.js} +148 -5
- package/dist/{rate-limits-BI1dMHDG.js → rate-limits-hFtzt2Up.js} +1 -1
- package/dist/{sandbox-guard-C1qEeZ5C.js → request-CCm4LaED.js} +183 -2
- package/dist/{run-attempt-BV3HzuCf.js → run-attempt-BwNQDH2u.js} +599 -361
- package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-DeBvleJw.js} +1 -1
- package/dist/{session-binding-BTrLf9Qm.js → session-binding-q2WSTVmC.js} +195 -122
- package/dist/{session-catalog-ezP_UcRM.js → session-catalog-C2Tae4rI.js} +229 -122
- package/dist/session-catalog-home-id-DAKUrm3C.js +112 -0
- package/dist/{session-cli-B1hKvfkI.js → session-cli-BuDjm5Ou.js} +1 -1
- package/dist/session-permission-policy-gLm40Vtq.js +160 -0
- package/dist/session-retirement-CdkI0bvb.js +90 -0
- package/dist/{session-upstream-marker-D_2npHlA.js → session-upstream-marker-Bcy33kam.js} +2 -3
- package/dist/{settled-turn-finalizer-Dx1onIqg.js → settled-turn-finalizer-B8JJcxCi.js} +7 -6
- package/dist/{shared-client-Dw-rzii0.js → shared-client-kNkljY-R.js} +1720 -786
- package/dist/{side-question-DbXkJZzg.js → side-question-GwD73tX6.js} +69 -39
- package/dist/{thread-lifecycle-DKdrnTMX.js → thread-lifecycle-Ss-uwnC4.js} +852 -359
- package/dist/{thread-ownership-i2NBwDUL.js → thread-ownership-CeYBqg_4.js} +18 -8
- package/dist/{plugin-app-cache-key-DMNQ8Zi8.js → thread-resume-DF54hagX.js} +52 -6
- package/dist/{transcript-mirror-BU0_LKAL.js → transcript-mirror-CkEQIna-.js} +112 -13
- package/dist/transport-stdio-C7-s9TLG.js +708 -0
- package/dist/{upstream-session-fork-BDVJCLAD.js → upstream-session-fork-BACGlOFa.js} +78 -86
- package/dist/{usage-9dKJCgcy.js → usage-C2l8Mils.js} +3 -3
- package/dist/{web-search-provider.runtime-DCdx4DGu.js → web-search-provider.runtime-B2XgRdFv.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/thread-resume-CdJk2Ehf.js +0 -30
- package/dist/transport-stdio-DhoGy33Z.js +0 -99
|
@@ -1,42 +1,46 @@
|
|
|
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 {
|
|
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-Cxw3Cl3k.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-kNkljY-R.js";
|
|
3
|
+
import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, i as createCodexSessionGenerationSupersededError, l as resolveCodexRunSessionBindingAuthority, u as scopeCodexRunBindingStore } from "./session-binding-q2WSTVmC.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-CVPvp9dL.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-D3PHFFXh.js";
|
|
7
|
+
import { i as buildCodexPluginAppCacheKey, r as buildCodexAppServerRuntimeFingerprint, s as defaultCodexAppInventoryCache } from "./thread-resume-DF54hagX.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-Ss-uwnC4.js";
|
|
9
|
+
import { l as isIncognitoSessionKey, r as retainCodexAppServerBindingSubscription } from "./thread-ownership-CeYBqg_4.js";
|
|
10
10
|
import { i as readUpstreamUserText, n as attachUpstreamUserText, r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-CFmsKwr9.js";
|
|
11
|
-
import { a as buildCodexUserPromptMessage,
|
|
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-
|
|
11
|
+
import { a as buildCodexUserPromptMessage, i as mirrorPromptAtTurnStartBestEffort, l as readCodexMirrorSourceFingerprint, n as createCodexAppServerUserMessagePersistenceNotifier, o as promptSnapshot, s as applyCodexTranscriptTaint, t as codexTranscriptMirrorRuntime, u as serializeCodexMirrorSourceEvidence } from "./transcript-mirror-CkEQIna-.js";
|
|
12
|
+
import { t as CODEX_CONTROL_METHODS } from "./capabilities-CGm_94eL.js";
|
|
13
|
+
import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-hFtzt2Up.js";
|
|
14
|
+
import { r as formatCodexDisplayText } from "./command-formatters-C54Yg3eA.js";
|
|
15
|
+
import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, r as resolveCodexEffectiveSessionPermissionPolicy } from "./session-permission-policy-gLm40Vtq.js";
|
|
16
|
+
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-CCQFs8lf.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
|
|
21
|
-
import {
|
|
22
|
-
import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse,
|
|
19
|
+
import { i as createAssistantMirrorMessage, n as createAssistantCommentaryMessage, r as createAssistantMessage, t as createAssistantAsyncMessage } from "./event-projector-assistant-message-C5-Ds8mA.js";
|
|
20
|
+
import { a as readCodexMirroredSessionHistoryMessages, c as inferCodexDynamicToolMeta, d as sanitizeCodexToolArguments, f as sanitizeCodexToolResponse, i as CodexToolTranscriptProjection, l as isCodexCommandBearingToolCall, n as CodexEventProjection, o as CodexToolProgressProjection, r as emitCodexAgentEvent, s as shouldEmitTranscriptToolProgress, t as codexNativeSubagentMonitorRuntime, u as resolveCodexToolProgressDetailMode } from "./native-subagent-monitor-CwFyoylz.js";
|
|
21
|
+
import { C as shouldRequireCodexSandboxExecServerEnvironment, D as CodexNativeToolLifecycleProjector, E as readBoundedCodexRemoteWorkspaceFile, S as shouldEnableCodexAppServerNativeToolSurface, _ as resolveCodexAppServerHookChannelId, a as emitDynamicToolStartedDiagnostic, c as resolveCodexProviderWebSearchSupport, d as releaseCodexSandboxExecServerEnvironment, f as buildDynamicTools, g as resolveCodexAppServerExecutionCwd, h as formatCodexDynamicToolBuildStageSummary, i as emitDynamicToolErrorDiagnostic, m as disableCodexPluginThreadConfig, n as projectCodexExecutableDynamicTools, o as emitDynamicToolTerminalDiagnostic, p as createCodexDynamicToolBuildStageTracker, r as routeCodexAppServerElicitationRequest, s as handleCodexAppServerApprovalRequest, t as createCodexDynamicToolBridge, u as ensureCodexSandboxExecServerEnvironment, v as resolveCodexExternalSandboxPolicyForOpenClawSandbox, w as shouldWarnCodexDynamicToolBuildStageSummary, x as resolveCodexSandboxEnvironmentSelection, y as resolveCodexMessageToolProvider } from "./dynamic-tools-BFoUcRdx.js";
|
|
22
|
+
import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-CulOABwu.js";
|
|
23
23
|
import { asBoolean, asFiniteNumber, asOptionalRecord, hasNonEmptyString, normalizeOptionalString, readNonBlankString, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
24
24
|
import fs from "node:fs/promises";
|
|
25
25
|
import path from "node:path";
|
|
26
26
|
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
27
27
|
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,
|
|
28
|
+
import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, agentHarnessAttemptTerminal, agentHarnessStructuredInput, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine, buildBootstrapContextForFiles, buildEmbeddedForegroundPromptContext, buildHarnessContextEngineRuntimeContext, buildWatchedSessionsHarnessContext, callGatewayTool, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, 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
29
|
import crypto, { createHash } from "node:crypto";
|
|
30
|
-
import { hostname } from "node:os";
|
|
31
30
|
import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
31
|
+
import { resolveAgentConfig as resolveAgentConfig$1, resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
32
32
|
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
33
33
|
import { parseSqliteSessionFileMarker } from "openclaw/plugin-sdk/session-store-runtime";
|
|
34
|
+
import { addAbortListener } from "node:events";
|
|
34
35
|
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
36
|
import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
37
|
+
import { isPathStrictlyInside, root } from "openclaw/plugin-sdk/file-access-runtime";
|
|
38
|
+
import { captureFinalCodexCronCreatorToolAllowlist, materializeStaticMcpToolsForScheduledHarnessRun, resolveCodexMcpToolOverridesForAgent } from "openclaw/plugin-sdk/codex-mcp-projection";
|
|
39
|
+
import { hasPromptImageInput } from "openclaw/plugin-sdk/session-transcript-runtime";
|
|
38
40
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
41
|
+
import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
39
42
|
import { prepareMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
|
|
43
|
+
import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-local-roots";
|
|
40
44
|
import { isSilentReplyPayloadText } from "openclaw/plugin-sdk/reply-chunking";
|
|
41
45
|
import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
|
|
42
46
|
import { resolveGeneratedMediaMaxBytes } from "openclaw/plugin-sdk/media-generation-runtime";
|
|
@@ -68,6 +72,12 @@ function createCodexSteeringQueue(params) {
|
|
|
68
72
|
let sendChain = Promise.resolve();
|
|
69
73
|
let sealedError;
|
|
70
74
|
let closedError;
|
|
75
|
+
const assertActive = () => {
|
|
76
|
+
const unavailableError = closedError ?? sealedError;
|
|
77
|
+
if (unavailableError) throw unavailableError;
|
|
78
|
+
params.signal.throwIfAborted();
|
|
79
|
+
params.assertActive();
|
|
80
|
+
};
|
|
71
81
|
const clearBatchTimer = () => {
|
|
72
82
|
if (batchTimer) {
|
|
73
83
|
clearTimeout(batchTimer);
|
|
@@ -120,19 +130,20 @@ function createCodexSteeringQueue(params) {
|
|
|
120
130
|
const sendBatch = async (items) => {
|
|
121
131
|
const liveItems = items.filter((item) => !item.settled);
|
|
122
132
|
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);
|
|
133
|
+
let clientUserMessageId;
|
|
131
134
|
try {
|
|
135
|
+
assertActive();
|
|
136
|
+
const input = [];
|
|
137
|
+
for (const item of liveItems) {
|
|
138
|
+
input.push(...await params.prepareMessage(item.text, item));
|
|
139
|
+
assertActive();
|
|
140
|
+
}
|
|
141
|
+
clientUserMessageId = `openclaw:${params.turnId}:steer:${++batchSequence}`;
|
|
142
|
+
dispatchedBatches.set(clientUserMessageId, { items: liveItems });
|
|
132
143
|
await params.client.request("turn/steer", {
|
|
133
144
|
threadId: params.threadId,
|
|
134
145
|
expectedTurnId: params.turnId,
|
|
135
|
-
input
|
|
146
|
+
input,
|
|
136
147
|
clientUserMessageId
|
|
137
148
|
}, {
|
|
138
149
|
timeoutMs: params.requestTimeoutMs,
|
|
@@ -140,8 +151,8 @@ function createCodexSteeringQueue(params) {
|
|
|
140
151
|
});
|
|
141
152
|
for (const item of liveItems) reportItemAcceptance(item, true);
|
|
142
153
|
} catch (error) {
|
|
143
|
-
dispatchedBatches.delete(clientUserMessageId);
|
|
144
|
-
const acceptedUnconfirmed = isCodexAppServerIndeterminateRequestCancellationError(error) || isCodexAppServerIndeterminateTransportError(error);
|
|
154
|
+
if (clientUserMessageId) dispatchedBatches.delete(clientUserMessageId);
|
|
155
|
+
const acceptedUnconfirmed = clientUserMessageId !== void 0 && (isCodexAppServerIndeterminateRequestCancellationError(error) || isCodexAppServerIndeterminateTransportError(error));
|
|
145
156
|
for (const item of liveItems) {
|
|
146
157
|
if (acceptedUnconfirmed) reportItemAcceptance(item, true);
|
|
147
158
|
rejectItem(item, error);
|
|
@@ -175,15 +186,12 @@ function createCodexSteeringQueue(params) {
|
|
|
175
186
|
rejectDelivery = reject;
|
|
176
187
|
});
|
|
177
188
|
const item = {
|
|
189
|
+
...options,
|
|
178
190
|
acceptance: "open",
|
|
179
191
|
text,
|
|
180
|
-
images: options?.images,
|
|
181
|
-
isInboundUserMessage: options?.isInboundUserMessage,
|
|
182
|
-
onQueueAccepted: options?.onQueueAccepted,
|
|
183
192
|
resolve: resolveDelivery,
|
|
184
193
|
reject: rejectDelivery,
|
|
185
|
-
settled: false
|
|
186
|
-
userTurnTranscriptRecorder: options?.userTurnTranscriptRecorder
|
|
194
|
+
settled: false
|
|
187
195
|
};
|
|
188
196
|
pendingMessages.add(item);
|
|
189
197
|
return {
|
|
@@ -195,10 +203,11 @@ function createCodexSteeringQueue(params) {
|
|
|
195
203
|
if (params.signal.aborted) abortQueue();
|
|
196
204
|
return {
|
|
197
205
|
async queue(text, options) {
|
|
198
|
-
|
|
199
|
-
|
|
206
|
+
try {
|
|
207
|
+
assertActive();
|
|
208
|
+
} catch (error) {
|
|
200
209
|
options?.onQueueAccepted?.(false);
|
|
201
|
-
throw
|
|
210
|
+
throw error;
|
|
202
211
|
}
|
|
203
212
|
const { item, delivery } = createPendingMessage(text, options);
|
|
204
213
|
batchedMessages.push(item);
|
|
@@ -242,15 +251,17 @@ function normalizeCodexSteerDebounceMs(value) {
|
|
|
242
251
|
//#endregion
|
|
243
252
|
//#region extensions/codex/src/app-server/event-projector-assistant.ts
|
|
244
253
|
var CodexAssistantProjection = class {
|
|
245
|
-
constructor(params, emitAgentEvent, matchesToolProgressEcho, nextTranscriptTimestamp) {
|
|
254
|
+
constructor(params, emitAgentEvent, matchesToolProgressEcho, nextTranscriptTimestamp, checkpointCommentary) {
|
|
246
255
|
this.params = params;
|
|
247
256
|
this.emitAgentEvent = emitAgentEvent;
|
|
248
257
|
this.matchesToolProgressEcho = matchesToolProgressEcho;
|
|
249
258
|
this.nextTranscriptTimestamp = nextTranscriptTimestamp;
|
|
259
|
+
this.checkpointCommentary = checkpointCommentary;
|
|
250
260
|
this.assistantTextByItem = /* @__PURE__ */ new Map();
|
|
251
261
|
this.assistantItemOrder = [];
|
|
252
262
|
this.assistantTimestampByItem = /* @__PURE__ */ new Map();
|
|
253
263
|
this.assistantPhaseByItem = /* @__PURE__ */ new Map();
|
|
264
|
+
this.assistantDeliveryByItem = /* @__PURE__ */ new Map();
|
|
254
265
|
this.latestTerminalAssistantCandidateSuperseded = false;
|
|
255
266
|
this.latestTerminalAssistantCandidateCanReleaseAfterToolHandoff = false;
|
|
256
267
|
this.terminalAssistantCandidateEarlierActiveItemIds = /* @__PURE__ */ new Set();
|
|
@@ -261,7 +272,9 @@ var CodexAssistantProjection = class {
|
|
|
261
272
|
this.assistantStarted = false;
|
|
262
273
|
this.streamedPartialAssistantItemReplaceable = false;
|
|
263
274
|
this.persistableAssistantBarrier = 0;
|
|
275
|
+
this.persistedAssistantBoundary = false;
|
|
264
276
|
this.persistableAssistantBarrierItemIds = /* @__PURE__ */ new Set();
|
|
277
|
+
this.completedAssistantItemIds = /* @__PURE__ */ new Set();
|
|
265
278
|
}
|
|
266
279
|
hasCompletedTerminalAssistantText(completedItemIds) {
|
|
267
280
|
const latestCompletedItemId = this.latestCompletedTerminalAssistantItemId;
|
|
@@ -293,7 +306,8 @@ var CodexAssistantProjection = class {
|
|
|
293
306
|
if (!delta) return;
|
|
294
307
|
if (itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
295
308
|
const isCommentary = this.isCommentaryAssistantItem(itemId);
|
|
296
|
-
|
|
309
|
+
const isAsync = this.isAsyncAssistantItem(itemId);
|
|
310
|
+
if (!isCommentary && !isAsync && itemId !== this.latestTerminalAssistantCandidateItemId) this.markTerminalAssistantCandidateSupersededBy();
|
|
297
311
|
if (!this.assistantStarted) {
|
|
298
312
|
this.assistantStarted = true;
|
|
299
313
|
await this.params.onAssistantMessageStart?.();
|
|
@@ -301,6 +315,7 @@ var CodexAssistantProjection = class {
|
|
|
301
315
|
this.rememberAssistantItem(itemId);
|
|
302
316
|
const text = `${this.assistantTextByItem.get(itemId) ?? ""}${delta}`;
|
|
303
317
|
this.assistantTextByItem.set(itemId, text);
|
|
318
|
+
if (isAsync) return;
|
|
304
319
|
if (isCommentary) {
|
|
305
320
|
this.emitCommentaryProgress({
|
|
306
321
|
itemId,
|
|
@@ -332,24 +347,25 @@ var CodexAssistantProjection = class {
|
|
|
332
347
|
}
|
|
333
348
|
recordItemStarted(item, itemId) {
|
|
334
349
|
this.noteNativeWorkBarrier(item);
|
|
335
|
-
if (item?.type === "agentMessage" && itemId && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
336
350
|
this.rememberAssistantPhase(item);
|
|
351
|
+
if (item?.type === "agentMessage" && itemId && !this.isNonTerminalAssistantItem(itemId) && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
337
352
|
if (item?.type === "agentMessage" && itemId) this.rememberAssistantItem(itemId);
|
|
338
|
-
if (itemId && itemId !== this.latestTerminalAssistantCandidateItemId) {
|
|
353
|
+
if (itemId && !this.isNonTerminalAssistantItem(itemId) && itemId !== this.latestTerminalAssistantCandidateItemId) {
|
|
339
354
|
this.markTerminalAssistantCandidateSupersededBy(itemId, { preserveEarlierActiveItem: true });
|
|
340
355
|
if (this.latestTerminalAssistantCandidateSuperseded) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
341
356
|
}
|
|
342
357
|
}
|
|
343
358
|
recordItemCompleted(item, itemId, activeItemIds) {
|
|
359
|
+
if (itemId && item?.type === "agentMessage") this.completedAssistantItemIds.add(itemId);
|
|
344
360
|
this.noteNativeWorkBarrier(item);
|
|
345
|
-
if (item?.type === "agentMessage" && itemId && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
346
|
-
if (itemId) this.latestCompletedItemId = itemId;
|
|
347
361
|
this.rememberAssistantPhase(item);
|
|
348
|
-
if (item?.type === "agentMessage" && !this.
|
|
362
|
+
if (item?.type === "agentMessage" && itemId && !this.isNonTerminalAssistantItem(itemId) && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
363
|
+
if (itemId && !this.isNonTerminalAssistantItem(itemId)) this.latestCompletedItemId = itemId;
|
|
364
|
+
if (item?.type === "agentMessage" && !this.isNonTerminalAssistantItem(item.id)) {
|
|
349
365
|
this.latestCompletedTerminalAssistantItemId = item.id;
|
|
350
366
|
this.markLatestTerminalAssistantCandidate(item.id, activeItemIds);
|
|
351
367
|
this.pendingRawTerminalAssistantEchoItemId = item.id;
|
|
352
|
-
} else if (itemId) {
|
|
368
|
+
} else if (itemId && !this.isNonTerminalAssistantItem(itemId)) {
|
|
353
369
|
this.markTerminalAssistantCandidateSupersededBy(itemId, { preserveEarlierActiveItem: true });
|
|
354
370
|
if (this.latestTerminalAssistantCandidateSuperseded) this.pendingRawTerminalAssistantEchoItemId = void 0;
|
|
355
371
|
}
|
|
@@ -362,14 +378,17 @@ var CodexAssistantProjection = class {
|
|
|
362
378
|
text: item.text
|
|
363
379
|
});
|
|
364
380
|
this.pendingRawCommentaryEchoes += 1;
|
|
365
|
-
} else if (item.text && this.isFinalAnswerAssistantItem(item.id)) this.emitAnswerCandidate(item.id, "candidate");
|
|
381
|
+
} else if (item.text && !this.isAsyncAssistantItem(item.id) && this.isFinalAnswerAssistantItem(item.id)) this.emitAnswerCandidate(item.id, "candidate");
|
|
382
|
+
return this.createAsyncDelivery(item.id);
|
|
366
383
|
}
|
|
367
384
|
}
|
|
368
385
|
recordSnapshotItem(item) {
|
|
386
|
+
if (item.type === "agentMessage") this.completedAssistantItemIds.add(item.id);
|
|
369
387
|
this.rememberAssistantPhase(item);
|
|
370
388
|
if (item.type === "agentMessage" && typeof item.text === "string") {
|
|
371
389
|
this.rememberAssistantItem(item.id);
|
|
372
390
|
this.assistantTextByItem.set(item.id, item.text);
|
|
391
|
+
return this.createAsyncDelivery(item.id);
|
|
373
392
|
}
|
|
374
393
|
}
|
|
375
394
|
handleRawResponseItemCompleted(item, activeItemIds) {
|
|
@@ -403,6 +422,7 @@ var CodexAssistantProjection = class {
|
|
|
403
422
|
const isIdlessTerminalAssistantAfterCompletedWork = candidateWasSupersededBeforeRaw && rawItemId === void 0 && pendingTerminalAssistantEchoItemId === void 0 && activeItemIds.size === 0;
|
|
404
423
|
if (text && phase !== "commentary" && candidateWasSupersededBeforeRaw && itemId !== this.streamedPartialAssistantItemId && !isIdlessTerminalAssistantAfterCompletedWork) return;
|
|
405
424
|
if (phase) this.assistantPhaseByItem.set(itemId, phase);
|
|
425
|
+
this.completedAssistantItemIds.add(itemId);
|
|
406
426
|
this.rememberAssistantItem(itemId);
|
|
407
427
|
this.assistantTextByItem.set(itemId, text);
|
|
408
428
|
if (!text) return;
|
|
@@ -418,6 +438,7 @@ var CodexAssistantProjection = class {
|
|
|
418
438
|
const audibleAfterHandoff = afterHandoff.filter((text) => !isSilentReplyPayloadText(text));
|
|
419
439
|
if (audibleAfterHandoff.length > 0) return audibleAfterHandoff;
|
|
420
440
|
if (afterHandoff.length > 0) return afterHandoff.slice(-1);
|
|
441
|
+
if (this.persistedAssistantBoundary) return [];
|
|
421
442
|
const recoveredAudible = this.collectPersistableAssistantTexts(0).filter((text) => !isSilentReplyPayloadText(text));
|
|
422
443
|
if (recoveredAudible.length > 0) return recoveredAudible.slice(-1);
|
|
423
444
|
const recovered = this.resolveFinalAssistantTextItem()?.text;
|
|
@@ -425,16 +446,52 @@ var CodexAssistantProjection = class {
|
|
|
425
446
|
}
|
|
426
447
|
collectCommentaryMessages() {
|
|
427
448
|
return this.assistantItemOrder.flatMap((itemId) => {
|
|
428
|
-
|
|
449
|
+
const message = this.readCommentaryMessage(itemId);
|
|
450
|
+
return message ? [{
|
|
451
|
+
itemId,
|
|
452
|
+
message
|
|
453
|
+
}] : [];
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
readCommentaryMessage(itemId) {
|
|
457
|
+
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
458
|
+
const timestamp = this.assistantTimestampByItem.get(itemId);
|
|
459
|
+
return this.isCommentaryAssistantItem(itemId) && text && timestamp !== void 0 ? createAssistantCommentaryMessage(this.params, text, itemId, timestamp) : void 0;
|
|
460
|
+
}
|
|
461
|
+
collectAsyncMessages() {
|
|
462
|
+
return this.assistantItemOrder.flatMap((itemId) => {
|
|
463
|
+
if (!this.isAsyncAssistantItem(itemId)) return [];
|
|
429
464
|
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
430
465
|
const timestamp = this.assistantTimestampByItem.get(itemId);
|
|
431
466
|
if (!text || timestamp === void 0) return [];
|
|
432
467
|
return [{
|
|
433
468
|
itemId,
|
|
434
|
-
message:
|
|
469
|
+
message: createAssistantAsyncMessage(this.params, text, itemId, timestamp)
|
|
470
|
+
}];
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
collectCompletedAssistantMessages(completedItemIds, options) {
|
|
474
|
+
return this.assistantItemOrder.flatMap((itemId) => {
|
|
475
|
+
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
476
|
+
if (!completedItemIds.has(itemId) || this.isNonTerminalAssistantItem(itemId) || !text || isSilentReplyPayloadText(text) || this.isToolProgressEchoText(itemId, text)) return [];
|
|
477
|
+
const message = this.createAssistantMessage(text, options);
|
|
478
|
+
const timestamp = this.assistantTimestampByItem.get(itemId) ?? message.timestamp;
|
|
479
|
+
return [{
|
|
480
|
+
itemId,
|
|
481
|
+
message: {
|
|
482
|
+
...message,
|
|
483
|
+
timestamp
|
|
484
|
+
}
|
|
435
485
|
}];
|
|
436
486
|
});
|
|
437
487
|
}
|
|
488
|
+
markAssistantBoundaryPersisted(itemId) {
|
|
489
|
+
const index = this.assistantItemOrder.indexOf(itemId);
|
|
490
|
+
if (index >= 0) {
|
|
491
|
+
this.persistableAssistantBarrier = Math.max(this.persistableAssistantBarrier, index + 1);
|
|
492
|
+
this.persistedAssistantBoundary = true;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
438
495
|
finalizeAnswerCandidate(turn) {
|
|
439
496
|
if (turn.status !== "completed") {
|
|
440
497
|
this.supersedeVisibleAnswerCandidate();
|
|
@@ -444,7 +501,7 @@ var CodexAssistantProjection = class {
|
|
|
444
501
|
const authoritativeIndex = turnItems.findLastIndex((item) => {
|
|
445
502
|
if (item.type !== "agentMessage" || typeof item.text !== "string" || item.text.trim().length === 0) return false;
|
|
446
503
|
const phase = readItemString(item, "phase");
|
|
447
|
-
return phase === "final_answer" || phase === void 0;
|
|
504
|
+
return readItemString(item, "delivery") !== "async" && (phase === "final_answer" || phase === void 0);
|
|
448
505
|
});
|
|
449
506
|
const authoritative = authoritativeIndex >= 0 ? turnItems[authoritativeIndex] : void 0;
|
|
450
507
|
if (turnItems.slice(authoritativeIndex + 1).some(shouldClearTerminalPresentationForNativeItem) || authoritative?.id === this.latestTerminalAssistantCandidateItemId && this.latestTerminalAssistantCandidateSuperseded) {
|
|
@@ -462,7 +519,7 @@ var CodexAssistantProjection = class {
|
|
|
462
519
|
hasAssistantItemTextForSynthesis() {
|
|
463
520
|
for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
|
|
464
521
|
const itemId = this.assistantItemOrder[i];
|
|
465
|
-
if (!itemId || this.
|
|
522
|
+
if (!itemId || this.isNonTerminalAssistantItem(itemId)) continue;
|
|
466
523
|
const text = this.assistantTextByItem.get(itemId);
|
|
467
524
|
if (text && text.length > 0) return true;
|
|
468
525
|
}
|
|
@@ -471,7 +528,7 @@ var CodexAssistantProjection = class {
|
|
|
471
528
|
createCurrentAttemptAssistantMessage(options) {
|
|
472
529
|
for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
|
|
473
530
|
const itemId = this.assistantItemOrder[i];
|
|
474
|
-
if (!itemId || this.
|
|
531
|
+
if (!itemId || this.isNonTerminalAssistantItem(itemId) || !this.assistantTextByItem.has(itemId)) continue;
|
|
475
532
|
const text = this.assistantTextByItem.get(itemId) ?? "";
|
|
476
533
|
const normalizedText = text.trim();
|
|
477
534
|
if (normalizedText && this.isToolProgressEchoText(itemId, normalizedText)) continue;
|
|
@@ -492,10 +549,18 @@ var CodexAssistantProjection = class {
|
|
|
492
549
|
if (item?.type !== "agentMessage") return;
|
|
493
550
|
const phase = readItemString(item, "phase");
|
|
494
551
|
if (phase) this.assistantPhaseByItem.set(item.id, phase);
|
|
552
|
+
const delivery = readItemString(item, "delivery");
|
|
553
|
+
if (delivery) this.assistantDeliveryByItem.set(item.id, delivery);
|
|
495
554
|
}
|
|
496
555
|
isCommentaryAssistantItem(itemId) {
|
|
497
556
|
return this.assistantPhaseByItem.get(itemId) === "commentary";
|
|
498
557
|
}
|
|
558
|
+
isAsyncAssistantItem(itemId) {
|
|
559
|
+
return this.assistantDeliveryByItem.get(itemId) === "async";
|
|
560
|
+
}
|
|
561
|
+
isNonTerminalAssistantItem(itemId) {
|
|
562
|
+
return this.isCommentaryAssistantItem(itemId) || this.isAsyncAssistantItem(itemId);
|
|
563
|
+
}
|
|
499
564
|
isFinalAnswerAssistantItem(itemId) {
|
|
500
565
|
return this.assistantPhaseByItem.get(itemId) === "final_answer";
|
|
501
566
|
}
|
|
@@ -503,7 +568,7 @@ var CodexAssistantProjection = class {
|
|
|
503
568
|
return this.assistantPhaseByItem.get(itemId) === "final_answer";
|
|
504
569
|
}
|
|
505
570
|
emitCommentaryProgress(params) {
|
|
506
|
-
const progressText = params.text.
|
|
571
|
+
const progressText = params.text.trim();
|
|
507
572
|
if (!progressText || this.lastCommentaryProgressTextByItem.get(params.itemId) === progressText) return;
|
|
508
573
|
this.lastCommentaryProgressTextByItem.set(params.itemId, progressText);
|
|
509
574
|
this.emitAgentEvent({
|
|
@@ -570,7 +635,7 @@ var CodexAssistantProjection = class {
|
|
|
570
635
|
const itemId = this.assistantItemOrder[i];
|
|
571
636
|
if (!itemId) continue;
|
|
572
637
|
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
573
|
-
if (this.
|
|
638
|
+
if (this.isNonTerminalAssistantItem(itemId)) continue;
|
|
574
639
|
if (text && !this.isToolProgressEchoText(itemId, text)) return {
|
|
575
640
|
itemId,
|
|
576
641
|
text
|
|
@@ -582,7 +647,7 @@ var CodexAssistantProjection = class {
|
|
|
582
647
|
let replaceable = false;
|
|
583
648
|
for (let index = minIndex; index < this.assistantItemOrder.length; index += 1) {
|
|
584
649
|
const itemId = this.assistantItemOrder[index];
|
|
585
|
-
if (!itemId || this.
|
|
650
|
+
if (!itemId || this.isNonTerminalAssistantItem(itemId)) continue;
|
|
586
651
|
const text = this.assistantTextByItem.get(itemId)?.trim();
|
|
587
652
|
if (!text || this.isToolProgressEchoText(itemId, text)) continue;
|
|
588
653
|
if (isSilentReplyPayloadText(text)) {
|
|
@@ -606,9 +671,26 @@ var CodexAssistantProjection = class {
|
|
|
606
671
|
this.persistableAssistantBarrier = this.assistantItemOrder.length;
|
|
607
672
|
}
|
|
608
673
|
rememberAssistantItem(itemId) {
|
|
609
|
-
if (!itemId
|
|
610
|
-
this.
|
|
611
|
-
|
|
674
|
+
if (!itemId) return;
|
|
675
|
+
if (!this.assistantTimestampByItem.has(itemId)) {
|
|
676
|
+
this.assistantItemOrder.push(itemId);
|
|
677
|
+
this.assistantTimestampByItem.set(itemId, this.nextTranscriptTimestamp());
|
|
678
|
+
}
|
|
679
|
+
if (this.isCommentaryAssistantItem(itemId)) this.checkpointCommentary?.(itemId, {
|
|
680
|
+
read: () => this.readCommentaryMessage(itemId),
|
|
681
|
+
ready: () => this.completedAssistantItemIds.has(itemId)
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
createAsyncDelivery(itemId) {
|
|
685
|
+
if (!this.isAsyncAssistantItem(itemId)) return;
|
|
686
|
+
const text = this.assistantTextByItem.get(itemId);
|
|
687
|
+
const timestamp = this.assistantTimestampByItem.get(itemId);
|
|
688
|
+
if (!text?.trim() || timestamp === void 0) return;
|
|
689
|
+
return {
|
|
690
|
+
itemId,
|
|
691
|
+
message: createAssistantAsyncMessage(this.params, text, itemId, timestamp),
|
|
692
|
+
text
|
|
693
|
+
};
|
|
612
694
|
}
|
|
613
695
|
isToolProgressEchoText(itemId, text) {
|
|
614
696
|
return this.rawPromotedAssistantItemIds.has(itemId) && this.matchesToolProgressEcho(text);
|
|
@@ -618,6 +700,40 @@ function shouldAdvancePersistableAssistantBarrier(item) {
|
|
|
618
700
|
return shouldClearTerminalPresentationForNativeItem(item) || item.type === "dynamicToolCall" || item.type === "sleep";
|
|
619
701
|
}
|
|
620
702
|
//#endregion
|
|
703
|
+
//#region extensions/codex/src/app-server/event-projector-async-delivery.ts
|
|
704
|
+
/** Owns authorization, exactly-once settlement, and terminal retry for async user messages. */
|
|
705
|
+
var CodexAsyncDeliveryProjection = class {
|
|
706
|
+
constructor(params, threadId, turnId, options) {
|
|
707
|
+
this.params = params;
|
|
708
|
+
this.threadId = threadId;
|
|
709
|
+
this.turnId = turnId;
|
|
710
|
+
this.options = options;
|
|
711
|
+
this.settledItemIds = /* @__PURE__ */ new Set();
|
|
712
|
+
this.pendingDeliveries = /* @__PURE__ */ new Map();
|
|
713
|
+
}
|
|
714
|
+
allows(item, reportUnauthorized = false) {
|
|
715
|
+
if (item?.type !== "agentMessage" || item.delivery !== "async") return true;
|
|
716
|
+
const allowed = this.params.disableTools !== true && (this.options.asyncUserMessageAllowed ?? (this.params.toolsAllow === void 0 || this.params.toolsAllow.some((name) => name === "*" || name === "message")));
|
|
717
|
+
if (!allowed && reportUnauthorized) embeddedAgentLog.warn("blocked unauthorized codex async user message", {
|
|
718
|
+
itemId: item.id,
|
|
719
|
+
threadId: this.threadId,
|
|
720
|
+
turnId: this.turnId
|
|
721
|
+
});
|
|
722
|
+
return allowed;
|
|
723
|
+
}
|
|
724
|
+
pending() {
|
|
725
|
+
return [...this.pendingDeliveries.values()];
|
|
726
|
+
}
|
|
727
|
+
async deliver(delivery) {
|
|
728
|
+
if (this.settledItemIds.has(delivery.itemId)) return;
|
|
729
|
+
const settlement = await this.options.onAsyncDelivery?.(delivery);
|
|
730
|
+
if (settlement === "settled") {
|
|
731
|
+
this.settledItemIds.add(delivery.itemId);
|
|
732
|
+
this.pendingDeliveries.delete(delivery.itemId);
|
|
733
|
+
} else if (settlement === "retry") this.pendingDeliveries.set(delivery.itemId, delivery);
|
|
734
|
+
}
|
|
735
|
+
};
|
|
736
|
+
//#endregion
|
|
621
737
|
//#region extensions/codex/src/app-server/event-projector-media.ts
|
|
622
738
|
const GENERATED_IMAGE_MEDIA_SUBDIR = "tool-image-generation";
|
|
623
739
|
var CodexGeneratedMediaProjection = class {
|
|
@@ -911,45 +1027,55 @@ function reasoningMethodOrder(method) {
|
|
|
911
1027
|
const attemptTerminal = agentHarnessAttemptTerminal;
|
|
912
1028
|
//#endregion
|
|
913
1029
|
//#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
1030
|
function buildCodexMessagesSnapshot(params) {
|
|
937
1031
|
const messages = promptSnapshot(params.runParams, params.turnId, params.upstreamUserText);
|
|
938
1032
|
if (params.reasoningText) messages.push(attachCodexMirrorIdentity(params.createAssistantMirrorMessage("Codex reasoning", params.reasoningText), `${params.turnId}:reasoning`));
|
|
939
|
-
|
|
940
|
-
const
|
|
1033
|
+
const commentaryMessages = params.runParams.config?.ui?.prefs?.chatPersistCommentary === false ? [] : params.commentaryMessages.map(({ itemId, message }) => attachCodexMirrorIdentity(message, `${params.turnId}:commentary:${itemId}`));
|
|
1034
|
+
const asyncMessages = params.asyncMessages.map(({ itemId, message }) => attachCodexMirrorIdentity(message, `${params.turnId}:async:${itemId}`));
|
|
1035
|
+
const visibleWorkMessages = [
|
|
1036
|
+
...commentaryMessages,
|
|
1037
|
+
...asyncMessages,
|
|
1038
|
+
...(params.assistantMessages ?? []).map(({ itemId, message }) => attachCodexMirrorIdentity(message, `${params.turnId}:assistant:${itemId}`)),
|
|
1039
|
+
...params.toolMessages
|
|
1040
|
+
].toSorted((left, right) => (asDateTimestampMs(left.timestamp) ?? 0) - (asDateTimestampMs(right.timestamp) ?? 0));
|
|
941
1041
|
messages.push(...visibleWorkMessages);
|
|
942
1042
|
if (params.lastAssistant) messages.push(attachCodexMirrorIdentity(params.lastAssistant, `${params.turnId}:assistant`));
|
|
943
|
-
|
|
1043
|
+
const taint = { tainted: false };
|
|
1044
|
+
return messages.map((message) => projectAgentHarnessTranscriptMessageForDisplay({
|
|
944
1045
|
hidden: params.runParams.trigger === "memory",
|
|
945
|
-
message
|
|
1046
|
+
message: applyCodexTranscriptTaint(message, taint)
|
|
946
1047
|
}));
|
|
947
1048
|
}
|
|
1049
|
+
function buildCodexSteeringMessagesSnapshot(params) {
|
|
1050
|
+
const asyncMessages = params.assistantProjection.collectAsyncMessages().filter(({ itemId }) => params.completedItemIds.has(itemId));
|
|
1051
|
+
const commentaryMessages = params.assistantProjection.collectCommentaryMessages().filter(({ itemId }) => params.completedItemIds.has(itemId));
|
|
1052
|
+
const assistantMessages = params.assistantProjection.collectCompletedAssistantMessages(params.completedItemIds, {
|
|
1053
|
+
tokenUsage: void 0,
|
|
1054
|
+
aborted: false,
|
|
1055
|
+
promptError: void 0
|
|
1056
|
+
});
|
|
1057
|
+
return {
|
|
1058
|
+
messages: buildCodexMessagesSnapshot({
|
|
1059
|
+
runParams: params.runParams,
|
|
1060
|
+
turnId: params.turnId,
|
|
1061
|
+
upstreamUserText: params.upstreamUserText,
|
|
1062
|
+
reasoningText: void 0,
|
|
1063
|
+
asyncMessages,
|
|
1064
|
+
commentaryMessages,
|
|
1065
|
+
assistantMessages,
|
|
1066
|
+
toolMessages: params.toolMessages,
|
|
1067
|
+
lastAssistant: void 0,
|
|
1068
|
+
createAssistantMirrorMessage: (title, text) => params.assistantProjection.createAssistantMirrorMessage(title, text)
|
|
1069
|
+
}).filter((message) => message.role !== "user"),
|
|
1070
|
+
assistantBoundaryItemId: assistantMessages.at(-1)?.itemId
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
948
1073
|
//#endregion
|
|
949
1074
|
//#region extensions/codex/src/app-server/event-projector-result.ts
|
|
950
1075
|
function buildCodexAttemptResult(input) {
|
|
951
1076
|
input.nativeToolLifecycleProjection.finalizeActive();
|
|
952
1077
|
const assistantTexts = input.assistantProjection.collectAssistantTexts();
|
|
1078
|
+
const asyncMessages = input.assistantProjection.collectAsyncMessages();
|
|
953
1079
|
const commentaryMessages = input.assistantProjection.collectCommentaryMessages();
|
|
954
1080
|
const reasoningText = input.reasoningProjection.reasoningText();
|
|
955
1081
|
const planText = input.reasoningProjection.planText();
|
|
@@ -984,7 +1110,7 @@ function buildCodexAttemptResult(input) {
|
|
|
984
1110
|
turnId: input.turnId,
|
|
985
1111
|
upstreamUserText: input.upstreamUserText,
|
|
986
1112
|
reasoningText,
|
|
987
|
-
|
|
1113
|
+
asyncMessages,
|
|
988
1114
|
commentaryMessages,
|
|
989
1115
|
toolMessages: input.toolTranscriptProjection.transcriptMessages,
|
|
990
1116
|
lastAssistant,
|
|
@@ -1050,6 +1176,78 @@ function buildCodexAttemptResult(input) {
|
|
|
1050
1176
|
};
|
|
1051
1177
|
}
|
|
1052
1178
|
//#endregion
|
|
1179
|
+
//#region extensions/codex/src/app-server/transcript-checkpoint.ts
|
|
1180
|
+
/** Commits completed work in receipt order without waiting for the enclosing turn. */
|
|
1181
|
+
var CodexTranscriptCheckpoint = class {
|
|
1182
|
+
constructor(params, threadId, turnId) {
|
|
1183
|
+
this.params = params;
|
|
1184
|
+
this.threadId = threadId;
|
|
1185
|
+
this.turnId = turnId;
|
|
1186
|
+
this.pending = [];
|
|
1187
|
+
this.commentaryItemIds = /* @__PURE__ */ new Set();
|
|
1188
|
+
this.lastTimestamp = 0;
|
|
1189
|
+
this.writing = Promise.resolve();
|
|
1190
|
+
this.tainted = false;
|
|
1191
|
+
this.closed = false;
|
|
1192
|
+
this.nextTimestamp = () => {
|
|
1193
|
+
this.lastTimestamp = Math.max(Date.now(), this.lastTimestamp + 1);
|
|
1194
|
+
return this.lastTimestamp;
|
|
1195
|
+
};
|
|
1196
|
+
this.enqueueCommentary = (itemId, entry) => {
|
|
1197
|
+
if (this.params.config?.ui?.prefs?.chatPersistCommentary === false || this.commentaryItemIds.has(itemId)) return;
|
|
1198
|
+
this.commentaryItemIds.add(itemId);
|
|
1199
|
+
this.enqueue({
|
|
1200
|
+
...entry,
|
|
1201
|
+
read: () => {
|
|
1202
|
+
const message = entry.read();
|
|
1203
|
+
return message ? attachCodexMirrorIdentity(message, `${this.turnId}:commentary:${itemId}`) : void 0;
|
|
1204
|
+
}
|
|
1205
|
+
});
|
|
1206
|
+
};
|
|
1207
|
+
this.enqueue = (entry) => {
|
|
1208
|
+
if (this.params.sessionTarget && !this.closed) this.pending.push(entry);
|
|
1209
|
+
};
|
|
1210
|
+
}
|
|
1211
|
+
flush(close = false) {
|
|
1212
|
+
if (this.closed) return this.writing;
|
|
1213
|
+
this.closed = close;
|
|
1214
|
+
this.writing = this.writing.then(async () => {
|
|
1215
|
+
const blocked = close ? -1 : this.pending.findIndex((entry) => entry.ready?.() === false);
|
|
1216
|
+
const count = blocked < 0 ? this.pending.length : blocked;
|
|
1217
|
+
if (count === 0) return;
|
|
1218
|
+
const taint = { tainted: this.tainted };
|
|
1219
|
+
const messages = this.pending.slice(0, count).flatMap((entry) => {
|
|
1220
|
+
const message = entry.read();
|
|
1221
|
+
return message ? [projectAgentHarnessTranscriptMessageForDisplay({
|
|
1222
|
+
hidden: this.params.trigger === "memory",
|
|
1223
|
+
message: applyCodexTranscriptTaint(message, taint)
|
|
1224
|
+
})] : [];
|
|
1225
|
+
});
|
|
1226
|
+
try {
|
|
1227
|
+
await codexTranscriptMirrorRuntime.mirror({
|
|
1228
|
+
...this.params.sessionTarget,
|
|
1229
|
+
sessionId: this.params.sessionId,
|
|
1230
|
+
cwd: this.params.workspaceDir,
|
|
1231
|
+
messages,
|
|
1232
|
+
idempotencyScope: `codex-app-server:${this.threadId}`,
|
|
1233
|
+
runId: this.params.runId,
|
|
1234
|
+
runMirrorIdentityPrefix: `${this.turnId}:`,
|
|
1235
|
+
config: this.params.config
|
|
1236
|
+
});
|
|
1237
|
+
this.pending.splice(0, count);
|
|
1238
|
+
this.tainted = taint.tainted;
|
|
1239
|
+
} catch (error) {
|
|
1240
|
+
embeddedAgentLog.warn("failed to checkpoint codex app-server transcript", {
|
|
1241
|
+
runId: this.params.runId,
|
|
1242
|
+
sessionId: this.params.sessionId,
|
|
1243
|
+
error: formatErrorMessage(error)
|
|
1244
|
+
});
|
|
1245
|
+
}
|
|
1246
|
+
});
|
|
1247
|
+
return this.writing;
|
|
1248
|
+
}
|
|
1249
|
+
};
|
|
1250
|
+
//#endregion
|
|
1053
1251
|
//#region extensions/codex/src/app-server/usage-limit-error.ts
|
|
1054
1252
|
/**
|
|
1055
1253
|
* Enriches Codex usage-limit failures with current rate-limit information and
|
|
@@ -1204,7 +1402,8 @@ var CodexAppServerEventProjector = class {
|
|
|
1204
1402
|
this.aborted = false;
|
|
1205
1403
|
this.responseCompletions = new CodexResponseCompletionProjection();
|
|
1206
1404
|
this.completedCompactionCount = 0;
|
|
1207
|
-
this.
|
|
1405
|
+
this.transcriptCheckpoint = new CodexTranscriptCheckpoint(params, threadId, turnId);
|
|
1406
|
+
this.asyncDeliveryProjection = new CodexAsyncDeliveryProjection(params, threadId, turnId, options);
|
|
1208
1407
|
this.contextTokens = options.initialContextTokens;
|
|
1209
1408
|
this.contextTokensSource = options.initialContextTokens === void 0 ? void 0 : "resolved";
|
|
1210
1409
|
this.diagnostics = new CodexProjectionDiagnostics(threadId, turnId);
|
|
@@ -1216,35 +1415,37 @@ var CodexAppServerEventProjector = class {
|
|
|
1216
1415
|
signal: options.runAbortSignal
|
|
1217
1416
|
});
|
|
1218
1417
|
this.toolProgressProjection = new CodexToolProgressProjection(params);
|
|
1219
|
-
this.toolTranscriptProjection = new CodexToolTranscriptProjection(params, threadId, turnId, this.toolProgressProjection,
|
|
1418
|
+
this.toolTranscriptProjection = new CodexToolTranscriptProjection(params, threadId, turnId, this.toolProgressProjection, this.transcriptCheckpoint.nextTimestamp, {
|
|
1220
1419
|
nativePostToolUseRelayEnabled: options.nativePostToolUseRelayEnabled,
|
|
1221
1420
|
prepareNativeMcpAppResultDetails: options.prepareNativeMcpAppResultDetails,
|
|
1222
|
-
trajectoryRecorder: options.trajectoryRecorder
|
|
1421
|
+
trajectoryRecorder: options.trajectoryRecorder,
|
|
1422
|
+
checkpointMessage: this.transcriptCheckpoint.enqueue
|
|
1223
1423
|
});
|
|
1224
1424
|
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),
|
|
1425
|
+
this.assistantProjection = new CodexAssistantProjection(params, (event) => this.emitAgentEvent(event), (text) => this.toolProgressProjection.matchesEcho(text), this.transcriptCheckpoint.nextTimestamp, this.transcriptCheckpoint.enqueueCommentary);
|
|
1226
1426
|
this.reasoningProjection = new CodexReasoningProjection(params, (event) => this.emitAgentEvent(event), options.onNativePlanUpdate);
|
|
1227
1427
|
}
|
|
1228
|
-
nextTranscriptTimestamp() {
|
|
1229
|
-
this.lastTranscriptTimestamp = Math.max(Date.now(), this.lastTranscriptTimestamp + 1);
|
|
1230
|
-
return this.lastTranscriptTimestamp;
|
|
1231
|
-
}
|
|
1232
1428
|
getCompletedTurnStatus() {
|
|
1233
1429
|
return this.completedTurn?.status;
|
|
1234
1430
|
}
|
|
1235
1431
|
buildSteeringTranscriptPrefix() {
|
|
1236
|
-
const
|
|
1237
|
-
return buildCodexMessagesSnapshot({
|
|
1432
|
+
const snapshot = buildCodexSteeringMessagesSnapshot({
|
|
1238
1433
|
runParams: this.params,
|
|
1239
1434
|
turnId: this.turnId,
|
|
1240
1435
|
upstreamUserText: this.options.upstreamUserText,
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1436
|
+
completedItemIds: this.completedItemIds,
|
|
1437
|
+
assistantProjection: this.assistantProjection,
|
|
1438
|
+
toolMessages: this.toolTranscriptProjection.transcriptMessages
|
|
1439
|
+
});
|
|
1440
|
+
this.pendingSteeringAssistantBoundaryItemId = snapshot.assistantBoundaryItemId;
|
|
1441
|
+
return snapshot.messages;
|
|
1442
|
+
}
|
|
1443
|
+
markSteeringTranscriptPersisted() {
|
|
1444
|
+
const itemId = this.pendingSteeringAssistantBoundaryItemId;
|
|
1445
|
+
if (itemId) {
|
|
1446
|
+
this.assistantProjection.markAssistantBoundaryPersisted(itemId);
|
|
1447
|
+
this.pendingSteeringAssistantBoundaryItemId = void 0;
|
|
1448
|
+
}
|
|
1248
1449
|
}
|
|
1249
1450
|
hasCompletedTerminalAssistantText() {
|
|
1250
1451
|
return this.assistantProjection.hasCompletedTerminalAssistantText(this.completedItemIds);
|
|
@@ -1284,8 +1485,9 @@ var CodexAppServerEventProjector = class {
|
|
|
1284
1485
|
if (!params) return;
|
|
1285
1486
|
if (notification.method === "hook/started" || notification.method === "hook/completed") {
|
|
1286
1487
|
if (!this.isHookNotificationForCurrentThread(params)) return;
|
|
1287
|
-
} else if (notification.method === "guardianWarning") {
|
|
1288
|
-
|
|
1488
|
+
} else if (notification.method === "guardianWarning" || notification.method === "warning" || notification.method === "configWarning") {
|
|
1489
|
+
const warningThreadId = readCodexNotificationThreadId(params);
|
|
1490
|
+
if (notification.method === "guardianWarning" && warningThreadId !== this.threadId || warningThreadId && warningThreadId !== this.threadId) return;
|
|
1289
1491
|
} else if (!isCodexNotificationForTurn(params, this.threadId, this.turnId)) return;
|
|
1290
1492
|
if (notification.method !== "guardianWarning" && notification.method !== "item/autoApprovalReview/started" && notification.method !== "item/autoApprovalReview/completed") this.eventProjection.flushPendingGuardianWarning();
|
|
1291
1493
|
this.nativeToolLifecycleProjector.handleNotification(notification);
|
|
@@ -1306,9 +1508,11 @@ var CodexAppServerEventProjector = class {
|
|
|
1306
1508
|
break;
|
|
1307
1509
|
case "item/started":
|
|
1308
1510
|
await this.handleItemStarted(params);
|
|
1511
|
+
await this.transcriptCheckpoint.flush();
|
|
1309
1512
|
break;
|
|
1310
1513
|
case "item/completed":
|
|
1311
1514
|
await this.handleItemCompleted(params);
|
|
1515
|
+
await this.transcriptCheckpoint.flush();
|
|
1312
1516
|
break;
|
|
1313
1517
|
case "item/commandExecution/outputDelta":
|
|
1314
1518
|
this.toolProgressProjection.handleOutputDelta(params, "bash");
|
|
@@ -1317,9 +1521,16 @@ var CodexAppServerEventProjector = class {
|
|
|
1317
1521
|
case "item/autoApprovalReview/completed":
|
|
1318
1522
|
this.eventProjection.handleGuardianReview(notification.method, params);
|
|
1319
1523
|
break;
|
|
1524
|
+
case "autoApprovalReview/strictReviewRequired":
|
|
1525
|
+
this.eventProjection.handleStrictReviewRequired(params);
|
|
1526
|
+
break;
|
|
1320
1527
|
case "guardianWarning":
|
|
1321
1528
|
this.eventProjection.handleGuardianWarning(params);
|
|
1322
1529
|
break;
|
|
1530
|
+
case "warning":
|
|
1531
|
+
case "configWarning":
|
|
1532
|
+
this.eventProjection.handleWarning(params);
|
|
1533
|
+
break;
|
|
1323
1534
|
case "hook/started":
|
|
1324
1535
|
case "hook/completed":
|
|
1325
1536
|
this.eventProjection.handleHook(notification.method, params);
|
|
@@ -1331,7 +1542,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1331
1542
|
this.contextTokensSource = this.params.authoredContextTokenCap === void 0 ? "runtime" : "runtime-configured";
|
|
1332
1543
|
}
|
|
1333
1544
|
this.emitAgentEvent({
|
|
1334
|
-
stream: "
|
|
1545
|
+
stream: "usage",
|
|
1335
1546
|
data
|
|
1336
1547
|
});
|
|
1337
1548
|
});
|
|
@@ -1344,6 +1555,10 @@ var CodexAppServerEventProjector = class {
|
|
|
1344
1555
|
break;
|
|
1345
1556
|
case "rawResponseItem/completed":
|
|
1346
1557
|
await this.handleRawResponseItemCompleted(params);
|
|
1558
|
+
await this.transcriptCheckpoint.flush();
|
|
1559
|
+
break;
|
|
1560
|
+
case "model/rerouted":
|
|
1561
|
+
this.eventProjection.handleModelRerouted(params);
|
|
1347
1562
|
break;
|
|
1348
1563
|
case "error": {
|
|
1349
1564
|
this.responseCompletions.clear();
|
|
@@ -1363,7 +1578,6 @@ var CodexAppServerEventProjector = class {
|
|
|
1363
1578
|
case "item/fileChange/outputDelta":
|
|
1364
1579
|
case "item/fileChange/patchUpdated":
|
|
1365
1580
|
case "item/mcpToolCall/progress":
|
|
1366
|
-
case "model/rerouted":
|
|
1367
1581
|
case "model/verification":
|
|
1368
1582
|
case "turn/moderationMetadata":
|
|
1369
1583
|
case "model/safetyBuffering/updated": break;
|
|
@@ -1495,7 +1709,9 @@ var CodexAppServerEventProjector = class {
|
|
|
1495
1709
|
this.activeItemIds.delete(itemId);
|
|
1496
1710
|
this.completedItemIds.add(itemId);
|
|
1497
1711
|
}
|
|
1498
|
-
this.
|
|
1712
|
+
if (!this.asyncDeliveryProjection.allows(item, true)) return;
|
|
1713
|
+
const asyncMessage = this.assistantProjection.recordItemCompleted(item, itemId, this.activeItemIds);
|
|
1714
|
+
if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
|
|
1499
1715
|
this.reasoningProjection.recordItem(item);
|
|
1500
1716
|
await this.generatedMediaProjection.recordNative(item);
|
|
1501
1717
|
if (item?.type === "contextCompaction" && itemId) {
|
|
@@ -1525,9 +1741,9 @@ var CodexAppServerEventProjector = class {
|
|
|
1525
1741
|
threadId: this.threadId,
|
|
1526
1742
|
turnId: this.turnId,
|
|
1527
1743
|
itemId,
|
|
1528
|
-
timestamp: this.
|
|
1744
|
+
timestamp: this.transcriptCheckpoint.nextTimestamp()
|
|
1529
1745
|
});
|
|
1530
|
-
this.emitCompactionEnd(itemId, true);
|
|
1746
|
+
this.eventProjection.emitCompactionEnd(itemId, true);
|
|
1531
1747
|
}
|
|
1532
1748
|
this.toolProgressProjection.recordToolMeta(item);
|
|
1533
1749
|
this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
|
|
@@ -1573,10 +1789,11 @@ var CodexAppServerEventProjector = class {
|
|
|
1573
1789
|
for (const itemId of failedCompactionItemIds) {
|
|
1574
1790
|
this.activeItemIds.delete(itemId);
|
|
1575
1791
|
this.activeCompactionItemIds.delete(itemId);
|
|
1576
|
-
this.emitCompactionEnd(itemId, false);
|
|
1792
|
+
this.eventProjection.emitCompactionEnd(itemId, false);
|
|
1577
1793
|
}
|
|
1578
1794
|
}
|
|
1579
1795
|
const turnItems = turn.items ?? [];
|
|
1796
|
+
const unsettledAsyncDeliveries = this.asyncDeliveryProjection.pending();
|
|
1580
1797
|
for (let index = turnItems.length - 1; index >= 0; index -= 1) {
|
|
1581
1798
|
const item = turnItems[index];
|
|
1582
1799
|
if (!item || !this.isCurrentTurnSnapshotItem(item)) continue;
|
|
@@ -1587,8 +1804,10 @@ var CodexAppServerEventProjector = class {
|
|
|
1587
1804
|
}
|
|
1588
1805
|
}
|
|
1589
1806
|
for (const item of turnItems) {
|
|
1807
|
+
if (!this.asyncDeliveryProjection.allows(item)) continue;
|
|
1590
1808
|
this.diagnostics.warnUnknownItemStatus(item);
|
|
1591
|
-
this.assistantProjection.recordSnapshotItem(item);
|
|
1809
|
+
const asyncMessage = this.assistantProjection.recordSnapshotItem(item);
|
|
1810
|
+
if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
|
|
1592
1811
|
this.reasoningProjection.recordItem(item);
|
|
1593
1812
|
await this.generatedMediaProjection.recordNative(item);
|
|
1594
1813
|
this.toolProgressProjection.recordToolMeta(item);
|
|
@@ -1601,23 +1820,11 @@ var CodexAppServerEventProjector = class {
|
|
|
1601
1820
|
this.toolProgressProjection.emitToolResultOutput(item);
|
|
1602
1821
|
}
|
|
1603
1822
|
this.toolProgressProjection.approvalTimeoutKinds.clear();
|
|
1823
|
+
for (const delivery of unsettledAsyncDeliveries) await this.asyncDeliveryProjection.deliver(delivery);
|
|
1604
1824
|
this.assistantProjection.finalizeAnswerCandidate(turn);
|
|
1605
1825
|
this.activeCompactionItemIds.clear();
|
|
1606
1826
|
await this.reasoningProjection.maybeEndReasoning();
|
|
1607
1827
|
}
|
|
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
1828
|
async emitSnapshotOnlyNativeToolProgress(item) {
|
|
1622
1829
|
if (!shouldSynthesizeToolProgressForItem(item) || !this.isCurrentTurnSnapshotItem(item) || this.completedItemIds.has(item.id) || itemStatus(item) === "running") return;
|
|
1623
1830
|
if (!this.activeItemIds.has(item.id)) {
|
|
@@ -1675,24 +1882,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1675
1882
|
return usageLimitMessage ? createCodexUsageLimitPromptError(usageLimitMessage) : readCodexErrorNotificationMessage(params);
|
|
1676
1883
|
}
|
|
1677
1884
|
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
|
-
}
|
|
1885
|
+
emitCodexAgentEvent(this.params, event);
|
|
1696
1886
|
}
|
|
1697
1887
|
isHookNotificationForCurrentThread(params) {
|
|
1698
1888
|
const threadId = readStringField(params, "threadId");
|
|
@@ -1701,11 +1891,28 @@ var CodexAppServerEventProjector = class {
|
|
|
1701
1891
|
}
|
|
1702
1892
|
};
|
|
1703
1893
|
//#endregion
|
|
1894
|
+
//#region extensions/codex/src/app-server/mcp-tool-metadata.ts
|
|
1895
|
+
/** Hosted app ownership is authoritative only on metadata supplied by Codex. */
|
|
1896
|
+
function readCodexMcpToolConnectorId(tool) {
|
|
1897
|
+
const metadata = asOptionalRecord(asOptionalRecord(tool)?.["_meta"]);
|
|
1898
|
+
return normalizeOptionalString(metadata?.connector_id) ?? normalizeOptionalString(metadata?.connectorId);
|
|
1899
|
+
}
|
|
1900
|
+
/** Preserve MCP App visibility so model-only tools cannot become widget authority. */
|
|
1901
|
+
function readCodexMcpToolUiVisibility(tool) {
|
|
1902
|
+
const visibility = asOptionalRecord(asOptionalRecord(asOptionalRecord(tool)?.["_meta"])?.ui)?.visibility;
|
|
1903
|
+
if (!Array.isArray(visibility)) return;
|
|
1904
|
+
return [...new Set(visibility.filter((value) => value === "app" || value === "model"))].toSorted();
|
|
1905
|
+
}
|
|
1906
|
+
//#endregion
|
|
1704
1907
|
//#region extensions/codex/src/app-server/native-mcp-app.ts
|
|
1908
|
+
const CODEX_APPS_MCP_SERVER$1 = "codex_apps";
|
|
1705
1909
|
function readMcpAppResourceUri(item) {
|
|
1706
1910
|
const uri = normalizeOptionalString(asOptionalRecord(item.appContext)?.resourceUri) ?? normalizeOptionalString(item.mcpAppResourceUri);
|
|
1707
1911
|
return uri?.startsWith("ui://") ? uri : void 0;
|
|
1708
1912
|
}
|
|
1913
|
+
function readMcpAppConnectorId(item) {
|
|
1914
|
+
return normalizeOptionalString(asOptionalRecord(item.appContext)?.connectorId);
|
|
1915
|
+
}
|
|
1709
1916
|
function readMcpToolResult(item) {
|
|
1710
1917
|
const result = asOptionalRecord(item.result);
|
|
1711
1918
|
if (!result || !Array.isArray(result.content)) return;
|
|
@@ -1743,13 +1950,16 @@ function createNativeMcpRuntime(params) {
|
|
|
1743
1950
|
launchSummary: "Codex native MCP connection",
|
|
1744
1951
|
toolCount: Object.keys(status.tools).length
|
|
1745
1952
|
}])),
|
|
1746
|
-
tools: loaded.flatMap((status) => statusTools(status).map((tool) =>
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1953
|
+
tools: loaded.flatMap((status) => statusTools(status).map((tool) => {
|
|
1954
|
+
const uiVisibility = readCodexMcpToolUiVisibility(tool);
|
|
1955
|
+
return Object.assign({
|
|
1956
|
+
serverName: status.name,
|
|
1957
|
+
safeServerName: status.name,
|
|
1958
|
+
toolName: String(tool.name),
|
|
1959
|
+
inputSchema: asOptionalRecord(tool.inputSchema) ?? { type: "object" },
|
|
1960
|
+
fallbackDescription: normalizeOptionalString(tool.description) ?? String(tool.name)
|
|
1961
|
+
}, uiVisibility ? { uiVisibility } : {});
|
|
1962
|
+
}))
|
|
1753
1963
|
};
|
|
1754
1964
|
return catalog;
|
|
1755
1965
|
};
|
|
@@ -1777,11 +1987,18 @@ function createNativeMcpRuntime(params) {
|
|
|
1777
1987
|
const status = (await loadStatuses()).find((entry) => entry.name === serverName);
|
|
1778
1988
|
return { tools: status ? statusTools(status) : [] };
|
|
1779
1989
|
},
|
|
1780
|
-
readResource: async (serverName, uri) =>
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1990
|
+
readResource: async (serverName, uri) => {
|
|
1991
|
+
const isCodexAppsServer = serverName === CODEX_APPS_MCP_SERVER$1;
|
|
1992
|
+
const response = await params.client.request("mcpServer/resource/read", {
|
|
1993
|
+
threadId: params.threadId,
|
|
1994
|
+
...isCodexAppsServer ? { originCallId: params.originCallId } : {},
|
|
1995
|
+
server: serverName,
|
|
1996
|
+
uri,
|
|
1997
|
+
...params.connectorId ? { connectorId: params.connectorId } : {}
|
|
1998
|
+
});
|
|
1999
|
+
if (isCodexAppsServer && response.originCallId !== params.originCallId) throw new Error(`Codex MCP resource response originCallId mismatch: expected ${params.originCallId}, received ${response.originCallId}`);
|
|
2000
|
+
return response;
|
|
2001
|
+
},
|
|
1785
2002
|
listResources: async (serverName) => {
|
|
1786
2003
|
return { resources: (await loadStatuses()).find((entry) => entry.name === serverName)?.resources ?? [] };
|
|
1787
2004
|
},
|
|
@@ -1794,15 +2011,25 @@ function createNativeMcpRuntime(params) {
|
|
|
1794
2011
|
}
|
|
1795
2012
|
function createCodexNativeMcpAppResultDetailsPreparer(params) {
|
|
1796
2013
|
if (params.attempt.config?.mcp?.apps?.enabled !== true) return;
|
|
1797
|
-
const runtime = createNativeMcpRuntime(params);
|
|
1798
2014
|
return async (item) => {
|
|
1799
2015
|
const serverName = normalizeOptionalString(item.server);
|
|
1800
2016
|
const toolName = normalizeOptionalString(item.tool);
|
|
1801
2017
|
const uiResourceUri = readMcpAppResourceUri(item);
|
|
2018
|
+
const connectorId = readMcpAppConnectorId(item);
|
|
1802
2019
|
const toolResult = readMcpToolResult(item);
|
|
1803
2020
|
if (!serverName || !toolName || !uiResourceUri || !toolResult) return;
|
|
1804
|
-
|
|
1805
|
-
|
|
2021
|
+
if (serverName === CODEX_APPS_MCP_SERVER$1 && !connectorId) return;
|
|
2022
|
+
const runtime = createNativeMcpRuntime({
|
|
2023
|
+
...params,
|
|
2024
|
+
originCallId: item.id,
|
|
2025
|
+
...connectorId ? { connectorId } : {}
|
|
2026
|
+
});
|
|
2027
|
+
const tools = (await runtime.listTools?.(serverName))?.tools ?? [];
|
|
2028
|
+
const allowedAppToolNames = new Set(tools.filter((tool) => {
|
|
2029
|
+
const uiVisibility = readCodexMcpToolUiVisibility(tool);
|
|
2030
|
+
return (uiVisibility === void 0 || uiVisibility.includes("app")) && (serverName !== CODEX_APPS_MCP_SERVER$1 || readCodexMcpToolConnectorId(tool) === connectorId);
|
|
2031
|
+
}).map((tool) => tool.name));
|
|
2032
|
+
if (!allowedAppToolNames.has(toolName)) return;
|
|
1806
2033
|
return await prepareHarnessNativeMcpAppPreview({
|
|
1807
2034
|
runtime,
|
|
1808
2035
|
serverName,
|
|
@@ -2208,6 +2435,16 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2208
2435
|
}, resourceState.thread.threadId, activeTurnId, {
|
|
2209
2436
|
initialContextTokens: connection.mutable.startupContextTokens,
|
|
2210
2437
|
nativePostToolUseRelayEnabled: resourceState.nativeHookRelay?.allowedEvents.includes("post_tool_use") === true && resourceState.nativeHookRelay.shouldRelayEvent("post_tool_use"),
|
|
2438
|
+
asyncUserMessageAllowed: params.disableTools !== true && (params.toolsAllow === void 0 || toolBridge.availableTools.some((tool) => tool.name === "message")),
|
|
2439
|
+
onAsyncDelivery: async (delivery) => {
|
|
2440
|
+
return await codexTranscriptMirrorRuntime.deliverAsyncMessageBestEffort({
|
|
2441
|
+
params: dynamicToolParams,
|
|
2442
|
+
cwd: effectiveCwd,
|
|
2443
|
+
threadId: resourceState.thread.threadId,
|
|
2444
|
+
turnId: activeTurnId,
|
|
2445
|
+
...delivery
|
|
2446
|
+
});
|
|
2447
|
+
},
|
|
2211
2448
|
readRecentRateLimits: () => readRecentCodexRateLimits(resourceState.client),
|
|
2212
2449
|
runAbortSignal: runAbortController.signal,
|
|
2213
2450
|
remoteWorkspaceRoot: connection.appServer.remoteWorkspaceRoot,
|
|
@@ -2265,6 +2502,18 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2265
2502
|
turnWatches.armAttemptIdleWatch();
|
|
2266
2503
|
turnWatches.touchActivity("turn:start", { attemptProgress: true });
|
|
2267
2504
|
for (const failure of pendingNativePreToolUseFailures.splice(0)) activeProjector.recordNativeToolPreToolUseFailure(failure);
|
|
2505
|
+
const notifyUserMessagePersisted = createCodexAppServerUserMessagePersistenceNotifier(params);
|
|
2506
|
+
const promptMirrorPromise = mirrorPromptAtTurnStartBestEffort({
|
|
2507
|
+
params,
|
|
2508
|
+
agentId: sessionAgentId,
|
|
2509
|
+
notifyUserMessagePersisted,
|
|
2510
|
+
sessionKey: sandboxSessionKey,
|
|
2511
|
+
cwd: effectiveCwd,
|
|
2512
|
+
threadId: resourceState.thread.threadId,
|
|
2513
|
+
turnId: activeTurnId,
|
|
2514
|
+
upstreamUserText: turnState.codexTurnPromptText
|
|
2515
|
+
});
|
|
2516
|
+
await promptMirrorPromise;
|
|
2268
2517
|
if (resourceState.turnRoute) try {
|
|
2269
2518
|
await resourceState.turnRoute.bindTurn(activeTurnId);
|
|
2270
2519
|
} catch (error) {
|
|
@@ -2289,40 +2538,65 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2289
2538
|
turnId: activeTurnId
|
|
2290
2539
|
});
|
|
2291
2540
|
}
|
|
2292
|
-
const
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
turnId: activeTurnId,
|
|
2301
|
-
upstreamUserText: turnState.codexTurnPromptText
|
|
2541
|
+
const assertSteeringActive = () => {
|
|
2542
|
+
params.hostCapabilities.assertActive();
|
|
2543
|
+
runAbortController.signal.throwIfAborted();
|
|
2544
|
+
if (state.completed || state.terminalTurnNotificationQueued || state.timedOut) throw new Error("codex app-server turn is no longer accepting steering");
|
|
2545
|
+
};
|
|
2546
|
+
const workspaceOnly = resolveAttemptFsWorkspaceOnly({
|
|
2547
|
+
config: params.config,
|
|
2548
|
+
sessionAgentId
|
|
2302
2549
|
});
|
|
2550
|
+
const imageContext = {
|
|
2551
|
+
workspaceDir: connection.effectiveWorkspace,
|
|
2552
|
+
model: params.model,
|
|
2553
|
+
config: params.config,
|
|
2554
|
+
workspaceOnly,
|
|
2555
|
+
localRoots: workspaceOnly ? void 0 : getAgentScopedMediaLocalRoots(params.config ?? {}, sessionAgentId),
|
|
2556
|
+
sandbox: connection.sandbox?.enabled && connection.sandbox.fsBridge ? {
|
|
2557
|
+
root: connection.sandbox.workspaceDir,
|
|
2558
|
+
bridge: connection.sandbox.fsBridge
|
|
2559
|
+
} : void 0
|
|
2560
|
+
};
|
|
2303
2561
|
const activeSteeringQueue = createCodexSteeringQueue({
|
|
2304
2562
|
client: resourceState.client,
|
|
2305
2563
|
threadId: resourceState.thread.threadId,
|
|
2306
2564
|
turnId: activeTurnId,
|
|
2307
2565
|
requestTimeoutMs: connection.appServer.requestTimeoutMs,
|
|
2308
2566
|
signal: runAbortController.signal,
|
|
2567
|
+
assertActive: assertSteeringActive,
|
|
2568
|
+
prepareMessage: async (text, options) => {
|
|
2569
|
+
const result = await detectAndLoadAgentHarnessPromptImages({
|
|
2570
|
+
...imageContext,
|
|
2571
|
+
prompt: text,
|
|
2572
|
+
existingImages: options.images,
|
|
2573
|
+
imageOrder: options.imageOrder,
|
|
2574
|
+
media: options.media,
|
|
2575
|
+
userTurnTranscriptRecorder: options.userTurnTranscriptRecorder
|
|
2576
|
+
});
|
|
2577
|
+
if (result.failedMediaCount) throw new Error(`failed to hydrate ${result.failedMediaCount} structured image attachment(s) for Codex steering`);
|
|
2578
|
+
return buildCodexUserInput(text, result.images);
|
|
2579
|
+
},
|
|
2309
2580
|
beforeConfirmConsumed: async (items) => {
|
|
2310
2581
|
const inboundItems = items.filter((item) => item.isInboundUserMessage === true);
|
|
2311
2582
|
if (inboundItems.length === 0) return;
|
|
2312
2583
|
await promptMirrorPromise;
|
|
2313
2584
|
const messages = activeProjector.buildSteeringTranscriptPrefix();
|
|
2314
|
-
if (params.sessionTarget && messages.length > 0)
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2585
|
+
if (params.sessionTarget && messages.length > 0) {
|
|
2586
|
+
await codexTranscriptMirrorRuntime.mirror({
|
|
2587
|
+
agentId: sessionAgentId,
|
|
2588
|
+
sessionKey: contextSessionKey,
|
|
2589
|
+
sessionId: params.sessionId,
|
|
2590
|
+
storePath: params.sessionTarget.storePath,
|
|
2591
|
+
cwd: effectiveCwd,
|
|
2592
|
+
messages,
|
|
2593
|
+
idempotencyScope: `codex-app-server:${resourceState.thread.threadId}`,
|
|
2594
|
+
runId: params.runId,
|
|
2595
|
+
runMirrorIdentityPrefix: `${activeTurnId}:`,
|
|
2596
|
+
config: params.config
|
|
2597
|
+
});
|
|
2598
|
+
activeProjector.markSteeringTranscriptPersisted();
|
|
2599
|
+
}
|
|
2326
2600
|
for (const item of inboundItems) {
|
|
2327
2601
|
const recorder = item.userTurnTranscriptRecorder;
|
|
2328
2602
|
if (!recorder) continue;
|
|
@@ -2333,7 +2607,8 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2333
2607
|
});
|
|
2334
2608
|
steeringQueueRef.current = activeSteeringQueue;
|
|
2335
2609
|
const claimPendingUserInputAnswer = async (text, optionsLocal) => {
|
|
2336
|
-
if (optionsLocal?.isInboundUserMessage !== true || optionsLocal
|
|
2610
|
+
if (optionsLocal?.isInboundUserMessage !== true || hasPromptImageInput(optionsLocal)) return false;
|
|
2611
|
+
assertSteeringActive();
|
|
2337
2612
|
return await claimPendingAgentQuestionAnswer({
|
|
2338
2613
|
sessionKey: params.sessionKey ?? params.sessionId,
|
|
2339
2614
|
text,
|
|
@@ -2347,14 +2622,17 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2347
2622
|
resolvedBy
|
|
2348
2623
|
});
|
|
2349
2624
|
const queueMessage = async (text, optionsLocal) => {
|
|
2350
|
-
const isInboundUserMessage = optionsLocal?.isInboundUserMessage === true;
|
|
2351
2625
|
if (await claimPendingUserInputAnswer(text, optionsLocal)) {
|
|
2352
2626
|
optionsLocal?.onQueueAccepted?.(true);
|
|
2353
2627
|
return;
|
|
2354
|
-
}
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2628
|
+
}
|
|
2629
|
+
if (optionsLocal?.isInboundUserMessage === true && hasPromptImageInput(optionsLocal)) {
|
|
2630
|
+
assertSteeringActive();
|
|
2631
|
+
try {
|
|
2632
|
+
await cancelPendingUserInput("image-reply");
|
|
2633
|
+
} catch (error) {
|
|
2634
|
+
embeddedAgentLog.warn("failed to cancel codex gateway question before image steering", { error });
|
|
2635
|
+
}
|
|
2358
2636
|
}
|
|
2359
2637
|
try {
|
|
2360
2638
|
await activeSteeringQueue.queue(text, optionsLocal);
|
|
@@ -2369,6 +2647,7 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2369
2647
|
const handle = {
|
|
2370
2648
|
kind: "embedded",
|
|
2371
2649
|
runId: params.runId,
|
|
2650
|
+
startedAtMs: params.startedAtMs,
|
|
2372
2651
|
toolAuthorityFingerprint: params.toolAuthorityFingerprint,
|
|
2373
2652
|
claimPendingUserInputAnswer,
|
|
2374
2653
|
cancelPendingUserInput,
|
|
@@ -2383,7 +2662,7 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2383
2662
|
isAbortable: () => !terminalState.terminalOutcomeFrozen || terminalState.sharedAbortAllowedAfterTerminalOutcome,
|
|
2384
2663
|
isCompacting: () => projectorRef.current?.isCompacting() ?? false,
|
|
2385
2664
|
supportsTranscriptCommitWait: true,
|
|
2386
|
-
supportsQueueMessageImages:
|
|
2665
|
+
supportsQueueMessageImages: params.model.input.includes("image"),
|
|
2387
2666
|
sourceReplyDeliveryMode: params.sourceReplyDeliveryMode,
|
|
2388
2667
|
taskSuggestionDeliveryMode: params.taskSuggestionDeliveryMode,
|
|
2389
2668
|
cancel: () => abortExplicitly("cancelled"),
|
|
@@ -2412,7 +2691,15 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
|
|
|
2412
2691
|
})().finally(completeTurn);
|
|
2413
2692
|
return;
|
|
2414
2693
|
}
|
|
2415
|
-
interruptTurn(activeTurnId)
|
|
2694
|
+
const interrupted = interruptTurn(activeTurnId);
|
|
2695
|
+
if (terminalState.explicitCancellationObserved) state.abortCleanup = interrupted.then(async (confirmed) => {
|
|
2696
|
+
if (!confirmed) throw new Error("Codex cancellation could not confirm the turn stopped; background terminals may still be running.");
|
|
2697
|
+
await terminateCodexBackgroundTerminals(resourceState.client, resourceState.thread.threadId);
|
|
2698
|
+
});
|
|
2699
|
+
(terminalState.explicitCancellationObserved ? state.abortCleanup : interrupted).then(completeTurn, (error) => {
|
|
2700
|
+
embeddedAgentLog.warn("codex app-server cancellation cleanup failed", { error });
|
|
2701
|
+
completeTurn();
|
|
2702
|
+
});
|
|
2416
2703
|
};
|
|
2417
2704
|
runAbortController.signal.addEventListener("abort", abortListener, { once: true });
|
|
2418
2705
|
if (runAbortController.signal.aborted) abortListener();
|
|
@@ -2437,6 +2724,8 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2437
2724
|
const { codexModelCallDiagnostics } = requestRuntime;
|
|
2438
2725
|
const { activeTurnId, abortListener, handle, freezeRunTerminalOutcome } = activeTurn;
|
|
2439
2726
|
prompt.context.attemptTools.scheduledAppAuthoritySourceRef.current = void 0;
|
|
2727
|
+
freezeRunTerminalOutcome();
|
|
2728
|
+
await state.abortCleanup.catch(() => void 0);
|
|
2440
2729
|
try {
|
|
2441
2730
|
steeringQueueRef.current?.cancel();
|
|
2442
2731
|
if (params.isFinalFallbackAttempt !== false) await maybeEmitFastModeAutoResetBestEffort();
|
|
@@ -2460,15 +2749,11 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2460
2749
|
const retainLiveIncognitoThread = terminalState.turnSucceeded && isIncognitoSessionKey(params.sessionKey);
|
|
2461
2750
|
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
2751
|
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);
|
|
2752
|
+
return await retainCodexAppServerBindingSubscription(resourceState.client, resourceState.thread.threadId, {
|
|
2753
|
+
release: resourceState.thread.liveThreadOwnership?.release,
|
|
2754
|
+
configFingerprint: resourceState.thread.liveThreadConfigFingerprint,
|
|
2755
|
+
serviceTier: connection.mutable.pluginAppServer.serviceTier
|
|
2756
|
+
});
|
|
2472
2757
|
}) : false;
|
|
2473
2758
|
const retainLiveThread = retainLiveIncognitoThread || retainedPersistentThread;
|
|
2474
2759
|
const bindingReleased = isIncognitoSessionKey(params.sessionKey) && !retainLiveIncognitoThread ? await bindingStore.mutate(bindingIdentity, {
|
|
@@ -2486,7 +2771,13 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2486
2771
|
} finally {
|
|
2487
2772
|
await runCleanupStep("codex-user-input-cancel", () => userInputBridgeRef.current?.cancelPending());
|
|
2488
2773
|
await runCleanupStep("codex-turn-watch-clear", () => turnWatches.clearAllTimers());
|
|
2774
|
+
await runCleanupStep("codex-dynamic-tool-cleanup", async () => {
|
|
2775
|
+
const cleanupReason = terminalState.turnSucceeded ? "completion" : state.timedOut ? "timeout" : runAbortController.signal.aborted ? "cancel" : "error";
|
|
2776
|
+
const cleanups = prompt.context.attemptTools.runCleanups.splice(0);
|
|
2777
|
+
await Promise.allSettled(cleanups.map(async (cleanup) => await cleanup(cleanupReason)));
|
|
2778
|
+
});
|
|
2489
2779
|
await runCleanupStep("codex-route-release", releaseCurrentRoute);
|
|
2780
|
+
await runCleanupStep("codex-transcript-checkpoint", () => activeTurn.activeProjector.transcriptCheckpoint.flush(true));
|
|
2490
2781
|
await runCleanupStep("codex-shared-client-release", releaseSharedClientLeaseAndRetireOneShotClient);
|
|
2491
2782
|
const nativeHookRelay = resourceState.nativeHookRelay;
|
|
2492
2783
|
resourceState.nativeHookRelay = void 0;
|
|
@@ -2505,12 +2796,12 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2505
2796
|
runAbortController.signal.removeEventListener("abort", abortListener);
|
|
2506
2797
|
});
|
|
2507
2798
|
await runCleanupStep("codex-steering-cancel", () => steeringQueueRef.current?.cancel());
|
|
2508
|
-
await runCleanupStep("codex-terminal-freeze", freezeRunTerminalOutcome);
|
|
2509
2799
|
await runCleanupStep("codex-reply-backend-detach", () => params.replyOperation?.detachBackend(handle));
|
|
2510
2800
|
await runCleanupStep("codex-active-run-clear", () => {
|
|
2511
2801
|
clearActiveEmbeddedRun(params.sessionId, handle, params.sessionKey, params.sessionFile);
|
|
2512
2802
|
});
|
|
2513
2803
|
}
|
|
2804
|
+
await state.abortCleanup;
|
|
2514
2805
|
}
|
|
2515
2806
|
//#endregion
|
|
2516
2807
|
//#region extensions/codex/src/app-server/workspace-dir-cache.ts
|
|
@@ -2579,105 +2870,6 @@ async function runCodexAgentEndHook(params, hookParams) {
|
|
|
2579
2870
|
runAgentEndSideEffects(sideEffectParams);
|
|
2580
2871
|
}
|
|
2581
2872
|
//#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
2873
|
//#region extensions/codex/src/app-server/startup-binding.ts
|
|
2682
2874
|
const CODEX_APP_SERVER_NATIVE_THREAD_FALLBACK_MAX_TOKENS = 3e5;
|
|
2683
2875
|
const CODEX_APP_SERVER_NATIVE_THREAD_DEFAULT_RESERVE_TOKENS = 2e4;
|
|
@@ -2994,7 +3186,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
2994
3186
|
const pluginConfig = readCodexPluginConfig(options.pluginConfig);
|
|
2995
3187
|
const requirementsToml = readCodexRequirementsToml({});
|
|
2996
3188
|
const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig });
|
|
2997
|
-
const { sessionAgentId } =
|
|
3189
|
+
const { sessionAgentId } = resolveSessionAgentIdsStrict({
|
|
2998
3190
|
sessionKey: params.sessionKey,
|
|
2999
3191
|
config: params.config,
|
|
3000
3192
|
agentId: params.agentId
|
|
@@ -3150,6 +3342,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3150
3342
|
const sessionPermissionCwd = resolveCodexSessionPermissionCwd({
|
|
3151
3343
|
permissionMode: params.permissionMode,
|
|
3152
3344
|
sessionRoot: params.sessionRoot,
|
|
3345
|
+
defaultRoot: effectiveWorkspace,
|
|
3153
3346
|
requestedCwd,
|
|
3154
3347
|
fallbackCwd: effectiveWorkspace
|
|
3155
3348
|
});
|
|
@@ -3160,14 +3353,20 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3160
3353
|
appServer,
|
|
3161
3354
|
permissionMode: params.permissionMode,
|
|
3162
3355
|
sessionRoot: params.sessionRoot,
|
|
3356
|
+
defaultRoot: effectiveWorkspace,
|
|
3163
3357
|
pluginConfig,
|
|
3164
3358
|
canUseAutoReview: canUseCodexModelBackedApprovalsReviewerForModel({
|
|
3165
3359
|
modelProvider: selection.modelProvider,
|
|
3166
3360
|
model: selection.model,
|
|
3167
3361
|
config: params.config,
|
|
3168
|
-
env:
|
|
3362
|
+
env: {
|
|
3363
|
+
...process.env,
|
|
3364
|
+
...appServer.start.env,
|
|
3365
|
+
...shellEnvironment
|
|
3366
|
+
},
|
|
3169
3367
|
agentDir,
|
|
3170
|
-
homeScope: appServer.start.homeScope
|
|
3368
|
+
homeScope: appServer.start.homeScope,
|
|
3369
|
+
codexArgs: appServer.start.args
|
|
3171
3370
|
}),
|
|
3172
3371
|
requirementsToml,
|
|
3173
3372
|
policyLocked: startupBinding?.connectionScope === "supervision",
|
|
@@ -3180,7 +3379,11 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3180
3379
|
provider: selection.modelProvider,
|
|
3181
3380
|
model: selection.model,
|
|
3182
3381
|
config: params.config,
|
|
3183
|
-
env:
|
|
3382
|
+
env: {
|
|
3383
|
+
...process.env,
|
|
3384
|
+
...session.start.env,
|
|
3385
|
+
...shellEnvironment
|
|
3386
|
+
},
|
|
3184
3387
|
agentDir
|
|
3185
3388
|
});
|
|
3186
3389
|
return {
|
|
@@ -3244,6 +3447,17 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3244
3447
|
resolvedAppServer = resolveFinalAppServer(configuredAppServer, reviewerPolicyContext);
|
|
3245
3448
|
appServer = resolvedAppServer.appServer;
|
|
3246
3449
|
}
|
|
3450
|
+
const sessionPermissionPolicy = resolveCodexEffectiveSessionPermissionPolicy({
|
|
3451
|
+
appServer,
|
|
3452
|
+
permissionMode: params.permissionMode,
|
|
3453
|
+
sessionRoot: params.sessionRoot,
|
|
3454
|
+
defaultRoot: effectiveWorkspace
|
|
3455
|
+
});
|
|
3456
|
+
if (sessionPermissionPolicy) {
|
|
3457
|
+
params.permissionMode = sessionPermissionPolicy.mode;
|
|
3458
|
+
params.sessionRoot = sessionPermissionPolicy.root;
|
|
3459
|
+
(params.execOverrides ??= {}).mode = sessionPermissionPolicy.execMode;
|
|
3460
|
+
}
|
|
3247
3461
|
const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
|
|
3248
3462
|
configuredEvents: options.nativeHookRelay?.events,
|
|
3249
3463
|
appServer
|
|
@@ -3290,6 +3504,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3290
3504
|
effectiveWorkspace,
|
|
3291
3505
|
effectiveCwd,
|
|
3292
3506
|
appServer,
|
|
3507
|
+
sessionPermissionPolicy,
|
|
3293
3508
|
nativeHookRelayEvents,
|
|
3294
3509
|
runAbortController,
|
|
3295
3510
|
terminalState,
|
|
@@ -4439,7 +4654,11 @@ function createCodexTrajectoryRecorder(params) {
|
|
|
4439
4654
|
if (!params.trajectory) return null;
|
|
4440
4655
|
const trajectory = params.trajectory;
|
|
4441
4656
|
return {
|
|
4442
|
-
recordEvent:
|
|
4657
|
+
recordEvent: (type, data) => {
|
|
4658
|
+
try {
|
|
4659
|
+
trajectory.recordEvent(type, data);
|
|
4660
|
+
} catch {}
|
|
4661
|
+
},
|
|
4443
4662
|
flush: trajectory.flush
|
|
4444
4663
|
};
|
|
4445
4664
|
}
|
|
@@ -4501,7 +4720,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4501
4720
|
const { hookContextWindowFields, hookRunner } = context;
|
|
4502
4721
|
const { connection, preparedAuthBinding } = runtime;
|
|
4503
4722
|
const { effectiveRuntimeProviderId, effectiveRuntimeModelId } = runtime;
|
|
4504
|
-
const { params, terminalState, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, usesSupervisionConnection, sessionAgentId, contextSessionKey, effectiveCwd, attemptStartedAt, startupAuthProfileId } = connection;
|
|
4723
|
+
const { params, terminalState, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, usesSupervisionConnection, sessionAgentId, contextSessionKey, effectiveCwd, agentDir, attemptStartedAt, startupAuthProfileId } = connection;
|
|
4505
4724
|
const { toolBridge, toolState } = attemptTools;
|
|
4506
4725
|
const { state, completion, pendingOpenClawDynamicToolCompletionIds, activeTurnItemIds, activeCompletionBlockerItemIds, activeFinalizationHookRunIds, turnWatches } = turnRuntime;
|
|
4507
4726
|
const { emitLifecycleTerminal, buildLifecycleTerminalMeta } = lifecycle;
|
|
@@ -4509,7 +4728,20 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4509
4728
|
const { codexModelCallDiagnostics } = requestRuntime;
|
|
4510
4729
|
const { activeTurnId, activeProjector, streamState, freezeRunTerminalOutcome, notifyUserMessagePersisted } = activeTurn;
|
|
4511
4730
|
await completion;
|
|
4512
|
-
await
|
|
4731
|
+
await state.abortCleanup;
|
|
4732
|
+
const drain = drainNotificationQueue();
|
|
4733
|
+
const abortGraceElapsed = createDeferred();
|
|
4734
|
+
let abortGraceTimer;
|
|
4735
|
+
const abortListener = addAbortListener(runAbortController.signal, () => {
|
|
4736
|
+
abortGraceTimer = setTimeout(() => abortGraceElapsed.resolve(), TURN_FINALIZE_DRAIN_ABORT_GRACE_MS);
|
|
4737
|
+
abortGraceTimer.unref?.();
|
|
4738
|
+
});
|
|
4739
|
+
try {
|
|
4740
|
+
await Promise.race([drain, abortGraceElapsed.promise]);
|
|
4741
|
+
} finally {
|
|
4742
|
+
abortListener[Symbol.dispose]();
|
|
4743
|
+
clearTimeout(abortGraceTimer);
|
|
4744
|
+
}
|
|
4513
4745
|
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
4746
|
const hasRecoverableCompletedAssistant = !turnWatches.isCompletionIdleWatchPinnedByTerminalError() && turnWatches.isAssistantCompletionIdleWatchArmed() && hasQuiescentCompletedAssistant;
|
|
4515
4747
|
const recoveredTurnWatchTimeout = state.turnCompletionIdleTimedOut && !terminalState.explicitCancellationObserved && hasRecoverableCompletedAssistant && activeProjector.recoverCompletedTerminalAssistantAfterTurnWatchTimeout();
|
|
@@ -4680,20 +4912,11 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
4680
4912
|
modelIterations: result.modelIterations ?? 0,
|
|
4681
4913
|
skillWorkshopAvailable: flattenCodexDynamicToolFunctions(attemptTools.toolBridge.availableSpecs).some((tool) => tool.name === "skill_workshop"),
|
|
4682
4914
|
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
4915
|
senderId: params.senderId ?? void 0,
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4916
|
+
foregroundPromptContext: buildEmbeddedForegroundPromptContext({
|
|
4917
|
+
...params,
|
|
4918
|
+
agentId: sessionAgentId
|
|
4919
|
+
}, agentDir)
|
|
4697
4920
|
},
|
|
4698
4921
|
hookRunner
|
|
4699
4922
|
});
|
|
@@ -5854,10 +6077,6 @@ function resolveScheduledCodexAppCreatorCaptureDecision(params) {
|
|
|
5854
6077
|
...unavailableReason ? { unavailableReason } : {}
|
|
5855
6078
|
};
|
|
5856
6079
|
}
|
|
5857
|
-
function readConnectorId(tool) {
|
|
5858
|
-
const meta = asOptionalRecord(asOptionalRecord(tool)?.["_meta"]);
|
|
5859
|
-
return normalizeOptionalString(meta?.connector_id) ?? normalizeOptionalString(meta?.connectorId);
|
|
5860
|
-
}
|
|
5861
6080
|
function normalizeApprovalMode(value) {
|
|
5862
6081
|
return value === "allow" || value === "deny" || value === "auto" || value === "ask" ? value : void 0;
|
|
5863
6082
|
}
|
|
@@ -5924,7 +6143,7 @@ async function readCodexScheduledAppToolNamesByApp(params) {
|
|
|
5924
6143
|
if (!isJsonObject(status) || !isJsonObject(status.tools)) throw new Error("Codex scheduled app inventory contained an invalid server status");
|
|
5925
6144
|
if (status.name !== CODEX_APPS_MCP_SERVER) continue;
|
|
5926
6145
|
for (const [toolName, tool] of Object.entries(status.tools)) {
|
|
5927
|
-
const connectorId =
|
|
6146
|
+
const connectorId = readCodexMcpToolConnectorId(tool);
|
|
5928
6147
|
if (connectorId) {
|
|
5929
6148
|
const names = toolNamesByApp.get(connectorId) ?? /* @__PURE__ */ new Set();
|
|
5930
6149
|
names.add(toolName);
|
|
@@ -6518,6 +6737,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6518
6737
|
data: {
|
|
6519
6738
|
phase: "start",
|
|
6520
6739
|
name: call.tool,
|
|
6740
|
+
itemId: call.callId,
|
|
6521
6741
|
toolCallId: call.callId,
|
|
6522
6742
|
...toolMeta ? { meta: toolMeta } : {},
|
|
6523
6743
|
...toolArgs ? { args: toolArgs } : {},
|
|
@@ -6540,7 +6760,8 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6540
6760
|
})) terminalDiagnosticObserved = true;
|
|
6541
6761
|
}, { include: DYNAMIC_TOOL_TERMINAL_DIAGNOSTIC_TYPES });
|
|
6542
6762
|
try {
|
|
6543
|
-
const { execution } = openClawDynamicToolExecutions.claim(call, () => {
|
|
6763
|
+
const { execution } = openClawDynamicToolExecutions.claim(call, async () => {
|
|
6764
|
+
await projector?.transcriptCheckpoint.flush();
|
|
6544
6765
|
emitDynamicToolStartedDiagnostic({
|
|
6545
6766
|
call,
|
|
6546
6767
|
agentId: sessionAgentId,
|
|
@@ -6548,7 +6769,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6548
6769
|
sessionId: params.sessionId,
|
|
6549
6770
|
sessionKey: params.sessionKey
|
|
6550
6771
|
});
|
|
6551
|
-
|
|
6772
|
+
const response = await handleDynamicToolCallWithTimeout({
|
|
6552
6773
|
call,
|
|
6553
6774
|
toolBridge,
|
|
6554
6775
|
signal,
|
|
@@ -6570,6 +6791,9 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6570
6791
|
});
|
|
6571
6792
|
}
|
|
6572
6793
|
});
|
|
6794
|
+
recordCodexDynamicToolResult(projector, call, response, toCodexDynamicToolProtocolResponse(response));
|
|
6795
|
+
await projector?.transcriptCheckpoint.flush();
|
|
6796
|
+
return response;
|
|
6573
6797
|
});
|
|
6574
6798
|
const response = await execution;
|
|
6575
6799
|
const protocolResponse = toCodexDynamicToolProtocolResponse(response);
|
|
@@ -6593,7 +6817,6 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6593
6817
|
success: protocolResponse.success,
|
|
6594
6818
|
contentItems: protocolResponse.contentItems
|
|
6595
6819
|
});
|
|
6596
|
-
recordCodexDynamicToolResult(projector, call, response, protocolResponse);
|
|
6597
6820
|
if (protocolResponse.success && call.tool === "progress_card") {
|
|
6598
6821
|
const progressCardInput = response.executedArguments ?? call.arguments;
|
|
6599
6822
|
await projector?.recordDynamicProgressCardUpdate(progressCardInput);
|
|
@@ -6606,6 +6829,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6606
6829
|
data: {
|
|
6607
6830
|
phase: "result",
|
|
6608
6831
|
name: call.tool,
|
|
6832
|
+
itemId: call.callId,
|
|
6609
6833
|
toolCallId: call.callId,
|
|
6610
6834
|
...toolMeta ? { meta: toolMeta } : {},
|
|
6611
6835
|
...commandBearing ? { commandBearing: true } : {},
|
|
@@ -6681,7 +6905,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
6681
6905
|
//#region extensions/codex/src/app-server/attempt-runtime-artifact.ts
|
|
6682
6906
|
async function verifyStartupArtifact(params) {
|
|
6683
6907
|
if (!params.request) return;
|
|
6684
|
-
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-
|
|
6908
|
+
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-DeBvleJw.js");
|
|
6685
6909
|
const runtimeArtifact = readCodexAppServerClientRuntimeArtifact(params.client);
|
|
6686
6910
|
const expected = params.request.expected;
|
|
6687
6911
|
const matchesExpected = !expected || runtimeArtifact?.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint;
|
|
@@ -6711,19 +6935,17 @@ function startCodexComputerUseHealthMonitor(params) {
|
|
|
6711
6935
|
}
|
|
6712
6936
|
const fingerprint = buildComputerUseHealthMonitorFingerprint(params.config);
|
|
6713
6937
|
const intervalMs = params.config.healthCheckIntervalMinutes * 6e4;
|
|
6714
|
-
if (existing?.fingerprint === fingerprint
|
|
6938
|
+
if (existing?.fingerprint === fingerprint) return {
|
|
6715
6939
|
started: false,
|
|
6716
6940
|
intervalMs,
|
|
6717
6941
|
reason: "already_started"
|
|
6718
6942
|
};
|
|
6719
6943
|
if (existing) clearComputerUseHealthMonitor(params.client, existing);
|
|
6720
|
-
const repairComputerUseMcpChildren = params.repairComputerUseMcpChildren ?? (() => killStaleComputerUseMcpChildren({ ancestorPid: params.client.getTransportPid() }));
|
|
6721
6944
|
const monitor = {
|
|
6722
6945
|
fingerprint,
|
|
6723
6946
|
intervalMs,
|
|
6724
|
-
repairComputerUseMcpChildren: params.repairComputerUseMcpChildren,
|
|
6725
6947
|
timer: setInterval(() => {
|
|
6726
|
-
runCodexComputerUseHealthProbe(params.client, params.config, monitor
|
|
6948
|
+
runCodexComputerUseHealthProbe(params.client, params.config, monitor);
|
|
6727
6949
|
}, intervalMs),
|
|
6728
6950
|
disposeCloseHandler: () => void 0,
|
|
6729
6951
|
running: false
|
|
@@ -6748,13 +6970,12 @@ function buildComputerUseHealthMonitorFingerprint(config) {
|
|
|
6748
6970
|
toolCallTimeoutMs: config.toolCallTimeoutMs
|
|
6749
6971
|
});
|
|
6750
6972
|
}
|
|
6751
|
-
async function runCodexComputerUseHealthProbe(client, config, monitor
|
|
6973
|
+
async function runCodexComputerUseHealthProbe(client, config, monitor) {
|
|
6752
6974
|
if (monitor.running) return;
|
|
6753
6975
|
monitor.running = true;
|
|
6754
6976
|
try {
|
|
6755
6977
|
const { liveTest, repair } = await runCodexComputerUseLiveTest({
|
|
6756
6978
|
config,
|
|
6757
|
-
repairComputerUseMcpChildren: options.repairComputerUseMcpChildren,
|
|
6758
6979
|
request: async (method, requestParams, requestOptions) => await client.request(method, requestParams, { timeoutMs: requestOptions?.timeoutMs ?? config.liveTestTimeoutMs })
|
|
6759
6980
|
});
|
|
6760
6981
|
if (!liveTest.ok) {
|
|
@@ -6767,10 +6988,7 @@ async function runCodexComputerUseHealthProbe(client, config, monitor, options)
|
|
|
6767
6988
|
});
|
|
6768
6989
|
return;
|
|
6769
6990
|
}
|
|
6770
|
-
if (repair?.
|
|
6771
|
-
mcpServerName: config.mcpServerName,
|
|
6772
|
-
killedPids: repair.killedPids
|
|
6773
|
-
});
|
|
6991
|
+
if (repair?.attempted && repair.warnings.length === 0) embeddedAgentLog.info("codex computer-use periodic health reloaded MCP servers", { mcpServerName: config.mcpServerName });
|
|
6774
6992
|
} catch (error) {
|
|
6775
6993
|
embeddedAgentLog.warn("codex computer-use periodic health probe crashed", {
|
|
6776
6994
|
mcpServerName: config.mcpServerName,
|
|
@@ -6865,6 +7083,7 @@ function createCodexPluginThreadConfigStartupProvider(params) {
|
|
|
6865
7083
|
build: async (buildOptions) => {
|
|
6866
7084
|
const config = await buildCodexPluginThreadConfigWithinDeadline({
|
|
6867
7085
|
...buildParams,
|
|
7086
|
+
threadId: buildOptions?.threadId,
|
|
6868
7087
|
appCache: appCache ?? defaultCodexAppInventoryCache,
|
|
6869
7088
|
metadataCache,
|
|
6870
7089
|
failClosedOnTimeout: Boolean(params.scheduledRuntimeAuthority),
|
|
@@ -6897,7 +7116,7 @@ function isCodexPluginThreadConfigTimeoutError(error) {
|
|
|
6897
7116
|
* Startup orchestration for Codex app-server attempts, including shared-client
|
|
6898
7117
|
* leasing, plugin thread config, sandbox environment, and thread lifecycle binding.
|
|
6899
7118
|
*/
|
|
6900
|
-
const
|
|
7119
|
+
const CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS = 3;
|
|
6901
7120
|
const CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED = "CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED";
|
|
6902
7121
|
/** True when a pre-write context restart must replay on the newly selected owner. */
|
|
6903
7122
|
function isCodexContextRestartSelectionChangedError(error) {
|
|
@@ -7009,7 +7228,7 @@ async function startCodexAttemptThread(params) {
|
|
|
7009
7228
|
signal: startupAbandonController.signal
|
|
7010
7229
|
});
|
|
7011
7230
|
} catch (error) {
|
|
7012
|
-
if (startupAbandonController.signal.aborted) throw error;
|
|
7231
|
+
if (startupAbandonController.signal.aborted || isCodexAppServerStartSelectionChangedError(error)) throw error;
|
|
7013
7232
|
throw new AgentHarnessPreflightError(`Codex Computer Use readiness failed: ${formatErrorMessage(error)}`, {
|
|
7014
7233
|
cause: error,
|
|
7015
7234
|
scope: "harness"
|
|
@@ -7023,7 +7242,8 @@ async function startCodexAttemptThread(params) {
|
|
|
7023
7242
|
accountId: params.startupAuthAccountCacheKey,
|
|
7024
7243
|
envApiKeyFingerprint: params.startupEnvApiKeyCacheKey,
|
|
7025
7244
|
appServerVersion: activeStartupClient.getServerVersion(),
|
|
7026
|
-
runtimeIdentity: startupRuntimeIdentity
|
|
7245
|
+
runtimeIdentity: startupRuntimeIdentity,
|
|
7246
|
+
desktopGenerationFingerprint: readCodexAppServerClientDesktopGenerationFingerprint(activeStartupClient)
|
|
7027
7247
|
});
|
|
7028
7248
|
const appServerRuntimeFingerprint = buildCodexAppServerRuntimeFingerprint({
|
|
7029
7249
|
appServer: params.appServer,
|
|
@@ -7127,6 +7347,7 @@ async function startCodexAttemptThread(params) {
|
|
|
7127
7347
|
finalConfigPatch: params.finalConfigPatch,
|
|
7128
7348
|
buildFinalConfigPatch: params.buildFinalConfigPatch,
|
|
7129
7349
|
nativeHookRelayGeneration: params.nativeHookRelayGeneration,
|
|
7350
|
+
nativeHookRelayRequired: params.nativeHookRelayRequired,
|
|
7130
7351
|
nativeCodeModeEnabled: params.nativeToolSurfaceEnabled,
|
|
7131
7352
|
nativeProviderWebSearchSupport: params.nativeProviderWebSearchSupport,
|
|
7132
7353
|
nativeCodeModeOnlyEnabled: params.appServer.codeModeOnly,
|
|
@@ -7221,30 +7442,31 @@ async function startCodexAttemptThread(params) {
|
|
|
7221
7442
|
}
|
|
7222
7443
|
}
|
|
7223
7444
|
};
|
|
7224
|
-
for (let attempt = 1; attempt <=
|
|
7445
|
+
for (let attempt = 1; attempt <= CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS; attempt += 1) try {
|
|
7225
7446
|
return await startupAttempt();
|
|
7226
7447
|
} catch (error) {
|
|
7227
7448
|
const selectionChanged = isCodexAppServerStartSelectionChangedError(error);
|
|
7228
7449
|
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) {
|
|
7450
|
+
const refreshedSharedClient = selectionChanged ? retireSharedCodexAppServerClientIfCurrent(attemptedClient) : clearSharedCodexAppServerClientIfCurrent(attemptedClient);
|
|
7451
|
+
if (startupClientForAbandonedRequestCleanup === attemptedClient) startupClientForAbandonedRequestCleanup = void 0;
|
|
7452
|
+
if (attempt >= CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS) {
|
|
7233
7453
|
embeddedAgentLog.warn(selectionChanged ? "codex app-server executable selection kept changing during startup; retries exhausted" : "codex app-server connection closed during startup; retries exhausted", {
|
|
7234
7454
|
attempt,
|
|
7235
|
-
maxAttempts:
|
|
7455
|
+
maxAttempts: CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS,
|
|
7236
7456
|
refreshedSharedClient,
|
|
7237
7457
|
error: formatErrorMessage(error)
|
|
7238
7458
|
});
|
|
7239
7459
|
throw error;
|
|
7240
7460
|
}
|
|
7461
|
+
const retryDelayMs = selectionChanged ? 0 : 1e3 * 2 ** (attempt - 1);
|
|
7241
7462
|
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
7463
|
attempt,
|
|
7243
7464
|
nextAttempt: attempt + 1,
|
|
7244
|
-
maxAttempts:
|
|
7465
|
+
maxAttempts: CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS,
|
|
7245
7466
|
refreshedSharedClient,
|
|
7246
7467
|
error: formatErrorMessage(error)
|
|
7247
7468
|
});
|
|
7469
|
+
await sleepWithAbort(retryDelayMs, startupAbandonController.signal);
|
|
7248
7470
|
}
|
|
7249
7471
|
throw new Error("codex app-server startup retry loop exited unexpectedly");
|
|
7250
7472
|
}
|
|
@@ -7257,7 +7479,7 @@ async function startCodexAttemptThread(params) {
|
|
|
7257
7479
|
releaseSharedClientLease
|
|
7258
7480
|
};
|
|
7259
7481
|
} catch (error) {
|
|
7260
|
-
if (params.signal.aborted ||
|
|
7482
|
+
if (params.signal.aborted || isCodexAppServerStartupError(error)) {
|
|
7261
7483
|
releaseSharedClientLease?.();
|
|
7262
7484
|
releaseSharedClientLease = void 0;
|
|
7263
7485
|
await closeCodexStartupClientBestEffort(startupClientForAbandonedRequestCleanup);
|
|
@@ -7276,13 +7498,11 @@ async function startCodexAttemptThread(params) {
|
|
|
7276
7498
|
params.signal.removeEventListener("abort", abandonStartupAcquire);
|
|
7277
7499
|
}
|
|
7278
7500
|
}
|
|
7279
|
-
function shouldClearSharedClientAfterStartupAbandon(error) {
|
|
7280
|
-
return isCodexAppServerStartupError(error);
|
|
7281
|
-
}
|
|
7282
7501
|
function shouldClearSharedClientAfterStartupRace(error) {
|
|
7283
|
-
return
|
|
7502
|
+
return isCodexAppServerStartupError(error) || isCodexAppServerRequestTimeoutError(error);
|
|
7284
7503
|
}
|
|
7285
7504
|
function shouldClearSharedClientAfterStartupFailure(params) {
|
|
7505
|
+
if (isCodexAppServerOverloadError(params.error)) return false;
|
|
7286
7506
|
return isCodexAppServerBrokenPipeError(params.error) || !params.spawnedBy;
|
|
7287
7507
|
}
|
|
7288
7508
|
//#endregion
|
|
@@ -7296,6 +7516,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
7296
7516
|
const developerInstructions = joinPresentSections(turnState.promptBuild.developerInstructions, attemptTools.scheduledConfiguredMcp?.diagnosticNotice);
|
|
7297
7517
|
const { params, attemptClientFactory, bindingStore, appServer, pluginConfig, computerUseConfig, startupClientAuthProfileId, runtimeArtifactRequest, startupPreparedAuth, agentDir, sessionAgentId, effectiveWorkspace, effectiveCwd, sandbox, runAbortController, usesSupervisionConnection, resolveReviewerPolicyContext, resolveRuntimeOptionsForCurrentBinding, startupAuthProfileId, startupAuthRequirement, abortFromUpstream } = connection;
|
|
7298
7518
|
let pluginAppServer = withCodexAppServerFastModeServiceTier(appServer, runtimeParams);
|
|
7519
|
+
const loopDetectionEnabled = (sessionAgentId && params.config ? resolveAgentConfig$1(params.config, sessionAgentId)?.tools?.loopDetection?.enabled : void 0) ?? params.config?.tools?.loopDetection?.enabled ?? false;
|
|
7299
7520
|
try {
|
|
7300
7521
|
emitCodexAppServerEvent(params, {
|
|
7301
7522
|
stream: "codex_app_server.lifecycle",
|
|
@@ -7330,6 +7551,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
7330
7551
|
developerInstructions,
|
|
7331
7552
|
agentWorkspaceDeveloperInstructions: context.agentWorkspaceDeveloperInstructions,
|
|
7332
7553
|
buildFinalConfigPatch: buildNativeHookRelayFinalConfigPatch,
|
|
7554
|
+
nativeHookRelayRequired: connection.options.nativeHookRelay?.enabled !== false && params.pluginHarnessToolPolicyRestricted !== true && connection.nativeHookRelayEvents.includes("pre_tool_use") && (hasBeforeToolCallPolicy() || appServer.loopDetectionPreToolUseRelay && Boolean(connection.sandboxSessionKey) && loopDetectionEnabled),
|
|
7333
7555
|
bundleMcpThreadConfig,
|
|
7334
7556
|
configuredMcpOwnershipVersion: attemptTools.configuredMcpOwnershipVersion,
|
|
7335
7557
|
nativeToolSurfaceEnabled,
|
|
@@ -7436,7 +7658,7 @@ function isAuthorityResolutionOperationAbort(error, signal) {
|
|
|
7436
7658
|
}
|
|
7437
7659
|
async function prepareCodexAttemptTools(runtime) {
|
|
7438
7660
|
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;
|
|
7661
|
+
const { params, preDynamicStartupStages, mutable, startupAuthProfileId, resolvedWorkspace, effectiveWorkspace, effectiveCwd, sandboxSessionKey, sandbox, sessionPermissionPolicy, runAbortController, sessionAgentId, pluginConfig, profilerEnabled, agentDir } = connection;
|
|
7440
7662
|
const preDynamicSummary = preDynamicStartupStages.snapshot();
|
|
7441
7663
|
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
7664
|
runId: params.runId,
|
|
@@ -7479,6 +7701,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7479
7701
|
...onCodexToolOutcome ? { onToolOutcome: onCodexToolOutcome } : {}
|
|
7480
7702
|
};
|
|
7481
7703
|
const computerContextEpoch = { value: 0 };
|
|
7704
|
+
const runCleanups = [];
|
|
7482
7705
|
const cronCreatorToolAllowlist = [];
|
|
7483
7706
|
const cronCreatorToolAllowlistCaptureRef = {};
|
|
7484
7707
|
const scheduledAppAuthoritySourceRef = {};
|
|
@@ -7509,6 +7732,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7509
7732
|
effectiveCwd,
|
|
7510
7733
|
sandboxSessionKey,
|
|
7511
7734
|
sandbox,
|
|
7735
|
+
sessionPermissionPolicy,
|
|
7512
7736
|
nativeToolSurfaceEnabled,
|
|
7513
7737
|
nativeProviderWebSearchSupport,
|
|
7514
7738
|
runAbortController,
|
|
@@ -7539,6 +7763,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7539
7763
|
};
|
|
7540
7764
|
const tools = await buildDynamicTools({
|
|
7541
7765
|
...commonToolParams,
|
|
7766
|
+
registerRunCleanup: (cleanup) => runCleanups.push(cleanup),
|
|
7542
7767
|
cronCreatorToolAllowlistRef: cronCreatorToolAllowlist,
|
|
7543
7768
|
cronCreatorToolAllowlistCaptureRef,
|
|
7544
7769
|
onPersistentWebSearchPolicyResolved: (allowed) => {
|
|
@@ -7759,6 +7984,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
7759
7984
|
dynamicToolParams,
|
|
7760
7985
|
compactionPlanState,
|
|
7761
7986
|
computerContextEpoch,
|
|
7987
|
+
runCleanups,
|
|
7762
7988
|
toolBridge,
|
|
7763
7989
|
toolState,
|
|
7764
7990
|
toolOutcomeOrdinals,
|
|
@@ -8240,8 +8466,10 @@ function createCodexAttemptTurnWatchController(params) {
|
|
|
8240
8466
|
function scheduleAttemptIdleWatch() {
|
|
8241
8467
|
scheduleWatch("attempt", fireAttemptIdleTimeout, attemptLastProgressAt, attemptIdleTimeoutOverrideMs ?? turnAttemptIdleTimeoutMs, attemptIdleWatchArmed && !shouldPauseAttemptIdleWatch());
|
|
8242
8468
|
}
|
|
8469
|
+
const terminalWorkIsActive = () => params.getActiveAppServerTurnRequests() > 0 || params.isTerminalTurnNotificationQueued() && params.getActiveFinalizationHookCount() > 0;
|
|
8470
|
+
const terminalIdleTimeoutMs = () => params.isTerminalTurnNotificationQueued() && !terminalWorkIsActive() ? Math.min(TURN_TERMINAL_SETTLEMENT_IDLE_TIMEOUT_MS, turnTerminalIdleTimeoutMs) : turnTerminalIdleTimeoutMs;
|
|
8243
8471
|
function scheduleTerminalIdleWatch() {
|
|
8244
|
-
scheduleWatch("terminal", fireTerminalIdleTimeout, completionLastActivityAt,
|
|
8472
|
+
scheduleWatch("terminal", fireTerminalIdleTimeout, completionLastActivityAt, terminalIdleTimeoutMs(), terminalIdleWatchArmed && (params.isTerminalTurnNotificationQueued() || params.getActiveAppServerTurnRequests() === 0));
|
|
8245
8473
|
}
|
|
8246
8474
|
function scheduleProgressWatches() {
|
|
8247
8475
|
scheduleAttemptIdleWatch();
|
|
@@ -8362,18 +8590,26 @@ function createCodexAttemptTurnWatchController(params) {
|
|
|
8362
8590
|
});
|
|
8363
8591
|
}
|
|
8364
8592
|
function fireTerminalIdleTimeout() {
|
|
8365
|
-
if (params.isCompleted() || params.
|
|
8593
|
+
if (params.isCompleted() || params.signal.aborted || !terminalIdleWatchArmed) return;
|
|
8594
|
+
if (!params.isTerminalTurnNotificationQueued() && params.getActiveAppServerTurnRequests() > 0) {
|
|
8595
|
+
scheduleTerminalIdleWatch();
|
|
8596
|
+
return;
|
|
8597
|
+
}
|
|
8598
|
+
const timeoutMs = terminalIdleTimeoutMs();
|
|
8366
8599
|
const idleMs = Math.max(0, Date.now() - completionLastActivityAt);
|
|
8367
|
-
if (idleMs <
|
|
8600
|
+
if (idleMs < timeoutMs) {
|
|
8368
8601
|
scheduleTerminalIdleWatch();
|
|
8369
8602
|
return;
|
|
8370
8603
|
}
|
|
8371
8604
|
reportTimeout({
|
|
8372
8605
|
kind: "terminal",
|
|
8373
8606
|
idleMs,
|
|
8374
|
-
timeoutMs
|
|
8607
|
+
timeoutMs,
|
|
8375
8608
|
lastActivityReason: completionLastActivityReason,
|
|
8376
|
-
details:
|
|
8609
|
+
details: {
|
|
8610
|
+
...completionLastActivityDetails,
|
|
8611
|
+
terminalTurnNotificationQueued: params.isTerminalTurnNotificationQueued()
|
|
8612
|
+
}
|
|
8377
8613
|
});
|
|
8378
8614
|
}
|
|
8379
8615
|
return {
|
|
@@ -8430,6 +8666,7 @@ function createCodexAttemptTurnWatchController(params) {
|
|
|
8430
8666
|
completionLastActivityReason = `notification:${method}`;
|
|
8431
8667
|
if (options?.details !== void 0) completionLastActivityDetails = options.details;
|
|
8432
8668
|
if (options?.attemptProgress) recordAttemptProgress(completionLastActivityReason, options);
|
|
8669
|
+
if (params.isTerminalTurnNotificationQueued()) scheduleTerminalIdleWatch();
|
|
8433
8670
|
},
|
|
8434
8671
|
extendAttemptIdleWatch: (timeoutMs) => {
|
|
8435
8672
|
attemptIdleTimeoutOverrideMs = resolveWatchTimeoutMs(timeoutMs);
|
|
@@ -8452,6 +8689,7 @@ function createCodexAttemptTurnState(resources) {
|
|
|
8452
8689
|
latestStartupErrorNotification: void 0,
|
|
8453
8690
|
rateLimitsRevisionBeforeLastTurnStart: void 0,
|
|
8454
8691
|
completed: false,
|
|
8692
|
+
abortCleanup: Promise.resolve(),
|
|
8455
8693
|
localCompletionRequested: false,
|
|
8456
8694
|
terminalTurnNotificationQueued: false,
|
|
8457
8695
|
sawCodexInterruptMarker: false,
|