@openclaw/codex 2026.9.1 → 2026.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/api.js +18 -23
- package/dist/apply-B6el6hdO.js +357 -0
- package/dist/{attempt-client-cleanup-DYHcRQAa.js → attempt-client-cleanup-D6cR54TV.js} +113 -49
- package/dist/{attempt-context-DmQUNWwT.js → attempt-context-AO4DSjE0.js} +11 -9
- package/dist/{event-projector-usage-C5mcrGjp.js → attempt-notifications--H8zXR5-.js} +3 -89
- package/dist/auth-cache-key-Kq6oerr6.js +498 -0
- package/dist/auth-profile-CwzO4_RG.js +43 -0
- package/dist/auth-profile-selection-DFu9e167.js +45 -0
- package/dist/{binding-connection-E6uDsPlx.js → binding-connection-QqgcPCgk.js} +18 -3
- package/dist/{bounded-turn-wzJrwKKe.js → bounded-turn-lRpmZHFv.js} +54 -150
- package/dist/build-state-6RL6qohz.js +19 -0
- package/dist/{capabilities-dIjNVCYH.js → capabilities-BeqLPbtM.js} +2 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/client-BEKu4yDx.js +3983 -0
- package/dist/command-dispatch-CisT9Jqq.js +21 -0
- package/dist/{command-formatters-CLHhEB1Q.js → command-formatters-DeTfrapr.js} +2 -2
- package/dist/{command-handlers-CTGb2csu.js → command-handlers-BfIsJEuA.js} +158 -76
- package/dist/command-rpc-BMqRQOFX.js +226 -0
- package/dist/{compact-_t0HQrUS.js → compact-CGJZ2rlb.js} +89 -49
- package/dist/config-JDfTI4VI.js +106 -0
- package/dist/{config-BhmfC1s6.js → config-options-jnIFvwxD.js} +208 -654
- package/dist/config-runtime-BWf6JLWG.js +11 -0
- package/dist/config-utils-C57JiJrU.js +69 -0
- package/dist/conversation-binding-CxOlHiix.js +889 -0
- package/dist/{plugin-marketplace-discovery-CfFlKqDl.js → conversation-control-CUCrSIQI.js} +36 -155
- package/dist/doctor-contract-api.js +8 -9
- package/dist/{dynamic-tools-BU9tmlYm.js → dynamic-tools-D-JBoaLt.js} +734 -698
- package/dist/{effective-mcp-catalog-DzYBW4h1.js → effective-mcp-catalog-J_5Ep5Um.js} +4 -3
- package/dist/{elicitation-input-DMkeki8d.js → elicitation-input-DPoK8F7w.js} +8 -22
- package/dist/ephemeral-turn-DSwzP8YY.js +101 -0
- package/dist/{event-projector-assistant-message-DHRFXKbS.js → event-projector-assistant-message-BmBM4qBV.js} +23 -27
- package/dist/event-projector-usage-CIyrYYid.js +102 -0
- package/dist/{harness-DXVZ5II5.js → harness-FR6eQgyO.js} +47 -17
- package/dist/harness.js +1 -1
- package/dist/history-rejection-B4nOXNXF.js +13 -0
- package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
- package/dist/incognito-session-uhrBF6wJ.js +15 -0
- package/dist/index.js +413 -2893
- package/dist/{isolated-completion-kg9kv4iH.js → isolated-completion-DHBefrzg.js} +12 -21
- package/dist/{managed-binary-4-Vjz5GH.js → managed-binary-DrjjRRUD.js} +17 -84
- package/dist/managed-thread-store-D1t5jh3G.js +66 -0
- package/dist/media-understanding-provider.js +4 -1
- package/dist/{model-catalog-CUM68Hkl.js → model-catalog-B_6M04Wo.js} +6 -5
- package/dist/{models-sYnEc0gd.js → models-P9k2qAof.js} +4 -4
- package/dist/native-execution-policy-umd0tgh4.js +128 -0
- package/dist/{native-subagent-monitor-CnH147jH.js → native-subagent-monitor-BbCUKRwC.js} +76 -48
- package/dist/node-cli-sessions-rj0ysJwM.js +527 -0
- package/dist/{node-exec-server.runtime-CstNHCmC.js → node-exec-server.runtime-BY_ctYnT.js} +54 -23
- package/dist/plan-BMJdMOEF.js +711 -0
- package/dist/plugin-activation-BQK-f5sV.js +133 -0
- package/dist/{thread-resume-C7pyVKeW.js → plugin-app-cache-key-CdSQzWyX.js} +5 -53
- package/dist/{plugin-approval-roundtrip-CNe-Xrjx.js → plugin-approval-roundtrip-DeW95wB5.js} +1 -1
- package/dist/plugin-inventory-CoRCzWW4.js +325 -0
- package/dist/plugin-marketplace-discovery-3akBizzF.js +134 -0
- package/dist/{plugin-metadata-cache-BFrPhb2c.js → plugin-metadata-cache-DgNfRAGA.js} +13 -9
- package/dist/protocol-CAAcVIKF.js +275 -0
- package/dist/{provider-capabilities-DW5p4k9w.js → provider-capabilities-W4tfK5Y5.js} +2 -2
- package/dist/{rate-limits-CawQJfUS.js → rate-limits-Bqnx1N4z.js} +1 -1
- package/dist/request-CGvGOpeR.js +198 -0
- package/dist/{run-attempt-D1hJO4fX.js → run-attempt-DwKds3DN.js} +1498 -1028
- package/dist/{runtime-artifact-C3jVimFn.js → runtime-artifact-T-NwqeSH.js} +28 -28
- package/dist/sandbox-guard-BcT66fWy.js +165 -0
- package/dist/{session-binding-BHuTCRZQ.js → session-binding-CKSepwIC.js} +118 -324
- package/dist/session-binding-record-CaZjYwNS.js +256 -0
- package/dist/session-catalog-HaDcp7Sv.js +1533 -0
- package/dist/session-catalog-adoption-BKLtSrwi.js +251 -0
- package/dist/session-catalog-archive-D0i2pGj2.js +56 -0
- package/dist/session-catalog-home-id-D7-aLiNt.js +190 -0
- package/dist/session-catalog-node-adoption-BUuDYY8R.js +182 -0
- package/dist/session-catalog-node-continue-CBtc4wkI.js +238 -0
- package/dist/session-catalog-parsing-CdD3JhdM.js +280 -0
- package/dist/session-catalog-provenance-DkJHo735.js +124 -0
- package/dist/{session-cli-CmFEXMAM.js → session-cli-CbgaHh0f.js} +3 -2
- package/dist/session-history-Cz-tOOYj.js +96 -0
- package/dist/{session-upstream-marker-C351-5Qw.js → session-history-import-DFN7sWRU.js} +5 -49
- package/dist/session-history-read-cxPUxyVV.js +50 -0
- package/dist/session-history-worker-runtime.js +60 -0
- package/dist/{settled-turn-context-D3SNWtUn.js → session-history.worker-CNEvGaU5.js} +75 -69
- package/dist/session-history.worker.js +2 -0
- package/dist/{session-initialization-BeWzjGiR.js → session-initialization-Jo86C60I.js} +2 -1
- package/dist/{session-permission-policy-DeWVTCMj.js → session-permission-policy-B22InTp_.js} +4 -7
- package/dist/{session-retirement-BujDjXVF.js → session-retirement-BSNG_mhf.js} +8 -7
- package/dist/session-upstream-marker-D15C9NHp.js +46 -0
- package/dist/settled-turn-context-Du6gdUDd.js +45 -0
- package/dist/{settled-turn-finalizer-BVJx4yoc.js → settled-turn-finalizer-BuLUrZl2.js} +54 -42
- package/dist/shared-client-CVhez2Uo.js +2911 -0
- package/dist/{side-question-BTZAII4l.js → side-question-DLbr2vUU.js} +135 -191
- package/dist/source-Da-h6f7e.js +518 -0
- package/dist/thread-archive-guard-D1bP04Tf.js +53 -0
- package/dist/{thread-lifecycle-DAcEJ_Om.js → thread-lifecycle-D1pzRwHB.js} +467 -977
- package/dist/{thread-ownership-zGokd8i1.js → thread-ownership-D6oASVRu.js} +15 -17
- package/dist/{thread-policy-g4KbJPzp.js → thread-policy-D8kI7yAO.js} +2 -2
- package/dist/thread-resume-T5cveyxA.js +52 -0
- package/dist/timeout-BVw8aaM1.js +33 -0
- package/dist/transcript-mirror-attestation-DibE0krH.js +89 -0
- package/dist/{transcript-mirror-DTUxFWa_.js → transcript-mirror-t5TOccct.js} +111 -379
- package/dist/{transport-stdio-CyPldczm.js → transport-stdio-BGjHoYLr.js} +80 -48
- package/dist/{upstream-session-fork-CYlBIGVt.js → upstream-session-fork-De-sLJ2r.js} +94 -166
- package/dist/{usage-Bj-rrzkR.js → usage-CPPTmBvZ.js} +4 -3
- package/dist/version-omm6IPI3.js +12 -0
- package/dist/{web-search-provider.runtime-D2FWSK4w.js → web-search-provider.runtime-CSVgQL0w.js} +3 -3
- package/openclaw.plugin.json +22 -1
- package/package.json +6 -6
- package/dist/request-DYAI5FQE.js +0 -475
- package/dist/session-catalog-yyvTWFOw.js +0 -3120
- package/dist/session-history-C5J1AKzG.js +0 -87
- package/dist/shared-client-DxcfF9KX.js +0 -7494
- package/dist/{auth-binding-Ds_QVm-X.js → auth-binding-Co2Vfcf_.js} +1 -1
|
@@ -1,54 +1,110 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { c as
|
|
4
|
-
import {
|
|
5
|
-
import { a as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { a as
|
|
10
|
-
import {
|
|
1
|
+
import { l as sessionBindingIdentity, n as assertCodexBindingMayBeReplaced } from "./session-binding-record-CaZjYwNS.js";
|
|
2
|
+
import { n as defineCodexBuildState } from "./build-state-6RL6qohz.js";
|
|
3
|
+
import { b as readCodexRequirementsToml, c as hasCodexMcpToolApprovalOverrides, d as withMcpElicitationsApprovalPolicy, i as resolveCodexAppServerHomeScope, m as resolveCodexModelBackedReviewerPolicyContext, o as resolveCodexComputerUseConfig, u as shouldAutoApproveCodexAppServerApprovals } from "./config-options-jnIFvwxD.js";
|
|
4
|
+
import { S as resolveCodexPluginsPolicy, a as flattenCodexDynamicToolFunctions, b as isCodexSandboxExecServerEnabled, o as isJsonObject, s as resolveCodexAppServerHomeDir, v as isCodexPairedNodeRemoteExecPlacementSandbox, x as readCodexPluginConfig, y as isCodexRemoteExecPlacementSandbox } from "./protocol-CAAcVIKF.js";
|
|
5
|
+
import { A as isMatchingDynamicToolTerminalDiagnostic, D as handleDynamicToolCallWithTimeout, E as createCodexElicitationResponse, F as toCodexDynamicToolProgressResponse, I as toCodexDynamicToolProtocolResponse, L as resolveCodexToolAbortTerminalReason, M as resolveTerminalDynamicToolBatchAction, N as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, O as hasPendingDynamicToolTerminalDiagnostic, P as shouldReleaseTurnAfterTerminalDynamicTool, S as readCodexDynamicToolCallParams, T as readCodexTurnCompletedNotification, a as isCodexAppServerBrokenPipeError, c as isCodexAppServerIndeterminateTransportError, d as isCodexAppServerRequestTimeoutError, i as isCodexAppServerApprovalRequest, j as resolveDynamicToolCallTimeoutMs, k as isDynamicToolTerminalDiagnosticEvent, l as isCodexAppServerOverloadError, o as isCodexAppServerConnectionClosedError, p as resolveCodexAppServerClientInstanceId, r as getCodexAppServerClientInstanceId, s as isCodexAppServerIndeterminateRequestCancellationError, w as readCodexTurn, x as assertCodexTurnStartResponse } from "./client-BEKu4yDx.js";
|
|
6
|
+
import { c as resolveCodexAppServerPreparedApiKeyCacheKey, m as retireSharedCodexAppServerClientIfCurrent, s as resolveCodexAppServerFallbackApiKeyCacheKey } from "./auth-cache-key-Kq6oerr6.js";
|
|
7
|
+
import { t as isIncognitoSessionKey } from "./incognito-session-uhrBF6wJ.js";
|
|
8
|
+
import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-Bqnx1N4z.js";
|
|
9
|
+
import { a as formatCodexDisplayText } from "./command-formatters-DeTfrapr.js";
|
|
10
|
+
import { r as CodexAppServerRpcError } from "./session-catalog-provenance-DkJHo735.js";
|
|
11
|
+
import { t as CODEX_CONTROL_METHODS } from "./capabilities-BeqLPbtM.js";
|
|
11
12
|
import { r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-LphB8slG.js";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { n as
|
|
17
|
-
import {
|
|
13
|
+
import { n as buildCodexAppServerRuntimeFingerprint, r as buildCodexPluginAppCacheKey, s as defaultCodexAppInventoryCache } from "./plugin-app-cache-key-CdSQzWyX.js";
|
|
14
|
+
import { t as withAbortableTimeout } from "./timeout-BVw8aaM1.js";
|
|
15
|
+
import { n as resolveOpenClawExecPolicyForCodexAppServer, t as canUseCodexModelBackedApprovalsReviewerForModel } from "./config-JDfTI4VI.js";
|
|
16
|
+
import { o as hasCodexMirrorOrigin, t as applyCodexTranscriptTaint } from "./transcript-mirror-attestation-DibE0krH.js";
|
|
17
|
+
import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-Co2Vfcf_.js";
|
|
18
|
+
import { i as resolveCodexBindingAppServerConnection, t as assertCodexSessionRuntimeOwnership } from "./binding-connection-QqgcPCgk.js";
|
|
19
|
+
import { i as resolveCodexAppServerAuthProfileIdForAgent, r as resolveCodexAppServerAuthProfileId } from "./auth-profile-CwzO4_RG.js";
|
|
20
|
+
import { B as prepareCodexWorkspaceReferences, D as TURN_FINALIZE_DRAIN_ABORT_GRACE_MS, E as CodexAppServerStartupError, F as ensureCodexAppServerClientRuntime, J as rememberCodexRateLimitsRead, K as readCodexRateLimitsRevision, M as withCodexStartupTimeout, O as TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS, V as protectCodexAppServerLiveThread, X as resolveCodexAppServerAuthAccountCacheKey, Z as resolveCodexAppServerPreparedAuthHandoff, a as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, c as getLeasedSharedCodexAppServerClient, f as readCodexAppServerClientDesktopGenerationFingerprint, h as releaseLeasedSharedCodexAppServerClient, i as clearSharedCodexAppServerClientIfCurrent, j as resolveCodexStartupTimeoutMs, k as isCodexAppServerStartupError, l as getSharedCodexAppServerClient, q as readRecentCodexRateLimits, s as createIsolatedCodexAppServerClient, u as isCodexAppServerStartSelectionChangedError, v as retainSharedCodexAppServerClientIfCurrent } from "./shared-client-CVhez2Uo.js";
|
|
21
|
+
import { F as readCodexProviderRefusal, H as readNullableString, L as readItem, M as extractRawAssistantText, O as matchesCodexSnapshotTurn, P as readCodexErrorNotificationMessage, R as readItemString, U as splitPlanText, V as readNonNegativeInteger, a as closeCodexStartupClientBestEffort, d as unsubscribeCodexThreadBestEffort, f as CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS, g as readCodexNotificationThreadId, h as isCodexNotificationForTurn, k as shouldClearTerminalPresentationForNativeItem, l as retireUnsafeCodexTurnClientBestEffort, m as CodexProjectionDiagnostics, o as interruptCodexTurnAndWaitBestEffort, p as getCodexAppServerTurnRouter, r as CodexAppServerUnsafeSubscriptionError, u as terminateCodexBackgroundTerminals } from "./attempt-client-cleanup-D6cR54TV.js";
|
|
22
|
+
import { a as isRawFunctionToolOutputCompletionNotification, c as readNotificationItemId, i as isPendingOpenClawDynamicToolCompletionNotification, l as readRawResponseToolCallId, o as isTerminalTurnStatus, r as isCodexTurnAbortMarkerNotification, s as readCodexNotificationItem, t as codexExecutionToolName, u as updateActiveTurnItemIds } from "./attempt-notifications--H8zXR5-.js";
|
|
23
|
+
import { t as CodexUsageProjection } from "./event-projector-usage-CIyrYYid.js";
|
|
24
|
+
import { s as resolveRecoverableCodexPluginConfigKeys } from "./plugin-inventory-CoRCzWW4.js";
|
|
25
|
+
import { $ as codexLegacyDynamicToolsFingerprint, A as readCodexMcpToolConnectorId, B as emitCodexNativePreToolUseFailureDiagnostic, C as buildDeveloperInstructions, Ct as buildCodexPluginThreadConfigTimeoutFallback, D as resolveCodexAppServerThreadModelSelection, Dt as shouldBuildCodexPluginThreadConfig, H as resolveCodexNativeHookRelayTtlMs, I as buildCodexNativeHookRelayConfig, K as hasCodexNativeToolCatalog, L as buildCodexNativeHookRelayDisabledConfig, M as isCodexAppServerProfilerEnabled, P as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, Q as codexDynamicToolsFingerprint, S as resolveCodexWebSearchPlan, St as buildCodexPluginThreadConfigInputFingerprint, Tt as mergeCodexThreadConfigs, U as scheduleCodexNativeHookRelayUnregister, V as resolveCodexNativeHookRelayEvents, _t as projectContextEngineAssemblyForCodex, bt as resolveCodexContinuityProjectionMaxChars, c as assertScheduledCodexAppAuthorityRuntime, d as buildScheduledCodexAppServerConnectionIdentity, f as captureScheduledCodexAppAuthority, ft as CodexContextAttachmentError, gt as neutralizeCodexExplicitMentionSigils, h as resolveScheduledCodexAppCreatorCaptureDecision, ht as isCodexDurableCustomMessage, i as buildCodexUserInput, j as readCodexMcpToolUiVisibility, l as buildLegacyScheduledCodexAppRecoveryPrompt, lt as resolveCodexDynamicToolsLoadingForRuntime, m as readCurrentCodexScheduledAppPolicy$1, mt as fitCodexProjectedContextForTurnStart, n as buildTurnCollaborationMode, nt as filterCodexDynamicTools, ot as isSystemAgentOnlyCodexDynamicToolAllowlist, p as intersectCodexPluginThreadConfigWithScheduledAuthority, pt as buildCodexContinuityCalibration, q as loadCodexNativeToolCatalog, r as buildTurnStartParams, s as startOrResumeThread, u as buildScheduledCodexAppAuthorityInputFingerprint, ut as buildContextEngineBinding, vt as resolveCodexContextEngineProjectionMaxChars, xt as buildCodexPluginThreadConfig, yt as resolveCodexContextEngineProjectionReserveTokens, z as createCodexNativeHookRelay } from "./thread-lifecycle-D1pzRwHB.js";
|
|
26
|
+
import { a as resolveCodexRunSessionBindingAuthority, n as createCodexSessionGenerationSupersededError, o as resolveCodexSessionBinding, s as scopeCodexRunBindingStore } from "./session-binding-CKSepwIC.js";
|
|
27
|
+
import { n as CodexThreadPolicyHandoffError } from "./thread-policy-D8kI7yAO.js";
|
|
28
|
+
import { r as retainCodexAppServerBindingSubscription } from "./thread-ownership-D6oASVRu.js";
|
|
29
|
+
import { i as mirrorPromptAtTurnStartBestEffort, n as createCodexAppServerUserMessagePersistenceNotifier, o as buildCodexUserPromptMessage, s as promptSnapshot, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-t5TOccct.js";
|
|
18
30
|
import { t as persistCodexContextCompactionActivity } from "./context-compaction-activity-CMla5FPJ.js";
|
|
19
|
-
import { i as createAssistantReasoningMessage, n as createAssistantCommentaryMessage, r as createAssistantMessage, t as createAssistantAsyncMessage } from "./event-projector-assistant-message-
|
|
20
|
-
import { a as
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import { a as
|
|
25
|
-
import { n as
|
|
26
|
-
import {
|
|
31
|
+
import { i as createAssistantReasoningMessage, n as createAssistantCommentaryMessage, r as createAssistantMessage, t as createAssistantAsyncMessage } from "./event-projector-assistant-message-BmBM4qBV.js";
|
|
32
|
+
import { C as shouldRequireCodexSandboxExecServerEnvironment, S as shouldEnableCodexAppServerNativeToolSurface, _ as resolveCodexAppServerHookChannelId, a as emitDynamicToolStartedDiagnostic, c as ensureCodexSandboxExecServerEnvironment, d as CodexNativeToolLifecycleProjector, f as buildDynamicTools, g as resolveCodexAppServerExecutionCwd, h as formatCodexDynamicToolBuildStageSummary, i as emitDynamicToolErrorDiagnostic, l as releaseCodexSandboxExecServerEnvironment, m as disableCodexPluginThreadConfig, n as projectCodexExecutableDynamicTools, o as emitDynamicToolTerminalDiagnostic, p as createCodexDynamicToolBuildStageTracker, r as routeCodexAppServerElicitationRequest, s as handleCodexAppServerApprovalRequest, t as createCodexDynamicToolBridge, u as readBoundedCodexRemoteWorkspaceFile, v as resolveCodexExternalSandboxPolicyForOpenClawSandbox, w as shouldWarnCodexDynamicToolBuildStageSummary, x as resolveCodexSandboxEnvironmentSelection, y as resolveCodexMessageToolProvider } from "./dynamic-tools-D-JBoaLt.js";
|
|
33
|
+
import { t as resolveCodexProviderWebSearchSupport } from "./provider-capabilities-W4tfK5Y5.js";
|
|
34
|
+
import { a as CodexToolProgressProjection, c as isCodexCommandBearingToolCall, d as sanitizeCodexToolResponse, i as CodexToolTranscriptProjection, l as resolveCodexToolProgressDetailMode, n as CodexEventProjection, o as shouldEmitTranscriptToolProgress, r as emitCodexAgentEvent, s as inferCodexDynamicToolMeta, t as codexNativeSubagentMonitorRuntime, u as sanitizeCodexToolArguments } from "./native-subagent-monitor-BbCUKRwC.js";
|
|
35
|
+
import { a as requestPluginApprovalOutcome } from "./plugin-approval-roundtrip-DeW95wB5.js";
|
|
36
|
+
import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, r as resolveCodexEffectiveSessionPermissionPolicy } from "./session-permission-policy-B22InTp_.js";
|
|
37
|
+
import { a as getCodexWorkspaceMemoryToolNames, c as readContextEngineThreadBootstrapProjection, d as resolveCodexDeliveryHintPreservedInputRange, f as resolveContextEngineBootstrapProjectionDecision, i as buildCodexWorkspaceBootstrapContext, l as readMirroredSessionHistoryMessages, n as buildCodexSystemPromptReport, r as buildCodexWatchedSessionsContext, s as prependCodexOpenClawPromptContext, t as buildCodexOpenClawPromptContext, u as renderCodexSkillsCollaborationInstructions } from "./attempt-context-AO4DSjE0.js";
|
|
38
|
+
import { n as captureCodexSettledTurnFinalizationContext } from "./settled-turn-context-Du6gdUDd.js";
|
|
39
|
+
import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-DgNfRAGA.js";
|
|
27
40
|
import { asOptionalRecord, normalizeOptionalString, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
28
|
-
import
|
|
41
|
+
import { createHash } from "node:crypto";
|
|
42
|
+
import { resolveAgentConfig, resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
43
|
+
import { MAX_TIMER_TIMEOUT_MS, asDateTimestampMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
29
44
|
import path from "node:path";
|
|
45
|
+
import fs from "node:fs/promises";
|
|
46
|
+
import { addAbortListener } from "node:events";
|
|
47
|
+
import { truncateUtf16Safe, truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
48
|
+
import { Buffer as Buffer$1 } from "node:buffer";
|
|
30
49
|
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
31
|
-
import { MAX_TIMER_TIMEOUT_MS, asDateTimestampMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
32
|
-
import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, agentHarnessAttemptTerminal, agentHarnessStructuredInput, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildEmbeddedForegroundPromptContext, buildHarnessContextEngineRuntimeContext, callGatewayTool, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, detectAndLoadAgentHarnessPromptImages, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, formatErrorMessage, formatFastModeAutoProgressText, getAgentHarnessHookRunner, hasBeforeToolCallPolicy, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, prepareHarnessNativeMcpAppPreview, projectAgentHarnessTranscriptMessageForDisplay, resolveAgentDir, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveAttemptFsWorkspaceOnly, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveUserPath, runAgentCleanupStep, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
33
50
|
import { isPathStrictlyInside, root } from "openclaw/plugin-sdk/file-access-runtime";
|
|
34
|
-
import {
|
|
51
|
+
import { isDeepStrictEqual } from "node:util";
|
|
35
52
|
import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1 } from "openclaw/plugin-sdk/agent-runtime";
|
|
36
|
-
import {
|
|
53
|
+
import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, agentHarnessAttemptTerminal, agentHarnessStructuredInput, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildEmbeddedForegroundPromptContext, buildHarnessContextEngineRuntimeContext, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, detectAndLoadAgentHarnessPromptImages, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, formatErrorMessage, formatFastModeAutoProgressText, getAgentHarnessHookRunner, hasBeforeToolCallPolicy, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, prepareHarnessNativeMcpAppPreview, projectAgentHarnessTranscriptMessageForDisplay, projectProgressCardChannelUpdate, resolveAgentDir as resolveAgentDir$2, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveAttemptFsWorkspaceOnly, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveUserPath, runAgentCleanupStep, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
37
54
|
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
38
55
|
import { parseSqliteSessionFileMarker } from "openclaw/plugin-sdk/session-store-runtime";
|
|
39
|
-
import { addAbortListener } from "node:events";
|
|
40
|
-
import { truncateUtf16Safe, truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
41
56
|
import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
42
57
|
import { captureFinalCodexCronCreatorToolAllowlist, formatMcpCodexApprovalRemedy, materializeStaticMcpToolsForHarnessRun, resolveCodexMcpToolOverridesForAgent, resolveCodexTtsProvenanceTransfer } from "openclaw/plugin-sdk/codex-mcp-projection";
|
|
43
|
-
import { hasPromptImageInput } from "openclaw/plugin-sdk/session-transcript-runtime";
|
|
44
|
-
import { Buffer as Buffer$1 } from "node:buffer";
|
|
45
|
-
import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
58
|
+
import { appendSessionYieldContext, hasPromptImageInput } from "openclaw/plugin-sdk/session-transcript-runtime";
|
|
46
59
|
import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-local-roots";
|
|
47
60
|
import { isSilentReplyPayloadText } from "openclaw/plugin-sdk/reply-chunking";
|
|
48
61
|
import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
|
|
49
62
|
import { resolveGeneratedMediaMaxBytes } from "openclaw/plugin-sdk/media-generation-runtime";
|
|
50
63
|
import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
|
|
51
64
|
import { stripInvisibleUnicode } from "openclaw/plugin-sdk/web-content-extractor";
|
|
65
|
+
import { acknowledgeInternalToolResult } from "openclaw/plugin-sdk/agent-harness-tool-runtime";
|
|
66
|
+
import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
67
|
+
//#region extensions/codex/src/app-server/attempt-preparation-timing.ts
|
|
68
|
+
/** Records startup before the native turn owns inference and tool execution. */
|
|
69
|
+
function createCodexAttemptPreparationTiming(params) {
|
|
70
|
+
const tracker = createCodexDynamicToolBuildStageTracker();
|
|
71
|
+
const profilerEnabled = isCodexAppServerProfilerEnabled(params.config);
|
|
72
|
+
const totalWarnMs = profilerEnabled ? 1e3 : 1e4;
|
|
73
|
+
const stageWarnMs = profilerEnabled ? 500 : 5e3;
|
|
74
|
+
const log = (stage, outcome) => {
|
|
75
|
+
const summary = tracker.snapshot();
|
|
76
|
+
const lastStage = summary.stages.at(-1);
|
|
77
|
+
const slowTotal = outcome !== "completed" && summary.totalMs >= totalWarnMs;
|
|
78
|
+
const slowStage = outcome !== "ready" && (lastStage?.durationMs ?? 0) >= stageWarnMs;
|
|
79
|
+
if (!slowTotal && !slowStage) return;
|
|
80
|
+
embeddedAgentLog.warn(`codex app-server preparation timings runId=${params.runId} sessionId=${params.sessionId} stage=${stage} outcome=${outcome} totalMs=${summary.totalMs} stages=${formatCodexDynamicToolBuildStageSummary(summary)}`, {
|
|
81
|
+
runId: params.runId,
|
|
82
|
+
sessionId: params.sessionId,
|
|
83
|
+
sessionKey: params.sessionKey,
|
|
84
|
+
stage,
|
|
85
|
+
outcome,
|
|
86
|
+
totalMs: summary.totalMs,
|
|
87
|
+
stages: summary.stages
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
return {
|
|
91
|
+
async measure(stage, run) {
|
|
92
|
+
let outcome = "error";
|
|
93
|
+
try {
|
|
94
|
+
const result = await run();
|
|
95
|
+
outcome = "completed";
|
|
96
|
+
return result;
|
|
97
|
+
} finally {
|
|
98
|
+
tracker.mark(stage);
|
|
99
|
+
log(stage, outcome);
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
ready() {
|
|
103
|
+
log("native-turn-handoff", "ready");
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//#endregion
|
|
52
108
|
//#region extensions/codex/src/app-server/attempt-steering.ts
|
|
53
109
|
/**
|
|
54
110
|
* Debounced steering queue for forwarding user messages to an active Codex
|
|
@@ -130,30 +186,67 @@ function createCodexSteeringQueue(params) {
|
|
|
130
186
|
closeQueue(/* @__PURE__ */ new Error("codex app-server steering queue cancelled"));
|
|
131
187
|
};
|
|
132
188
|
const sendBatch = async (items) => {
|
|
133
|
-
|
|
189
|
+
let liveItems = items.filter((item) => !item.settled);
|
|
134
190
|
if (liveItems.length === 0) return;
|
|
135
191
|
let clientUserMessageId;
|
|
192
|
+
let skippedRevokedBatch = false;
|
|
136
193
|
try {
|
|
137
194
|
assertActive();
|
|
138
|
-
const
|
|
195
|
+
const prepared = /* @__PURE__ */ new Map();
|
|
196
|
+
const isCurrent = (item) => {
|
|
197
|
+
if (item.settled) return false;
|
|
198
|
+
try {
|
|
199
|
+
item.assertCurrent();
|
|
200
|
+
return true;
|
|
201
|
+
} catch (error) {
|
|
202
|
+
rejectItem(item, error);
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
139
206
|
for (const item of liveItems) {
|
|
140
|
-
|
|
207
|
+
if (!isCurrent(item)) continue;
|
|
208
|
+
try {
|
|
209
|
+
prepared.set(item, await params.prepareMessage(item.text, item));
|
|
210
|
+
} catch (error) {
|
|
211
|
+
if (isCurrent(item)) throw error;
|
|
212
|
+
}
|
|
213
|
+
assertActive();
|
|
214
|
+
isCurrent(item);
|
|
215
|
+
}
|
|
216
|
+
liveItems = liveItems.filter(isCurrent);
|
|
217
|
+
if (liveItems.length === 0) return;
|
|
218
|
+
if (params.beforeSubmit) {
|
|
219
|
+
await params.beforeSubmit(liveItems);
|
|
141
220
|
assertActive();
|
|
221
|
+
liveItems = liveItems.filter(isCurrent);
|
|
222
|
+
if (liveItems.length === 0) return;
|
|
142
223
|
}
|
|
143
224
|
clientUserMessageId = `openclaw:${params.turnId}:steer:${++batchSequence}`;
|
|
144
225
|
dispatchedBatches.set(clientUserMessageId, { items: liveItems });
|
|
145
|
-
|
|
226
|
+
const request = {
|
|
146
227
|
threadId: params.threadId,
|
|
147
228
|
expectedTurnId: params.turnId,
|
|
148
|
-
input,
|
|
229
|
+
input: liveItems.flatMap((item) => prepared.get(item) ?? []),
|
|
149
230
|
clientUserMessageId
|
|
150
|
-
}
|
|
231
|
+
};
|
|
232
|
+
await params.client.request("turn/steer", request, {
|
|
151
233
|
timeoutMs: params.requestTimeoutMs,
|
|
152
|
-
signal: params.signal
|
|
234
|
+
signal: params.signal,
|
|
235
|
+
assertCurrent: () => {
|
|
236
|
+
assertActive();
|
|
237
|
+
liveItems = liveItems.filter(isCurrent);
|
|
238
|
+
request.input = liveItems.flatMap((item) => prepared.get(item) ?? []);
|
|
239
|
+
dispatchedBatches.set(request.clientUserMessageId, { items: liveItems });
|
|
240
|
+
if (liveItems.length === 0) {
|
|
241
|
+
skippedRevokedBatch = true;
|
|
242
|
+
throw new Error("Codex steering batch has no authorized inputs");
|
|
243
|
+
}
|
|
244
|
+
}
|
|
153
245
|
});
|
|
154
246
|
for (const item of liveItems) reportItemAcceptance(item, true);
|
|
155
247
|
} catch (error) {
|
|
156
248
|
if (clientUserMessageId) dispatchedBatches.delete(clientUserMessageId);
|
|
249
|
+
if (skippedRevokedBatch) return;
|
|
157
250
|
const acceptedUnconfirmed = clientUserMessageId !== void 0 && (isCodexAppServerIndeterminateRequestCancellationError(error) || isCodexAppServerIndeterminateTransportError(error));
|
|
158
251
|
for (const item of liveItems) {
|
|
159
252
|
if (acceptedUnconfirmed) reportItemAcceptance(item, true);
|
|
@@ -180,7 +273,7 @@ function createCodexSteeringQueue(params) {
|
|
|
180
273
|
send.catch(() => void 0);
|
|
181
274
|
return send;
|
|
182
275
|
};
|
|
183
|
-
const createPendingMessage = (text, options) => {
|
|
276
|
+
const createPendingMessage = (text, options, assertCurrent = () => {}) => {
|
|
184
277
|
let resolveDelivery;
|
|
185
278
|
let rejectDelivery;
|
|
186
279
|
const delivery = new Promise((resolve, reject) => {
|
|
@@ -189,6 +282,7 @@ function createCodexSteeringQueue(params) {
|
|
|
189
282
|
});
|
|
190
283
|
const item = {
|
|
191
284
|
...options,
|
|
285
|
+
assertCurrent,
|
|
192
286
|
acceptance: "open",
|
|
193
287
|
text,
|
|
194
288
|
resolve: resolveDelivery,
|
|
@@ -204,14 +298,15 @@ function createCodexSteeringQueue(params) {
|
|
|
204
298
|
params.signal.addEventListener("abort", abortQueue, { once: true });
|
|
205
299
|
if (params.signal.aborted) abortQueue();
|
|
206
300
|
return {
|
|
207
|
-
async queue(text, options) {
|
|
301
|
+
async queue(text, options, assertCurrent = () => {}) {
|
|
208
302
|
try {
|
|
209
303
|
assertActive();
|
|
304
|
+
assertCurrent();
|
|
210
305
|
} catch (error) {
|
|
211
306
|
options?.onQueueAccepted?.(false);
|
|
212
307
|
throw error;
|
|
213
308
|
}
|
|
214
|
-
const { item, delivery } = createPendingMessage(text, options);
|
|
309
|
+
const { item, delivery } = createPendingMessage(text, options, assertCurrent);
|
|
215
310
|
batchedMessages.push(item);
|
|
216
311
|
clearBatchTimer();
|
|
217
312
|
const debounceMs = normalizeCodexSteerDebounceMs(options?.debounceMs);
|
|
@@ -226,21 +321,8 @@ function createCodexSteeringQueue(params) {
|
|
|
226
321
|
const batch = dispatchedBatches.get(clientUserMessageId);
|
|
227
322
|
if (!batch) return false;
|
|
228
323
|
dispatchedBatches.delete(clientUserMessageId);
|
|
229
|
-
for (const item of batch.items)
|
|
230
|
-
|
|
231
|
-
for (const item of batch.items) resolveItem(item);
|
|
232
|
-
return true;
|
|
233
|
-
};
|
|
234
|
-
const rejectBatch = (error) => {
|
|
235
|
-
for (const item of batch.items) rejectItem(item, error);
|
|
236
|
-
return true;
|
|
237
|
-
};
|
|
238
|
-
if (!params.beforeConfirmConsumed) return resolveBatch();
|
|
239
|
-
try {
|
|
240
|
-
return params.beforeConfirmConsumed(batch.items).then(resolveBatch, rejectBatch);
|
|
241
|
-
} catch (error) {
|
|
242
|
-
return rejectBatch(error);
|
|
243
|
-
}
|
|
324
|
+
for (const item of batch.items) resolveItem(item);
|
|
325
|
+
return true;
|
|
244
326
|
},
|
|
245
327
|
sealAdmission: sealQueueAdmission,
|
|
246
328
|
cancel: cancelQueue
|
|
@@ -251,6 +333,9 @@ function normalizeCodexSteerDebounceMs(value) {
|
|
|
251
333
|
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : CODEX_STEER_ALL_DEBOUNCE_MS;
|
|
252
334
|
}
|
|
253
335
|
//#endregion
|
|
336
|
+
//#region extensions/codex/src/app-server/attempt-terminal.ts
|
|
337
|
+
const attemptTerminal = agentHarnessAttemptTerminal;
|
|
338
|
+
//#endregion
|
|
254
339
|
//#region extensions/codex/src/app-server/event-projector-assistant.ts
|
|
255
340
|
var CodexAssistantProjection = class {
|
|
256
341
|
constructor(params, emitAgentEvent, matchesToolProgressEcho, nextTranscriptTimestamp, checkpointCommentary) {
|
|
@@ -320,6 +405,7 @@ var CodexAssistantProjection = class {
|
|
|
320
405
|
this.emitAgentEvent({
|
|
321
406
|
stream: "assistant",
|
|
322
407
|
data: {
|
|
408
|
+
itemId,
|
|
323
409
|
...streamPayload,
|
|
324
410
|
...replaceable ? { replaceable: true } : {}
|
|
325
411
|
}
|
|
@@ -1000,8 +1086,61 @@ function reasoningMethodOrder(method) {
|
|
|
1000
1086
|
return method === "item/reasoning/summaryTextDelta" ? 0 : 1;
|
|
1001
1087
|
}
|
|
1002
1088
|
//#endregion
|
|
1003
|
-
//#region extensions/codex/src/app-server/
|
|
1004
|
-
|
|
1089
|
+
//#region extensions/codex/src/app-server/event-projector-settlement.ts
|
|
1090
|
+
var CodexProjectionSettlement = class {
|
|
1091
|
+
constructor(params, isActive) {
|
|
1092
|
+
this.turnTainted = false;
|
|
1093
|
+
this.pending = /* @__PURE__ */ new Map();
|
|
1094
|
+
const detach = (stage, callback) => callback ? (...args) => {
|
|
1095
|
+
if (!isActive()) return;
|
|
1096
|
+
const completion = createDeferred();
|
|
1097
|
+
this.pending.set(completion.promise, stage);
|
|
1098
|
+
const settled = () => {
|
|
1099
|
+
this.pending.delete(completion.promise);
|
|
1100
|
+
completion.resolve();
|
|
1101
|
+
};
|
|
1102
|
+
const failed = (error) => {
|
|
1103
|
+
embeddedAgentLog.warn(`codex app-server ${stage} callback failed: ${String(error)}`);
|
|
1104
|
+
settled();
|
|
1105
|
+
};
|
|
1106
|
+
try {
|
|
1107
|
+
Promise.resolve(callback(...args)).then(settled, failed);
|
|
1108
|
+
} catch (error) {
|
|
1109
|
+
failed(error);
|
|
1110
|
+
}
|
|
1111
|
+
} : void 0;
|
|
1112
|
+
this.params = {
|
|
1113
|
+
...params,
|
|
1114
|
+
onAssistantMessageStart: detach("onAssistantMessageStart", params.onAssistantMessageStart),
|
|
1115
|
+
onPartialReply: detach("onPartialReply", params.onPartialReply),
|
|
1116
|
+
onReasoningStream: detach("onReasoningStream", params.onReasoningStream),
|
|
1117
|
+
onReasoningEnd: detach("onReasoningEnd", params.onReasoningEnd)
|
|
1118
|
+
};
|
|
1119
|
+
}
|
|
1120
|
+
get pendingStage() {
|
|
1121
|
+
return this.stage ?? this.pending.values().next().value;
|
|
1122
|
+
}
|
|
1123
|
+
get completedAnswer() {
|
|
1124
|
+
const turn = this.terminalReceipt;
|
|
1125
|
+
const answer = turn?.items?.findLast((item) => item.type === "agentMessage" && item.phase !== "commentary" && item.delivery !== "async" && typeof item.text === "string" && item.text.trim().length > 0);
|
|
1126
|
+
return turn?.status === "completed" && answer ? {
|
|
1127
|
+
turn,
|
|
1128
|
+
answer
|
|
1129
|
+
} : void 0;
|
|
1130
|
+
}
|
|
1131
|
+
async project(stage, project) {
|
|
1132
|
+
const previous = this.stage;
|
|
1133
|
+
this.stage = stage;
|
|
1134
|
+
try {
|
|
1135
|
+
return await project();
|
|
1136
|
+
} finally {
|
|
1137
|
+
this.stage = previous;
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
async drain() {
|
|
1141
|
+
while (this.pending.size > 0) await Promise.all(this.pending.keys());
|
|
1142
|
+
}
|
|
1143
|
+
};
|
|
1005
1144
|
//#endregion
|
|
1006
1145
|
//#region extensions/codex/src/app-server/event-projector-snapshot.ts
|
|
1007
1146
|
function buildCodexMessagesSnapshot(params) {
|
|
@@ -1016,7 +1155,10 @@ function buildCodexMessagesSnapshot(params) {
|
|
|
1016
1155
|
...params.toolMessages
|
|
1017
1156
|
].toSorted((left, right) => (asDateTimestampMs(left.timestamp) ?? 0) - (asDateTimestampMs(right.timestamp) ?? 0));
|
|
1018
1157
|
messages.push(...visibleWorkMessages);
|
|
1019
|
-
if (params.lastAssistant)
|
|
1158
|
+
if (params.lastAssistant) {
|
|
1159
|
+
const assistant = applyCodexTranscriptTaint(params.lastAssistant, { tainted: params.turnTainted === true });
|
|
1160
|
+
messages.push(attachCodexMirrorIdentity(assistant, `${params.turnId}:assistant`));
|
|
1161
|
+
}
|
|
1020
1162
|
const taint = { tainted: false };
|
|
1021
1163
|
return messages.map((message) => projectAgentHarnessTranscriptMessageForDisplay({
|
|
1022
1164
|
hidden: params.runParams.trigger === "memory",
|
|
@@ -1047,202 +1189,39 @@ function buildCodexSteeringMessagesSnapshot(params) {
|
|
|
1047
1189
|
};
|
|
1048
1190
|
}
|
|
1049
1191
|
//#endregion
|
|
1050
|
-
//#region extensions/codex/src/app-server/event-projector-result.ts
|
|
1051
|
-
function buildCodexAttemptResult(input) {
|
|
1052
|
-
input.nativeToolLifecycleProjection.finalizeActive();
|
|
1053
|
-
const assistantTexts = input.assistantProjection.collectAssistantTexts();
|
|
1054
|
-
const asyncMessages = input.assistantProjection.collectAsyncMessages();
|
|
1055
|
-
const commentaryMessages = input.assistantProjection.collectCommentaryMessages();
|
|
1056
|
-
const reasoningText = input.reasoningProjection.reasoningText();
|
|
1057
|
-
const planText = input.reasoningProjection.planText();
|
|
1058
|
-
const unavailableThreadUsage = input.tokenUsage ? {
|
|
1059
|
-
...input.tokenUsage,
|
|
1060
|
-
contextUsage: { state: "unavailable" }
|
|
1061
|
-
} : void 0;
|
|
1062
|
-
const completedUsage = input.responseCompletions.usage ?? (input.responseCompletions.modelIterations > 0 ? unavailableThreadUsage : input.tokenUsage);
|
|
1063
|
-
const projectedUsage = input.aborted ? unavailableThreadUsage : completedUsage;
|
|
1064
|
-
const hasAssistantItemText = input.assistantProjection.hasAssistantItemTextForSynthesis();
|
|
1065
|
-
const legacyFailClosed = !input.completedTurn || input.completedTurn.status !== "completed" || hasAssistantItemText;
|
|
1066
|
-
const hasDeliverableAssistantOnCompletedTurn = input.completedTurn?.status === "completed" && assistantTexts.some((text) => text.trim().length > 0);
|
|
1067
|
-
const synthesizedMissingToolResultError = input.toolTranscriptProjection.synthesizeMissingToolResults({
|
|
1068
|
-
synthesize: legacyFailClosed,
|
|
1069
|
-
terminalDisposition: input.aborted ? "tool_error" : hasDeliverableAssistantOnCompletedTurn ? "diagnostic_only" : "prompt_error"
|
|
1070
|
-
});
|
|
1071
|
-
const storedMissingToolResultError = synthesizedMissingToolResultError ?? input.synthesizedMissingToolResultError;
|
|
1072
|
-
let promptErrorSource = input.promptErrorSource;
|
|
1073
|
-
if (synthesizedMissingToolResultError) {
|
|
1074
|
-
input.recordSynthesizedMissingToolResultError(synthesizedMissingToolResultError);
|
|
1075
|
-
promptErrorSource = promptErrorSource ?? "prompt";
|
|
1076
|
-
}
|
|
1077
|
-
const assistantMessageOptions = {
|
|
1078
|
-
tokenUsage: projectedUsage,
|
|
1079
|
-
aborted: input.aborted,
|
|
1080
|
-
promptError: input.promptError
|
|
1081
|
-
};
|
|
1082
|
-
const lastAssistant = assistantTexts.length ? input.assistantProjection.createAssistantMessage(assistantTexts.join("\n\n"), assistantMessageOptions) : void 0;
|
|
1083
|
-
const currentAttemptAssistant = input.assistantProjection.createCurrentAttemptAssistantMessage(assistantMessageOptions);
|
|
1084
|
-
const messagesSnapshot = buildCodexMessagesSnapshot({
|
|
1085
|
-
runParams: input.runParams,
|
|
1086
|
-
turnId: input.turnId,
|
|
1087
|
-
upstreamUserText: input.upstreamUserText,
|
|
1088
|
-
reasoningText,
|
|
1089
|
-
asyncMessages,
|
|
1090
|
-
commentaryMessages,
|
|
1091
|
-
toolMessages: input.toolTranscriptProjection.transcriptMessages,
|
|
1092
|
-
lastAssistant
|
|
1093
|
-
});
|
|
1094
|
-
const turnFailed = input.completedTurn?.status === "failed";
|
|
1095
|
-
const promptError = input.promptError ?? storedMissingToolResultError ?? (turnFailed ? input.completedTurn?.error?.message ?? "codex app-server turn failed" : null);
|
|
1096
|
-
const agentHarnessResultClassification = classifyAgentHarnessTerminalOutcome({
|
|
1097
|
-
assistantTexts,
|
|
1098
|
-
reasoningText,
|
|
1099
|
-
planText,
|
|
1100
|
-
promptError,
|
|
1101
|
-
turnCompleted: Boolean(input.completedTurn)
|
|
1102
|
-
});
|
|
1103
|
-
const toolMetas = input.toolProgressProjection.toolMetas;
|
|
1104
|
-
const hadPotentialSideEffects = input.toolTelemetry.didSendViaMessagingTool || Boolean(input.toolTelemetry.successfulCronAdds || input.toolTelemetry.acceptedSessionSpawns?.length) || input.generatedMediaProjection.hasGeneratedMedia() || input.toolProgressProjection.hasPotentialSideEffects;
|
|
1105
|
-
const sentMediaUrls = new Set(input.toolTelemetry.messagingToolSentMediaUrls.map((url) => url.trim()));
|
|
1106
|
-
const toolAutoDeliveryMediaUrls = input.toolTelemetry.toolAutoDeliveryMediaUrls?.filter((url) => !sentMediaUrls.has(url.trim()));
|
|
1107
|
-
const result = {
|
|
1108
|
-
terminal: attemptTerminal.normalize({
|
|
1109
|
-
aborted: input.aborted,
|
|
1110
|
-
promptError,
|
|
1111
|
-
promptErrorSource: promptError ? promptErrorSource || "prompt" : null
|
|
1112
|
-
}),
|
|
1113
|
-
sessionIdUsed: input.runParams.sessionId,
|
|
1114
|
-
terminalTurnId: input.turnId,
|
|
1115
|
-
...agentHarnessResultClassification ? { agentHarnessResultClassification } : {},
|
|
1116
|
-
bootstrapPromptWarningSignaturesSeen: input.runParams.bootstrapPromptWarningSignaturesSeen,
|
|
1117
|
-
bootstrapPromptWarningSignature: input.runParams.bootstrapPromptWarningSignature,
|
|
1118
|
-
...input.responseCompletions.modelIterations > 0 ? { modelIterations: input.responseCompletions.modelIterations } : {},
|
|
1119
|
-
messagesSnapshot,
|
|
1120
|
-
assistantTexts,
|
|
1121
|
-
toolMetas,
|
|
1122
|
-
lastAssistant,
|
|
1123
|
-
currentAttemptAssistant,
|
|
1124
|
-
...input.toolProgressProjection.lastToolError ? { lastToolError: input.toolProgressProjection.lastToolError } : {},
|
|
1125
|
-
didSendViaMessagingTool: input.toolTelemetry.didSendViaMessagingTool,
|
|
1126
|
-
didDeliverSourceReplyViaMessageTool: input.toolTelemetry.didDeliverSourceReplyViaMessageTool === true,
|
|
1127
|
-
messagingToolSentTexts: input.toolTelemetry.messagingToolSentTexts,
|
|
1128
|
-
messagingToolSentMediaUrls: input.toolTelemetry.messagingToolSentMediaUrls,
|
|
1129
|
-
messagingToolSentTargets: input.toolTelemetry.messagingToolSentTargets,
|
|
1130
|
-
messagingToolSourceReplyPayloads: input.toolTelemetry.messagingToolSourceReplyPayloads ?? [],
|
|
1131
|
-
heartbeatToolResponse: input.toolTelemetry.heartbeatToolResponse,
|
|
1132
|
-
toolMediaUrls: input.generatedMediaProjection.buildToolMediaUrls(input.toolTelemetry),
|
|
1133
|
-
hostOwnedToolMediaUrls: input.generatedMediaProjection.buildHostOwnedMediaUrls(input.toolTelemetry),
|
|
1134
|
-
toolAudioAsVoice: input.toolTelemetry.toolAudioAsVoice,
|
|
1135
|
-
successfulCronAdds: input.toolTelemetry.successfulCronAdds,
|
|
1136
|
-
acceptedSessionSpawns: input.toolTelemetry.acceptedSessionSpawns,
|
|
1137
|
-
cloudCodeAssistFormatError: false,
|
|
1138
|
-
contextTokens: input.contextTokens,
|
|
1139
|
-
contextTokensSource: input.contextTokensSource,
|
|
1140
|
-
attemptUsage: projectedUsage,
|
|
1141
|
-
...input.completedCompactionCount > 0 ? { compactionCount: input.completedCompactionCount } : {},
|
|
1142
|
-
replayMetadata: {
|
|
1143
|
-
hadPotentialSideEffects,
|
|
1144
|
-
replaySafe: !hadPotentialSideEffects
|
|
1145
|
-
},
|
|
1146
|
-
itemLifecycle: {
|
|
1147
|
-
startedCount: input.activeItemCount + input.completedItemCount,
|
|
1148
|
-
completedCount: input.completedItemCount,
|
|
1149
|
-
activeCount: input.activeItemCount
|
|
1150
|
-
},
|
|
1151
|
-
yieldDetected: input.yieldDetected || false,
|
|
1152
|
-
didSendDeterministicApprovalPrompt: input.guardianReviewCount > 0 ? false : void 0
|
|
1153
|
-
};
|
|
1154
|
-
const transferTtsProvenance = resolveCodexTtsProvenanceTransfer(input.runParams.hostCapabilities);
|
|
1155
|
-
for (const toolResult of input.toolTelemetry.coreTtsToolResults ?? []) transferTtsProvenance?.(toolResult, result, toolAutoDeliveryMediaUrls ?? []);
|
|
1156
|
-
return result;
|
|
1157
|
-
}
|
|
1158
|
-
//#endregion
|
|
1159
|
-
//#region extensions/codex/src/app-server/transcript-checkpoint.ts
|
|
1160
|
-
/** Commits completed work in receipt order without waiting for the enclosing turn. */
|
|
1161
|
-
var CodexTranscriptCheckpoint = class {
|
|
1162
|
-
constructor(params, threadId, turnId) {
|
|
1163
|
-
this.params = params;
|
|
1164
|
-
this.threadId = threadId;
|
|
1165
|
-
this.turnId = turnId;
|
|
1166
|
-
this.pending = [];
|
|
1167
|
-
this.commentaryItemIds = /* @__PURE__ */ new Set();
|
|
1168
|
-
this.lastTimestamp = 0;
|
|
1169
|
-
this.writing = Promise.resolve();
|
|
1170
|
-
this.tainted = false;
|
|
1171
|
-
this.closed = false;
|
|
1172
|
-
this.nextTimestamp = () => {
|
|
1173
|
-
this.lastTimestamp = Math.max(Date.now(), this.lastTimestamp + 1);
|
|
1174
|
-
return this.lastTimestamp;
|
|
1175
|
-
};
|
|
1176
|
-
this.enqueueCommentary = (itemId, entry) => {
|
|
1177
|
-
if (this.params.config?.ui?.prefs?.chatPersistCommentary === false || this.commentaryItemIds.has(itemId)) return;
|
|
1178
|
-
this.commentaryItemIds.add(itemId);
|
|
1179
|
-
this.enqueue({
|
|
1180
|
-
...entry,
|
|
1181
|
-
read: () => {
|
|
1182
|
-
const message = entry.read();
|
|
1183
|
-
return message ? attachCodexMirrorIdentity(message, `${this.turnId}:commentary:${itemId}`) : void 0;
|
|
1184
|
-
}
|
|
1185
|
-
});
|
|
1186
|
-
};
|
|
1187
|
-
this.enqueue = (entry) => {
|
|
1188
|
-
if (this.params.sessionTarget && !this.closed) this.pending.push(entry);
|
|
1189
|
-
};
|
|
1190
|
-
}
|
|
1191
|
-
flush(close = false) {
|
|
1192
|
-
if (this.closed) return this.writing;
|
|
1193
|
-
this.closed = close;
|
|
1194
|
-
this.writing = this.writing.then(async () => {
|
|
1195
|
-
const blocked = close ? -1 : this.pending.findIndex((entry) => entry.ready?.() === false);
|
|
1196
|
-
const count = blocked < 0 ? this.pending.length : blocked;
|
|
1197
|
-
if (count === 0) return;
|
|
1198
|
-
const taint = { tainted: this.tainted };
|
|
1199
|
-
const messages = this.pending.slice(0, count).flatMap((entry) => {
|
|
1200
|
-
const message = entry.read();
|
|
1201
|
-
return message ? [projectAgentHarnessTranscriptMessageForDisplay({
|
|
1202
|
-
hidden: this.params.trigger === "memory",
|
|
1203
|
-
message: applyCodexTranscriptTaint(message, taint)
|
|
1204
|
-
})] : [];
|
|
1205
|
-
});
|
|
1206
|
-
try {
|
|
1207
|
-
await codexTranscriptMirrorRuntime.mirror({
|
|
1208
|
-
...this.params.sessionTarget,
|
|
1209
|
-
sessionId: this.params.sessionId,
|
|
1210
|
-
cwd: this.params.workspaceDir,
|
|
1211
|
-
messages,
|
|
1212
|
-
idempotencyScope: `codex-app-server:${this.threadId}`,
|
|
1213
|
-
runId: this.params.runId,
|
|
1214
|
-
runMirrorIdentityPrefix: `${this.turnId}:`,
|
|
1215
|
-
config: this.params.config
|
|
1216
|
-
});
|
|
1217
|
-
this.pending.splice(0, count);
|
|
1218
|
-
this.tainted = taint.tainted;
|
|
1219
|
-
} catch (error) {
|
|
1220
|
-
embeddedAgentLog.warn("failed to checkpoint codex app-server transcript", {
|
|
1221
|
-
runId: this.params.runId,
|
|
1222
|
-
sessionId: this.params.sessionId,
|
|
1223
|
-
error: formatErrorMessage(error)
|
|
1224
|
-
});
|
|
1225
|
-
}
|
|
1226
|
-
});
|
|
1227
|
-
return this.writing;
|
|
1228
|
-
}
|
|
1229
|
-
};
|
|
1230
|
-
//#endregion
|
|
1231
1192
|
//#region extensions/codex/src/app-server/usage-limit-error.ts
|
|
1232
1193
|
/**
|
|
1233
1194
|
* Enriches Codex usage-limit failures with current rate-limit information and
|
|
1234
1195
|
* marks blocked auth profiles when Codex exposes a reset time.
|
|
1235
1196
|
*/
|
|
1236
1197
|
const CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS = 5e3;
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1198
|
+
var CodexUsageLimitPromptError = class extends Error {
|
|
1199
|
+
constructor(..._args) {
|
|
1200
|
+
super(..._args);
|
|
1201
|
+
this.status = 429;
|
|
1202
|
+
}
|
|
1203
|
+
};
|
|
1240
1204
|
function resolveCodexPromptError(source) {
|
|
1241
1205
|
const usageLimitMessage = formatCodexUsageLimitErrorMessage(source);
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1206
|
+
if (usageLimitMessage) return new CodexUsageLimitPromptError(usageLimitMessage);
|
|
1207
|
+
const info = source.codexErrorInfo;
|
|
1208
|
+
let status = info === "rateLimitExceeded" ? 429 : info === "serverOverloaded" ? 503 : info === "internalServerError" ? 500 : void 0;
|
|
1209
|
+
if (isJsonObject(info)) for (const variant of [
|
|
1210
|
+
"httpConnectionFailed",
|
|
1211
|
+
"responseStreamConnectionFailed",
|
|
1212
|
+
"responseStreamDisconnected",
|
|
1213
|
+
"responseTooManyFailedAttempts"
|
|
1214
|
+
]) {
|
|
1215
|
+
const detail = info[variant];
|
|
1216
|
+
if (isJsonObject(detail) && typeof detail.httpStatusCode === "number") {
|
|
1217
|
+
status = detail.httpStatusCode;
|
|
1218
|
+
break;
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
return status === void 0 ? source.message ?? void 0 : Object.assign(new Error(source.message ?? "codex app-server error"), {
|
|
1222
|
+
status,
|
|
1223
|
+
...info === "serverOverloaded" ? { code: "OVERLOADED" } : {}
|
|
1224
|
+
});
|
|
1246
1225
|
}
|
|
1247
1226
|
/** Marks a Codex auth profile blocked until the reset time advertised by rate limits. */
|
|
1248
1227
|
async function markCodexAuthProfileBlockedFromRateLimits(params) {
|
|
@@ -1368,8 +1347,106 @@ function readCodexErrorPayload(error) {
|
|
|
1368
1347
|
};
|
|
1369
1348
|
}
|
|
1370
1349
|
//#endregion
|
|
1371
|
-
//#region extensions/codex/src/app-server/event-projector.ts
|
|
1372
|
-
var
|
|
1350
|
+
//#region extensions/codex/src/app-server/event-projector-terminal-failure.ts
|
|
1351
|
+
var CodexTerminalFailureProjection = class {
|
|
1352
|
+
constructor() {
|
|
1353
|
+
this.promptErrorSource = null;
|
|
1354
|
+
}
|
|
1355
|
+
record(params) {
|
|
1356
|
+
this.providerRefusal ??= readCodexProviderRefusal(params.message, params.codexErrorInfo);
|
|
1357
|
+
if (this.providerRefusal) return;
|
|
1358
|
+
this.promptError = resolveCodexPromptError({
|
|
1359
|
+
message: params.message,
|
|
1360
|
+
codexErrorInfo: params.codexErrorInfo,
|
|
1361
|
+
rateLimits: params.rateLimits
|
|
1362
|
+
}) ?? params.fallbackMessage;
|
|
1363
|
+
this.promptErrorSource = params.promptErrorSource;
|
|
1364
|
+
}
|
|
1365
|
+
};
|
|
1366
|
+
//#endregion
|
|
1367
|
+
//#region extensions/codex/src/app-server/transcript-checkpoint.ts
|
|
1368
|
+
/** Commits completed work in receipt order without waiting for the enclosing turn. */
|
|
1369
|
+
var CodexTranscriptCheckpoint = class {
|
|
1370
|
+
constructor(params, threadId, turnId) {
|
|
1371
|
+
this.params = params;
|
|
1372
|
+
this.threadId = threadId;
|
|
1373
|
+
this.turnId = turnId;
|
|
1374
|
+
this.pending = [];
|
|
1375
|
+
this.commentaryItemIds = /* @__PURE__ */ new Set();
|
|
1376
|
+
this.lastTimestamp = 0;
|
|
1377
|
+
this.writing = Promise.resolve();
|
|
1378
|
+
this.tainted = false;
|
|
1379
|
+
this.closed = false;
|
|
1380
|
+
this.abandoned = false;
|
|
1381
|
+
this.nextTimestamp = () => {
|
|
1382
|
+
this.lastTimestamp = Math.max(Date.now(), this.lastTimestamp + 1);
|
|
1383
|
+
return this.lastTimestamp;
|
|
1384
|
+
};
|
|
1385
|
+
this.enqueueCommentary = (itemId, entry) => {
|
|
1386
|
+
if (this.params.config?.ui?.prefs?.chatPersistCommentary === false || this.commentaryItemIds.has(itemId)) return;
|
|
1387
|
+
this.commentaryItemIds.add(itemId);
|
|
1388
|
+
this.enqueue({
|
|
1389
|
+
...entry,
|
|
1390
|
+
read: () => {
|
|
1391
|
+
const message = entry.read();
|
|
1392
|
+
return message ? attachCodexMirrorIdentity(message, `${this.turnId}:commentary:${itemId}`) : void 0;
|
|
1393
|
+
}
|
|
1394
|
+
});
|
|
1395
|
+
};
|
|
1396
|
+
this.enqueue = (entry) => {
|
|
1397
|
+
if (this.params.sessionTarget && !this.closed) this.pending.push(entry);
|
|
1398
|
+
};
|
|
1399
|
+
}
|
|
1400
|
+
abandon() {
|
|
1401
|
+
this.closed = this.abandoned = true;
|
|
1402
|
+
this.pending.length = 0;
|
|
1403
|
+
}
|
|
1404
|
+
flush(close = false) {
|
|
1405
|
+
if (this.closed) return this.writing;
|
|
1406
|
+
this.closed = close;
|
|
1407
|
+
this.writing = this.writing.then(async () => {
|
|
1408
|
+
const blocked = close ? -1 : this.pending.findIndex((entry) => entry.ready?.() === false);
|
|
1409
|
+
const count = blocked < 0 ? this.pending.length : blocked;
|
|
1410
|
+
if (count === 0) return;
|
|
1411
|
+
const taint = { tainted: this.tainted };
|
|
1412
|
+
const messages = this.pending.slice(0, count).flatMap((entry) => {
|
|
1413
|
+
const message = entry.read();
|
|
1414
|
+
return message ? [projectAgentHarnessTranscriptMessageForDisplay({
|
|
1415
|
+
hidden: this.params.trigger === "memory",
|
|
1416
|
+
message: applyCodexTranscriptTaint(message, taint)
|
|
1417
|
+
})] : [];
|
|
1418
|
+
});
|
|
1419
|
+
try {
|
|
1420
|
+
await codexTranscriptMirrorRuntime.mirror({
|
|
1421
|
+
assertWriteCurrent: () => {
|
|
1422
|
+
if (this.abandoned) throw new Error("Codex transcript checkpoint was retired before write");
|
|
1423
|
+
},
|
|
1424
|
+
...this.params.sessionTarget,
|
|
1425
|
+
sessionId: this.params.sessionId,
|
|
1426
|
+
cwd: this.params.workspaceDir,
|
|
1427
|
+
messages,
|
|
1428
|
+
idempotencyScope: `codex-app-server:${this.threadId}`,
|
|
1429
|
+
runId: this.params.runId,
|
|
1430
|
+
runMirrorIdentityPrefix: `${this.turnId}:`,
|
|
1431
|
+
config: this.params.config
|
|
1432
|
+
});
|
|
1433
|
+
this.pending.splice(0, count);
|
|
1434
|
+
this.tainted = taint.tainted;
|
|
1435
|
+
} catch (error) {
|
|
1436
|
+
embeddedAgentLog.warn("failed to checkpoint codex app-server transcript", {
|
|
1437
|
+
runId: this.params.runId,
|
|
1438
|
+
sessionId: this.params.sessionId,
|
|
1439
|
+
error: formatErrorMessage(error)
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
});
|
|
1443
|
+
return this.writing;
|
|
1444
|
+
}
|
|
1445
|
+
};
|
|
1446
|
+
//#endregion
|
|
1447
|
+
//#region extensions/codex/src/app-server/event-projector-result.ts
|
|
1448
|
+
/** Owns per-turn projection state and builds results from the same state. */
|
|
1449
|
+
var CodexTurnProjection = class {
|
|
1373
1450
|
constructor(params, threadId, turnId, options = {}) {
|
|
1374
1451
|
this.params = params;
|
|
1375
1452
|
this.threadId = threadId;
|
|
@@ -1378,15 +1455,14 @@ var CodexAppServerEventProjector = class {
|
|
|
1378
1455
|
this.activeItemIds = /* @__PURE__ */ new Set();
|
|
1379
1456
|
this.completedItemIds = /* @__PURE__ */ new Set();
|
|
1380
1457
|
this.activeCompactionItemIds = /* @__PURE__ */ new Set();
|
|
1381
|
-
this.
|
|
1382
|
-
this.nativeToolOutcomeOrdinals = /* @__PURE__ */ new Map();
|
|
1383
|
-
this.projectionClosed = false;
|
|
1458
|
+
this.projectionController = new AbortController();
|
|
1384
1459
|
this.settledTurnFailureFinalizationAllowed = false;
|
|
1385
|
-
this.
|
|
1460
|
+
this.terminalFailure = new CodexTerminalFailureProjection();
|
|
1386
1461
|
this.synthesizedMissingToolResultError = null;
|
|
1387
1462
|
this.aborted = false;
|
|
1388
|
-
this.
|
|
1463
|
+
this.usageProjection = new CodexUsageProjection();
|
|
1389
1464
|
this.completedCompactionCount = 0;
|
|
1465
|
+
this.settlement = new CodexProjectionSettlement(params, () => !this.projectionClosed);
|
|
1390
1466
|
this.transcriptCheckpoint = new CodexTranscriptCheckpoint(params, threadId, turnId);
|
|
1391
1467
|
this.asyncDeliveryProjection = new CodexAsyncDeliveryProjection(params, threadId, turnId, options);
|
|
1392
1468
|
this.contextTokens = options.initialContextTokens;
|
|
@@ -1397,7 +1473,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1397
1473
|
remoteWorkspaceRoot: options.remoteWorkspaceRoot,
|
|
1398
1474
|
readFile: options.readRemoteWorkspaceFile,
|
|
1399
1475
|
requestTimeoutMs: options.remoteWorkspaceRequestTimeoutMs,
|
|
1400
|
-
signal: options.runAbortSignal
|
|
1476
|
+
signal: options.runAbortSignal ? AbortSignal.any([options.runAbortSignal, this.projectionController.signal]) : this.projectionController.signal
|
|
1401
1477
|
});
|
|
1402
1478
|
this.toolProgressProjection = new CodexToolProgressProjection(params);
|
|
1403
1479
|
this.toolTranscriptProjection = new CodexToolTranscriptProjection(params, threadId, turnId, this.toolProgressProjection, this.transcriptCheckpoint.nextTimestamp, {
|
|
@@ -1407,12 +1483,151 @@ var CodexAppServerEventProjector = class {
|
|
|
1407
1483
|
checkpointMessage: this.transcriptCheckpoint.enqueue
|
|
1408
1484
|
});
|
|
1409
1485
|
this.eventProjection = new CodexEventProjection(threadId, turnId, (event) => this.emitAgentEvent(event), this.toolProgressProjection, this.toolTranscriptProjection, options.onNativeToolResultRecorded);
|
|
1410
|
-
this.assistantProjection = new CodexAssistantProjection(params, (event) => this.emitAgentEvent(event), (text) => this.toolProgressProjection.matchesEcho(text), this.transcriptCheckpoint.nextTimestamp, this.transcriptCheckpoint.enqueueCommentary);
|
|
1411
|
-
this.reasoningProjection = new CodexReasoningProjection(params, (event) => this.emitAgentEvent(event), options.onNativePlanUpdate);
|
|
1486
|
+
this.assistantProjection = new CodexAssistantProjection(this.settlement.params, (event) => this.emitAgentEvent(event), (text) => this.toolProgressProjection.matchesEcho(text), this.transcriptCheckpoint.nextTimestamp, this.transcriptCheckpoint.enqueueCommentary);
|
|
1487
|
+
this.reasoningProjection = new CodexReasoningProjection(this.settlement.params, (event) => this.emitAgentEvent(event), options.onNativePlanUpdate);
|
|
1412
1488
|
}
|
|
1489
|
+
get projectionClosed() {
|
|
1490
|
+
return this.projectionController.signal.aborted;
|
|
1491
|
+
}
|
|
1492
|
+
buildResult(toolTelemetry, options) {
|
|
1493
|
+
this.eventProjection.flushPendingGuardianWarning();
|
|
1494
|
+
const { params: runParams, turnId, completedTurn, aborted, contextTokens, contextTokensSource, completedCompactionCount, synthesizedMissingToolResultError: previousMissingToolResultError } = this;
|
|
1495
|
+
const { promptError: initialPromptError, promptErrorSource: initialPromptErrorSource, providerRefusal } = this.terminalFailure;
|
|
1496
|
+
const upstreamUserText = this.options.upstreamUserText;
|
|
1497
|
+
const turnTainted = this.settlement.turnTainted;
|
|
1498
|
+
const activeItemCount = this.activeItemIds.size;
|
|
1499
|
+
const completedItemCount = this.completedItemIds.size;
|
|
1500
|
+
const guardianReviewCount = this.eventProjection.guardianReviewCount;
|
|
1501
|
+
const yieldDetected = options?.yieldDetected;
|
|
1502
|
+
this.nativeToolLifecycleProjector.finalizeActive();
|
|
1503
|
+
const assistantTexts = this.assistantProjection.collectAssistantTexts();
|
|
1504
|
+
const asyncMessages = this.assistantProjection.collectAsyncMessages();
|
|
1505
|
+
const commentaryMessages = this.assistantProjection.collectCommentaryMessages();
|
|
1506
|
+
const reasoningText = this.reasoningProjection.reasoningText();
|
|
1507
|
+
const planText = this.reasoningProjection.planText();
|
|
1508
|
+
const usage = this.usageProjection.usage;
|
|
1509
|
+
const projectedUsage = aborted && usage ? {
|
|
1510
|
+
...usage,
|
|
1511
|
+
contextUsage: { state: "unavailable" }
|
|
1512
|
+
} : usage;
|
|
1513
|
+
const hasAssistantItemText = this.assistantProjection.hasAssistantItemTextForSynthesis();
|
|
1514
|
+
const legacyFailClosed = !completedTurn || completedTurn.status !== "completed" || hasAssistantItemText;
|
|
1515
|
+
const hasDeliverableAssistantOnCompletedTurn = completedTurn?.status === "completed" && assistantTexts.some((text) => text.trim().length > 0);
|
|
1516
|
+
const synthesizedMissingToolResultError = this.toolTranscriptProjection.synthesizeMissingToolResults({
|
|
1517
|
+
synthesize: legacyFailClosed,
|
|
1518
|
+
terminalDisposition: aborted ? "tool_error" : hasDeliverableAssistantOnCompletedTurn ? "diagnostic_only" : "prompt_error"
|
|
1519
|
+
});
|
|
1520
|
+
const storedMissingToolResultError = synthesizedMissingToolResultError ?? previousMissingToolResultError;
|
|
1521
|
+
let promptErrorSource = initialPromptErrorSource;
|
|
1522
|
+
if (synthesizedMissingToolResultError) {
|
|
1523
|
+
this.synthesizedMissingToolResultError = synthesizedMissingToolResultError;
|
|
1524
|
+
promptErrorSource = promptErrorSource ?? "prompt";
|
|
1525
|
+
}
|
|
1526
|
+
const assistantMessageOptions = {
|
|
1527
|
+
tokenUsage: projectedUsage,
|
|
1528
|
+
aborted,
|
|
1529
|
+
promptError: initialPromptError,
|
|
1530
|
+
providerRefusal
|
|
1531
|
+
};
|
|
1532
|
+
const lastAssistant = providerRefusal ? this.assistantProjection.createAssistantMessage("", assistantMessageOptions) : assistantTexts.length ? this.assistantProjection.createAssistantMessage(assistantTexts.join("\n\n"), assistantMessageOptions) : void 0;
|
|
1533
|
+
const currentAttemptAssistant = providerRefusal ? lastAssistant : this.assistantProjection.createCurrentAttemptAssistantMessage(assistantMessageOptions);
|
|
1534
|
+
const messagesSnapshot = buildCodexMessagesSnapshot({
|
|
1535
|
+
runParams,
|
|
1536
|
+
turnId,
|
|
1537
|
+
upstreamUserText,
|
|
1538
|
+
reasoningText,
|
|
1539
|
+
asyncMessages,
|
|
1540
|
+
commentaryMessages,
|
|
1541
|
+
toolMessages: this.toolTranscriptProjection.transcriptMessages,
|
|
1542
|
+
lastAssistant,
|
|
1543
|
+
turnTainted
|
|
1544
|
+
});
|
|
1545
|
+
const turnFailed = completedTurn?.status === "failed";
|
|
1546
|
+
const promptError = providerRefusal ? null : initialPromptError ?? storedMissingToolResultError ?? (turnFailed ? completedTurn?.error?.message ?? "codex app-server turn failed" : null);
|
|
1547
|
+
const agentHarnessResultClassification = providerRefusal ? void 0 : classifyAgentHarnessTerminalOutcome({
|
|
1548
|
+
assistantTexts,
|
|
1549
|
+
reasoningText,
|
|
1550
|
+
planText,
|
|
1551
|
+
promptError,
|
|
1552
|
+
turnCompleted: Boolean(completedTurn)
|
|
1553
|
+
});
|
|
1554
|
+
const toolMetas = this.toolProgressProjection.toolMetas;
|
|
1555
|
+
const hadPotentialSideEffects = toolTelemetry.didSendViaMessagingTool || Boolean(toolTelemetry.successfulCronAdds || toolTelemetry.acceptedSessionSpawns?.length) || this.generatedMediaProjection.hasGeneratedMedia() || this.toolProgressProjection.hasPotentialSideEffects;
|
|
1556
|
+
const sentMediaUrls = new Set(toolTelemetry.messagingToolSentMediaUrls.map((url) => url.trim()));
|
|
1557
|
+
const toolAutoDeliveryMediaUrls = toolTelemetry.toolAutoDeliveryMediaUrls?.filter((url) => !sentMediaUrls.has(url.trim()));
|
|
1558
|
+
const result = {
|
|
1559
|
+
terminal: attemptTerminal.normalize({
|
|
1560
|
+
aborted,
|
|
1561
|
+
promptError,
|
|
1562
|
+
promptErrorSource: promptError ? promptErrorSource || "prompt" : null
|
|
1563
|
+
}),
|
|
1564
|
+
sessionIdUsed: runParams.sessionId,
|
|
1565
|
+
terminalTurnId: turnId,
|
|
1566
|
+
...agentHarnessResultClassification ? { agentHarnessResultClassification } : {},
|
|
1567
|
+
bootstrapPromptWarningSignaturesSeen: runParams.bootstrapPromptWarningSignaturesSeen,
|
|
1568
|
+
bootstrapPromptWarningSignature: runParams.bootstrapPromptWarningSignature,
|
|
1569
|
+
...this.usageProjection.modelIterations > 0 ? { modelIterations: this.usageProjection.modelIterations } : {},
|
|
1570
|
+
messagesSnapshot,
|
|
1571
|
+
assistantTexts,
|
|
1572
|
+
toolMetas,
|
|
1573
|
+
lastAssistant,
|
|
1574
|
+
currentAttemptAssistant,
|
|
1575
|
+
...this.toolProgressProjection.lastToolError ? { lastToolError: this.toolProgressProjection.lastToolError } : {},
|
|
1576
|
+
didSendViaMessagingTool: toolTelemetry.didSendViaMessagingTool,
|
|
1577
|
+
didDeliverSourceReplyViaMessageTool: toolTelemetry.didDeliverSourceReplyViaMessageTool === true,
|
|
1578
|
+
sourceReplyDelivered: toolTelemetry.sourceReplyDelivered,
|
|
1579
|
+
messagingToolSentTexts: toolTelemetry.messagingToolSentTexts,
|
|
1580
|
+
messagingToolSentMediaUrls: toolTelemetry.messagingToolSentMediaUrls,
|
|
1581
|
+
messagingToolSentTargets: toolTelemetry.messagingToolSentTargets,
|
|
1582
|
+
messagingToolSourceReplyPayloads: toolTelemetry.messagingToolSourceReplyPayloads ?? [],
|
|
1583
|
+
heartbeatToolResponse: toolTelemetry.heartbeatToolResponse,
|
|
1584
|
+
toolMediaUrls: this.generatedMediaProjection.buildToolMediaUrls(toolTelemetry),
|
|
1585
|
+
hostOwnedToolMediaUrls: this.generatedMediaProjection.buildHostOwnedMediaUrls(toolTelemetry),
|
|
1586
|
+
toolAudioAsVoice: toolTelemetry.toolAudioAsVoice,
|
|
1587
|
+
successfulCronAdds: toolTelemetry.successfulCronAdds,
|
|
1588
|
+
acceptedSessionSpawns: toolTelemetry.acceptedSessionSpawns,
|
|
1589
|
+
cloudCodeAssistFormatError: false,
|
|
1590
|
+
contextTokens,
|
|
1591
|
+
contextTokensSource,
|
|
1592
|
+
attemptUsage: projectedUsage,
|
|
1593
|
+
...completedCompactionCount > 0 ? { compactionCount: completedCompactionCount } : {},
|
|
1594
|
+
replayMetadata: {
|
|
1595
|
+
hadPotentialSideEffects,
|
|
1596
|
+
replaySafe: !hadPotentialSideEffects
|
|
1597
|
+
},
|
|
1598
|
+
itemLifecycle: {
|
|
1599
|
+
startedCount: activeItemCount + completedItemCount,
|
|
1600
|
+
completedCount: completedItemCount,
|
|
1601
|
+
activeCount: activeItemCount
|
|
1602
|
+
},
|
|
1603
|
+
yieldDetected: yieldDetected || false,
|
|
1604
|
+
didSendDeterministicApprovalPrompt: guardianReviewCount > 0 ? false : void 0
|
|
1605
|
+
};
|
|
1606
|
+
const transferTtsProvenance = resolveCodexTtsProvenanceTransfer(runParams.hostCapabilities);
|
|
1607
|
+
for (const toolResult of toolTelemetry.coreTtsToolResults ?? []) transferTtsProvenance?.(toolResult, result, toolAutoDeliveryMediaUrls ?? []);
|
|
1608
|
+
return result;
|
|
1609
|
+
}
|
|
1610
|
+
emitAgentEvent(event) {
|
|
1611
|
+
if (!this.projectionClosed) emitCodexAgentEvent(this.params, event);
|
|
1612
|
+
}
|
|
1613
|
+
};
|
|
1614
|
+
//#endregion
|
|
1615
|
+
//#region extensions/codex/src/app-server/event-projector.ts
|
|
1616
|
+
var CodexAppServerEventProjector = class extends CodexTurnProjection {
|
|
1413
1617
|
getCompletedTurnStatus() {
|
|
1414
1618
|
return this.completedTurn?.status;
|
|
1415
1619
|
}
|
|
1620
|
+
/** Native completion owns the answer independently of unfinished host projection. */
|
|
1621
|
+
recoverCompletedAnswer() {
|
|
1622
|
+
const completed = this.settlement.completedAnswer;
|
|
1623
|
+
if (!completed || this.aborted || this.terminalFailure.promptError) return false;
|
|
1624
|
+
this.projectionController.abort();
|
|
1625
|
+
this.transcriptCheckpoint.abandon();
|
|
1626
|
+
this.completedTurn = completed.turn;
|
|
1627
|
+
this.assistantProjection.recordSnapshotItem(completed.answer);
|
|
1628
|
+
this.assistantProjection.finalizeAnswerCandidate(completed.turn);
|
|
1629
|
+
return true;
|
|
1630
|
+
}
|
|
1416
1631
|
getActiveMcpToolCall(serverName) {
|
|
1417
1632
|
if (this.projectionClosed || this.aborted) return;
|
|
1418
1633
|
return this.nativeToolLifecycleProjector.getActiveMcpToolCall(serverName);
|
|
@@ -1441,14 +1656,12 @@ var CodexAppServerEventProjector = class {
|
|
|
1441
1656
|
}
|
|
1442
1657
|
/** Fence delayed projections before the turn's final snapshot leaves its owner. */
|
|
1443
1658
|
closeProjection() {
|
|
1444
|
-
this.
|
|
1445
|
-
return this.transcriptCheckpoint.flush(true);
|
|
1659
|
+
this.projectionController.abort();
|
|
1660
|
+
return this.settlement.project("transcript/checkpoint", () => this.transcriptCheckpoint.flush(true));
|
|
1446
1661
|
}
|
|
1447
1662
|
/** Resolves the shared model-order position for a native tool item. */
|
|
1448
1663
|
recordNativeToolOutcome(item) {
|
|
1449
|
-
|
|
1450
|
-
const ordinal = this.params.allocateToolOutcomeOrdinal?.(item.id);
|
|
1451
|
-
if (ordinal !== void 0) this.nativeToolOutcomeOrdinals.set(item.id, ordinal);
|
|
1664
|
+
this.nativeToolLifecycleProjector.recordNativeToolOutcome(item);
|
|
1452
1665
|
}
|
|
1453
1666
|
recordNativeToolApprovalFailure(toolCallId, disposition, approvalKind) {
|
|
1454
1667
|
this.nativeToolLifecycleProjector.recordApprovalFailureDisposition(toolCallId, disposition);
|
|
@@ -1486,11 +1699,9 @@ var CodexAppServerEventProjector = class {
|
|
|
1486
1699
|
break;
|
|
1487
1700
|
case "item/started":
|
|
1488
1701
|
await this.handleItemStarted(params);
|
|
1489
|
-
await this.transcriptCheckpoint.flush();
|
|
1490
1702
|
break;
|
|
1491
1703
|
case "item/completed":
|
|
1492
1704
|
await this.handleItemCompleted(params);
|
|
1493
|
-
await this.transcriptCheckpoint.flush();
|
|
1494
1705
|
break;
|
|
1495
1706
|
case "item/commandExecution/outputDelta":
|
|
1496
1707
|
this.toolProgressProjection.handleOutputDelta(params, "bash");
|
|
@@ -1513,43 +1724,46 @@ var CodexAppServerEventProjector = class {
|
|
|
1513
1724
|
case "hook/completed":
|
|
1514
1725
|
this.eventProjection.handleHook(notification.method, params);
|
|
1515
1726
|
break;
|
|
1516
|
-
case "thread/tokenUsage/updated":
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
});
|
|
1727
|
+
case "thread/tokenUsage/updated": {
|
|
1728
|
+
const data = this.usageProjection.recordThread(params);
|
|
1729
|
+
if (data.modelContextWindow !== void 0) {
|
|
1730
|
+
this.contextTokens = data.modelContextWindow;
|
|
1731
|
+
this.contextTokensSource = this.params.authoredContextTokenCap === void 0 ? "runtime" : "runtime-configured";
|
|
1732
|
+
}
|
|
1733
|
+
if (Object.keys(data).length > 0) this.emitAgentEvent({
|
|
1734
|
+
stream: "usage",
|
|
1735
|
+
data
|
|
1526
1736
|
});
|
|
1527
1737
|
break;
|
|
1738
|
+
}
|
|
1528
1739
|
case "turn/completed":
|
|
1529
1740
|
await this.handleTurnCompleted(params);
|
|
1530
1741
|
break;
|
|
1531
1742
|
case "rawResponse/completed":
|
|
1532
|
-
this.
|
|
1743
|
+
this.usageProjection.record(params, this.params.hostCapabilities.reportOutputTokens);
|
|
1533
1744
|
break;
|
|
1534
1745
|
case "rawResponseItem/completed":
|
|
1535
1746
|
await this.handleRawResponseItemCompleted(params);
|
|
1536
|
-
await this.transcriptCheckpoint.flush();
|
|
1537
1747
|
break;
|
|
1538
1748
|
case "model/rerouted":
|
|
1539
1749
|
this.eventProjection.handleModelRerouted(params);
|
|
1540
1750
|
break;
|
|
1541
1751
|
case "error": {
|
|
1542
|
-
this.
|
|
1543
|
-
if (params.willRetry === true)
|
|
1752
|
+
this.usageProjection.invalidateContext();
|
|
1753
|
+
if (params.willRetry === true) {
|
|
1754
|
+
this.eventProjection.handleRetry(params);
|
|
1755
|
+
break;
|
|
1756
|
+
}
|
|
1544
1757
|
const codexErrorInfo = isJsonObject(params.error) ? params.error.codexErrorInfo : void 0;
|
|
1545
1758
|
const compactionFailure = codexErrorInfo === "other" && this.isCompacting();
|
|
1546
1759
|
this.settledTurnFailureFinalizationAllowed = codexErrorInfo === "serverOverloaded" || compactionFailure;
|
|
1547
|
-
this.
|
|
1760
|
+
this.terminalFailure.record({
|
|
1548
1761
|
message: readCodexErrorNotificationMessage(params),
|
|
1549
1762
|
codexErrorInfo,
|
|
1550
|
-
rateLimits: this.options.readRecentRateLimits?.()
|
|
1551
|
-
|
|
1552
|
-
|
|
1763
|
+
rateLimits: this.options.readRecentRateLimits?.(),
|
|
1764
|
+
fallbackMessage: "codex app-server error",
|
|
1765
|
+
promptErrorSource: compactionFailure ? "compaction" : "prompt"
|
|
1766
|
+
});
|
|
1553
1767
|
break;
|
|
1554
1768
|
}
|
|
1555
1769
|
case "thread/compacted":
|
|
@@ -1565,47 +1779,23 @@ var CodexAppServerEventProjector = class {
|
|
|
1565
1779
|
case "model/safetyBuffering/updated": break;
|
|
1566
1780
|
default: this.diagnostics.warnUnknownEvent(notification, params);
|
|
1567
1781
|
}
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
turnId: this.turnId,
|
|
1574
|
-
upstreamUserText: this.options.upstreamUserText,
|
|
1575
|
-
completedTurn: this.completedTurn,
|
|
1576
|
-
promptError: this.promptError,
|
|
1577
|
-
promptErrorSource: this.promptErrorSource,
|
|
1578
|
-
synthesizedMissingToolResultError: this.synthesizedMissingToolResultError,
|
|
1579
|
-
recordSynthesizedMissingToolResultError: (error) => {
|
|
1580
|
-
this.synthesizedMissingToolResultError = error;
|
|
1581
|
-
this.promptErrorSource = this.promptErrorSource ?? "prompt";
|
|
1582
|
-
},
|
|
1583
|
-
aborted: this.aborted,
|
|
1584
|
-
tokenUsage: this.tokenUsage,
|
|
1585
|
-
contextTokens: this.contextTokens,
|
|
1586
|
-
contextTokensSource: this.contextTokensSource,
|
|
1587
|
-
completedCompactionCount: this.completedCompactionCount,
|
|
1588
|
-
activeItemCount: this.activeItemIds.size,
|
|
1589
|
-
completedItemCount: this.completedItemIds.size,
|
|
1590
|
-
guardianReviewCount: this.eventProjection.guardianReviewCount,
|
|
1591
|
-
toolTelemetry,
|
|
1592
|
-
yieldDetected: options?.yieldDetected,
|
|
1593
|
-
nativeToolLifecycleProjection: this.nativeToolLifecycleProjector,
|
|
1594
|
-
assistantProjection: this.assistantProjection,
|
|
1595
|
-
reasoningProjection: this.reasoningProjection,
|
|
1596
|
-
responseCompletions: this.responseCompletions,
|
|
1597
|
-
toolTranscriptProjection: this.toolTranscriptProjection,
|
|
1598
|
-
toolProgressProjection: this.toolProgressProjection,
|
|
1599
|
-
generatedMediaProjection: this.generatedMediaProjection
|
|
1600
|
-
});
|
|
1782
|
+
if (!this.projectionClosed && [
|
|
1783
|
+
"item/started",
|
|
1784
|
+
"item/completed",
|
|
1785
|
+
"rawResponseItem/completed"
|
|
1786
|
+
].includes(notification.method)) await this.settlement.project("transcript/checkpoint", () => this.transcriptCheckpoint.flush());
|
|
1601
1787
|
}
|
|
1602
1788
|
recordDynamicToolCall(params) {
|
|
1603
1789
|
this.toolTranscriptProjection.recordDynamicToolCall(params);
|
|
1604
1790
|
}
|
|
1605
1791
|
/** Projects a successful OpenClaw progress_card call through the native plan stream. */
|
|
1606
1792
|
async recordDynamicProgressCardUpdate(params) {
|
|
1607
|
-
|
|
1608
|
-
|
|
1793
|
+
const update = projectProgressCardChannelUpdate(params);
|
|
1794
|
+
if (update) {
|
|
1795
|
+
const projected = {
|
|
1796
|
+
plan: update.steps,
|
|
1797
|
+
...update.explanation ? { explanation: update.explanation } : {}
|
|
1798
|
+
};
|
|
1609
1799
|
await this.reasoningProjection.handleTurnPlanUpdated(projected, "openclaw");
|
|
1610
1800
|
}
|
|
1611
1801
|
}
|
|
@@ -1616,16 +1806,19 @@ var CodexAppServerEventProjector = class {
|
|
|
1616
1806
|
}
|
|
1617
1807
|
markTimedOut() {
|
|
1618
1808
|
this.aborted = true;
|
|
1619
|
-
this.promptError = "codex app-server attempt timed out";
|
|
1620
|
-
this.promptErrorSource = "prompt";
|
|
1809
|
+
this.terminalFailure.promptError = "codex app-server attempt timed out";
|
|
1810
|
+
this.terminalFailure.promptErrorSource = "prompt";
|
|
1621
1811
|
}
|
|
1622
1812
|
markAborted() {
|
|
1623
1813
|
this.aborted = true;
|
|
1624
|
-
this.
|
|
1814
|
+
this.usageProjection.invalidateContext();
|
|
1625
1815
|
}
|
|
1626
1816
|
isCompacting() {
|
|
1627
1817
|
return this.activeCompactionItemIds.size > 0;
|
|
1628
1818
|
}
|
|
1819
|
+
isCompactionProjectionActive() {
|
|
1820
|
+
return !this.projectionClosed && !this.aborted && !this.options.runAbortSignal?.aborted;
|
|
1821
|
+
}
|
|
1629
1822
|
async handleItemStarted(params) {
|
|
1630
1823
|
const item = readItem(params.item);
|
|
1631
1824
|
const itemId = item?.id ?? readStringField(params, "itemId");
|
|
@@ -1633,12 +1826,16 @@ var CodexAppServerEventProjector = class {
|
|
|
1633
1826
|
if (itemId) this.activeItemIds.add(itemId);
|
|
1634
1827
|
this.recordNativeToolOutcome(item);
|
|
1635
1828
|
if (item?.type === "contextCompaction" && itemId) {
|
|
1829
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1636
1830
|
this.activeCompactionItemIds.add(itemId);
|
|
1831
|
+
const messages = await this.toolTranscriptProjection.readMirroredSessionMessages(this.options.runAbortSignal);
|
|
1832
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1637
1833
|
await runAgentHarnessBeforeCompactionHook({
|
|
1638
1834
|
sessionFile: this.params.sessionFile,
|
|
1639
|
-
messages
|
|
1835
|
+
messages,
|
|
1640
1836
|
ctx: this.options.agentHookContext ?? {}
|
|
1641
1837
|
});
|
|
1838
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1642
1839
|
this.emitAgentEvent({
|
|
1643
1840
|
stream: "compaction",
|
|
1644
1841
|
data: {
|
|
@@ -1675,7 +1872,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1675
1872
|
const item = readItem(params.item);
|
|
1676
1873
|
this.diagnostics.warnUnknownItemStatus(item);
|
|
1677
1874
|
this.recordNativeToolOutcome(item);
|
|
1678
|
-
this.clearTerminalPresentationForNativeItem(item);
|
|
1875
|
+
this.nativeToolLifecycleProjector.clearTerminalPresentationForNativeItem(item);
|
|
1679
1876
|
const itemId = item?.id ?? readStringField(params, "itemId");
|
|
1680
1877
|
if (itemId) {
|
|
1681
1878
|
this.activeItemIds.delete(itemId);
|
|
@@ -1686,20 +1883,23 @@ var CodexAppServerEventProjector = class {
|
|
|
1686
1883
|
if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
|
|
1687
1884
|
if (this.projectionClosed) return;
|
|
1688
1885
|
this.reasoningProjection.recordItem(item);
|
|
1689
|
-
await this.generatedMediaProjection.recordNative(item);
|
|
1886
|
+
await this.settlement.project("media_projection", () => this.generatedMediaProjection.recordNative(item));
|
|
1690
1887
|
if (this.projectionClosed) return;
|
|
1691
1888
|
if (item?.type === "contextCompaction" && itemId) {
|
|
1889
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1692
1890
|
this.activeCompactionItemIds.delete(itemId);
|
|
1693
1891
|
this.completedCompactionCount += 1;
|
|
1694
1892
|
await this.options.onContextCompacted?.();
|
|
1695
|
-
if (this.
|
|
1893
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1894
|
+
const messages = await this.toolTranscriptProjection.readMirroredSessionMessages(this.options.runAbortSignal);
|
|
1895
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1696
1896
|
await runAgentHarnessAfterCompactionHook({
|
|
1697
1897
|
sessionFile: this.params.sessionFile,
|
|
1698
|
-
messages
|
|
1898
|
+
messages,
|
|
1699
1899
|
compactedCount: -1,
|
|
1700
1900
|
ctx: this.options.agentHookContext ?? {}
|
|
1701
1901
|
});
|
|
1702
|
-
if (this.
|
|
1902
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1703
1903
|
await persistCodexContextCompactionActivity({
|
|
1704
1904
|
sessionTarget: this.params.sessionTarget,
|
|
1705
1905
|
config: this.params.config,
|
|
@@ -1710,6 +1910,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1710
1910
|
itemId,
|
|
1711
1911
|
timestamp: this.transcriptCheckpoint.nextTimestamp()
|
|
1712
1912
|
});
|
|
1913
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1713
1914
|
this.eventProjection.emitCompactionEnd(itemId, true);
|
|
1714
1915
|
}
|
|
1715
1916
|
this.toolProgressProjection.recordToolMeta(item);
|
|
@@ -1724,8 +1925,9 @@ var CodexAppServerEventProjector = class {
|
|
|
1724
1925
|
});
|
|
1725
1926
|
if (this.projectionClosed) return;
|
|
1726
1927
|
this.toolTranscriptProjection.recordNativeToolCall(item);
|
|
1727
|
-
await this.toolTranscriptProjection.
|
|
1928
|
+
const details = await this.toolTranscriptProjection.prepareNativeToolResultDetails(item);
|
|
1728
1929
|
if (this.projectionClosed) return;
|
|
1930
|
+
this.toolTranscriptProjection.recordNativeToolResult(item, details);
|
|
1729
1931
|
this.toolProgressProjection.emitToolResultSummary(item);
|
|
1730
1932
|
this.toolProgressProjection.emitToolResultOutput(item);
|
|
1731
1933
|
this.emitAgentEvent({
|
|
@@ -1741,16 +1943,18 @@ var CodexAppServerEventProjector = class {
|
|
|
1741
1943
|
const turn = readCodexTurn(params.turn);
|
|
1742
1944
|
if (!turn || turn.id !== this.turnId) return;
|
|
1743
1945
|
this.completedTurn = turn;
|
|
1744
|
-
const compactionFailure = turn.status === "failed" && (this.promptErrorSource === "compaction" || turn.error?.codexErrorInfo === "other" && this.isCompacting());
|
|
1946
|
+
const compactionFailure = turn.status === "failed" && (this.terminalFailure.promptErrorSource === "compaction" || turn.error?.codexErrorInfo === "other" && this.isCompacting());
|
|
1745
1947
|
this.settledTurnFailureFinalizationAllowed = turn.status === "failed" && (turn.error?.codexErrorInfo === "serverOverloaded" || compactionFailure);
|
|
1746
|
-
if (turn.status !== "completed") this.
|
|
1948
|
+
if (turn.status !== "completed") this.usageProjection.invalidateContext();
|
|
1747
1949
|
if (turn.status === "failed") {
|
|
1748
|
-
|
|
1950
|
+
const codexErrorInfo = turn.error?.codexErrorInfo;
|
|
1951
|
+
this.terminalFailure.record({
|
|
1749
1952
|
message: turn.error?.message,
|
|
1750
|
-
codexErrorInfo
|
|
1751
|
-
rateLimits: this.options.readRecentRateLimits?.()
|
|
1752
|
-
|
|
1753
|
-
|
|
1953
|
+
codexErrorInfo,
|
|
1954
|
+
rateLimits: this.options.readRecentRateLimits?.(),
|
|
1955
|
+
fallbackMessage: "codex app-server turn failed",
|
|
1956
|
+
promptErrorSource: compactionFailure ? "compaction" : "prompt"
|
|
1957
|
+
});
|
|
1754
1958
|
}
|
|
1755
1959
|
if (compactionFailure) {
|
|
1756
1960
|
const failedCompactionItemIds = [...this.activeCompactionItemIds];
|
|
@@ -1763,7 +1967,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1763
1967
|
const turnItems = turn.items ?? [];
|
|
1764
1968
|
const unsettledAsyncDeliveries = this.asyncDeliveryProjection.pending();
|
|
1765
1969
|
const lastToolItem = turnItems.findLast((item) => matchesCodexSnapshotTurn(item, this.turnId) && (item.type === "dynamicToolCall" || shouldClearTerminalPresentationForNativeItem(item)));
|
|
1766
|
-
if (lastToolItem?.type !== "dynamicToolCall") this.clearTerminalPresentationForNativeItem(lastToolItem);
|
|
1970
|
+
if (lastToolItem?.type !== "dynamicToolCall") this.nativeToolLifecycleProjector.clearTerminalPresentationForNativeItem(lastToolItem);
|
|
1767
1971
|
for (const item of turnItems) {
|
|
1768
1972
|
if (!this.asyncDeliveryProjection.allows(item)) continue;
|
|
1769
1973
|
this.diagnostics.warnUnknownItemStatus(item);
|
|
@@ -1771,15 +1975,21 @@ var CodexAppServerEventProjector = class {
|
|
|
1771
1975
|
if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
|
|
1772
1976
|
if (this.projectionClosed) return;
|
|
1773
1977
|
this.reasoningProjection.recordItem(item);
|
|
1774
|
-
await this.generatedMediaProjection.recordNative(item);
|
|
1978
|
+
await this.settlement.project("media_projection", () => this.generatedMediaProjection.recordNative(item));
|
|
1775
1979
|
if (this.projectionClosed) return;
|
|
1776
1980
|
this.toolProgressProjection.recordToolMeta(item);
|
|
1777
1981
|
this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
|
|
1778
|
-
await this.emitSnapshotOnlyNativeToolProgress(
|
|
1982
|
+
await this.eventProjection.emitSnapshotOnlyNativeToolProgress({
|
|
1983
|
+
item,
|
|
1984
|
+
activeItemIds: this.activeItemIds,
|
|
1985
|
+
completedItemIds: this.completedItemIds,
|
|
1986
|
+
isActive: () => !this.projectionClosed
|
|
1987
|
+
});
|
|
1779
1988
|
if (this.projectionClosed) return;
|
|
1780
1989
|
this.toolTranscriptProjection.recordNativeToolCall(item);
|
|
1781
|
-
await this.toolTranscriptProjection.
|
|
1990
|
+
const details = await this.toolTranscriptProjection.prepareNativeToolResultDetails(item);
|
|
1782
1991
|
if (this.projectionClosed) return;
|
|
1992
|
+
this.toolTranscriptProjection.recordNativeToolResult(item, details);
|
|
1783
1993
|
this.toolTranscriptProjection.emitAfterToolCallObservation(item);
|
|
1784
1994
|
this.toolProgressProjection.emitToolResultSummary(item);
|
|
1785
1995
|
this.toolProgressProjection.emitToolResultOutput(item);
|
|
@@ -1794,52 +2004,12 @@ var CodexAppServerEventProjector = class {
|
|
|
1794
2004
|
this.activeCompactionItemIds.clear();
|
|
1795
2005
|
await this.reasoningProjection.maybeEndReasoning();
|
|
1796
2006
|
}
|
|
1797
|
-
async emitSnapshotOnlyNativeToolProgress(item) {
|
|
1798
|
-
if (!shouldSynthesizeToolProgressForItem(item) || !matchesCodexSnapshotTurn(item, this.turnId) || this.completedItemIds.has(item.id) || itemStatus(item) === "running") return;
|
|
1799
|
-
if (!this.activeItemIds.has(item.id)) {
|
|
1800
|
-
this.eventProjection.emitStandardItemEvent({
|
|
1801
|
-
phase: "start",
|
|
1802
|
-
item
|
|
1803
|
-
});
|
|
1804
|
-
await this.eventProjection.emitNormalizedToolItemEvent({
|
|
1805
|
-
phase: "start",
|
|
1806
|
-
item
|
|
1807
|
-
});
|
|
1808
|
-
}
|
|
1809
|
-
if (this.projectionClosed) return;
|
|
1810
|
-
this.activeItemIds.delete(item.id);
|
|
1811
|
-
this.eventProjection.emitStandardItemEvent({
|
|
1812
|
-
phase: "end",
|
|
1813
|
-
item
|
|
1814
|
-
});
|
|
1815
|
-
await this.eventProjection.emitNormalizedToolItemEvent({
|
|
1816
|
-
phase: "result",
|
|
1817
|
-
item
|
|
1818
|
-
});
|
|
1819
|
-
this.completedItemIds.add(item.id);
|
|
1820
|
-
}
|
|
1821
2007
|
async handleRawResponseItemCompleted(params) {
|
|
1822
2008
|
const item = isJsonObject(params.item) ? params.item : void 0;
|
|
1823
2009
|
if (!item) return;
|
|
1824
2010
|
this.toolTranscriptProjection.recordRawNativeToolItem(item);
|
|
1825
2011
|
this.assistantProjection.handleRawResponseItemCompleted(item, this.activeItemIds);
|
|
1826
|
-
await this.generatedMediaProjection.recordRaw(item);
|
|
1827
|
-
}
|
|
1828
|
-
clearTerminalPresentationForNativeItem(item) {
|
|
1829
|
-
if (!item || this.terminalPresentationClearedItemIds.has(item.id) || !shouldClearTerminalPresentationForNativeItem(item)) return;
|
|
1830
|
-
const toolCallOrdinal = this.nativeToolOutcomeOrdinals.get(item.id);
|
|
1831
|
-
this.terminalPresentationClearedItemIds.add(item.id);
|
|
1832
|
-
this.params.onToolOutcome?.({
|
|
1833
|
-
toolName: itemName(item) ?? item.type,
|
|
1834
|
-
argsHash: "",
|
|
1835
|
-
resultHash: "",
|
|
1836
|
-
...toolCallOrdinal !== void 0 ? { toolCallOrdinal } : {},
|
|
1837
|
-
terminalPresentation: void 0,
|
|
1838
|
-
presentationOnly: true
|
|
1839
|
-
});
|
|
1840
|
-
}
|
|
1841
|
-
emitAgentEvent(event) {
|
|
1842
|
-
if (!this.projectionClosed) emitCodexAgentEvent(this.params, event);
|
|
2012
|
+
await this.settlement.project("media_projection", () => this.generatedMediaProjection.recordRaw(item));
|
|
1843
2013
|
}
|
|
1844
2014
|
isHookNotificationForCurrentThread(params) {
|
|
1845
2015
|
const threadId = readStringField(params, "threadId");
|
|
@@ -1950,6 +2120,7 @@ function createNativeMcpRuntime(params) {
|
|
|
1950
2120
|
listResourceTemplates: async (serverName) => {
|
|
1951
2121
|
return { resourceTemplates: (await loadStatuses()).find((entry) => entry.name === serverName)?.resourceTemplates ?? [] };
|
|
1952
2122
|
},
|
|
2123
|
+
joinCleanup: async () => {},
|
|
1953
2124
|
dispose: async () => {}
|
|
1954
2125
|
};
|
|
1955
2126
|
return runtime;
|
|
@@ -2107,7 +2278,6 @@ const MAX_USER_INPUT_HEADER = 64;
|
|
|
2107
2278
|
const MAX_USER_INPUT_TEXT = 4096;
|
|
2108
2279
|
/** Creates the single per-turn owner for Codex operator input. */
|
|
2109
2280
|
function createCodexUserInputBridge(params) {
|
|
2110
|
-
const gatewayCall = params.gatewayCall ?? callGatewayTool;
|
|
2111
2281
|
const jobs = [];
|
|
2112
2282
|
let activeCompletion;
|
|
2113
2283
|
const inputSessionKey = params.paramsForRun.sessionKey ?? params.paramsForRun.sessionId;
|
|
@@ -2158,7 +2328,7 @@ function createCodexUserInputBridge(params) {
|
|
|
2158
2328
|
agentId: params.paramsForRun.agentId,
|
|
2159
2329
|
runId: params.paramsForRun.runId,
|
|
2160
2330
|
timeoutMs,
|
|
2161
|
-
gatewayCall,
|
|
2331
|
+
gatewayCall: params.gatewayCall,
|
|
2162
2332
|
delivery: params.paramsForRun,
|
|
2163
2333
|
signal,
|
|
2164
2334
|
promptOptions: {
|
|
@@ -2188,9 +2358,9 @@ function createCodexUserInputBridge(params) {
|
|
|
2188
2358
|
});
|
|
2189
2359
|
},
|
|
2190
2360
|
async handleElicitationRequest(request) {
|
|
2191
|
-
if (
|
|
2361
|
+
if (readOwnDataString(request.params, "threadId") !== params.threadId) return;
|
|
2192
2362
|
const requestSnapshot = agentHarnessStructuredInput.snapshot(request.params);
|
|
2193
|
-
if (requestSnapshot
|
|
2363
|
+
if (!agentHarnessStructuredInput.isRecord(requestSnapshot)) {
|
|
2194
2364
|
const cancelValue = createCodexElicitationResponse("cancel");
|
|
2195
2365
|
return await enqueue({
|
|
2196
2366
|
requestId: request.id,
|
|
@@ -2206,10 +2376,10 @@ function createCodexUserInputBridge(params) {
|
|
|
2206
2376
|
}
|
|
2207
2377
|
});
|
|
2208
2378
|
}
|
|
2209
|
-
|
|
2379
|
+
if (readOwnDataString(requestSnapshot, "threadId") !== params.threadId) return;
|
|
2380
|
+
const { compileCodexOrdinaryElicitation } = await import("./elicitation-input-DPoK8F7w.js");
|
|
2210
2381
|
const compiled = compileCodexOrdinaryElicitation({
|
|
2211
|
-
|
|
2212
|
-
threadId: params.threadId,
|
|
2382
|
+
snapshot: requestSnapshot,
|
|
2213
2383
|
turnId: params.turnId
|
|
2214
2384
|
});
|
|
2215
2385
|
if (compiled.kind === "ignored") return;
|
|
@@ -2235,7 +2405,7 @@ function createCodexUserInputBridge(params) {
|
|
|
2235
2405
|
handleNotification(notification) {
|
|
2236
2406
|
if (notification.method !== "serverRequest/resolved" || !isJsonObject(notification.params)) return;
|
|
2237
2407
|
const requestId = readRequestId(notification.params);
|
|
2238
|
-
if (requestId === void 0 ||
|
|
2408
|
+
if (requestId === void 0 || readOwnDataString(notification.params, "threadId") !== params.threadId) return;
|
|
2239
2409
|
const job = jobs.find((candidate) => typeof candidate.requestId === typeof requestId && candidate.requestId === requestId);
|
|
2240
2410
|
if (job) cancelJob(job);
|
|
2241
2411
|
},
|
|
@@ -2314,11 +2484,7 @@ function readArray(record, key, maximum) {
|
|
|
2314
2484
|
const value = readValue(record, key);
|
|
2315
2485
|
return Array.isArray(value) && value.length <= maximum ? value : void 0;
|
|
2316
2486
|
}
|
|
2317
|
-
function
|
|
2318
|
-
const descriptor = Object.getOwnPropertyDescriptor(record, key);
|
|
2319
|
-
return descriptor && "value" in descriptor && typeof descriptor.value === "string" ? descriptor.value : void 0;
|
|
2320
|
-
}
|
|
2321
|
-
function readRawOwnString(value, key) {
|
|
2487
|
+
function readOwnDataString(value, key) {
|
|
2322
2488
|
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
2323
2489
|
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
2324
2490
|
return descriptor && "value" in descriptor && typeof descriptor.value === "string" ? descriptor.value : void 0;
|
|
@@ -2350,6 +2516,22 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2350
2516
|
const { emitExecutionPhaseOnce, emitLifecycleStart, maybeAnnounceFastModeAutoOff } = lifecycle;
|
|
2351
2517
|
const { enqueueNotification } = notifications;
|
|
2352
2518
|
const activeTurnId = turn.turn.id;
|
|
2519
|
+
const { thread } = resourceState;
|
|
2520
|
+
const runtimeModelSelection = thread.preserveNativeModel && thread.model && thread.modelProvider ? {
|
|
2521
|
+
provider: thread.modelProvider,
|
|
2522
|
+
model: thread.model
|
|
2523
|
+
} : void 0;
|
|
2524
|
+
const projectionParams = runtimeModelSelection ? {
|
|
2525
|
+
...dynamicToolParams,
|
|
2526
|
+
provider: runtimeModelSelection.provider,
|
|
2527
|
+
modelId: runtimeModelSelection.model,
|
|
2528
|
+
model: {
|
|
2529
|
+
...dynamicToolParams.model,
|
|
2530
|
+
id: runtimeModelSelection.model,
|
|
2531
|
+
name: runtimeModelSelection.model,
|
|
2532
|
+
provider: runtimeModelSelection.provider
|
|
2533
|
+
}
|
|
2534
|
+
} : dynamicToolParams;
|
|
2353
2535
|
const progressCardTool = toolBridge.availableTools.find((tool) => tool.name === "progress_card");
|
|
2354
2536
|
let nativePlanUpdateOrdinal = 0;
|
|
2355
2537
|
const prepareNativeMcpAppResultDetails = createCodexNativeMcpAppResultDetailsPreparer({
|
|
@@ -2375,7 +2557,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2375
2557
|
imagesCount: params.images?.length ?? 0
|
|
2376
2558
|
});
|
|
2377
2559
|
projectorRef.current = new CodexAppServerEventProjector({
|
|
2378
|
-
...
|
|
2560
|
+
...projectionParams,
|
|
2379
2561
|
onAgentEvent: (event) => {
|
|
2380
2562
|
if (event.stream === "assistant" && typeof event.data.delta === "string") {
|
|
2381
2563
|
streamState.eventEmitted = true;
|
|
@@ -2390,7 +2572,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2390
2572
|
asyncUserMessageAllowed: params.disableTools !== true && (params.toolsAllow === void 0 || toolBridge.availableTools.some((tool) => tool.name === "message")),
|
|
2391
2573
|
onAsyncDelivery: async (delivery) => {
|
|
2392
2574
|
return await codexTranscriptMirrorRuntime.deliverAsyncMessageBestEffort({
|
|
2393
|
-
params:
|
|
2575
|
+
params: projectionParams,
|
|
2394
2576
|
cwd: effectiveCwd,
|
|
2395
2577
|
threadId: resourceState.thread.threadId,
|
|
2396
2578
|
turnId: activeTurnId,
|
|
@@ -2447,6 +2629,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2447
2629
|
}
|
|
2448
2630
|
});
|
|
2449
2631
|
if (isTerminalTurnStatus(turn.turn.status)) {
|
|
2632
|
+
projectorRef.current.settlement.terminalReceipt = turn.turn;
|
|
2450
2633
|
state.terminalTurnNotificationQueued = true;
|
|
2451
2634
|
deadlines.beginSettlement(Date.now());
|
|
2452
2635
|
}
|
|
@@ -2510,7 +2693,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2510
2693
|
}
|
|
2511
2694
|
};
|
|
2512
2695
|
const assertSteeringActive = () => {
|
|
2513
|
-
|
|
2696
|
+
connection.assertCurrent();
|
|
2514
2697
|
runAbortController.signal.throwIfAborted();
|
|
2515
2698
|
if (state.completed || state.terminalTurnNotificationQueued) throw new Error("codex app-server turn is no longer accepting steering");
|
|
2516
2699
|
};
|
|
@@ -2548,13 +2731,15 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2548
2731
|
if (result.failedMediaCount) throw new Error(`failed to hydrate ${result.failedMediaCount} structured image attachment(s) for Codex steering`);
|
|
2549
2732
|
return buildCodexUserInput(text, result.images);
|
|
2550
2733
|
},
|
|
2551
|
-
|
|
2734
|
+
beforeSubmit: async (items) => {
|
|
2552
2735
|
const transcriptItems = items.filter((item) => item.isInboundUserMessage === true || item.userTurnTranscriptRecorder !== void 0);
|
|
2553
2736
|
if (transcriptItems.length === 0) return;
|
|
2554
2737
|
await promptMirrorPromise;
|
|
2738
|
+
assertSteeringActive();
|
|
2555
2739
|
const messages = activeProjector.buildSteeringTranscriptPrefix();
|
|
2556
2740
|
if (params.sessionTarget && messages.length > 0) {
|
|
2557
2741
|
await codexTranscriptMirrorRuntime.mirror({
|
|
2742
|
+
assertCurrent: assertSteeringActive,
|
|
2558
2743
|
agentId: sessionAgentId,
|
|
2559
2744
|
sessionKey: contextSessionKey,
|
|
2560
2745
|
sessionId: params.sessionId,
|
|
@@ -2566,47 +2751,66 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2566
2751
|
runMirrorIdentityPrefix: `${activeTurnId}:`,
|
|
2567
2752
|
config: params.config
|
|
2568
2753
|
});
|
|
2754
|
+
assertSteeringActive();
|
|
2569
2755
|
activeProjector.markSteeringTranscriptPersisted();
|
|
2570
2756
|
}
|
|
2571
2757
|
for (const item of transcriptItems) {
|
|
2572
2758
|
const recorder = item.userTurnTranscriptRecorder;
|
|
2573
2759
|
if (!recorder) continue;
|
|
2760
|
+
assertSteeringActive();
|
|
2574
2761
|
await recorder.persistApproved();
|
|
2575
|
-
if (!recorder.hasPersisted()) throw new Error("Codex
|
|
2762
|
+
if (!recorder.hasPersisted()) throw new Error("Codex steering requires a persisted user turn before submission");
|
|
2576
2763
|
}
|
|
2577
2764
|
}
|
|
2578
2765
|
});
|
|
2579
2766
|
steeringQueueRef.current = activeSteeringQueue;
|
|
2580
|
-
const
|
|
2767
|
+
const injectionGuard = (assertCurrent) => () => {
|
|
2768
|
+
assertCurrent?.();
|
|
2769
|
+
assertSteeringActive();
|
|
2770
|
+
return true;
|
|
2771
|
+
};
|
|
2772
|
+
const claimPendingUserInputAnswer = async (text, optionsLocal, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run") => {
|
|
2581
2773
|
if (optionsLocal?.isInboundUserMessage !== true || hasPromptImageInput(optionsLocal)) return false;
|
|
2582
2774
|
assertSteeringActive();
|
|
2583
2775
|
return await claimPendingAgentQuestionAnswer({
|
|
2584
2776
|
sessionKey: params.sessionKey ?? params.sessionId,
|
|
2585
2777
|
text,
|
|
2778
|
+
authority: {
|
|
2779
|
+
kind: authorityKind,
|
|
2780
|
+
assertCurrent: injectionGuard(assertCurrent)
|
|
2781
|
+
},
|
|
2782
|
+
sourceRecorder: optionsLocal.userTurnTranscriptRecorder,
|
|
2586
2783
|
persist: optionsLocal.userTurnTranscriptRecorder ? async () => {
|
|
2587
2784
|
await optionsLocal.userTurnTranscriptRecorder?.persistApproved();
|
|
2588
2785
|
} : void 0
|
|
2589
2786
|
});
|
|
2590
2787
|
};
|
|
2591
|
-
const cancelPendingUserInput = (resolvedBy) => cancelPendingAgentQuestionForSession({
|
|
2788
|
+
const cancelPendingUserInput = (resolvedBy, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run") => cancelPendingAgentQuestionForSession({
|
|
2592
2789
|
sessionKey: params.sessionKey ?? params.sessionId,
|
|
2593
|
-
resolvedBy
|
|
2790
|
+
resolvedBy,
|
|
2791
|
+
authority: {
|
|
2792
|
+
kind: authorityKind,
|
|
2793
|
+
assertCurrent: injectionGuard(assertCurrent)
|
|
2794
|
+
}
|
|
2594
2795
|
});
|
|
2595
|
-
const queueMessage = async (text, optionsLocal) => {
|
|
2596
|
-
|
|
2796
|
+
const queueMessage = async (text, optionsLocal, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run") => {
|
|
2797
|
+
const canClaim = injectionGuard(assertCurrent);
|
|
2798
|
+
if (await claimPendingUserInputAnswer(text, optionsLocal, assertCurrent, authorityKind)) {
|
|
2597
2799
|
optionsLocal?.onQueueAccepted?.(true);
|
|
2598
2800
|
return;
|
|
2599
2801
|
}
|
|
2600
2802
|
if (optionsLocal?.isInboundUserMessage === true && hasPromptImageInput(optionsLocal)) {
|
|
2601
2803
|
assertSteeringActive();
|
|
2602
2804
|
try {
|
|
2603
|
-
await cancelPendingUserInput("image-reply");
|
|
2805
|
+
await cancelPendingUserInput("image-reply", assertCurrent, authorityKind);
|
|
2604
2806
|
} catch (error) {
|
|
2807
|
+
canClaim();
|
|
2808
|
+
if (error instanceof Error && error.name === "QuestionDispatchRefusedError") throw error;
|
|
2605
2809
|
embeddedAgentLog.warn("failed to cancel codex gateway question before image steering", { error });
|
|
2606
2810
|
}
|
|
2607
2811
|
}
|
|
2608
2812
|
try {
|
|
2609
|
-
await activeSteeringQueue.queue(text, optionsLocal);
|
|
2813
|
+
await activeSteeringQueue.queue(text, optionsLocal, injectionGuard(assertCurrent));
|
|
2610
2814
|
} catch (error) {
|
|
2611
2815
|
if (error instanceof CodexSteeringAcceptedUnconfirmedError) return {
|
|
2612
2816
|
transcriptCommit: "unconfirmed",
|
|
@@ -2615,6 +2819,13 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2615
2819
|
throw error;
|
|
2616
2820
|
}
|
|
2617
2821
|
};
|
|
2822
|
+
const messageInjection = {
|
|
2823
|
+
version: 2,
|
|
2824
|
+
isAvailable: () => !state.completed && !state.terminalTurnNotificationQueued && !runAbortController.signal.aborted,
|
|
2825
|
+
queueMessage,
|
|
2826
|
+
claimPendingUserInputAnswer,
|
|
2827
|
+
cancelPendingUserInput
|
|
2828
|
+
};
|
|
2618
2829
|
const handle = {
|
|
2619
2830
|
kind: "embedded",
|
|
2620
2831
|
runId: params.runId,
|
|
@@ -2632,10 +2843,8 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2632
2843
|
claimPendingUserInputAnswer,
|
|
2633
2844
|
cancelPendingUserInput,
|
|
2634
2845
|
queueMessage,
|
|
2635
|
-
messageInjection
|
|
2636
|
-
|
|
2637
|
-
queueMessage
|
|
2638
|
-
},
|
|
2846
|
+
messageInjection,
|
|
2847
|
+
messageInjectionV2: messageInjection,
|
|
2639
2848
|
isStreaming: () => !state.completed && !runAbortController.signal.aborted,
|
|
2640
2849
|
isAborted: () => runAbortController.signal.aborted,
|
|
2641
2850
|
isStopped: () => state.completed || runAbortController.signal.aborted,
|
|
@@ -2650,7 +2859,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2650
2859
|
abort: () => abortExplicitly("aborted")
|
|
2651
2860
|
};
|
|
2652
2861
|
params.replyOperation?.attachBackend(handle);
|
|
2653
|
-
setActiveEmbeddedRun(params.sessionId, handle, params.sessionKey, params.sessionFile);
|
|
2862
|
+
setActiveEmbeddedRun(params.sessionId, handle, params.sessionKey, params.sessionFile, sessionAgentId);
|
|
2654
2863
|
const freezeRunTerminalOutcome = () => {
|
|
2655
2864
|
if (terminalState.terminalOutcomeFrozen) return;
|
|
2656
2865
|
terminalState.terminalOutcomeFrozen = true;
|
|
@@ -2663,6 +2872,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2663
2872
|
return {
|
|
2664
2873
|
activeTurnId,
|
|
2665
2874
|
activeProjector,
|
|
2875
|
+
runtimeModelSelection,
|
|
2666
2876
|
streamState,
|
|
2667
2877
|
handle,
|
|
2668
2878
|
freezeRunTerminalOutcome,
|
|
@@ -2686,7 +2896,9 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2686
2896
|
const projectionClose = state.projectionClosed ? void 0 : activeTurn.activeProjector.closeProjection();
|
|
2687
2897
|
state.projectionClosed = true;
|
|
2688
2898
|
const checkpointCleanup = projectionClose ? runCleanupStep("codex-transcript-checkpoint", () => projectionClose) : void 0;
|
|
2689
|
-
await
|
|
2899
|
+
if (params.oneShotCliRun) await runCleanupStep("codex-abort-cleanup", () => state.abortCleanup);
|
|
2900
|
+
else await state.abortCleanup?.catch(() => {});
|
|
2901
|
+
if (params.oneShotCliRun) await runCleanupStep("codex-one-shot-terminals", () => terminateCodexBackgroundTerminals(resourceState.client, resourceState.thread.threadId, true));
|
|
2690
2902
|
try {
|
|
2691
2903
|
steeringQueueRef.current?.cancel();
|
|
2692
2904
|
if (params.isFinalFallbackAttempt !== false) await maybeEmitFastModeAutoResetBestEffort();
|
|
@@ -2707,9 +2919,9 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2707
2919
|
aborted: runAbortController.signal.aborted && !state.clientClosedAbort
|
|
2708
2920
|
});
|
|
2709
2921
|
await runCleanupStep("codex-trajectory-flush", () => trajectoryRecorder?.flush());
|
|
2710
|
-
const retainLiveIncognitoThread = (terminalState.
|
|
2711
|
-
const retainLiveThread = ((retainLiveIncognitoThread && resourceState.thread.liveThreadEphemeralPolicy !== void 0 || terminalState.
|
|
2712
|
-
if (
|
|
2922
|
+
const retainLiveIncognitoThread = (terminalState.settledTurnStatus === "completed" || state.permissionChangeRestart === "confirmed" && !params.abortSignal?.aborted) && isIncognitoSessionKey(params.sessionKey);
|
|
2923
|
+
const retainLiveThread = ((retainLiveIncognitoThread && resourceState.thread.liveThreadEphemeralPolicy !== void 0 || terminalState.settledTurnStatus !== void 0 && !isIncognitoSessionKey(params.sessionKey) && params.cleanupBundleMcpOnRunEnd !== true && resourceState.thread.liveThreadConfigFingerprint !== void 0 && resourceState.thread.preserveNativeModel !== true && resourceState.thread.connectionScope !== "supervision" && !resourceState.thread.ringZeroConfigFingerprint) && resourceState.thread.clientId === resolveCodexAppServerClientInstanceId(resourceState.client) ? bindingStore.read(bindingIdentity)?.threadId === resourceState.thread.threadId && await bindingStore.withLease(bindingIdentity, async () => {
|
|
2924
|
+
if (bindingStore.read(bindingIdentity)?.threadId !== resourceState.thread.threadId) return false;
|
|
2713
2925
|
return await retainCodexAppServerBindingSubscription(resourceState.client, resourceState.thread.threadId, {
|
|
2714
2926
|
release: resourceState.thread.liveThreadOwnership?.release,
|
|
2715
2927
|
configFingerprint: resourceState.thread.liveThreadConfigFingerprint,
|
|
@@ -2726,16 +2938,22 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2726
2938
|
if (!await unsubscribeCodexThreadBestEffort(resourceState.client, {
|
|
2727
2939
|
threadId: resourceState.thread.threadId,
|
|
2728
2940
|
timeoutMs: 5e3
|
|
2729
|
-
}))
|
|
2941
|
+
})) {
|
|
2942
|
+
await closeCodexStartupClientBestEffort(resourceState.client);
|
|
2943
|
+
if (params.oneShotCliRun) await runCleanupStep("codex-one-shot-unsubscribe", async () => {
|
|
2944
|
+
throw new Error("Codex one-shot thread unsubscribe was not confirmed");
|
|
2945
|
+
});
|
|
2946
|
+
}
|
|
2730
2947
|
}
|
|
2731
2948
|
}
|
|
2732
2949
|
} finally {
|
|
2733
2950
|
await runCleanupStep("codex-user-input-cancel", () => userInputBridgeRef.current?.cancelPending());
|
|
2734
2951
|
await runCleanupStep("codex-turn-deadline-clear", () => deadlines.dispose());
|
|
2735
2952
|
await runCleanupStep("codex-dynamic-tool-cleanup", async () => {
|
|
2736
|
-
const cleanupReason = terminalState.
|
|
2953
|
+
const cleanupReason = terminalState.settledTurnStatus === "completed" ? "completion" : state.timeout ? "timeout" : runAbortController.signal.aborted ? "cancel" : "error";
|
|
2737
2954
|
const cleanups = prompt.context.attemptTools.runCleanups.splice(0);
|
|
2738
|
-
await Promise.allSettled(cleanups.map(async (cleanup) => await cleanup(cleanupReason)));
|
|
2955
|
+
const errors = (await Promise.allSettled(cleanups.map(async (cleanup) => await cleanup(cleanupReason)))).filter((result) => result.status === "rejected");
|
|
2956
|
+
if (params.oneShotCliRun && errors.length) throw new AggregateError(errors.map((result) => result.reason), "Codex tool cleanup failed");
|
|
2739
2957
|
});
|
|
2740
2958
|
await runCleanupStep("codex-route-release", releaseCurrentRoute);
|
|
2741
2959
|
await checkpointCleanup;
|
|
@@ -2744,15 +2962,13 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2744
2962
|
resourceState.nativeHookRelay = void 0;
|
|
2745
2963
|
await runCleanupStep("codex-native-hook-relay-release", () => {
|
|
2746
2964
|
if (!nativeHookRelay) return;
|
|
2747
|
-
if (state.shouldDelayNativeHookRelayUnregister) scheduleCodexNativeHookRelayUnregister({
|
|
2965
|
+
if (state.shouldDelayNativeHookRelayUnregister && !params.oneShotCliRun) scheduleCodexNativeHookRelayUnregister({
|
|
2748
2966
|
relay: nativeHookRelay,
|
|
2749
2967
|
hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec
|
|
2750
2968
|
});
|
|
2751
2969
|
else nativeHookRelay.unregister();
|
|
2752
2970
|
});
|
|
2753
2971
|
await runCleanupStep("codex-sandbox-release", releaseSandboxExecEnvironment);
|
|
2754
|
-
await runCleanupStep("codex-scoped-mcp-dispose", () => prompt.context.attemptTools.scopedMcpTools?.dispose());
|
|
2755
|
-
await runCleanupStep("codex-configured-mcp-dispose", () => prompt.context.attemptTools.configuredMcp?.dispose());
|
|
2756
2972
|
await runCleanupStep("codex-abort-listener-remove", () => {
|
|
2757
2973
|
runAbortController.signal.removeEventListener("abort", abortListener);
|
|
2758
2974
|
});
|
|
@@ -2995,8 +3211,9 @@ async function readCodexAppServerRolloutTokenSnapshot(file, openedHandle) {
|
|
|
2995
3211
|
bytesRead += result.bytesRead;
|
|
2996
3212
|
}
|
|
2997
3213
|
let lineEnd = bytesRead;
|
|
2998
|
-
|
|
2999
|
-
|
|
3214
|
+
while (lineEnd > 0) {
|
|
3215
|
+
const index = chunk.lastIndexOf(10, lineEnd - 1);
|
|
3216
|
+
if (index < 0) break;
|
|
3000
3217
|
const lineFragment = chunk.subarray(index + 1, lineEnd);
|
|
3001
3218
|
const line = partialLineFragments.length === 0 ? lineFragment.toString("utf8") : Buffer.concat([lineFragment, ...partialLineFragments.toReversed()]).toString("utf8");
|
|
3002
3219
|
partialLineFragments.length = 0;
|
|
@@ -3078,6 +3295,7 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
3078
3295
|
await Promise.all(rolloutFiles.map(async (file) => {
|
|
3079
3296
|
await file.handle?.close();
|
|
3080
3297
|
}));
|
|
3298
|
+
assertCodexBindingMayBeReplaced(binding, "rotating an oversized native transcript", params.expectedSessionRuntimeOwnership);
|
|
3081
3299
|
embeddedAgentLog.warn("codex app-server native transcript exceeded active byte limit; starting a fresh thread", {
|
|
3082
3300
|
threadId: binding.threadId,
|
|
3083
3301
|
maxBytes,
|
|
@@ -3089,7 +3307,7 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
3089
3307
|
await params.bindingStore.mutate(params.identity, {
|
|
3090
3308
|
kind: "clear",
|
|
3091
3309
|
threadId: binding.threadId
|
|
3092
|
-
});
|
|
3310
|
+
}, params.assertCurrent);
|
|
3093
3311
|
return { binding: void 0 };
|
|
3094
3312
|
}
|
|
3095
3313
|
}
|
|
@@ -3106,6 +3324,7 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
3106
3324
|
const sessionTokens = sessionRecord?.totalTokensFresh === true && sessionRecord.totalTokensVersion === 1 && typeof sessionRecord?.totalTokens === "number" && Number.isFinite(sessionRecord.totalTokens) ? sessionRecord.totalTokens : void 0;
|
|
3107
3325
|
const tokenCount = maxFiniteNumber([sessionTokens, nativeTokens]);
|
|
3108
3326
|
if (tokenCount !== void 0 && tokenCount >= maxTokens) {
|
|
3327
|
+
assertCodexBindingMayBeReplaced(binding, "rotating a full native context", params.expectedSessionRuntimeOwnership);
|
|
3109
3328
|
embeddedAgentLog.warn("codex app-server native transcript exceeded active token limit; starting a fresh thread", {
|
|
3110
3329
|
threadId: binding.threadId,
|
|
3111
3330
|
maxTokens,
|
|
@@ -3120,7 +3339,7 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
3120
3339
|
await params.bindingStore.mutate(params.identity, {
|
|
3121
3340
|
kind: "clear",
|
|
3122
3341
|
threadId: binding.threadId
|
|
3123
|
-
});
|
|
3342
|
+
}, params.assertCurrent);
|
|
3124
3343
|
return { binding: void 0 };
|
|
3125
3344
|
}
|
|
3126
3345
|
const startupContextTokens = nativeModelContextWindow ?? sessionModelContextWindow;
|
|
@@ -3142,7 +3361,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3142
3361
|
offAnnounced: false,
|
|
3143
3362
|
resetAnnounced: false
|
|
3144
3363
|
};
|
|
3145
|
-
const preDynamicStartupStages = createCodexDynamicToolBuildStageTracker(
|
|
3364
|
+
const preDynamicStartupStages = createCodexDynamicToolBuildStageTracker();
|
|
3146
3365
|
const runtimeArtifactRequest = params.captureRuntimeArtifact || params.expectedRuntimeArtifact ? params.expectedRuntimeArtifact ? { expected: params.expectedRuntimeArtifact } : {} : void 0;
|
|
3147
3366
|
const pluginConfig = readCodexPluginConfig(options.pluginConfig);
|
|
3148
3367
|
const requirementsToml = readCodexRequirementsToml({});
|
|
@@ -3178,7 +3397,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3178
3397
|
const preparedEnvironment = params.hostCapabilities.preparedEnvironment?.();
|
|
3179
3398
|
const remoteExec = isCodexRemoteExecPlacementSandbox(sandbox);
|
|
3180
3399
|
const assertLocalTargetSupported = (unsupported) => {
|
|
3181
|
-
if (preparedEnvironment?.localProcessEnv && unsupported) throw new Error("This runtime cannot target the diagnosed local installation. Use the saved prompt with a suggested external or manual handoff on this machine.");
|
|
3400
|
+
if (preparedEnvironment?.localProcessEnv && unsupported) throw new Error("This runtime cannot target the diagnosed local installation. Use an owned local Codex stdio process, or use the saved prompt with a suggested external or manual handoff on this machine.");
|
|
3182
3401
|
};
|
|
3183
3402
|
assertLocalTargetSupported(sandbox?.enabled === true || remoteExec);
|
|
3184
3403
|
const preparedShellEnvironment = preparedEnvironment ? {
|
|
@@ -3189,7 +3408,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3189
3408
|
const shellEnvironment = preparedShellEnvironment && Object.keys(preparedShellEnvironment).length > 0 ? preparedShellEnvironment : void 0;
|
|
3190
3409
|
const disableLoginShell = remoteExec || preparedEnvironment?.localProcessEnv !== void 0 || preparedEnvironment?.managedLocalIdentity === true || preparedEnvironment !== void 0 && Object.keys(preparedEnvironment.credentialScrubEnv).length > 0;
|
|
3191
3410
|
const withPreparedProcessEnv = (appServer) => {
|
|
3192
|
-
assertLocalTargetSupported(appServer.start.transport
|
|
3411
|
+
assertLocalTargetSupported(appServer.start.transport !== "stdio" || Boolean(appServer.remoteWorkspaceRoot));
|
|
3193
3412
|
return shellEnvironment ? {
|
|
3194
3413
|
...appServer,
|
|
3195
3414
|
start: {
|
|
@@ -3233,16 +3452,17 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3233
3452
|
bindingIdentity = physicalIdentity;
|
|
3234
3453
|
}
|
|
3235
3454
|
}
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
}
|
|
3455
|
+
const { binding: admittedBinding, assertCurrent } = await resolveCodexSessionBinding({
|
|
3456
|
+
reclaimStale: true,
|
|
3457
|
+
bindingStore,
|
|
3458
|
+
identity: bindingIdentity,
|
|
3459
|
+
config: params.config,
|
|
3460
|
+
storePath: params.sessionTarget?.storePath,
|
|
3461
|
+
assertCurrent: params.hostCapabilities.assertActive,
|
|
3462
|
+
signal: params.abortSignal,
|
|
3463
|
+
assertBinding: params.expectedSessionRuntimeOwnership ? (binding) => assertCodexSessionRuntimeOwnership(binding, params.expectedSessionRuntimeOwnership) : void 0
|
|
3464
|
+
});
|
|
3465
|
+
let startupBinding = admittedBinding;
|
|
3246
3466
|
preDynamicStartupStages.mark("read-binding");
|
|
3247
3467
|
const usesSupervisionConnection = startupBinding?.connectionScope === "supervision";
|
|
3248
3468
|
if (usesSupervisionConnection) activeContextEngine = void 0;
|
|
@@ -3365,7 +3585,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3365
3585
|
preDynamicStartupStages.mark("app-server-policy");
|
|
3366
3586
|
preDynamicStartupStages.mark("native-hook-relay");
|
|
3367
3587
|
const terminalState = {
|
|
3368
|
-
|
|
3588
|
+
settledTurnStatus: void 0,
|
|
3369
3589
|
explicitCancellationObserved: false,
|
|
3370
3590
|
explicitCancellationReason: void 0,
|
|
3371
3591
|
terminalOutcomeFrozen: false,
|
|
@@ -3393,104 +3613,113 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3393
3613
|
};
|
|
3394
3614
|
if (params.abortSignal?.aborted) abortFromUpstream();
|
|
3395
3615
|
else params.abortSignal?.addEventListener("abort", abortFromUpstream, { once: true });
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
preDynamicStartupStages.mark("rotate-binding");
|
|
3410
|
-
if (startupBinding !== startupBindingBeforeRotation) {
|
|
3411
|
-
reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
|
|
3412
|
-
configuredAppServer = resolveRuntimeOptionsForBinding(startupBinding, {
|
|
3413
|
-
modelProvider: reviewerPolicyContext.modelProvider,
|
|
3414
|
-
model: reviewerPolicyContext.model
|
|
3616
|
+
try {
|
|
3617
|
+
const startupBindingBeforeRotation = startupBinding;
|
|
3618
|
+
const startupBindingResolution = await rotateOversizedCodexAppServerStartupBinding({
|
|
3619
|
+
assertCurrent,
|
|
3620
|
+
binding: startupBinding,
|
|
3621
|
+
bindingStore,
|
|
3622
|
+
identity: bindingIdentity,
|
|
3623
|
+
sessionFile: params.sessionFile,
|
|
3624
|
+
agentDir,
|
|
3625
|
+
codexHome: appServer.start.env?.CODEX_HOME,
|
|
3626
|
+
config: params.config,
|
|
3627
|
+
contextEngineActive: Boolean(activeContextEngine),
|
|
3628
|
+
expectedSessionRuntimeOwnership: params.expectedSessionRuntimeOwnership
|
|
3415
3629
|
});
|
|
3416
|
-
|
|
3417
|
-
|
|
3630
|
+
startupBinding = startupBindingResolution.binding;
|
|
3631
|
+
const initialInactiveThreadBootstrapBindingForcedFreshStart = initialStartupBindingHadInactiveThreadBootstrap && !startupBinding?.threadId;
|
|
3632
|
+
preDynamicStartupStages.mark("rotate-binding");
|
|
3633
|
+
if (startupBinding !== startupBindingBeforeRotation) {
|
|
3634
|
+
reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
|
|
3635
|
+
configuredAppServer = resolveRuntimeOptionsForBinding(startupBinding, {
|
|
3636
|
+
modelProvider: reviewerPolicyContext.modelProvider,
|
|
3637
|
+
model: reviewerPolicyContext.model
|
|
3638
|
+
});
|
|
3639
|
+
resolvedAppServer = resolveFinalAppServer(configuredAppServer, reviewerPolicyContext);
|
|
3640
|
+
appServer = resolvedAppServer.appServer;
|
|
3641
|
+
}
|
|
3642
|
+
const sessionPermissionPolicy = resolveCodexEffectiveSessionPermissionPolicy({
|
|
3643
|
+
appServer,
|
|
3644
|
+
permissionMode: params.permissionMode,
|
|
3645
|
+
sessionRoot: params.sessionRoot,
|
|
3646
|
+
defaultRoot: effectiveWorkspace
|
|
3647
|
+
});
|
|
3648
|
+
if (sessionPermissionPolicy) {
|
|
3649
|
+
params.permissionMode = sessionPermissionPolicy.mode;
|
|
3650
|
+
params.sessionRoot = sessionPermissionPolicy.root;
|
|
3651
|
+
(params.execOverrides ??= {}).mode = sessionPermissionPolicy.execMode;
|
|
3652
|
+
}
|
|
3653
|
+
const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
|
|
3654
|
+
configuredEvents: options.nativeHookRelay?.events,
|
|
3655
|
+
appServer
|
|
3656
|
+
});
|
|
3657
|
+
const mutable = {
|
|
3658
|
+
startupBinding,
|
|
3659
|
+
startupContextTokens: startupBindingResolution.startupContextTokens,
|
|
3660
|
+
pluginAppServer: appServer,
|
|
3661
|
+
continuityCalibration: startupBindingBeforeRotation?.continuityCalibration
|
|
3662
|
+
};
|
|
3663
|
+
const resolveRuntimeOptionsForCurrentBinding = (selection) => resolveFinalAppServer(resolveRuntimeOptionsForBinding(mutable.startupBinding, selection), selection).appServer;
|
|
3664
|
+
assertCurrent();
|
|
3665
|
+
return {
|
|
3666
|
+
params,
|
|
3667
|
+
assertCurrent,
|
|
3668
|
+
options,
|
|
3669
|
+
attemptStartedAt,
|
|
3670
|
+
profilerEnabled,
|
|
3671
|
+
codexModelCallTrace,
|
|
3672
|
+
codexModelContentCapture,
|
|
3673
|
+
codexModelCallId,
|
|
3674
|
+
fastModeAutoStartedAtMs,
|
|
3675
|
+
fastModeAutoProgressState,
|
|
3676
|
+
preDynamicStartupStages,
|
|
3677
|
+
attemptClientFactory,
|
|
3678
|
+
runtimeArtifactRequest,
|
|
3679
|
+
pluginConfig,
|
|
3680
|
+
computerUseConfig,
|
|
3681
|
+
sessionAgentId,
|
|
3682
|
+
policyAgentId,
|
|
3683
|
+
resolvedWorkspace,
|
|
3684
|
+
sandboxSessionKey,
|
|
3685
|
+
contextSessionKey,
|
|
3686
|
+
sandbox,
|
|
3687
|
+
agentDir,
|
|
3688
|
+
shellEnvironment,
|
|
3689
|
+
disableLoginShell,
|
|
3690
|
+
bindingIdentity,
|
|
3691
|
+
bindingStore,
|
|
3692
|
+
activeContextEngine,
|
|
3693
|
+
isInactiveThreadBootstrapBinding,
|
|
3694
|
+
usesSupervisionConnection,
|
|
3695
|
+
startupAuthProfileId,
|
|
3696
|
+
startupAuthRequirement: preparedAuthRoute?.authRequirement,
|
|
3697
|
+
startupPreparedAuth,
|
|
3698
|
+
startupClientAuthProfileId,
|
|
3699
|
+
effectiveWorkspace,
|
|
3700
|
+
effectiveCwd,
|
|
3701
|
+
appServer,
|
|
3702
|
+
sessionPermissionPolicy,
|
|
3703
|
+
nativeHookRelayEvents,
|
|
3704
|
+
runAbortController,
|
|
3705
|
+
terminalState,
|
|
3706
|
+
abortExplicitly,
|
|
3707
|
+
abortFromUpstream,
|
|
3708
|
+
resolveReviewerPolicyContext,
|
|
3709
|
+
resolveRuntimeOptionsForCurrentBinding,
|
|
3710
|
+
mutable,
|
|
3711
|
+
initialStartupBindingHadInactiveThreadBootstrap,
|
|
3712
|
+
initialInactiveThreadBootstrapBindingForcedFreshStart
|
|
3713
|
+
};
|
|
3714
|
+
} catch (error) {
|
|
3715
|
+
params.abortSignal?.removeEventListener("abort", abortFromUpstream);
|
|
3716
|
+
throw error;
|
|
3418
3717
|
}
|
|
3419
|
-
const sessionPermissionPolicy = resolveCodexEffectiveSessionPermissionPolicy({
|
|
3420
|
-
appServer,
|
|
3421
|
-
permissionMode: params.permissionMode,
|
|
3422
|
-
sessionRoot: params.sessionRoot,
|
|
3423
|
-
defaultRoot: effectiveWorkspace
|
|
3424
|
-
});
|
|
3425
|
-
if (sessionPermissionPolicy) {
|
|
3426
|
-
params.permissionMode = sessionPermissionPolicy.mode;
|
|
3427
|
-
params.sessionRoot = sessionPermissionPolicy.root;
|
|
3428
|
-
(params.execOverrides ??= {}).mode = sessionPermissionPolicy.execMode;
|
|
3429
|
-
}
|
|
3430
|
-
const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
|
|
3431
|
-
configuredEvents: options.nativeHookRelay?.events,
|
|
3432
|
-
appServer
|
|
3433
|
-
});
|
|
3434
|
-
const mutable = {
|
|
3435
|
-
startupBinding,
|
|
3436
|
-
startupContextTokens: startupBindingResolution.startupContextTokens,
|
|
3437
|
-
pluginAppServer: appServer,
|
|
3438
|
-
continuityCalibration: startupBindingBeforeRotation?.continuityCalibration
|
|
3439
|
-
};
|
|
3440
|
-
const resolveRuntimeOptionsForCurrentBinding = (selection) => resolveFinalAppServer(resolveRuntimeOptionsForBinding(mutable.startupBinding, selection), selection).appServer;
|
|
3441
|
-
return {
|
|
3442
|
-
params,
|
|
3443
|
-
options,
|
|
3444
|
-
attemptStartedAt,
|
|
3445
|
-
profilerEnabled,
|
|
3446
|
-
codexModelCallTrace,
|
|
3447
|
-
codexModelContentCapture,
|
|
3448
|
-
codexModelCallId,
|
|
3449
|
-
fastModeAutoStartedAtMs,
|
|
3450
|
-
fastModeAutoProgressState,
|
|
3451
|
-
preDynamicStartupStages,
|
|
3452
|
-
attemptClientFactory,
|
|
3453
|
-
runtimeArtifactRequest,
|
|
3454
|
-
pluginConfig,
|
|
3455
|
-
computerUseConfig,
|
|
3456
|
-
sessionAgentId,
|
|
3457
|
-
policyAgentId,
|
|
3458
|
-
resolvedWorkspace,
|
|
3459
|
-
sandboxSessionKey,
|
|
3460
|
-
contextSessionKey,
|
|
3461
|
-
sandbox,
|
|
3462
|
-
agentDir,
|
|
3463
|
-
shellEnvironment,
|
|
3464
|
-
disableLoginShell,
|
|
3465
|
-
bindingIdentity,
|
|
3466
|
-
bindingStore,
|
|
3467
|
-
activeContextEngine,
|
|
3468
|
-
isInactiveThreadBootstrapBinding,
|
|
3469
|
-
usesSupervisionConnection,
|
|
3470
|
-
startupAuthProfileId,
|
|
3471
|
-
startupAuthRequirement: preparedAuthRoute?.authRequirement,
|
|
3472
|
-
startupPreparedAuth,
|
|
3473
|
-
startupClientAuthProfileId,
|
|
3474
|
-
effectiveWorkspace,
|
|
3475
|
-
effectiveCwd,
|
|
3476
|
-
appServer,
|
|
3477
|
-
sessionPermissionPolicy,
|
|
3478
|
-
nativeHookRelayEvents,
|
|
3479
|
-
runAbortController,
|
|
3480
|
-
terminalState,
|
|
3481
|
-
abortExplicitly,
|
|
3482
|
-
abortFromUpstream,
|
|
3483
|
-
resolveReviewerPolicyContext,
|
|
3484
|
-
resolveRuntimeOptionsForCurrentBinding,
|
|
3485
|
-
mutable,
|
|
3486
|
-
initialStartupBindingHadInactiveThreadBootstrap,
|
|
3487
|
-
initialInactiveThreadBootstrapBindingForcedFreshStart
|
|
3488
|
-
};
|
|
3489
3718
|
}
|
|
3490
3719
|
//#endregion
|
|
3491
3720
|
//#region extensions/codex/src/app-server/run-attempt-state.ts
|
|
3492
|
-
async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity, fields) {
|
|
3493
|
-
const currentBinding =
|
|
3721
|
+
async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity, fields, expected) {
|
|
3722
|
+
const currentBinding = bindingStore.read(identity);
|
|
3494
3723
|
const expectedThreadId = fields.threadId ?? currentBinding?.threadId;
|
|
3495
3724
|
if (!expectedThreadId) return;
|
|
3496
3725
|
if (currentBinding && currentBinding.threadId !== expectedThreadId) {
|
|
@@ -3500,8 +3729,8 @@ async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity,
|
|
|
3500
3729
|
});
|
|
3501
3730
|
return;
|
|
3502
3731
|
}
|
|
3503
|
-
if (currentBinding?.connectionScope === "supervision") {
|
|
3504
|
-
embeddedAgentLog.warn("codex app-server image payload error detected for
|
|
3732
|
+
if (expected || currentBinding?.connectionScope === "supervision") {
|
|
3733
|
+
embeddedAgentLog.warn("codex app-server image payload error detected for native-owned thread; preserving binding", fields);
|
|
3505
3734
|
return;
|
|
3506
3735
|
}
|
|
3507
3736
|
embeddedAgentLog.warn("codex app-server image payload error detected; clearing thread binding", fields);
|
|
@@ -3510,16 +3739,6 @@ async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity,
|
|
|
3510
3739
|
threadId: expectedThreadId
|
|
3511
3740
|
});
|
|
3512
3741
|
}
|
|
3513
|
-
async function markCodexAppServerBindingCoveredThroughTurn(params) {
|
|
3514
|
-
await params.bindingStore.mutate(params.identity, {
|
|
3515
|
-
kind: "patch",
|
|
3516
|
-
threadId: params.threadId,
|
|
3517
|
-
patch: {
|
|
3518
|
-
historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3519
|
-
...params.continuityCalibration ? { continuityCalibration: params.continuityCalibration } : {}
|
|
3520
|
-
}
|
|
3521
|
-
});
|
|
3522
|
-
}
|
|
3523
3742
|
function isNonEmptyString(value) {
|
|
3524
3743
|
return typeof value === "string" && value.length > 0;
|
|
3525
3744
|
}
|
|
@@ -3556,10 +3775,14 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
3556
3775
|
};
|
|
3557
3776
|
const readFencedHistory = async () => {
|
|
3558
3777
|
const transcriptReadFence = params.userTurnTranscriptRecorder?.getAdmissionReceipt();
|
|
3559
|
-
|
|
3778
|
+
const messages = await readMirroredSessionHistoryMessages({
|
|
3560
3779
|
...activeTranscriptTarget,
|
|
3780
|
+
signal: connection.runAbortController.signal,
|
|
3561
3781
|
...transcriptReadFence ? { admission: transcriptReadFence } : {}
|
|
3562
3782
|
});
|
|
3783
|
+
connection.runAbortController.signal.throwIfAborted();
|
|
3784
|
+
connection.assertCurrent();
|
|
3785
|
+
return messages;
|
|
3563
3786
|
};
|
|
3564
3787
|
const historyState = { messages: !activeContextEngine && initialStartupBindingHadInactiveThreadBootstrap ? [] : await readFencedHistory() ?? [] };
|
|
3565
3788
|
const hadSessionTranscriptState = historyState.messages.length > 0;
|
|
@@ -3574,6 +3797,10 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
3574
3797
|
sessionKey: contextSessionKey,
|
|
3575
3798
|
sessionId: params.sessionId,
|
|
3576
3799
|
workspaceDir: params.workspaceDir,
|
|
3800
|
+
...!usesSupervisionConnection && connection.mutable.startupBinding?.preserveNativeModel !== true ? {
|
|
3801
|
+
modelProviderId: params.provider,
|
|
3802
|
+
modelId: params.modelId
|
|
3803
|
+
} : {},
|
|
3577
3804
|
trigger: params.trigger,
|
|
3578
3805
|
...buildAgentHookContextChannelFields({
|
|
3579
3806
|
sessionKey: contextSessionKey,
|
|
@@ -3633,6 +3860,17 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
3633
3860
|
});
|
|
3634
3861
|
const agentWorkspaceDeveloperInstructions = workspaceBootstrapContext.threadDeveloperInstructions ? connection.mutable.startupBinding?.agentWorkspaceDeveloperInstructions ?? workspaceBootstrapContext.threadDeveloperInstructions : void 0;
|
|
3635
3862
|
const baseDeveloperInstructions = joinPresentSections(buildDeveloperInstructions(runtimeParams, { dynamicTools: toolBridge.availableSpecs }), agentWorkspaceDeveloperInstructions);
|
|
3863
|
+
const watchedSessionsContext = buildCodexWatchedSessionsContext({
|
|
3864
|
+
attempt: runtimeParams,
|
|
3865
|
+
dynamicTools: toolBridge.availableSpecs,
|
|
3866
|
+
sessionKey: contextSessionKey,
|
|
3867
|
+
sandboxed: sandbox?.enabled === true
|
|
3868
|
+
});
|
|
3869
|
+
const buildOpenClawPromptContext = (includeWorkspaceReferences) => buildCodexOpenClawPromptContext({
|
|
3870
|
+
params: runtimeParams,
|
|
3871
|
+
workspacePromptContext: includeWorkspaceReferences ? workspaceBootstrapContext.promptContext : void 0,
|
|
3872
|
+
watchedSessionsContext
|
|
3873
|
+
});
|
|
3636
3874
|
return {
|
|
3637
3875
|
runtime,
|
|
3638
3876
|
attemptTools,
|
|
@@ -3645,16 +3883,7 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
3645
3883
|
workspaceBootstrapContext,
|
|
3646
3884
|
agentWorkspaceDeveloperInstructions,
|
|
3647
3885
|
baseDeveloperInstructions,
|
|
3648
|
-
|
|
3649
|
-
params: runtimeParams,
|
|
3650
|
-
workspacePromptContext: workspaceBootstrapContext.promptContext,
|
|
3651
|
-
watchedSessionsContext: buildCodexWatchedSessionsContext({
|
|
3652
|
-
attempt: runtimeParams,
|
|
3653
|
-
dynamicTools: toolBridge.availableSpecs,
|
|
3654
|
-
sessionKey: contextSessionKey,
|
|
3655
|
-
sandboxed: sandbox?.enabled === true
|
|
3656
|
-
})
|
|
3657
|
-
}),
|
|
3886
|
+
buildOpenClawPromptContext,
|
|
3658
3887
|
skillsCollaborationInstructions: renderCodexSkillsCollaborationInstructions({
|
|
3659
3888
|
attempt: runtimeParams,
|
|
3660
3889
|
skillsPrompt: params.skillsSnapshot?.prompt
|
|
@@ -3901,6 +4130,7 @@ function recordCodexTrajectoryCompletion(recorder, params) {
|
|
|
3901
4130
|
yieldDetected: params.yieldDetected ?? false,
|
|
3902
4131
|
aborted: terminal.aborted,
|
|
3903
4132
|
promptError: normalizeCodexTrajectoryError(terminal.promptError),
|
|
4133
|
+
...terminal.settlementWarning ? { settlementWarning: terminal.settlementWarning } : {},
|
|
3904
4134
|
usage: params.result.attemptUsage,
|
|
3905
4135
|
assistantTexts: params.result.assistantTexts,
|
|
3906
4136
|
messagesSnapshot: params.result.messagesSnapshot
|
|
@@ -3940,265 +4170,395 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
3940
4170
|
const { effectiveRuntimeProviderId, effectiveRuntimeModelId } = runtime;
|
|
3941
4171
|
const { params, terminalState, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, usesSupervisionConnection, sessionAgentId, contextSessionKey, effectiveCwd, agentDir, attemptStartedAt, startupAuthProfileId } = connection;
|
|
3942
4172
|
const { toolBridge, toolState } = attemptTools;
|
|
3943
|
-
const
|
|
4173
|
+
const canClearBindingForRecovery = (operation) => {
|
|
4174
|
+
if (params.expectedSessionRuntimeOwnership) {
|
|
4175
|
+
embeddedAgentLog.warn("codex app-server preserved native binding instead of recovery rotation", {
|
|
4176
|
+
threadId: resourceState.thread.threadId,
|
|
4177
|
+
operation
|
|
4178
|
+
});
|
|
4179
|
+
return false;
|
|
4180
|
+
}
|
|
4181
|
+
assertCodexBindingMayBeReplaced(resourceState.thread, operation);
|
|
4182
|
+
return true;
|
|
4183
|
+
};
|
|
4184
|
+
const { state, completion, deadlines, settlementExpired } = turnRuntime;
|
|
3944
4185
|
const { emitLifecycleTerminal, buildLifecycleTerminalMeta } = lifecycle;
|
|
3945
4186
|
const { drainNotificationQueue } = notifications;
|
|
3946
4187
|
const { codexModelCallDiagnostics } = requestRuntime;
|
|
3947
|
-
const { activeTurnId, activeProjector, streamState, freezeRunTerminalOutcome, notifyUserMessagePersisted } = activeTurn;
|
|
4188
|
+
const { activeTurnId, activeProjector, runtimeModelSelection, streamState, freezeRunTerminalOutcome, notifyUserMessagePersisted } = activeTurn;
|
|
3948
4189
|
await completion;
|
|
3949
|
-
const
|
|
3950
|
-
let
|
|
3951
|
-
let
|
|
3952
|
-
const
|
|
3953
|
-
if (
|
|
3954
|
-
|
|
3955
|
-
|
|
4190
|
+
const drainGraceElapsed = createDeferred();
|
|
4191
|
+
let settlementPhase = "active";
|
|
4192
|
+
let drainGraceTimer;
|
|
4193
|
+
const beginDrainGrace = () => {
|
|
4194
|
+
if (settlementPhase !== "active" || drainGraceTimer) return;
|
|
4195
|
+
drainGraceTimer = setTimeout(() => {
|
|
4196
|
+
settlementPhase = "expired";
|
|
4197
|
+
drainGraceElapsed.resolve();
|
|
4198
|
+
}, TURN_FINALIZE_DRAIN_ABORT_GRACE_MS);
|
|
4199
|
+
drainGraceTimer.unref?.();
|
|
3956
4200
|
};
|
|
3957
4201
|
const abortListener = addAbortListener(runAbortController.signal, () => {
|
|
3958
|
-
state.abortCleanup.then(
|
|
4202
|
+
state.abortCleanup.then(beginDrainGrace, beginDrainGrace);
|
|
3959
4203
|
});
|
|
3960
4204
|
const closeProjection = () => {
|
|
3961
4205
|
state.projectionClosed = true;
|
|
3962
4206
|
return activeProjector.closeProjection();
|
|
3963
4207
|
};
|
|
3964
|
-
const
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
if (runAbortController.signal.aborted) await state.abortCleanup;
|
|
3968
|
-
} finally {
|
|
3969
|
-
settlementClosed = true;
|
|
4208
|
+
const closeSettlement = () => {
|
|
4209
|
+
if (settlementPhase === "closed") return;
|
|
4210
|
+
settlementPhase = "closed";
|
|
3970
4211
|
abortListener[Symbol.dispose]();
|
|
3971
|
-
clearTimeout(
|
|
4212
|
+
clearTimeout(drainGraceTimer);
|
|
3972
4213
|
deadlines.dispose();
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
const
|
|
3979
|
-
|
|
3980
|
-
let finalPromptError = resourceState.executionDisconnectError ?? clientClosedPromptErrorForFinal ?? (state.timeout?.kind === "settlement" ? "codex app-server terminal settlement timed out" : state.timeout?.kind === "execution" ? "codex app-server execution budget timed out" : projectedTerminal.promptError);
|
|
3981
|
-
const finalPromptErrorMessage = typeof finalPromptError === "string" ? finalPromptError : finalPromptError instanceof Error ? finalPromptError.message : finalPromptError ? formatErrorMessage(finalPromptError) : void 0;
|
|
3982
|
-
if (isInvalidCodexImagePayloadError(finalPromptErrorMessage)) await clearCodexBindingAfterInvalidImagePayload(bindingStore, bindingIdentity, {
|
|
3983
|
-
phase: "turn_completed",
|
|
3984
|
-
threadId: resourceState.thread.threadId,
|
|
3985
|
-
turnId: activeTurnId,
|
|
3986
|
-
error: finalPromptErrorMessage
|
|
4214
|
+
};
|
|
4215
|
+
const settlement = drainNotificationQueue().then(async () => {
|
|
4216
|
+
await closeProjection();
|
|
4217
|
+
await activeProjector.settlement.drain();
|
|
4218
|
+
});
|
|
4219
|
+
const degradedSettlement = settlementExpired.then(() => {
|
|
4220
|
+
beginDrainGrace();
|
|
3987
4221
|
});
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
4222
|
+
let projectionDrained = false;
|
|
4223
|
+
try {
|
|
4224
|
+
try {
|
|
4225
|
+
projectionDrained = await Promise.race([
|
|
4226
|
+
settlement.then(() => true),
|
|
4227
|
+
drainGraceElapsed.promise.then(() => false),
|
|
4228
|
+
degradedSettlement.then(() => false)
|
|
4229
|
+
]);
|
|
4230
|
+
if (runAbortController.signal.aborted) await state.abortCleanup;
|
|
4231
|
+
} finally {
|
|
4232
|
+
if (!state.projectionClosed) await resources.runCleanupStep("codex-transcript-checkpoint", closeProjection);
|
|
4233
|
+
}
|
|
4234
|
+
const result = activeProjector.buildResult(toolBridge.telemetry, { yieldDetected: toolState.yieldDetected });
|
|
4235
|
+
const projectedTerminal = attemptTerminal.project(result.terminal);
|
|
4236
|
+
const isFinalAborted = () => terminalState.explicitCancellationObserved || !resourceState.executionDisconnectError && (projectedTerminal.aborted || runAbortController.signal.aborted && !state.clientClosedAbort);
|
|
4237
|
+
const currentPromptError = (fallback) => resourceState.executionDisconnectError ?? state.clientClosedPromptError ?? (state.timeout ? `codex app-server ${state.timeout.kind === "execution" ? "execution budget" : "terminal settlement"} timed out` : fallback);
|
|
4238
|
+
let enrichedPromptError = currentPromptError(projectedTerminal.promptError);
|
|
4239
|
+
const enrichedPromptErrorMessage = typeof enrichedPromptError === "string" ? enrichedPromptError : enrichedPromptError instanceof Error ? enrichedPromptError.message : enrichedPromptError ? formatErrorMessage(enrichedPromptError) : void 0;
|
|
4240
|
+
if (isInvalidCodexImagePayloadError(enrichedPromptErrorMessage)) await clearCodexBindingAfterInvalidImagePayload(bindingStore, bindingIdentity, {
|
|
4241
|
+
phase: "turn_completed",
|
|
4242
|
+
threadId: resourceState.thread.threadId,
|
|
4243
|
+
turnId: activeTurnId,
|
|
4244
|
+
error: enrichedPromptErrorMessage
|
|
4245
|
+
}, params.expectedSessionRuntimeOwnership);
|
|
4246
|
+
if (resourceState.thread.connectionScope !== "supervision" && shouldUseFreshCodexThreadAfterContextEngineOverflow({
|
|
4247
|
+
error: enrichedPromptError,
|
|
4248
|
+
contextEngineActive: Boolean(activeContextEngine),
|
|
4249
|
+
thread: resourceState.thread
|
|
4250
|
+
}) && canClearBindingForRecovery("clearing a native context after overflow")) {
|
|
4251
|
+
embeddedAgentLog.warn("codex app-server context-engine turn overflowed after resume; clearing thread binding for recovery", {
|
|
4252
|
+
threadId: resourceState.thread.threadId,
|
|
4253
|
+
turnId: activeTurnId,
|
|
4254
|
+
error: enrichedPromptErrorMessage
|
|
4255
|
+
});
|
|
4256
|
+
await bindingStore.mutate(bindingIdentity, {
|
|
4257
|
+
kind: "clear",
|
|
4258
|
+
threadId: resourceState.thread.threadId
|
|
4259
|
+
});
|
|
4260
|
+
}
|
|
4261
|
+
const refreshedUsageLimitPromptError = await refreshCodexUsageLimitPromptError({
|
|
4262
|
+
client: resourceState.client,
|
|
4263
|
+
message: enrichedPromptErrorMessage,
|
|
4264
|
+
timeoutMs: appServer.requestTimeoutMs,
|
|
4265
|
+
signal: runAbortController.signal
|
|
4266
|
+
});
|
|
4267
|
+
if (refreshedUsageLimitPromptError) {
|
|
4268
|
+
await markCodexAuthProfileBlockedFromRateLimits({
|
|
4269
|
+
params,
|
|
4270
|
+
authProfileId: startupAuthProfileId,
|
|
4271
|
+
rateLimits: refreshedUsageLimitPromptError.rateLimitsForProfile
|
|
4272
|
+
});
|
|
4273
|
+
enrichedPromptError = new CodexUsageLimitPromptError(refreshedUsageLimitPromptError.message);
|
|
4274
|
+
} else if (enrichedPromptError instanceof CodexUsageLimitPromptError && state.rateLimitsRevisionBeforeLastTurnStart !== void 0 && readCodexRateLimitsRevision(resourceState.client) > state.rateLimitsRevisionBeforeLastTurnStart) await markCodexAuthProfileBlockedFromRateLimits({
|
|
4275
|
+
params,
|
|
4276
|
+
authProfileId: startupAuthProfileId,
|
|
4277
|
+
rateLimits: readRecentCodexRateLimits(resourceState.client)
|
|
4278
|
+
});
|
|
4279
|
+
const projectTerminalOutcome = () => {
|
|
4280
|
+
const effectiveTimedOut = state.timeout !== void 0;
|
|
4281
|
+
const clientClosedPromptErrorForFinal = state.clientClosedPromptError;
|
|
4282
|
+
const finalPromptError = currentPromptError(enrichedPromptError);
|
|
4283
|
+
const finalPromptErrorSource = effectiveTimedOut || clientClosedPromptErrorForFinal ? "prompt" : projectedTerminal.promptErrorSource;
|
|
4284
|
+
const codexAppServerFailureKind = clientClosedPromptErrorForFinal ? "client_closed_before_turn_completed" : state.timeout?.kind === "settlement" ? "turn_settlement_timeout" : void 0;
|
|
4285
|
+
const replayBlockedReason = codexAppServerFailureKind ? resolveCodexAppServerReplayBlockedReason(result) : void 0;
|
|
4286
|
+
const promptTimeoutOutcome = buildCodexAppServerPromptTimeoutOutcome(state.timeout);
|
|
4287
|
+
const failureDiagnostics = codexAppServerFailureKind === "client_closed_before_turn_completed" && state.clientClosedDiagnostic ? { transportError: state.clientClosedDiagnostic } : state.timeout?.kind === "settlement" ? { timeoutMs: state.timeout.timeoutMs } : void 0;
|
|
4288
|
+
const codexAppServerFailure = codexAppServerFailureKind ? {
|
|
4289
|
+
kind: codexAppServerFailureKind,
|
|
4290
|
+
transport: appServer.start.transport,
|
|
4291
|
+
threadId: resourceState.thread.threadId,
|
|
4292
|
+
turnId: activeTurnId,
|
|
4293
|
+
replaySafe: codexAppServerFailureKind === "client_closed_before_turn_completed" && replayBlockedReason === void 0,
|
|
4294
|
+
...replayBlockedReason ? { replayBlockedReason } : {},
|
|
4295
|
+
...failureDiagnostics ? { diagnostics: failureDiagnostics } : {}
|
|
4296
|
+
} : void 0;
|
|
4297
|
+
const finalAborted = isFinalAborted();
|
|
4298
|
+
if (finalAborted && result.attemptUsage) result.attemptUsage = {
|
|
4299
|
+
...result.attemptUsage,
|
|
4300
|
+
contextUsage: { state: "unavailable" }
|
|
4301
|
+
};
|
|
4302
|
+
const completedTurnStatus = activeProjector.getCompletedTurnStatus();
|
|
4303
|
+
const locallyCompletedTurn = state.completed && state.localCompletionRequested && !state.timeout && clientClosedPromptErrorForFinal === void 0;
|
|
4304
|
+
const turnSucceeded = !finalAborted && !effectiveTimedOut && (finalPromptError === null || finalPromptError === void 0) && (completedTurnStatus === "completed" || locallyCompletedTurn);
|
|
4305
|
+
if (toolBridge.telemetry.messagingToolSentTargets.some((target) => target.sourceReplyFinal === true)) result.agentHarnessResultClassification = void 0;
|
|
4306
|
+
const attemptSucceeded = turnSucceeded && result.agentHarnessResultClassification === void 0;
|
|
4307
|
+
result.terminal = attemptTerminal.normalize({
|
|
4308
|
+
settlementWarning: state.settlementWarning,
|
|
4309
|
+
timedOut: effectiveTimedOut,
|
|
4310
|
+
aborted: finalAborted,
|
|
4311
|
+
promptError: finalPromptError,
|
|
4312
|
+
promptErrorSource: finalPromptErrorSource
|
|
4313
|
+
});
|
|
4314
|
+
for (const message of [
|
|
4315
|
+
result.lastAssistant,
|
|
4316
|
+
result.currentAttemptAssistant,
|
|
4317
|
+
result.messagesSnapshot.find((candidate) => readMirrorIdentity(candidate) === `${activeTurnId}:assistant`)
|
|
4318
|
+
]) if (message?.role === "assistant") {
|
|
4319
|
+
if (!message.diagnostics?.some((diagnostic) => diagnostic.type === "provider_refusal") || finalAborted || finalPromptError) {
|
|
4320
|
+
message.stopReason = finalAborted ? "aborted" : finalPromptError ? "error" : "stop";
|
|
4321
|
+
message.errorMessage = finalPromptError ? formatErrorMessage(finalPromptError) : void 0;
|
|
4322
|
+
}
|
|
4323
|
+
}
|
|
4324
|
+
return {
|
|
4325
|
+
effectiveTimedOut,
|
|
4326
|
+
finalPromptError,
|
|
4327
|
+
codexAppServerFailure,
|
|
4328
|
+
promptTimeoutOutcome,
|
|
4329
|
+
finalAborted,
|
|
4330
|
+
turnSucceeded,
|
|
4331
|
+
attemptSucceeded,
|
|
4332
|
+
completedTurnStatus
|
|
4333
|
+
};
|
|
4334
|
+
};
|
|
4335
|
+
projectTerminalOutcome();
|
|
4336
|
+
const unavailableMirror = {
|
|
4337
|
+
assistantTranscriptOwned: false,
|
|
4338
|
+
mirroredMessages: []
|
|
4339
|
+
};
|
|
4340
|
+
let mirrorOutcome = unavailableMirror;
|
|
4341
|
+
const mirrorFinal = () => {
|
|
4342
|
+
const warning = state.settlementWarning;
|
|
4343
|
+
const mirrorTerminal = projectTerminalOutcome();
|
|
4344
|
+
state.pendingSettlementStage = "transcript/mirror";
|
|
4345
|
+
return codexTranscriptMirrorRuntime.mirrorBestEffort({
|
|
4346
|
+
assertWriteCurrent: () => {
|
|
4347
|
+
if (settlementPhase !== "active" || state.settlementWarning !== warning) throw new Error("Codex transcript settlement is no longer active");
|
|
4348
|
+
const current = projectTerminalOutcome();
|
|
4349
|
+
if (current.finalAborted !== mirrorTerminal.finalAborted || current.effectiveTimedOut !== mirrorTerminal.effectiveTimedOut || current.finalPromptError !== mirrorTerminal.finalPromptError) throw new Error("Codex transcript terminal outcome changed before write");
|
|
4350
|
+
},
|
|
4351
|
+
params,
|
|
4352
|
+
settlementWarning: warning,
|
|
4353
|
+
agentId: sessionAgentId,
|
|
4354
|
+
notifyUserMessagePersisted,
|
|
4355
|
+
result,
|
|
4356
|
+
sessionKey: contextSessionKey,
|
|
4357
|
+
cwd: effectiveCwd,
|
|
4358
|
+
threadId: resourceState.thread.threadId,
|
|
4359
|
+
turnId: activeTurnId
|
|
4360
|
+
});
|
|
4361
|
+
};
|
|
4362
|
+
try {
|
|
4363
|
+
if (projectionDrained && settlementPhase === "active" && !state.settlementWarning) mirrorOutcome = await Promise.race([
|
|
4364
|
+
mirrorFinal(),
|
|
4365
|
+
drainGraceElapsed.promise.then(() => unavailableMirror),
|
|
4366
|
+
degradedSettlement.then(() => unavailableMirror)
|
|
4367
|
+
]);
|
|
4368
|
+
if (state.settlementWarning && !runAbortController.signal.aborted) {
|
|
4369
|
+
mirrorOutcome = await Promise.race([mirrorFinal(), drainGraceElapsed.promise.then(() => unavailableMirror)]);
|
|
4370
|
+
if (mirrorOutcome === unavailableMirror) trajectoryRecorder?.recordEvent("turn.settlement_persistence_unavailable", {
|
|
4371
|
+
pendingStage: "transcript/mirror",
|
|
4372
|
+
threadId: resourceState.thread.threadId,
|
|
4373
|
+
turnId: activeTurnId
|
|
4374
|
+
});
|
|
4375
|
+
}
|
|
4376
|
+
if (toolState.yieldMessage && projectTerminalOutcome().turnSucceeded) {
|
|
4377
|
+
state.pendingSettlementStage = "transcript/yield-context";
|
|
4378
|
+
await Promise.race([
|
|
4379
|
+
appendSessionYieldContext({
|
|
4380
|
+
...activeTranscriptTarget.sessionTarget,
|
|
4381
|
+
agentId: activeTranscriptTarget.agentId,
|
|
4382
|
+
sessionId: activeTranscriptTarget.sessionId,
|
|
4383
|
+
sessionKey: activeTranscriptTarget.sessionKey,
|
|
4384
|
+
config: params.config,
|
|
4385
|
+
message: toolState.yieldMessage,
|
|
4386
|
+
assertCurrent: () => {
|
|
4387
|
+
connection.assertCurrent();
|
|
4388
|
+
if (settlementPhase !== "active" || !projectTerminalOutcome().turnSucceeded) throw new Error("Codex yield settlement is no longer active");
|
|
4389
|
+
}
|
|
4390
|
+
}),
|
|
4391
|
+
drainGraceElapsed.promise,
|
|
4392
|
+
degradedSettlement
|
|
4393
|
+
]);
|
|
4394
|
+
}
|
|
4395
|
+
if (runAbortController.signal.aborted) await state.abortCleanup;
|
|
4396
|
+
} finally {
|
|
4397
|
+
closeSettlement();
|
|
4398
|
+
}
|
|
4399
|
+
const { effectiveTimedOut, finalPromptError, codexAppServerFailure, promptTimeoutOutcome, finalAborted, turnSucceeded, attemptSucceeded, completedTurnStatus } = projectTerminalOutcome();
|
|
4400
|
+
terminalState.settledTurnStatus = turnSucceeded ? "completed" : completedTurnStatus === "failed" && !finalAborted && !effectiveTimedOut && !state.clientClosedPromptError && !resourceState.executionDisconnectError ? "failed" : void 0;
|
|
4401
|
+
terminalState.sharedAbortAllowedAfterTerminalOutcome = shouldKeepCodexSharedAbortOpen({
|
|
4402
|
+
trigger: params.trigger,
|
|
4403
|
+
result,
|
|
4404
|
+
attemptSucceeded,
|
|
4405
|
+
explicitCancellationObserved: terminalState.explicitCancellationObserved
|
|
4406
|
+
});
|
|
4407
|
+
freezeRunTerminalOutcome();
|
|
4408
|
+
const modelCallFailureKind = classifyCodexModelCallFailureKind({
|
|
4409
|
+
error: finalPromptError,
|
|
4410
|
+
timedOut: effectiveTimedOut,
|
|
4411
|
+
runAborted: finalAborted,
|
|
4412
|
+
abortReason: terminalState.explicitCancellationReason ?? runAbortController.signal.reason,
|
|
4413
|
+
clientClosedAbort: state.clientClosedAbort,
|
|
4414
|
+
formatError: formatErrorMessage
|
|
4415
|
+
}) ?? (finalAborted ? "aborted" : void 0);
|
|
4416
|
+
if (modelCallFailureKind) codexModelCallDiagnostics.emitError(finalPromptError ?? "codex app-server attempt interrupted", { failureKind: modelCallFailureKind });
|
|
4417
|
+
else if (finalPromptError) codexModelCallDiagnostics.emitError(finalPromptError);
|
|
4418
|
+
else codexModelCallDiagnostics.emitCompleted(result);
|
|
4419
|
+
const { assistantTranscriptOwned, assistantTranscriptIdempotencyKey, terminalAnchor } = mirrorOutcome;
|
|
4420
|
+
const settledTurnFinalizationContext = result.assistantTexts.every((text) => !text.trim()) && result.messagesSnapshot.some((message) => message.role === "toolResult") && (!finalPromptError || activeProjector.settledTurnFailureFinalizationAllowed) ? (!usesSupervisionConnection ? await captureCodexSettledTurnFinalizationContext({
|
|
4421
|
+
...activeTranscriptTarget,
|
|
4422
|
+
model: resourceState.thread.model,
|
|
4423
|
+
modelProvider: resourceState.thread.modelProvider,
|
|
4424
|
+
authProfileId: startupAuthProfileId,
|
|
4425
|
+
mirroredMessages: mirrorOutcome.mirroredMessages,
|
|
4426
|
+
settledMessages: result.messagesSnapshot,
|
|
4427
|
+
turnId: activeTurnId,
|
|
4428
|
+
signal: params.abortSignal,
|
|
4429
|
+
assertActive: connection.assertCurrent
|
|
4430
|
+
}) : void 0) ?? Object.freeze({ source: "unavailable" }) : void 0;
|
|
4431
|
+
if (settledTurnFinalizationContext?.source === "unavailable") embeddedAgentLog.warn("codex settled-turn finalization context is unavailable", {
|
|
4432
|
+
runId: params.runId,
|
|
3994
4433
|
threadId: resourceState.thread.threadId,
|
|
3995
4434
|
turnId: activeTurnId,
|
|
3996
|
-
|
|
4435
|
+
reason: usesSupervisionConnection ? "native_auth_finalization_unsupported" : "context_unavailable"
|
|
3997
4436
|
});
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4437
|
+
runAgentHarnessLlmOutputHook({
|
|
4438
|
+
event: {
|
|
4439
|
+
runId: params.runId,
|
|
4440
|
+
sessionId: params.sessionId,
|
|
4441
|
+
provider: usesSupervisionConnection ? resourceState.thread.modelProvider ?? effectiveRuntimeProviderId : params.provider,
|
|
4442
|
+
model: usesSupervisionConnection ? resourceState.thread.model ?? effectiveRuntimeModelId : params.modelId,
|
|
4443
|
+
...hookContextWindowFields,
|
|
4444
|
+
resolvedRef: usesSupervisionConnection ? `${resourceState.thread.modelProvider ?? effectiveRuntimeProviderId}/${resourceState.thread.model ?? effectiveRuntimeModelId}` : params.runtimePlan?.observability.resolvedRef ?? `${params.provider}/${params.modelId}`,
|
|
4445
|
+
...!usesSupervisionConnection && params.runtimePlan?.observability.harnessId ? { harnessId: params.runtimePlan.observability.harnessId } : {},
|
|
4446
|
+
assistantTexts: result.assistantTexts,
|
|
4447
|
+
...result.lastAssistant ? { lastAssistant: result.lastAssistant } : {},
|
|
4448
|
+
...result.attemptUsage ? { usage: result.attemptUsage } : {}
|
|
4449
|
+
},
|
|
4450
|
+
ctx: hookContext,
|
|
4451
|
+
hookRunner
|
|
4001
4452
|
});
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4453
|
+
const providerRefusal = result.currentAttemptAssistant?.diagnostics?.some((diagnostic) => diagnostic.type === "provider_refusal");
|
|
4454
|
+
await runCodexAgentEndHook(params, {
|
|
4455
|
+
skillExperienceReviewSource: providerRefusal ? void 0 : terminalAnchor,
|
|
4456
|
+
event: {
|
|
4457
|
+
messages: result.messagesSnapshot,
|
|
4458
|
+
success: !finalAborted && !finalPromptError,
|
|
4459
|
+
...finalPromptError ? { error: formatErrorMessage(finalPromptError) } : {},
|
|
4460
|
+
durationMs: Date.now() - attemptStartedAt
|
|
4461
|
+
},
|
|
4462
|
+
ctx: {
|
|
4463
|
+
...hookContext,
|
|
4464
|
+
modelProviderId: resourceState.thread.modelProvider ?? effectiveRuntimeProviderId,
|
|
4465
|
+
modelId: resourceState.thread.model ?? effectiveRuntimeModelId,
|
|
4466
|
+
authProfileId: resourceState.thread.authProfileId ?? startupAuthProfileId,
|
|
4467
|
+
modelIterations: result.modelIterations ?? 0,
|
|
4468
|
+
skillWorkshopAvailable: flattenCodexDynamicToolFunctions(attemptTools.toolBridge.availableSpecs).some((tool) => tool.name === "skill_workshop"),
|
|
4469
|
+
compacted: (result.compactionCount ?? 0) > 0,
|
|
4470
|
+
senderId: params.senderId ?? void 0,
|
|
4471
|
+
foregroundPromptContext: buildEmbeddedForegroundPromptContext({
|
|
4472
|
+
...params,
|
|
4473
|
+
agentId: sessionAgentId
|
|
4474
|
+
}, agentDir)
|
|
4475
|
+
},
|
|
4476
|
+
hookRunner
|
|
4014
4477
|
});
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
authProfileId: startupAuthProfileId,
|
|
4019
|
-
rateLimits: readRecentCodexRateLimits(resourceState.client)
|
|
4020
|
-
});
|
|
4021
|
-
finalPromptError = resourceState.executionDisconnectError ?? finalPromptError;
|
|
4022
|
-
const finalPromptErrorSource = effectiveTimedOut || clientClosedPromptErrorForFinal ? "prompt" : projectedTerminal.promptErrorSource;
|
|
4023
|
-
const codexAppServerFailureKind = clientClosedPromptErrorForFinal ? "client_closed_before_turn_completed" : state.timeout?.kind === "settlement" ? "turn_settlement_timeout" : void 0;
|
|
4024
|
-
const replayBlockedReason = codexAppServerFailureKind ? resolveCodexAppServerReplayBlockedReason(result) : void 0;
|
|
4025
|
-
const promptTimeoutOutcome = buildCodexAppServerPromptTimeoutOutcome(state.timeout);
|
|
4026
|
-
const failureDiagnostics = codexAppServerFailureKind === "client_closed_before_turn_completed" && state.clientClosedDiagnostic ? { transportError: state.clientClosedDiagnostic } : state.timeout?.kind === "settlement" ? { timeoutMs: state.timeout.timeoutMs } : void 0;
|
|
4027
|
-
const codexAppServerFailure = codexAppServerFailureKind ? {
|
|
4028
|
-
kind: codexAppServerFailureKind,
|
|
4029
|
-
transport: appServer.start.transport,
|
|
4030
|
-
threadId: resourceState.thread.threadId,
|
|
4031
|
-
turnId: activeTurnId,
|
|
4032
|
-
replaySafe: codexAppServerFailureKind === "client_closed_before_turn_completed" && replayBlockedReason === void 0,
|
|
4033
|
-
...replayBlockedReason ? { replayBlockedReason } : {},
|
|
4034
|
-
...failureDiagnostics ? { diagnostics: failureDiagnostics } : {}
|
|
4035
|
-
} : void 0;
|
|
4036
|
-
const finalAborted = isFinalAborted();
|
|
4037
|
-
const completedTurnStatus = activeProjector.getCompletedTurnStatus();
|
|
4038
|
-
const locallyCompletedTurn = state.completed && state.localCompletionRequested && !state.timeout && clientClosedPromptErrorForFinal === void 0;
|
|
4039
|
-
const turnSucceeded = !finalAborted && !effectiveTimedOut && (finalPromptError === null || finalPromptError === void 0) && (completedTurnStatus === "completed" || locallyCompletedTurn);
|
|
4040
|
-
if (toolBridge.telemetry.messagingToolSentTargets.some((target) => target.sourceReplyFinal === true)) result.agentHarnessResultClassification = void 0;
|
|
4041
|
-
const attemptSucceeded = turnSucceeded && result.agentHarnessResultClassification === void 0;
|
|
4042
|
-
terminalState.turnSucceeded = turnSucceeded;
|
|
4043
|
-
terminalState.sharedAbortAllowedAfterTerminalOutcome = shouldKeepCodexSharedAbortOpen({
|
|
4044
|
-
trigger: params.trigger,
|
|
4045
|
-
result,
|
|
4046
|
-
attemptSucceeded,
|
|
4047
|
-
explicitCancellationObserved: terminalState.explicitCancellationObserved
|
|
4048
|
-
});
|
|
4049
|
-
freezeRunTerminalOutcome();
|
|
4050
|
-
const modelCallFailureKind = classifyCodexModelCallFailureKind({
|
|
4051
|
-
error: finalPromptError,
|
|
4052
|
-
timedOut: effectiveTimedOut,
|
|
4053
|
-
runAborted: finalAborted,
|
|
4054
|
-
abortReason: terminalState.explicitCancellationReason ?? runAbortController.signal.reason,
|
|
4055
|
-
clientClosedAbort: state.clientClosedAbort,
|
|
4056
|
-
formatError: formatErrorMessage
|
|
4057
|
-
}) ?? (finalAborted ? "aborted" : void 0);
|
|
4058
|
-
if (modelCallFailureKind) codexModelCallDiagnostics.emitError(finalPromptError ?? "codex app-server attempt interrupted", { failureKind: modelCallFailureKind });
|
|
4059
|
-
else if (finalPromptError) codexModelCallDiagnostics.emitError(finalPromptError);
|
|
4060
|
-
else codexModelCallDiagnostics.emitCompleted(result);
|
|
4061
|
-
const mirrorOutcome = await codexTranscriptMirrorRuntime.mirrorBestEffort({
|
|
4062
|
-
params,
|
|
4063
|
-
agentId: sessionAgentId,
|
|
4064
|
-
notifyUserMessagePersisted,
|
|
4065
|
-
result,
|
|
4066
|
-
sessionKey: contextSessionKey,
|
|
4067
|
-
cwd: effectiveCwd,
|
|
4068
|
-
threadId: resourceState.thread.threadId,
|
|
4069
|
-
turnId: activeTurnId
|
|
4070
|
-
});
|
|
4071
|
-
const { assistantTranscriptOwned, assistantTranscriptIdempotencyKey, terminalAnchor } = mirrorOutcome;
|
|
4072
|
-
const settledTurnFinalizationContext = result.assistantTexts.every((text) => !text.trim()) && result.messagesSnapshot.some((message) => message.role === "toolResult") && (!finalPromptError || activeProjector.settledTurnFailureFinalizationAllowed) ? await captureCodexSettledTurnFinalizationContext({
|
|
4073
|
-
...activeTranscriptTarget,
|
|
4074
|
-
mirroredMessages: mirrorOutcome.mirroredMessages,
|
|
4075
|
-
settledMessages: result.messagesSnapshot,
|
|
4076
|
-
turnId: activeTurnId
|
|
4077
|
-
}) ?? Object.freeze({ source: "unavailable" }) : void 0;
|
|
4078
|
-
if (settledTurnFinalizationContext?.source === "unavailable") embeddedAgentLog.warn("codex settled-turn finalization context is unavailable", {
|
|
4079
|
-
threadId: resourceState.thread.threadId,
|
|
4080
|
-
turnId: activeTurnId
|
|
4081
|
-
});
|
|
4082
|
-
runAgentHarnessLlmOutputHook({
|
|
4083
|
-
event: {
|
|
4084
|
-
runId: params.runId,
|
|
4085
|
-
sessionId: params.sessionId,
|
|
4086
|
-
provider: usesSupervisionConnection ? resourceState.thread.modelProvider ?? effectiveRuntimeProviderId : params.provider,
|
|
4087
|
-
model: usesSupervisionConnection ? resourceState.thread.model ?? effectiveRuntimeModelId : params.modelId,
|
|
4088
|
-
...hookContextWindowFields,
|
|
4089
|
-
resolvedRef: usesSupervisionConnection ? `${resourceState.thread.modelProvider ?? effectiveRuntimeProviderId}/${resourceState.thread.model ?? effectiveRuntimeModelId}` : params.runtimePlan?.observability.resolvedRef ?? `${params.provider}/${params.modelId}`,
|
|
4090
|
-
...!usesSupervisionConnection && params.runtimePlan?.observability.harnessId ? { harnessId: params.runtimePlan.observability.harnessId } : {},
|
|
4091
|
-
assistantTexts: result.assistantTexts,
|
|
4092
|
-
...result.lastAssistant ? { lastAssistant: result.lastAssistant } : {},
|
|
4093
|
-
...result.attemptUsage ? { usage: result.attemptUsage } : {}
|
|
4094
|
-
},
|
|
4095
|
-
ctx: hookContext,
|
|
4096
|
-
hookRunner
|
|
4097
|
-
});
|
|
4098
|
-
await runCodexAgentEndHook(params, {
|
|
4099
|
-
event: {
|
|
4100
|
-
messages: result.messagesSnapshot,
|
|
4101
|
-
success: !finalAborted && !finalPromptError,
|
|
4102
|
-
...finalPromptError ? { error: formatErrorMessage(finalPromptError) } : {},
|
|
4103
|
-
durationMs: Date.now() - attemptStartedAt
|
|
4104
|
-
},
|
|
4105
|
-
ctx: {
|
|
4106
|
-
...hookContext,
|
|
4107
|
-
modelProviderId: resourceState.thread.modelProvider ?? effectiveRuntimeProviderId,
|
|
4108
|
-
modelId: resourceState.thread.model ?? effectiveRuntimeModelId,
|
|
4109
|
-
authProfileId: resourceState.thread.authProfileId ?? startupAuthProfileId,
|
|
4110
|
-
modelIterations: result.modelIterations ?? 0,
|
|
4111
|
-
skillWorkshopAvailable: flattenCodexDynamicToolFunctions(attemptTools.toolBridge.availableSpecs).some((tool) => tool.name === "skill_workshop"),
|
|
4112
|
-
compacted: (result.compactionCount ?? 0) > 0,
|
|
4113
|
-
senderId: params.senderId ?? void 0,
|
|
4114
|
-
foregroundPromptContext: buildEmbeddedForegroundPromptContext({
|
|
4115
|
-
...params,
|
|
4116
|
-
agentId: sessionAgentId
|
|
4117
|
-
}, agentDir)
|
|
4118
|
-
},
|
|
4119
|
-
hookRunner
|
|
4120
|
-
});
|
|
4121
|
-
state.shouldDelayNativeHookRelayUnregister = completedTurnStatus === "completed" && !effectiveTimedOut && !runAbortController.signal.aborted && !finalAborted && !finalPromptError;
|
|
4122
|
-
if (state.shouldDelayNativeHookRelayUnregister) try {
|
|
4123
|
-
await markCodexAppServerBindingCoveredThroughTurn({
|
|
4124
|
-
bindingStore,
|
|
4125
|
-
identity: bindingIdentity,
|
|
4126
|
-
threadId: resourceState.thread.threadId,
|
|
4127
|
-
continuityCalibration: context.promptState.noEngineContinuityProjectionApplied ? buildCodexContinuityCalibration({
|
|
4478
|
+
state.shouldDelayNativeHookRelayUnregister = completedTurnStatus === "completed" && !effectiveTimedOut && !runAbortController.signal.aborted && !finalAborted && !finalPromptError;
|
|
4479
|
+
if (state.shouldDelayNativeHookRelayUnregister) try {
|
|
4480
|
+
const continuityCalibration = context.promptState.noEngineContinuityProjectionApplied ? buildCodexContinuityCalibration({
|
|
4128
4481
|
promptChars: prompt.turnState.codexTurnPromptText.length,
|
|
4129
|
-
inputTokens:
|
|
4130
|
-
}) : void 0
|
|
4482
|
+
inputTokens: result.attemptUsage?.contextUsage?.state === "available" ? result.attemptUsage.contextUsage.promptTokens ?? 0 : 0
|
|
4483
|
+
}) : void 0;
|
|
4484
|
+
await bindingStore.mutate(bindingIdentity, {
|
|
4485
|
+
kind: "patch",
|
|
4486
|
+
threadId: resourceState.thread.threadId,
|
|
4487
|
+
patch: {
|
|
4488
|
+
historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4489
|
+
...continuityCalibration ? { continuityCalibration } : {}
|
|
4490
|
+
}
|
|
4491
|
+
}, connection.assertCurrent);
|
|
4492
|
+
} catch (error) {
|
|
4493
|
+
if (resourceState.thread.connectionScope === "supervision") throw error;
|
|
4494
|
+
if (canClearBindingForRecovery("clearing native coverage after a completed turn")) {
|
|
4495
|
+
if (!await bindingStore.mutate(bindingIdentity, {
|
|
4496
|
+
kind: "clear",
|
|
4497
|
+
threadId: resourceState.thread.threadId
|
|
4498
|
+
}, connection.assertCurrent)) throw error;
|
|
4499
|
+
embeddedAgentLog.warn("codex app-server binding coverage update failed after completed turn; cleared stale binding", {
|
|
4500
|
+
threadId: resourceState.thread.threadId,
|
|
4501
|
+
turnId: activeTurnId,
|
|
4502
|
+
error
|
|
4503
|
+
});
|
|
4504
|
+
}
|
|
4505
|
+
}
|
|
4506
|
+
recordCodexTrajectoryCompletion(trajectoryRecorder, {
|
|
4507
|
+
attempt: params,
|
|
4508
|
+
result,
|
|
4509
|
+
threadId: resourceState.thread.threadId,
|
|
4510
|
+
turnId: activeTurnId,
|
|
4511
|
+
timedOut: effectiveTimedOut,
|
|
4512
|
+
yieldDetected: toolState.yieldDetected
|
|
4131
4513
|
});
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
if (!await bindingStore.mutate(bindingIdentity, {
|
|
4135
|
-
kind: "clear",
|
|
4136
|
-
threadId: resourceState.thread.threadId
|
|
4137
|
-
})) throw error;
|
|
4138
|
-
embeddedAgentLog.warn("codex app-server binding coverage update failed after completed turn; cleared stale binding", {
|
|
4514
|
+
trajectoryRecorder?.recordEvent("session.ended", {
|
|
4515
|
+
status: finalPromptError ? "error" : finalAborted || effectiveTimedOut ? "interrupted" : "success",
|
|
4139
4516
|
threadId: resourceState.thread.threadId,
|
|
4140
4517
|
turnId: activeTurnId,
|
|
4141
|
-
|
|
4518
|
+
timedOut: effectiveTimedOut,
|
|
4519
|
+
yieldDetected: toolState.yieldDetected,
|
|
4520
|
+
promptError: normalizeCodexTrajectoryError(finalPromptError)
|
|
4521
|
+
});
|
|
4522
|
+
markTrajectoryEndRecorded();
|
|
4523
|
+
const terminalAssistantText = collectTerminalAssistantText(result);
|
|
4524
|
+
if (terminalAssistantText && (!streamState.eventEmitted || streamState.needsTerminalSnapshot) && !finalAborted && !finalPromptError) emitCodexAppServerEvent(params, {
|
|
4525
|
+
stream: "assistant",
|
|
4526
|
+
data: { text: terminalAssistantText }
|
|
4527
|
+
});
|
|
4528
|
+
emitLifecycleTerminal(finalPromptError ? {
|
|
4529
|
+
phase: "error",
|
|
4530
|
+
error: formatErrorMessage(finalPromptError),
|
|
4531
|
+
...buildLifecycleTerminalMeta({
|
|
4532
|
+
aborted: finalAborted,
|
|
4533
|
+
timedOut: effectiveTimedOut
|
|
4534
|
+
})
|
|
4535
|
+
} : {
|
|
4536
|
+
phase: "end",
|
|
4537
|
+
...buildLifecycleTerminalMeta({
|
|
4538
|
+
aborted: finalAborted,
|
|
4539
|
+
timedOut: effectiveTimedOut,
|
|
4540
|
+
yielded: toolState.yieldDetected
|
|
4541
|
+
})
|
|
4142
4542
|
});
|
|
4543
|
+
const finalizedResult = Object.assign(result, {
|
|
4544
|
+
...runtimeModelSelection ? { runtimeModelSelection } : {},
|
|
4545
|
+
...toolState.yieldAcknowledgment ? { yieldAcknowledgment: toolState.yieldAcknowledgment } : {},
|
|
4546
|
+
...codexAppServerFailure ? { codexAppServerFailure } : {},
|
|
4547
|
+
...promptTimeoutOutcome ? { promptTimeoutOutcome } : {},
|
|
4548
|
+
...assistantTranscriptOwned ? { assistantTranscriptOwned: true } : {},
|
|
4549
|
+
...assistantTranscriptIdempotencyKey ? { assistantTranscriptIdempotencyKey } : {},
|
|
4550
|
+
...terminalAnchor ? { contextEngineTerminalAnchor: terminalAnchor } : {},
|
|
4551
|
+
...settledTurnFinalizationContext ? { settledTurnFinalizationContext } : {},
|
|
4552
|
+
...resourceState.runtimeArtifact ? { runtimeArtifact: resourceState.runtimeArtifact } : {},
|
|
4553
|
+
...resourceState.runtimeContinuationStarted ? { runtimeContinuationStarted: true } : {},
|
|
4554
|
+
...!finalAborted && !effectiveTimedOut && !finalPromptError && preparedAuthBinding ? { authBindingFingerprint: preparedAuthBinding.fingerprint } : {},
|
|
4555
|
+
systemPromptReport
|
|
4556
|
+
});
|
|
4557
|
+
if (turnSucceeded && toolState.yieldDetected && !runAbortController.signal.aborted) resourceState.nativeHookRelay?.authorizeRetentionAfterSuccessfulYield();
|
|
4558
|
+
return finalizedResult;
|
|
4559
|
+
} finally {
|
|
4560
|
+
closeSettlement();
|
|
4143
4561
|
}
|
|
4144
|
-
recordCodexTrajectoryCompletion(trajectoryRecorder, {
|
|
4145
|
-
attempt: params,
|
|
4146
|
-
result,
|
|
4147
|
-
threadId: resourceState.thread.threadId,
|
|
4148
|
-
turnId: activeTurnId,
|
|
4149
|
-
timedOut: effectiveTimedOut,
|
|
4150
|
-
yieldDetected: toolState.yieldDetected
|
|
4151
|
-
});
|
|
4152
|
-
trajectoryRecorder?.recordEvent("session.ended", {
|
|
4153
|
-
status: finalPromptError ? "error" : finalAborted || effectiveTimedOut ? "interrupted" : "success",
|
|
4154
|
-
threadId: resourceState.thread.threadId,
|
|
4155
|
-
turnId: activeTurnId,
|
|
4156
|
-
timedOut: effectiveTimedOut,
|
|
4157
|
-
yieldDetected: toolState.yieldDetected,
|
|
4158
|
-
promptError: normalizeCodexTrajectoryError(finalPromptError)
|
|
4159
|
-
});
|
|
4160
|
-
markTrajectoryEndRecorded();
|
|
4161
|
-
const terminalAssistantText = collectTerminalAssistantText(result);
|
|
4162
|
-
if (terminalAssistantText && (!streamState.eventEmitted || streamState.needsTerminalSnapshot) && !finalAborted && !finalPromptError) emitCodexAppServerEvent(params, {
|
|
4163
|
-
stream: "assistant",
|
|
4164
|
-
data: { text: terminalAssistantText }
|
|
4165
|
-
});
|
|
4166
|
-
emitLifecycleTerminal(finalPromptError ? {
|
|
4167
|
-
phase: "error",
|
|
4168
|
-
error: formatErrorMessage(finalPromptError),
|
|
4169
|
-
...buildLifecycleTerminalMeta({
|
|
4170
|
-
aborted: finalAborted,
|
|
4171
|
-
timedOut: effectiveTimedOut
|
|
4172
|
-
})
|
|
4173
|
-
} : {
|
|
4174
|
-
phase: "end",
|
|
4175
|
-
...buildLifecycleTerminalMeta({
|
|
4176
|
-
aborted: finalAborted,
|
|
4177
|
-
timedOut: effectiveTimedOut,
|
|
4178
|
-
yielded: toolState.yieldDetected
|
|
4179
|
-
})
|
|
4180
|
-
});
|
|
4181
|
-
const finalizedResult = Object.assign(result, {
|
|
4182
|
-
...toolState.yieldAcknowledgment ? { yieldAcknowledgment: toolState.yieldAcknowledgment } : {},
|
|
4183
|
-
terminal: attemptTerminal.normalize({
|
|
4184
|
-
timedOut: effectiveTimedOut,
|
|
4185
|
-
aborted: finalAborted,
|
|
4186
|
-
promptError: finalPromptError,
|
|
4187
|
-
promptErrorSource: finalPromptErrorSource
|
|
4188
|
-
}),
|
|
4189
|
-
...codexAppServerFailure ? { codexAppServerFailure } : {},
|
|
4190
|
-
...promptTimeoutOutcome ? { promptTimeoutOutcome } : {},
|
|
4191
|
-
...assistantTranscriptOwned ? { assistantTranscriptOwned: true } : {},
|
|
4192
|
-
...assistantTranscriptIdempotencyKey ? { assistantTranscriptIdempotencyKey } : {},
|
|
4193
|
-
...terminalAnchor ? { contextEngineTerminalAnchor: terminalAnchor } : {},
|
|
4194
|
-
...settledTurnFinalizationContext ? { settledTurnFinalizationContext } : {},
|
|
4195
|
-
...resourceState.runtimeArtifact ? { runtimeArtifact: resourceState.runtimeArtifact } : {},
|
|
4196
|
-
...resourceState.runtimeContinuationStarted ? { runtimeContinuationStarted: true } : {},
|
|
4197
|
-
...!finalAborted && !effectiveTimedOut && !finalPromptError && preparedAuthBinding ? { authBindingFingerprint: preparedAuthBinding.fingerprint } : {},
|
|
4198
|
-
systemPromptReport
|
|
4199
|
-
});
|
|
4200
|
-
if (turnSucceeded && toolState.yieldDetected && !runAbortController.signal.aborted) resourceState.nativeHookRelay?.authorizeRetentionAfterSuccessfulYield();
|
|
4201
|
-
return finalizedResult;
|
|
4202
4562
|
}
|
|
4203
4563
|
//#endregion
|
|
4204
4564
|
//#region extensions/codex/src/app-server/attempt-notification-state.ts
|
|
@@ -4422,7 +4782,7 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
4422
4782
|
const { attemptTools, runtime } = context;
|
|
4423
4783
|
const { appServer, runAbortController } = runtime.connection;
|
|
4424
4784
|
const { allocateCodexToolOutcomeOrdinal } = attemptTools;
|
|
4425
|
-
const { state, turnIdRef, userInputBridgeRef, steeringQueueRef, activeTurnItemIds, pendingOpenClawDynamicToolCompletionIds, completeTurn, noteProgress, deadlines } = turnRuntime;
|
|
4785
|
+
const { state, turnIdRef, userInputBridgeRef, steeringQueueRef, activeTurnItemIds, pendingOpenClawDynamicToolCompletionIds, openClawDynamicToolExecutions, completeTurn, noteProgress, deadlines } = turnRuntime;
|
|
4426
4786
|
const { scheduleTerminalDynamicToolReleaseCheck, reportExecutionNotification, maybeAnnounceFastModeAutoOff } = lifecycle;
|
|
4427
4787
|
const isTerminalTurnNotificationForTurn = (notification, notificationTurnId) => isTerminalCodexTurnNotificationForTurn({
|
|
4428
4788
|
notification,
|
|
@@ -4457,7 +4817,15 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
4457
4817
|
if (notification.method === "item/completed") {
|
|
4458
4818
|
if (activeTurnItemIds.size === 0) scheduleTerminalDynamicToolReleaseCheck();
|
|
4459
4819
|
const item = readCodexNotificationItem(notification.params);
|
|
4460
|
-
if (item?.type === "
|
|
4820
|
+
if (item?.type === "dynamicToolCall" && typeof item.id === "string") {
|
|
4821
|
+
const response = await openClawDynamicToolExecutions.get({
|
|
4822
|
+
threadId: resourceState.thread.threadId,
|
|
4823
|
+
turnId,
|
|
4824
|
+
callId: item.id
|
|
4825
|
+
});
|
|
4826
|
+
if (response && !state.projectionClosed && !runAbortController.signal.aborted && turnIdRef.current === turnId && item.success === response.success && isDeepStrictEqual(item.contentItems, response.contentItems)) acknowledgeInternalToolResult(response);
|
|
4827
|
+
}
|
|
4828
|
+
if (item?.type === "userMessage" && typeof item.clientId === "string") steeringQueueRef.current?.confirmConsumed(item.clientId);
|
|
4461
4829
|
}
|
|
4462
4830
|
if (isCodexTurnAbortMarkerNotification(notification, { currentPromptTexts: [turnState.codexTurnPromptText] })) state.sawCodexInterruptMarker = true;
|
|
4463
4831
|
}
|
|
@@ -4498,6 +4866,8 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
4498
4866
|
if (!projector || !turnId || state.projectionClosed) return;
|
|
4499
4867
|
projector.recordMcpToolCallReceipt(notification);
|
|
4500
4868
|
if (isTerminalTurnNotificationForTurn(notification, turnId)) {
|
|
4869
|
+
const completed = readCodexTurnCompletedNotification(notification.params);
|
|
4870
|
+
if (completed) projector.settlement.terminalReceipt = completed.turn;
|
|
4501
4871
|
state.terminalTurnNotificationQueued = true;
|
|
4502
4872
|
steeringQueueRef.current?.sealAdmission();
|
|
4503
4873
|
deadlines.beginSettlement(receivedAtMs);
|
|
@@ -4506,7 +4876,10 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
4506
4876
|
const modelToolCallId = readRawResponseToolCallId(notification);
|
|
4507
4877
|
if (modelToolCallId) allocateCodexToolOutcomeOrdinal?.(modelToolCallId);
|
|
4508
4878
|
const nativeItem = readCodexNotificationItem(notification.params);
|
|
4509
|
-
if (nativeItem?.type === "webSearch")
|
|
4879
|
+
if (nativeItem?.type === "webSearch") {
|
|
4880
|
+
projector.settlement.turnTainted ||= notification.method === "item/completed";
|
|
4881
|
+
projector.recordNativeToolOutcome(nativeItem);
|
|
4882
|
+
}
|
|
4510
4883
|
}
|
|
4511
4884
|
};
|
|
4512
4885
|
const enqueueNotification = async (notification, scope) => {
|
|
@@ -4533,17 +4906,47 @@ function isRestrictivePromptToolsAllow(toolsAllow) {
|
|
|
4533
4906
|
return toolsAllow !== void 0 && !toolsAllow.some((name) => name.trim() === "*");
|
|
4534
4907
|
}
|
|
4535
4908
|
async function prepareCodexAttemptPrompt(context) {
|
|
4536
|
-
const { runtime, attemptTools, historyState, hookContext, workspaceBootstrapContext, buildActiveContextEngineRuntimeContext, baseDeveloperInstructions,
|
|
4909
|
+
const { runtime, attemptTools, historyState, hookContext, workspaceBootstrapContext, buildActiveContextEngineRuntimeContext, baseDeveloperInstructions, buildOpenClawPromptContext, skillsCollaborationInstructions, promptState, codexContextProjectionMaxChars, codexContinuityProjectionMaxChars } = context;
|
|
4537
4910
|
const { connection, buildActiveRunAttemptParams, effectiveContextTokenBudget, effectiveRuntimeModelId, effectiveRuntimeProviderId } = runtime;
|
|
4538
4911
|
const { params, activeContextEngine, usesSupervisionConnection, mutable, isInactiveThreadBootstrapBinding, bindingStore, bindingIdentity, agentDir, appServer, contextSessionKey, effectiveWorkspace, sandbox } = connection;
|
|
4539
4912
|
const { toolBridge } = attemptTools;
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4913
|
+
let contextImages = [];
|
|
4914
|
+
const currentUserTurnIdempotencyKey = params.userTurnTranscriptRecorder?.message?.idempotencyKey;
|
|
4915
|
+
const assertProjectionCurrent = () => {
|
|
4916
|
+
params.hostCapabilities.assertActive();
|
|
4917
|
+
connection.assertCurrent();
|
|
4918
|
+
connection.runAbortController.signal.throwIfAborted();
|
|
4919
|
+
};
|
|
4920
|
+
const prepareFileContext = async (message, maxChars) => {
|
|
4921
|
+
const prepare = params.hostCapabilities.prepareContextMedia;
|
|
4922
|
+
if (!prepare) {
|
|
4923
|
+
const media = asOptionalRecord(Reflect.get(message, "__openclaw"))?.media;
|
|
4924
|
+
if (Array.isArray(media) && media.length || message.role === "user" && Array.isArray(message.content) && message.content.some((part) => part.type === "image")) throw new CodexContextAttachmentError("Saved attachments require a newer OpenClaw host. Update the Gateway and Codex plugin together, then retry.");
|
|
4925
|
+
return { images: [] };
|
|
4926
|
+
}
|
|
4927
|
+
try {
|
|
4928
|
+
const files = await prepare({
|
|
4929
|
+
message,
|
|
4930
|
+
maxChars
|
|
4931
|
+
});
|
|
4932
|
+
assertProjectionCurrent();
|
|
4933
|
+
return files;
|
|
4934
|
+
} catch (error) {
|
|
4935
|
+
assertProjectionCurrent();
|
|
4936
|
+
throw new CodexContextAttachmentError("Saved attachment preparation failed. Retry the request after checking the attachment source.", { cause: error });
|
|
4937
|
+
}
|
|
4938
|
+
};
|
|
4939
|
+
const applyContinuityProjection = async (messages) => {
|
|
4940
|
+
const projection = await projectContextEngineAssemblyForCodex({
|
|
4941
|
+
assembledMessages: messages,
|
|
4543
4942
|
originalHistoryMessages: historyState.messages,
|
|
4544
4943
|
prompt: params.prompt,
|
|
4545
|
-
maxRenderedContextChars: codexContinuityProjectionMaxChars
|
|
4944
|
+
maxRenderedContextChars: codexContinuityProjectionMaxChars,
|
|
4945
|
+
prepareFileContext,
|
|
4946
|
+
currentUserTurnIdempotencyKey
|
|
4546
4947
|
});
|
|
4948
|
+
assertProjectionCurrent();
|
|
4949
|
+
contextImages = projection.images ?? [];
|
|
4547
4950
|
promptState.promptText = projection.promptText;
|
|
4548
4951
|
promptState.promptContextRange = projection.promptContextRange;
|
|
4549
4952
|
promptState.prePromptMessageCount = projection.prePromptMessageCount;
|
|
@@ -4572,14 +4975,6 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4572
4975
|
});
|
|
4573
4976
|
if (!assembled) throw new Error("context engine assemble returned no result");
|
|
4574
4977
|
const contextEngineProjection = readContextEngineThreadBootstrapProjection(assembled.contextProjection);
|
|
4575
|
-
const projection = projectContextEngineAssemblyForCodex({
|
|
4576
|
-
assembledMessages: assembled.messages,
|
|
4577
|
-
originalHistoryMessages: historyState.messages,
|
|
4578
|
-
prompt: params.prompt,
|
|
4579
|
-
systemPromptAddition: assembled.systemPromptAddition,
|
|
4580
|
-
maxRenderedContextChars: codexContextProjectionMaxChars,
|
|
4581
|
-
toolPayloadMode: contextEngineProjection ? "preserve" : "elide"
|
|
4582
|
-
});
|
|
4583
4978
|
const projectionDecision = contextEngineProjection ? resolveContextEngineBootstrapProjectionDecision({
|
|
4584
4979
|
startupBinding: decisionStartupBinding,
|
|
4585
4980
|
expectedBinding: buildContextEngineBinding(buildActiveRunAttemptParams(), contextEngineProjection),
|
|
@@ -4590,6 +4985,18 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4590
4985
|
project: true,
|
|
4591
4986
|
reason: "per-turn-projection"
|
|
4592
4987
|
};
|
|
4988
|
+
const projection = await projectContextEngineAssemblyForCodex({
|
|
4989
|
+
assembledMessages: assembled.messages,
|
|
4990
|
+
originalHistoryMessages: historyState.messages,
|
|
4991
|
+
prompt: params.prompt,
|
|
4992
|
+
systemPromptAddition: assembled.systemPromptAddition,
|
|
4993
|
+
maxRenderedContextChars: codexContextProjectionMaxChars,
|
|
4994
|
+
toolPayloadMode: contextEngineProjection ? "preserve" : "elide",
|
|
4995
|
+
...projectionDecision.project ? { prepareFileContext } : {},
|
|
4996
|
+
currentUserTurnIdempotencyKey
|
|
4997
|
+
});
|
|
4998
|
+
assertProjectionCurrent();
|
|
4999
|
+
contextImages = projectionDecision.project ? projection.images ?? [] : [];
|
|
4593
5000
|
const decisionBinding = decisionStartupBinding;
|
|
4594
5001
|
embeddedAgentLog.info("codex app-server context-engine projection decision", {
|
|
4595
5002
|
sessionId: params.sessionId,
|
|
@@ -4617,6 +5024,8 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4617
5024
|
if (activeContextEngine) try {
|
|
4618
5025
|
await applyActiveContextEngineProjection(runtime.nativeToolSurfaceEnabled ? mutable.startupBinding : void 0);
|
|
4619
5026
|
} catch (assembleErr) {
|
|
5027
|
+
if (assembleErr instanceof CodexContextAttachmentError) throw assembleErr;
|
|
5028
|
+
assertProjectionCurrent();
|
|
4620
5029
|
embeddedAgentLog.warn("context engine assemble failed; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
|
|
4621
5030
|
}
|
|
4622
5031
|
const codexModelInputHistoryMessages = [];
|
|
@@ -4633,7 +5042,7 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4633
5042
|
toolAuthority: {
|
|
4634
5043
|
fingerprint: params.toolAuthorityFingerprint,
|
|
4635
5044
|
activeToolNames: () => flattenCodexDynamicToolFunctions(toolBridge.availableSpecs).map((tool) => tool.name).filter(isNonEmptyString),
|
|
4636
|
-
assertActive:
|
|
5045
|
+
assertActive: connection.assertCurrent
|
|
4637
5046
|
}
|
|
4638
5047
|
});
|
|
4639
5048
|
};
|
|
@@ -4663,8 +5072,8 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4663
5072
|
}
|
|
4664
5073
|
};
|
|
4665
5074
|
};
|
|
4666
|
-
const decorateCodexTurnPromptText = (promptBuildResult) => {
|
|
4667
|
-
const turnPromptText = prependCodexOpenClawPromptContext(promptBuildResult.prompt,
|
|
5075
|
+
const decorateCodexTurnPromptText = (promptBuildResult, includeWorkspaceReferences = true) => {
|
|
5076
|
+
const turnPromptText = prependCodexOpenClawPromptContext(promptBuildResult.prompt, buildOpenClawPromptContext(includeWorkspaceReferences), { preservePromptWithoutContext: params.bootstrapContextMode === "lightweight" && params.bootstrapContextRunKind === "cron" });
|
|
4668
5077
|
const projectedRanges = resolveShiftedPromptContextRange(promptBuildResult.prompt, promptBuildResult.promptInputRange, turnPromptText);
|
|
4669
5078
|
const preservedRange = resolveShiftedPromptInputRange(promptBuildResult.prompt, promptBuildResult.promptInputRange, turnPromptText) ?? resolveCodexDeliveryHintPreservedInputRange({
|
|
4670
5079
|
prompt: promptBuildResult.prompt,
|
|
@@ -4704,28 +5113,19 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4704
5113
|
const selectNewerVisibleHistoryAfterBinding = (binding) => {
|
|
4705
5114
|
const cutoff = Date.parse(binding.historyCoveredThrough ?? "");
|
|
4706
5115
|
return historyState.messages.filter((message) => {
|
|
4707
|
-
if (message.role !== "user" && message.role !== "assistant") return false;
|
|
5116
|
+
if (message.role !== "user" && message.role !== "assistant" && !isCodexDurableCustomMessage(message)) return false;
|
|
4708
5117
|
const mirrorIdentity = readMirrorIdentity(message);
|
|
4709
5118
|
const timestamp = typeof message.timestamp === "number" ? message.timestamp : typeof message.timestamp === "string" ? Date.parse(message.timestamp) : NaN;
|
|
4710
5119
|
return !("idempotencyKey" in message && typeof message.idempotencyKey === "string" && message.idempotencyKey.startsWith("codex-app-server:")) && !hasCodexMirrorOrigin(message) && !mirrorIdentity?.startsWith("codex-app-server:") && Number.isFinite(timestamp) && timestamp > (Number.isFinite(cutoff) ? cutoff : 0);
|
|
4711
5120
|
});
|
|
4712
5121
|
};
|
|
4713
|
-
const applyResumeStaleBindingContinuityProjection = (binding) => {
|
|
5122
|
+
const applyResumeStaleBindingContinuityProjection = async (binding) => {
|
|
4714
5123
|
const newerVisibleMessages = selectNewerVisibleHistoryAfterBinding(binding);
|
|
4715
5124
|
if (newerVisibleMessages.length === 0) return false;
|
|
4716
|
-
|
|
4717
|
-
assembledMessages: newerVisibleMessages,
|
|
4718
|
-
originalHistoryMessages: historyState.messages,
|
|
4719
|
-
prompt: params.prompt,
|
|
4720
|
-
maxRenderedContextChars: codexContinuityProjectionMaxChars
|
|
4721
|
-
});
|
|
4722
|
-
promptState.promptText = projection.promptText;
|
|
4723
|
-
promptState.promptContextRange = projection.promptContextRange;
|
|
4724
|
-
promptState.prePromptMessageCount = projection.prePromptMessageCount;
|
|
4725
|
-
promptState.noEngineContinuityProjectionApplied = true;
|
|
5125
|
+
await applyContinuityProjection(newerVisibleMessages);
|
|
4726
5126
|
return true;
|
|
4727
5127
|
};
|
|
4728
|
-
const precomputeNoContextEngineStaleBindingProjection = () => {
|
|
5128
|
+
const precomputeNoContextEngineStaleBindingProjection = async () => {
|
|
4729
5129
|
promptState.precomputedStaleBindingContinuityProjectionApplied = false;
|
|
4730
5130
|
promptState.staleBindingContinuityForcedFreshStart = false;
|
|
4731
5131
|
const binding = mutable.startupBinding;
|
|
@@ -4734,30 +5134,31 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4734
5134
|
promptState.inactiveThreadBootstrapBindingForcedFreshStart = true;
|
|
4735
5135
|
return false;
|
|
4736
5136
|
}
|
|
4737
|
-
const projected = applyResumeStaleBindingContinuityProjection(binding);
|
|
5137
|
+
const projected = await applyResumeStaleBindingContinuityProjection(binding);
|
|
4738
5138
|
promptState.precomputedStaleBindingContinuityProjectionApplied = projected;
|
|
4739
5139
|
return projected;
|
|
4740
5140
|
};
|
|
4741
|
-
const applyNoContextEngineContinuityProjection = (action, binding) => {
|
|
4742
|
-
const hasContinuity = historyState.messages.some((message) => message.role === "user" || action === "started" && (message.role === "compactionSummary" || message.role === "branchSummary"));
|
|
5141
|
+
const applyNoContextEngineContinuityProjection = async (action, binding) => {
|
|
5142
|
+
const hasContinuity = historyState.messages.some((message) => message.role === "user" || isCodexDurableCustomMessage(message) || action === "started" && (message.role === "compactionSummary" || message.role === "branchSummary"));
|
|
4743
5143
|
if (activeContextEngine || !hasContinuity) return false;
|
|
4744
5144
|
if (action === "resumed" && promptState.precomputedStaleBindingContinuityProjectionApplied) return true;
|
|
4745
5145
|
if (action === "started" && promptState.staleBindingContinuityForcedFreshStart) return true;
|
|
4746
5146
|
if (action === "started" && promptState.inactiveThreadBootstrapBindingForcedFreshStart) return false;
|
|
4747
5147
|
if (action === "resumed" && binding) return applyResumeStaleBindingContinuityProjection(binding);
|
|
4748
5148
|
if (action === "started") {
|
|
4749
|
-
|
|
5149
|
+
await applyContinuityProjection(historyState.messages);
|
|
4750
5150
|
return true;
|
|
4751
5151
|
}
|
|
4752
5152
|
return false;
|
|
4753
5153
|
};
|
|
4754
|
-
if (precomputeNoContextEngineStaleBindingProjection()) await rebuildCodexPromptBuildFromCurrentProjection();
|
|
5154
|
+
if (await precomputeNoContextEngineStaleBindingProjection()) await rebuildCodexPromptBuildFromCurrentProjection();
|
|
4755
5155
|
const rotateStartupBindingForProjectedTurn = async () => {
|
|
4756
5156
|
const binding = mutable.startupBinding;
|
|
4757
5157
|
if (!binding?.threadId) return;
|
|
4758
5158
|
const previousThreadId = binding.threadId;
|
|
4759
5159
|
const hadInactiveThreadBootstrapBinding = isInactiveThreadBootstrapBinding(binding);
|
|
4760
5160
|
const startupBindingResolution = await rotateOversizedCodexAppServerStartupBinding({
|
|
5161
|
+
assertCurrent: connection.assertCurrent,
|
|
4761
5162
|
binding,
|
|
4762
5163
|
bindingStore,
|
|
4763
5164
|
identity: bindingIdentity,
|
|
@@ -4766,6 +5167,7 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4766
5167
|
codexHome: appServer.start.env?.CODEX_HOME,
|
|
4767
5168
|
config: params.config,
|
|
4768
5169
|
contextEngineActive: Boolean(activeContextEngine),
|
|
5170
|
+
expectedSessionRuntimeOwnership: params.expectedSessionRuntimeOwnership,
|
|
4769
5171
|
projectedTurnTokens: estimateCodexAppServerProjectedTurnTokens({
|
|
4770
5172
|
prompt: turnState.codexTurnPromptText,
|
|
4771
5173
|
developerInstructions: buildRenderedCodexDeveloperInstructions()
|
|
@@ -4776,12 +5178,14 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4776
5178
|
if (mutable.startupBinding?.threadId) return;
|
|
4777
5179
|
promptState.inactiveThreadBootstrapBindingForcedFreshStart = hadInactiveThreadBootstrapBinding;
|
|
4778
5180
|
promptState.staleBindingContinuityForcedFreshStart = promptState.precomputedStaleBindingContinuityProjectionApplied && !promptState.inactiveThreadBootstrapBindingForcedFreshStart;
|
|
4779
|
-
if (promptState.staleBindingContinuityForcedFreshStart)
|
|
5181
|
+
if (promptState.staleBindingContinuityForcedFreshStart) await applyContinuityProjection(historyState.messages);
|
|
4780
5182
|
if (activeContextEngine) {
|
|
4781
5183
|
promptState.contextEngineProjection = void 0;
|
|
4782
5184
|
try {
|
|
4783
5185
|
await applyActiveContextEngineProjection(void 0);
|
|
4784
5186
|
} catch (assembleErr) {
|
|
5187
|
+
if (assembleErr instanceof CodexContextAttachmentError) throw assembleErr;
|
|
5188
|
+
assertProjectionCurrent();
|
|
4785
5189
|
embeddedAgentLog.warn("context engine assemble failed; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
|
|
4786
5190
|
}
|
|
4787
5191
|
}
|
|
@@ -4795,22 +5199,36 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4795
5199
|
});
|
|
4796
5200
|
};
|
|
4797
5201
|
await rotateStartupBindingForProjectedTurn();
|
|
5202
|
+
const buildSystemPromptReport = (omitWorkspaceReferences = false) => buildCodexSystemPromptReport({
|
|
5203
|
+
attempt: params,
|
|
5204
|
+
sessionKey: contextSessionKey,
|
|
5205
|
+
workspaceDir: effectiveWorkspace,
|
|
5206
|
+
developerInstructions: buildRenderedCodexDeveloperInstructions(),
|
|
5207
|
+
workspaceBootstrapContext,
|
|
5208
|
+
omitWorkspaceReferences,
|
|
5209
|
+
skillsPrompt: skillsCollaborationInstructions ? params.skillsSnapshot?.prompt ?? "" : "",
|
|
5210
|
+
tools: toolBridge.availableSpecs
|
|
5211
|
+
});
|
|
5212
|
+
const systemPromptReport = buildSystemPromptReport();
|
|
5213
|
+
let workspaceReferencesIncluded = true;
|
|
4798
5214
|
return {
|
|
4799
5215
|
context,
|
|
5216
|
+
get contextImages() {
|
|
5217
|
+
return contextImages;
|
|
5218
|
+
},
|
|
4800
5219
|
codexModelInputHistoryMessages,
|
|
4801
5220
|
turnState,
|
|
5221
|
+
refreshWorkspaceReferences: (include) => {
|
|
5222
|
+
turnState.codexTurnPromptText = decorateCodexTurnPromptText(turnState.promptBuild, include);
|
|
5223
|
+
if (include !== workspaceReferencesIncluded) {
|
|
5224
|
+
Object.assign(systemPromptReport, buildSystemPromptReport(!include));
|
|
5225
|
+
workspaceReferencesIncluded = include;
|
|
5226
|
+
}
|
|
5227
|
+
},
|
|
4802
5228
|
buildRenderedCodexDeveloperInstructions,
|
|
4803
5229
|
rebuildCodexTurnPromptTextFromCurrentProjection,
|
|
4804
5230
|
applyNoContextEngineContinuityProjection,
|
|
4805
|
-
systemPromptReport
|
|
4806
|
-
attempt: params,
|
|
4807
|
-
sessionKey: contextSessionKey,
|
|
4808
|
-
workspaceDir: effectiveWorkspace,
|
|
4809
|
-
developerInstructions: buildRenderedCodexDeveloperInstructions(),
|
|
4810
|
-
workspaceBootstrapContext,
|
|
4811
|
-
skillsPrompt: skillsCollaborationInstructions ? params.skillsSnapshot?.prompt ?? "" : "",
|
|
4812
|
-
tools: toolBridge.availableSpecs
|
|
4813
|
-
})
|
|
5231
|
+
systemPromptReport
|
|
4814
5232
|
};
|
|
4815
5233
|
}
|
|
4816
5234
|
//#endregion
|
|
@@ -4909,10 +5327,11 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
4909
5327
|
closed: retired.closed,
|
|
4910
5328
|
matchedSharedClient: retired.found
|
|
4911
5329
|
});
|
|
4912
|
-
|
|
5330
|
+
const result = retired.closed ? await state.client.closeAndWait({
|
|
4913
5331
|
exitTimeoutMs: 2e3,
|
|
4914
5332
|
forceKillDelayMs: 250
|
|
4915
|
-
});
|
|
5333
|
+
}) : void 0;
|
|
5334
|
+
if (params.oneShotCliRun && result?.cleanup !== "closed") throw new Error("Codex one-shot client cleanup could not be confirmed");
|
|
4916
5335
|
};
|
|
4917
5336
|
const releaseSandboxExecEnvironment = async () => {
|
|
4918
5337
|
if (state.sandboxExecEnvironment) {
|
|
@@ -4926,10 +5345,13 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
4926
5345
|
await releaseSandboxExecEnvironment();
|
|
4927
5346
|
const ownedClient = state.releaseSharedClientLease ? state.client : void 0;
|
|
4928
5347
|
releaseSharedClientLeaseOnce();
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
5348
|
+
if (ownedClient) {
|
|
5349
|
+
const result = await ownedClient.closeAndWait({
|
|
5350
|
+
exitTimeoutMs: 2e3,
|
|
5351
|
+
forceKillDelayMs: 250
|
|
5352
|
+
});
|
|
5353
|
+
if (params.oneShotCliRun && result.cleanup !== "closed") throw new Error("Codex isolated client cleanup could not be confirmed");
|
|
5354
|
+
}
|
|
4933
5355
|
return;
|
|
4934
5356
|
}
|
|
4935
5357
|
releaseSharedClientLeaseOnce();
|
|
@@ -5016,6 +5438,7 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5016
5438
|
loopDetectionPreToolUseRelay: appServer.loopDetectionPreToolUseRelay,
|
|
5017
5439
|
signal: runAbortController.signal,
|
|
5018
5440
|
hostCapabilities: params.hostCapabilities,
|
|
5441
|
+
assertCurrent: connection.assertCurrent,
|
|
5019
5442
|
onPreToolUseFailure: (failure) => {
|
|
5020
5443
|
const projector = projectorRef.current;
|
|
5021
5444
|
if (projector) projector.recordNativeToolPreToolUseFailure(failure);
|
|
@@ -5057,7 +5480,7 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5057
5480
|
async function prepareCodexAttemptRoute(resources, turnRuntime, notifications, handleServerRequest) {
|
|
5058
5481
|
const { prompt, state: resourceState, trajectoryRecorder, releaseCurrentRoute, registerNativeSubagentMonitor, activateNativePreToolUseFailureFallback, releaseSandboxExecEnvironment, releaseSharedClientLeaseOnce } = resources;
|
|
5059
5482
|
const { connection } = prompt.context.runtime;
|
|
5060
|
-
const {
|
|
5483
|
+
const { runAbortController } = connection;
|
|
5061
5484
|
const { state, turnIdRef, completeTurn } = turnRuntime;
|
|
5062
5485
|
const { noteNotificationReceived, enqueueNotification } = notifications;
|
|
5063
5486
|
const attachRouteAbort = (route) => {
|
|
@@ -5112,7 +5535,6 @@ async function prepareCodexAttemptRoute(resources, turnRuntime, notifications, h
|
|
|
5112
5535
|
resourceState.nativeHookRelay?.unregister();
|
|
5113
5536
|
await releaseSandboxExecEnvironment();
|
|
5114
5537
|
releaseSharedClientLeaseOnce();
|
|
5115
|
-
params.abortSignal?.removeEventListener("abort", abortFromUpstream);
|
|
5116
5538
|
throw error;
|
|
5117
5539
|
}
|
|
5118
5540
|
return { ensureCurrentThreadRoute };
|
|
@@ -5125,6 +5547,7 @@ function prewarmCodexAttemptClient(params) {
|
|
|
5125
5547
|
const { appServer, attemptClientFactory, options, pluginConfig, runtimeArtifactRequest, startupAuthRequirement, startupClientAuthProfileId, startupPreparedAuth, agentDir, params: runParams, runAbortController } = connection;
|
|
5126
5548
|
if (options.clientFactory || attemptClientFactory !== getLeasedSharedCodexAppServerClient || runtimeArtifactRequest) return;
|
|
5127
5549
|
getSharedCodexAppServerClient({
|
|
5550
|
+
assertCurrent: connection.assertCurrent,
|
|
5128
5551
|
startOptions: appServer.start,
|
|
5129
5552
|
pluginConfig,
|
|
5130
5553
|
...startupPreparedAuth ? { preparedAuth: startupPreparedAuth } : { authProfileId: startupClientAuthProfileId },
|
|
@@ -5236,7 +5659,7 @@ async function prepareCodexAttemptRuntime(connection) {
|
|
|
5236
5659
|
const authenticatedScheduledMode = params.trigger === "cron" && params.scheduledToolPolicy !== void 0 && Array.isArray(params.toolsAllow);
|
|
5237
5660
|
const scheduledConfiguredMcpSurface = authenticatedScheduledMode && (bundleMcpThreadConfig.staticServerNames.length > 0 || mutable.startupBinding?.configuredMcpOwnershipVersion === 1);
|
|
5238
5661
|
const cronCreatorAuthorityCapability = params.cronCreatorAuthorityCapability;
|
|
5239
|
-
const hasFreshCreatorAuthority = cronCreatorAuthorityCapability?.active === true && cronCreatorAuthorityCapability.runId === params.runId && !cronCreatorAuthorityCapability.signal.aborted;
|
|
5662
|
+
const hasFreshCreatorAuthority = cronCreatorAuthorityCapability?.active === true && !(cronCreatorAuthorityCapability.controlUiAdmin && cronCreatorAuthorityCapability.callerOrigin.kind === "unknown") && cronCreatorAuthorityCapability.runId === params.runId && !cronCreatorAuthorityCapability.signal.aborted;
|
|
5240
5663
|
const mayResolveScheduledConfiguredMcpCreatorAuthority = !authenticatedScheduledMode && canResolveScheduledConfiguredMcpCreatorAuthority({
|
|
5241
5664
|
trigger: params.trigger,
|
|
5242
5665
|
connectionClass: appServer.connectionClass,
|
|
@@ -5401,10 +5824,10 @@ function createCodexDynamicToolExecutionRegistry() {
|
|
|
5401
5824
|
}
|
|
5402
5825
|
};
|
|
5403
5826
|
}
|
|
5404
|
-
function resolveCodexDynamicToolDirectNames(params, hostSystemAgentActive = false) {
|
|
5827
|
+
function resolveCodexDynamicToolDirectNames(params, registeredTools, hostSystemAgentActive = false) {
|
|
5405
5828
|
const names = [];
|
|
5406
5829
|
if (hostSystemAgentActive && isSystemAgentOnlyCodexDynamicToolAllowlist(params.toolsAllow)) names.push("openclaw");
|
|
5407
|
-
if (
|
|
5830
|
+
if (registeredTools.some((tool) => tool.name === "message")) names.push("message");
|
|
5408
5831
|
return names;
|
|
5409
5832
|
}
|
|
5410
5833
|
//#endregion
|
|
@@ -5677,7 +6100,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
5677
6100
|
//#region extensions/codex/src/app-server/attempt-runtime-artifact.ts
|
|
5678
6101
|
async function verifyStartupArtifact(params) {
|
|
5679
6102
|
if (!params.request) return;
|
|
5680
|
-
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-
|
|
6103
|
+
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-T-NwqeSH.js");
|
|
5681
6104
|
const runtimeArtifact = readCodexAppServerClientRuntimeArtifact(params.client);
|
|
5682
6105
|
const expected = params.request.expected;
|
|
5683
6106
|
const matchesExpected = !expected || runtimeArtifact?.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint;
|
|
@@ -5689,12 +6112,7 @@ async function verifyStartupArtifact(params) {
|
|
|
5689
6112
|
}
|
|
5690
6113
|
//#endregion
|
|
5691
6114
|
//#region extensions/codex/src/app-server/computer-use-health.ts
|
|
5692
|
-
const
|
|
5693
|
-
function getComputerUseHealthMonitorState() {
|
|
5694
|
-
const globalState = globalThis;
|
|
5695
|
-
globalState[COMPUTER_USE_HEALTH_MONITOR_STATE] ??= { monitors: /* @__PURE__ */ new WeakMap() };
|
|
5696
|
-
return globalState[COMPUTER_USE_HEALTH_MONITOR_STATE];
|
|
5697
|
-
}
|
|
6115
|
+
const getComputerUseHealthMonitorState = defineCodexBuildState("openclaw.codexComputerUseHealthMonitorState", () => ({ monitors: /* @__PURE__ */ new WeakMap() }));
|
|
5698
6116
|
function startCodexComputerUseHealthMonitor(params) {
|
|
5699
6117
|
const state = getComputerUseHealthMonitorState();
|
|
5700
6118
|
const existing = state.monitors.get(params.client);
|
|
@@ -5802,15 +6220,22 @@ function resolveCodexPluginThreadConfigStartupPolicy(params) {
|
|
|
5802
6220
|
/** Builds plugin config without allowing sequential RPC timeouts to consume the turn. */
|
|
5803
6221
|
async function buildCodexPluginThreadConfigWithinDeadline(params) {
|
|
5804
6222
|
const { requestTimeoutMs, signal, request, failClosedOnTimeout, transform, ...buildParams } = params;
|
|
6223
|
+
signal.throwIfAborted();
|
|
5805
6224
|
const timeoutMs = resolveCodexPluginThreadConfigTimeoutMs(requestTimeoutMs);
|
|
5806
6225
|
const deadlineMs = Date.now() + timeoutMs;
|
|
5807
|
-
|
|
6226
|
+
let requestTimedOut = false;
|
|
6227
|
+
const boundedRequest = async (method, requestParams) => {
|
|
5808
6228
|
const remainingTimeoutMs = deadlineMs - Date.now();
|
|
5809
|
-
if (remainingTimeoutMs <= 0) throw new CodexPluginThreadConfigDeadlineError();
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
6229
|
+
if (requestTimedOut || remainingTimeoutMs <= 0) throw new CodexPluginThreadConfigDeadlineError();
|
|
6230
|
+
try {
|
|
6231
|
+
return await request(method, requestParams, {
|
|
6232
|
+
timeoutMs: remainingTimeoutMs,
|
|
6233
|
+
signal
|
|
6234
|
+
});
|
|
6235
|
+
} catch (error) {
|
|
6236
|
+
requestTimedOut ||= isCodexPluginThreadConfigTimeoutError(error);
|
|
6237
|
+
throw error;
|
|
6238
|
+
}
|
|
5814
6239
|
};
|
|
5815
6240
|
try {
|
|
5816
6241
|
return await withAbortableTimeout({
|
|
@@ -5821,14 +6246,16 @@ async function buildCodexPluginThreadConfigWithinDeadline(params) {
|
|
|
5821
6246
|
...buildParams,
|
|
5822
6247
|
request: boundedRequest
|
|
5823
6248
|
});
|
|
5824
|
-
|
|
6249
|
+
const result = transform ? await transform(config, boundedRequest) : config;
|
|
6250
|
+
if (requestTimedOut || Date.now() >= deadlineMs) throw new CodexPluginThreadConfigDeadlineError();
|
|
6251
|
+
return result;
|
|
5825
6252
|
})(),
|
|
5826
6253
|
timeoutMessage: "Codex plugin thread config deadline elapsed",
|
|
5827
6254
|
createTimeoutError: () => new CodexPluginThreadConfigDeadlineError()
|
|
5828
6255
|
});
|
|
5829
6256
|
} catch (error) {
|
|
5830
|
-
if (signal.aborted || !isCodexPluginThreadConfigTimeoutError(error)) throw error;
|
|
5831
|
-
if (failClosedOnTimeout) throw new AgentHarnessPreflightError(`
|
|
6257
|
+
if (signal.aborted || !requestTimedOut && !isCodexPluginThreadConfigTimeoutError(error) && Date.now() < deadlineMs) throw error;
|
|
6258
|
+
if (failClosedOnTimeout) throw new AgentHarnessPreflightError(`Codex app policy verification exceeded its ${timeoutMs} ms startup budget. No app tools were executed. Retry after Codex app inventory is responsive.`);
|
|
5832
6259
|
return buildCodexPluginThreadConfigTimeoutFallback({
|
|
5833
6260
|
pluginConfig: buildParams.pluginConfig,
|
|
5834
6261
|
appCacheKey: buildParams.appCacheKey,
|
|
@@ -5842,7 +6269,7 @@ function createCodexPluginThreadConfigStartupProvider(params) {
|
|
|
5842
6269
|
const metadataCache = configuredMetadataCache ?? defaultCodexPluginMetadataCache;
|
|
5843
6270
|
return {
|
|
5844
6271
|
enabled: true,
|
|
5845
|
-
requiresCurrentPolicyCheck: Boolean(params.scheduledRuntimeAuthority),
|
|
6272
|
+
requiresCurrentPolicyCheck: Boolean(policy?.enabled || params.scheduledRuntimeAuthority),
|
|
5846
6273
|
inputFingerprint,
|
|
5847
6274
|
enabledPluginConfigKeys,
|
|
5848
6275
|
accountAppRecoveryEnabled: policy?.allowAllPlugins,
|
|
@@ -5905,7 +6332,6 @@ async function startCodexAttemptThread(params) {
|
|
|
5905
6332
|
let releaseSharedClientLease;
|
|
5906
6333
|
let startupClientForAbandonedRequestCleanup;
|
|
5907
6334
|
let releaseStartupResourcesOnTimeout;
|
|
5908
|
-
let startupAbandoned = false;
|
|
5909
6335
|
const startupAbandonController = new AbortController();
|
|
5910
6336
|
const abandonStartupAcquire = () => startupAbandonController.abort();
|
|
5911
6337
|
params.signal.addEventListener("abort", abandonStartupAcquire, { once: true });
|
|
@@ -5914,7 +6340,6 @@ async function startCodexAttemptThread(params) {
|
|
|
5914
6340
|
timeoutMs: params.startupTimeoutMs,
|
|
5915
6341
|
signal: params.signal,
|
|
5916
6342
|
onTimeout: async () => {
|
|
5917
|
-
startupAbandoned = true;
|
|
5918
6343
|
startupAbandonController.abort();
|
|
5919
6344
|
await params.onStartupTimeout();
|
|
5920
6345
|
await releaseStartupResourcesOnTimeout?.();
|
|
@@ -5942,7 +6367,9 @@ async function startCodexAttemptThread(params) {
|
|
|
5942
6367
|
let startupAttemptSucceeded = false;
|
|
5943
6368
|
try {
|
|
5944
6369
|
const attemptParams = params.buildAttemptParams();
|
|
6370
|
+
params.assertCurrent?.();
|
|
5945
6371
|
startupClient = await params.attemptClientFactory({
|
|
6372
|
+
assertCurrent: params.assertCurrent,
|
|
5946
6373
|
startOptions: params.appServer.start,
|
|
5947
6374
|
pluginConfig: params.pluginConfig,
|
|
5948
6375
|
...params.startupPreparedAuth ? { preparedAuth: params.startupPreparedAuth } : { authProfileId: params.startupAuthProfileId },
|
|
@@ -5958,7 +6385,7 @@ async function startCodexAttemptThread(params) {
|
|
|
5958
6385
|
config: params.config,
|
|
5959
6386
|
onStartedClient: (client) => {
|
|
5960
6387
|
startupClientForAbandonedRequestCleanup = client;
|
|
5961
|
-
if (
|
|
6388
|
+
if (startupAbandonController.signal.aborted) closeCodexStartupClientBestEffort(client);
|
|
5962
6389
|
},
|
|
5963
6390
|
abandonSignal: startupAbandonController.signal,
|
|
5964
6391
|
timeoutMs: params.appServer.requestTimeoutMs
|
|
@@ -5974,13 +6401,13 @@ async function startCodexAttemptThread(params) {
|
|
|
5974
6401
|
releaseSharedClientLease = startupClientLease;
|
|
5975
6402
|
attemptedClient = activeStartupClient;
|
|
5976
6403
|
startupClientForAbandonedRequestCleanup = activeStartupClient;
|
|
5977
|
-
if (startupAbandoned) throw new CodexAppServerStartupError("timed_out");
|
|
5978
6404
|
if (startupAbandonController.signal.aborted) throw new CodexAppServerStartupError("aborted");
|
|
5979
6405
|
const runtimeArtifact = await verifyStartupArtifact({
|
|
5980
6406
|
client: activeStartupClient,
|
|
5981
6407
|
request: params.runtimeArtifactRequest,
|
|
5982
6408
|
signal: startupAbandonController.signal
|
|
5983
6409
|
});
|
|
6410
|
+
params.assertCurrent?.();
|
|
5984
6411
|
ensureCodexAppServerClientRuntime(activeStartupClient, {
|
|
5985
6412
|
agentDir: params.agentDir,
|
|
5986
6413
|
authProfileId: startupRuntimeAuthProfileId,
|
|
@@ -6046,6 +6473,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6046
6473
|
};
|
|
6047
6474
|
releaseStartupResourcesOnTimeout = releaseStartupSandboxEnvironment;
|
|
6048
6475
|
try {
|
|
6476
|
+
params.assertCurrent?.();
|
|
6049
6477
|
const sandboxEnvironmentRequired = shouldRequireCodexSandboxExecServerEnvironment({
|
|
6050
6478
|
sandbox: params.sandbox,
|
|
6051
6479
|
nativeToolSurfaceEnabled: params.nativeToolSurfaceEnabled,
|
|
@@ -6061,10 +6489,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6061
6489
|
onExecutionDisconnect: params.onExecutionDisconnect
|
|
6062
6490
|
}) : void 0;
|
|
6063
6491
|
startupSandboxEnvironmentAcquired = Boolean(startupSandboxEnvironment);
|
|
6064
|
-
if (startupAbandonController.signal.aborted)
|
|
6065
|
-
await releaseStartupSandboxEnvironment();
|
|
6066
|
-
throw new CodexAppServerStartupError("aborted");
|
|
6067
|
-
}
|
|
6492
|
+
if (startupAbandonController.signal.aborted) throw new CodexAppServerStartupError("aborted");
|
|
6068
6493
|
if (sandboxEnvironmentRequired && !startupSandboxEnvironment) throw new Error("Codex app-server did not register an OpenClaw sandbox exec-server environment.");
|
|
6069
6494
|
} catch (error) {
|
|
6070
6495
|
await releaseStartupSandboxEnvironment();
|
|
@@ -6101,6 +6526,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6101
6526
|
client: activeStartupClient,
|
|
6102
6527
|
reserveResumeThread,
|
|
6103
6528
|
bindingStore: params.bindingStore,
|
|
6529
|
+
assertCurrent: params.assertCurrent,
|
|
6104
6530
|
params: params.buildAttemptParams(),
|
|
6105
6531
|
runtimeModelId: params.runtimeModelId,
|
|
6106
6532
|
agentId: params.sessionAgentId,
|
|
@@ -6191,7 +6617,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6191
6617
|
}
|
|
6192
6618
|
} catch (error) {
|
|
6193
6619
|
startupAttemptError = error;
|
|
6194
|
-
if (!
|
|
6620
|
+
if (!startupAbandonController.signal.aborted && !startupClient) {
|
|
6195
6621
|
const sharedClient = clearSharedCodexAppServerClientIfCurrentAndUnclaimed(startupClientForAbandonedRequestCleanup);
|
|
6196
6622
|
if (sharedClient.found && !sharedClient.closed) startupClientForAbandonedRequestCleanup = void 0;
|
|
6197
6623
|
}
|
|
@@ -6200,10 +6626,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6200
6626
|
if (!startupAttemptSucceeded) {
|
|
6201
6627
|
if (releaseSharedClientLease === startupClientLease) releaseSharedClientLease = void 0;
|
|
6202
6628
|
startupClientLease?.();
|
|
6203
|
-
if (
|
|
6204
|
-
if (startupClientForAbandonedRequestCleanup === startupClient) startupClientForAbandonedRequestCleanup = void 0;
|
|
6205
|
-
await closeCodexStartupClientBestEffort(startupClient);
|
|
6206
|
-
} else if (!isCodexAppServerStartSelectionChangedError(startupAttemptError) && (shouldClearSharedClientAfterStartupRace(startupAttemptError) || shouldClearSharedClientAfterStartupFailure(startupAttemptError, params.spawnedBy))) {
|
|
6629
|
+
if (shouldRetireCodexStartupClient(startupAttemptError, params.spawnedBy, startupAbandonController.signal)) {
|
|
6207
6630
|
if (startupClientForAbandonedRequestCleanup === startupClient) startupClientForAbandonedRequestCleanup = void 0;
|
|
6208
6631
|
await closeCodexStartupClientBestEffort(startupClient);
|
|
6209
6632
|
}
|
|
@@ -6214,7 +6637,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6214
6637
|
return await startupAttempt();
|
|
6215
6638
|
} catch (error) {
|
|
6216
6639
|
const selectionChanged = isCodexAppServerStartSelectionChangedError(error);
|
|
6217
|
-
if (
|
|
6640
|
+
if (startupAbandonController.signal.aborted || !selectionChanged && !isCodexAppServerConnectionClosedError(error)) throw error;
|
|
6218
6641
|
const refreshedSharedClient = selectionChanged ? retireSharedCodexAppServerClientIfCurrent(attemptedClient) : clearSharedCodexAppServerClientIfCurrent(attemptedClient);
|
|
6219
6642
|
if (startupClientForAbandonedRequestCleanup === attemptedClient) startupClientForAbandonedRequestCleanup = void 0;
|
|
6220
6643
|
if (attempt >= CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS) {
|
|
@@ -6247,12 +6670,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6247
6670
|
releaseSharedClientLease
|
|
6248
6671
|
};
|
|
6249
6672
|
} catch (error) {
|
|
6250
|
-
if (params.signal
|
|
6251
|
-
releaseSharedClientLease?.();
|
|
6252
|
-
releaseSharedClientLease = void 0;
|
|
6253
|
-
await closeCodexStartupClientBestEffort(startupClientForAbandonedRequestCleanup);
|
|
6254
|
-
startupClientForAbandonedRequestCleanup = void 0;
|
|
6255
|
-
} else if (!isCodexAppServerStartSelectionChangedError(error) && (shouldClearSharedClientAfterStartupRace(error) || shouldClearSharedClientAfterStartupFailure(error, params.spawnedBy))) {
|
|
6673
|
+
if (shouldRetireCodexStartupClient(error, params.spawnedBy, startupAbandonController.signal)) {
|
|
6256
6674
|
releaseSharedClientLease?.();
|
|
6257
6675
|
releaseSharedClientLease = void 0;
|
|
6258
6676
|
await closeCodexStartupClientBestEffort(startupClientForAbandonedRequestCleanup);
|
|
@@ -6263,30 +6681,29 @@ async function startCodexAttemptThread(params) {
|
|
|
6263
6681
|
params.signal.removeEventListener("abort", abandonStartupAcquire);
|
|
6264
6682
|
}
|
|
6265
6683
|
}
|
|
6266
|
-
function
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
function shouldClearSharedClientAfterStartupFailure(error, spawnedBy) {
|
|
6270
|
-
return !isCodexAppServerOverloadError(error) && !(error instanceof AgentHarnessPreflightError && error.scope === void 0) && (isCodexAppServerBrokenPipeError(error) || !spawnedBy);
|
|
6684
|
+
function shouldRetireCodexStartupClient(error, spawnedBy, signal) {
|
|
6685
|
+
if (signal.aborted || isCodexAppServerStartupError(error) || isCodexAppServerRequestTimeoutError(error)) return true;
|
|
6686
|
+
return !isCodexAppServerStartSelectionChangedError(error) && !isCodexAppServerOverloadError(error) && !(error instanceof AgentHarnessPreflightError && error.scope === void 0) && (isCodexAppServerBrokenPipeError(error) || !spawnedBy);
|
|
6271
6687
|
}
|
|
6272
6688
|
//#endregion
|
|
6273
6689
|
//#region extensions/codex/src/app-server/run-attempt-start.ts
|
|
6274
6690
|
async function startCodexAttemptRuntime(resources) {
|
|
6275
6691
|
const { prompt, state, trajectoryRecorder, activateNativePreToolUseFailureFallback, releaseSandboxExecEnvironment, releaseSharedClientLeaseAndRetireOneShotClient, releaseCurrentRoute, runCleanupStep, startupTimeoutMs, buildNativeHookRelayFinalConfigPatch } = resources;
|
|
6276
|
-
const { context, turnState,
|
|
6692
|
+
const { context, turnState, rebuildCodexTurnPromptTextFromCurrentProjection, applyNoContextEngineContinuityProjection } = prompt;
|
|
6277
6693
|
const { runtime, attemptTools, promptState } = context;
|
|
6278
6694
|
const { connection, runtimeParams, preparedAuthBinding, buildActiveRunAttemptParams, startupAuthAccountCacheKey, startupEnvApiKeyCacheKey, bundleMcpThreadConfig, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, effectiveRuntimeModelId, sandboxExecServerEnabled } = runtime;
|
|
6279
6695
|
const { toolBridge, toolState } = attemptTools;
|
|
6280
6696
|
const developerInstructions = joinPresentSections(turnState.promptBuild.developerInstructions, attemptTools.configuredMcp?.diagnosticNotice);
|
|
6281
|
-
const { params, attemptClientFactory, bindingStore, appServer, pluginConfig, computerUseConfig, startupClientAuthProfileId, runtimeArtifactRequest, startupPreparedAuth, agentDir, sessionAgentId, effectiveWorkspace, effectiveCwd, sandbox, runAbortController, usesSupervisionConnection, resolveReviewerPolicyContext, resolveRuntimeOptionsForCurrentBinding, startupAuthProfileId, startupAuthRequirement
|
|
6697
|
+
const { params, attemptClientFactory, bindingStore, appServer, pluginConfig, computerUseConfig, startupClientAuthProfileId, runtimeArtifactRequest, startupPreparedAuth, agentDir, sessionAgentId, effectiveWorkspace, effectiveCwd, sandbox, runAbortController, usesSupervisionConnection, resolveReviewerPolicyContext, resolveRuntimeOptionsForCurrentBinding, startupAuthProfileId, startupAuthRequirement } = connection;
|
|
6282
6698
|
let pluginAppServer = withCodexAppServerFastModeServiceTier(appServer, runtimeParams);
|
|
6283
|
-
const loopDetectionEnabled = (sessionAgentId && params.config ? resolveAgentConfig
|
|
6699
|
+
const loopDetectionEnabled = (sessionAgentId && params.config ? resolveAgentConfig(params.config, sessionAgentId)?.tools?.loopDetection?.enabled : void 0) ?? params.config?.tools?.loopDetection?.enabled ?? false;
|
|
6284
6700
|
try {
|
|
6285
6701
|
emitCodexAppServerEvent(params, {
|
|
6286
6702
|
stream: "codex_app_server.lifecycle",
|
|
6287
6703
|
data: { phase: "startup" }
|
|
6288
6704
|
});
|
|
6289
6705
|
const startupResult = await startCodexAttemptThread({
|
|
6706
|
+
assertCurrent: connection.assertCurrent,
|
|
6290
6707
|
attemptClientFactory,
|
|
6291
6708
|
bindingStore,
|
|
6292
6709
|
runtime: connection.options.runtime,
|
|
@@ -6342,6 +6759,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6342
6759
|
state.sandboxExecEnvironment = startupResult.sandboxEnvironment;
|
|
6343
6760
|
state.releaseSharedClientLease = startupResult.releaseSharedClientLease;
|
|
6344
6761
|
state.restartContextEngineCodexThread = startupResult.restartContextEngineCodexThread;
|
|
6762
|
+
await attemptTools.captureCronCreatorToolAllowlist();
|
|
6345
6763
|
pluginAppServer = startupResult.pluginAppServer;
|
|
6346
6764
|
toolBridge.setRemoteWorkspaceFileReader?.(({ path, maxBytes, workspaceRoot, signal, timeoutMs }) => readBoundedCodexRemoteWorkspaceFile({
|
|
6347
6765
|
client: startupResult.client,
|
|
@@ -6389,7 +6807,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6389
6807
|
clientId: state.client.getInstanceId()
|
|
6390
6808
|
}
|
|
6391
6809
|
});
|
|
6392
|
-
if (applyNoContextEngineContinuityProjection(state.thread.lifecycle.action, state.thread)) await rebuildCodexTurnPromptTextFromCurrentProjection();
|
|
6810
|
+
if (await applyNoContextEngineContinuityProjection(state.thread.lifecycle.action, state.thread)) await rebuildCodexTurnPromptTextFromCurrentProjection();
|
|
6393
6811
|
trajectoryRecorder?.recordEvent("session.started", {
|
|
6394
6812
|
sessionFile: params.sessionFile,
|
|
6395
6813
|
threadId: state.thread.threadId,
|
|
@@ -6397,13 +6815,6 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6397
6815
|
workspaceDir: effectiveWorkspace,
|
|
6398
6816
|
toolCount: flattenCodexDynamicToolFunctions(toolBridge.specs).length
|
|
6399
6817
|
});
|
|
6400
|
-
recordCodexTrajectoryContext(trajectoryRecorder, {
|
|
6401
|
-
attempt: params,
|
|
6402
|
-
cwd: effectiveCwd,
|
|
6403
|
-
developerInstructions: joinPresentSections(buildRenderedCodexDeveloperInstructions(), attemptTools.configuredMcp?.diagnosticNotice),
|
|
6404
|
-
prompt: turnState.codexTurnPromptText,
|
|
6405
|
-
tools: toolBridge.availableSpecs
|
|
6406
|
-
});
|
|
6407
6818
|
connection.mutable.pluginAppServer = pluginAppServer;
|
|
6408
6819
|
} catch (error) {
|
|
6409
6820
|
await runCleanupStep("codex-start-failure-hook-fallback", activateNativePreToolUseFailureFallback);
|
|
@@ -6413,7 +6824,6 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6413
6824
|
await runCleanupStep("codex-start-failure-native-hook-relay", () => nativeHookRelay?.unregister());
|
|
6414
6825
|
await runCleanupStep("codex-start-failure-sandbox-release", releaseSandboxExecEnvironment);
|
|
6415
6826
|
await runCleanupStep("codex-start-failure-shared-client-release", releaseSharedClientLeaseAndRetireOneShotClient);
|
|
6416
|
-
await runCleanupStep("codex-start-failure-abort-listener", () => params.abortSignal?.removeEventListener("abort", abortFromUpstream));
|
|
6417
6827
|
throw error instanceof CodexThreadPolicyHandoffError ? error : state.executionDisconnectError ?? error;
|
|
6418
6828
|
}
|
|
6419
6829
|
}
|
|
@@ -6424,15 +6834,14 @@ function isAuthorityResolutionOperationAbort(error, signal) {
|
|
|
6424
6834
|
}
|
|
6425
6835
|
async function prepareCodexAttemptTools(runtime) {
|
|
6426
6836
|
const { connection, bundleMcpThreadConfig, bundleManifestRegistry, runtimeParams, effectiveRuntimeModelId, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, hookChannelId, codexMcpToolOverrides, authenticatedScheduledMode, configuredMcpSurface, canResolveScheduledConfiguredMcpCreatorAuthority } = runtime;
|
|
6427
|
-
const { params, preDynamicStartupStages, mutable,
|
|
6837
|
+
const { params, preDynamicStartupStages, mutable, resolvedWorkspace, effectiveWorkspace, effectiveCwd, sandboxSessionKey, contextSessionKey, sandbox, sessionPermissionPolicy, runAbortController, sessionAgentId, policyAgentId, pluginConfig, profilerEnabled, agentDir } = connection;
|
|
6428
6838
|
const preDynamicSummary = preDynamicStartupStages.snapshot();
|
|
6429
|
-
if (shouldWarnCodexDynamicToolBuildStageSummary(preDynamicSummary)) embeddedAgentLog.warn(`codex app-server pre-dynamic startup timings runId=${params.runId} sessionId=${params.sessionId} totalMs=${preDynamicSummary.totalMs} stages=${formatCodexDynamicToolBuildStageSummary(preDynamicSummary)}`, {
|
|
6839
|
+
if (shouldWarnCodexDynamicToolBuildStageSummary(preDynamicSummary, profilerEnabled)) embeddedAgentLog.warn(`codex app-server pre-dynamic startup timings runId=${params.runId} sessionId=${params.sessionId} totalMs=${preDynamicSummary.totalMs} stages=${formatCodexDynamicToolBuildStageSummary(preDynamicSummary)}`, {
|
|
6430
6840
|
runId: params.runId,
|
|
6431
6841
|
sessionId: params.sessionId,
|
|
6432
6842
|
totalMs: preDynamicSummary.totalMs,
|
|
6433
6843
|
stages: preDynamicSummary.stages,
|
|
6434
6844
|
hasStartupBinding: Boolean(mutable.startupBinding?.threadId),
|
|
6435
|
-
startupAuthProfileId: startupAuthProfileId ?? null,
|
|
6436
6845
|
bundleMcpDiagnosticCount: bundleMcpThreadConfig.diagnostics.length,
|
|
6437
6846
|
nativeToolSurfaceEnabled
|
|
6438
6847
|
});
|
|
@@ -6495,7 +6904,6 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6495
6904
|
const canResolveScheduledCodexAppAuthority = appCreatorCapture.supported;
|
|
6496
6905
|
const requiresScheduledCodexAppAuthority = appCreatorCapture.required;
|
|
6497
6906
|
const canResolveAnyScheduledCreatorAuthority = canResolveScheduledConfiguredMcpCreatorAuthority || requiresScheduledCodexAppAuthority;
|
|
6498
|
-
let toolBridge;
|
|
6499
6907
|
let creatorAuthorityPromise;
|
|
6500
6908
|
let resolveCreatorAuthorityImpl;
|
|
6501
6909
|
const runtimeYieldCompletionClaim = {};
|
|
@@ -6516,8 +6924,9 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6516
6924
|
pluginConfig,
|
|
6517
6925
|
profilerEnabled,
|
|
6518
6926
|
...params.cronCreatorAuthorityUnavailableReason === "queued-local-operator" && bundleMcpThreadConfig.staticServerNames.length > 0 ? { cronCreatorAuthorityUnavailableReason: "queued-local-operator-configured-mcp" } : {},
|
|
6519
|
-
onYieldDetected: (acknowledgment) => {
|
|
6927
|
+
onYieldDetected: (message, acknowledgment) => {
|
|
6520
6928
|
toolState.yieldDetected = true;
|
|
6929
|
+
toolState.yieldMessage = message;
|
|
6521
6930
|
toolState.yieldAcknowledgment = acknowledgment;
|
|
6522
6931
|
},
|
|
6523
6932
|
claimYieldCompletion: () => runtimeYieldCompletionClaim.current?.() ?? false,
|
|
@@ -6540,8 +6949,9 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6540
6949
|
let nativeSpecs;
|
|
6541
6950
|
if (hasCodexNativeToolCatalog(mutable.startupBinding)) {
|
|
6542
6951
|
runAbortController.signal.throwIfAborted();
|
|
6543
|
-
|
|
6952
|
+
connection.assertCurrent();
|
|
6544
6953
|
const client = await connection.attemptClientFactory({
|
|
6954
|
+
assertCurrent: connection.assertCurrent,
|
|
6545
6955
|
startOptions: connection.appServer.start,
|
|
6546
6956
|
authProfileId: connection.startupClientAuthProfileId,
|
|
6547
6957
|
agentDir,
|
|
@@ -6556,16 +6966,20 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6556
6966
|
agentDir,
|
|
6557
6967
|
assertCurrent: () => {
|
|
6558
6968
|
runAbortController.signal.throwIfAborted();
|
|
6559
|
-
|
|
6969
|
+
connection.assertCurrent();
|
|
6560
6970
|
}
|
|
6561
6971
|
});
|
|
6562
6972
|
} finally {
|
|
6563
6973
|
releaseLeasedSharedCodexAppServerClient(client);
|
|
6564
6974
|
}
|
|
6565
6975
|
}
|
|
6976
|
+
let requireExplicitMessageTarget;
|
|
6566
6977
|
const tools = await buildDynamicTools({
|
|
6567
6978
|
...commonToolParams,
|
|
6568
6979
|
registerRunCleanup: (cleanup) => runCleanups.push(cleanup),
|
|
6980
|
+
onMessageToolTargetResolved: (required) => {
|
|
6981
|
+
requireExplicitMessageTarget = required;
|
|
6982
|
+
},
|
|
6569
6983
|
cronCreatorToolAllowlistRef: cronCreatorToolAllowlist,
|
|
6570
6984
|
cronCreatorToolAllowlistCaptureRef,
|
|
6571
6985
|
onPersistentWebSearchPolicyResolved: (allowed) => {
|
|
@@ -6588,7 +7002,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6588
7002
|
sessionId: params.sessionId,
|
|
6589
7003
|
runId: params.runId,
|
|
6590
7004
|
agentId: policyAgentId,
|
|
6591
|
-
agentDir: agentDir ?? resolveAgentDir(params.config ?? {}, sessionAgentId),
|
|
7005
|
+
agentDir: agentDir ?? resolveAgentDir$2(params.config ?? {}, sessionAgentId),
|
|
6592
7006
|
agentAccountId: params.agentAccountId,
|
|
6593
7007
|
messageProvider: params.messageProvider ?? params.messageChannel,
|
|
6594
7008
|
messageChannel: params.messageChannel,
|
|
@@ -6672,6 +7086,15 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6672
7086
|
warn: (message) => embeddedAgentLog.warn(message)
|
|
6673
7087
|
}) : void 0;
|
|
6674
7088
|
let scopedMcpTools = void 0;
|
|
7089
|
+
const disposeMcpTools = async () => {
|
|
7090
|
+
for (const [step, materialized] of [["codex-scoped-mcp-dispose", scopedMcpTools], ["codex-configured-mcp-dispose", configuredMcp]]) await runAgentCleanupStep({
|
|
7091
|
+
runId: params.runId,
|
|
7092
|
+
sessionId: params.sessionId,
|
|
7093
|
+
step,
|
|
7094
|
+
log: embeddedAgentLog,
|
|
7095
|
+
cleanup: async () => materialized?.dispose()
|
|
7096
|
+
});
|
|
7097
|
+
};
|
|
6675
7098
|
try {
|
|
6676
7099
|
scopedMcpTools = authenticatedScheduledMode ? void 0 : await materializeRequesterScopedMcpToolsForHarnessRun({
|
|
6677
7100
|
sessionId: params.sessionId,
|
|
@@ -6722,27 +7145,24 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6722
7145
|
...params.agentAccountId ? { turnSourceAccountId: params.agentAccountId } : {},
|
|
6723
7146
|
...params.currentThreadTs !== void 0 ? { turnSourceThreadId: params.currentThreadTs } : {}
|
|
6724
7147
|
};
|
|
6725
|
-
toolBridge = createCodexDynamicToolBridge({
|
|
7148
|
+
const toolBridge = createCodexDynamicToolBridge({
|
|
6726
7149
|
tools: toolsWithScopedMcp,
|
|
6727
7150
|
registeredTools: registeredWithScopedMcp,
|
|
6728
7151
|
registeredSpecs: nativeSpecs,
|
|
6729
7152
|
signal: runAbortController.signal,
|
|
6730
7153
|
computerContextEpoch,
|
|
6731
7154
|
loading: resolveCodexDynamicToolsLoadingForRuntime(pluginConfig, effectiveRuntimeModelId, { connectionClass: connection.appServer.connectionClass }),
|
|
6732
|
-
directToolNames: resolveCodexDynamicToolDirectNames(params, isHostScopedAgentToolActive("openclaw")),
|
|
7155
|
+
directToolNames: resolveCodexDynamicToolDirectNames(params, registeredWithScopedMcp, isHostScopedAgentToolActive("openclaw")),
|
|
6733
7156
|
hookContext
|
|
6734
7157
|
});
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
7158
|
+
const captureCronCreatorToolAllowlist = async () => {
|
|
7159
|
+
await captureFinalCodexCronCreatorToolAllowlist(cronCreatorToolAllowlist, cronCreatorToolAllowlistCaptureRef, toolBridge.availableTools, { nativeToolSurfaceEnabled });
|
|
7160
|
+
if (!authenticatedScheduledMode && bundleMcpThreadConfig.staticServerNames.length > 0 && !canResolveScheduledConfiguredMcpCreatorAuthority) delete cronCreatorToolAllowlistCaptureRef.value;
|
|
7161
|
+
if (requiresScheduledCodexAppAuthority) delete cronCreatorToolAllowlistCaptureRef.value;
|
|
7162
|
+
};
|
|
6738
7163
|
if (canResolveAnyScheduledCreatorAuthority) resolveCreatorAuthorityImpl = async (options) => {
|
|
6739
7164
|
options?.signal?.throwIfAborted();
|
|
6740
7165
|
if (codexAppAuthorityUnavailableReason) throw new Error(codexAppAuthorityUnavailableReason);
|
|
6741
|
-
if (!toolBridge) throw new Error("cron creator authority resolver lost the active tool bridge");
|
|
6742
|
-
const authorityTools = [];
|
|
6743
|
-
const captureRef = {};
|
|
6744
|
-
await captureFinalCodexCronCreatorToolAllowlist(authorityTools, captureRef, toolBridge.availableTools);
|
|
6745
|
-
if (!captureRef.value) throw new Error("cron creator authority snapshot did not produce provenance");
|
|
6746
7166
|
const appSource = scheduledAppAuthoritySourceRef.current;
|
|
6747
7167
|
const runtimeAuthority = canResolveScheduledCodexAppAuthority && scheduledCodexAppAuth ? appSource ? await captureScheduledCodexAppAuthority({
|
|
6748
7168
|
...appSource,
|
|
@@ -6751,46 +7171,39 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6751
7171
|
}) : (() => {
|
|
6752
7172
|
throw new Error("Codex app authority is unavailable before the exact creator thread is active. Retry this automation mutation from the current owner turn.");
|
|
6753
7173
|
})() : void 0;
|
|
6754
|
-
if (!canResolveScheduledConfiguredMcpCreatorAuthority) {
|
|
6755
|
-
options?.signal?.throwIfAborted();
|
|
6756
|
-
return Object.freeze({
|
|
6757
|
-
tools: Object.freeze(authorityTools.map((entry) => Object.freeze(entry))),
|
|
6758
|
-
provenance: Object.freeze(captureRef.value),
|
|
6759
|
-
...runtimeAuthority ? { runtimeAuthority } : {}
|
|
6760
|
-
});
|
|
6761
|
-
}
|
|
6762
|
-
const authorityRuntimeId = `cron-authority:${params.runId}`;
|
|
6763
7174
|
let materialized;
|
|
6764
7175
|
try {
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
7176
|
+
if (canResolveScheduledConfiguredMcpCreatorAuthority) try {
|
|
7177
|
+
materialized = await materializeStaticMcpToolsForHarnessRun({
|
|
7178
|
+
sessionId: `cron-authority:${params.runId}`,
|
|
7179
|
+
agentId: sessionAgentId,
|
|
7180
|
+
workspaceDir: effectiveWorkspace,
|
|
7181
|
+
agentDir: policyContext.agentDir,
|
|
7182
|
+
cfg: params.config,
|
|
7183
|
+
manifestRegistry: bundleManifestRegistry,
|
|
7184
|
+
reservedToolNames: toolBridge.availableTools.map((tool) => tool.name),
|
|
7185
|
+
toolsAllow: params.toolsAllow,
|
|
7186
|
+
toolOverrides: codexMcpToolOverrides,
|
|
7187
|
+
autoApproveCodexAppServerApprovals: shouldAutoApproveCodexAppServerApprovals(connection.appServer),
|
|
7188
|
+
projectedMcpServers: bundleMcpThreadConfig.configPatch?.mcp_servers,
|
|
7189
|
+
policyContext,
|
|
7190
|
+
warn: (message) => embeddedAgentLog.warn(message),
|
|
7191
|
+
retireSessionRuntimeAfterDispose: true
|
|
7192
|
+
});
|
|
7193
|
+
} catch (error) {
|
|
7194
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
7195
|
+
throw new Error(`Configured MCP discovery failed while resolving inherited automation authority: ${detail}. Retry after the server is available, or provide an explicit finite toolsAllow list containing only currently visible tools; no automation changes were saved.`, { cause: error });
|
|
7196
|
+
}
|
|
6786
7197
|
options?.signal?.throwIfAborted();
|
|
6787
|
-
if (materialized
|
|
6788
|
-
const
|
|
7198
|
+
if (materialized?.diagnosticNotice) throw new Error(`${materialized.diagnosticNotice} Sign in to the affected MCP server and retry, or provide an explicit finite toolsAllow list containing only currently visible tools. No automation changes were saved.`);
|
|
7199
|
+
const configuredTools = materialized ? projectCodexExecutableDynamicTools({
|
|
6789
7200
|
tools: filterCodexDynamicTools(materialized.tools, pluginConfig),
|
|
6790
7201
|
hookContext
|
|
6791
|
-
});
|
|
6792
|
-
|
|
6793
|
-
|
|
7202
|
+
}).availableTools : [];
|
|
7203
|
+
const authorityTools = [];
|
|
7204
|
+
const captureRef = {};
|
|
7205
|
+
await captureFinalCodexCronCreatorToolAllowlist(authorityTools, captureRef, [...toolBridge.availableTools, ...configuredTools], { nativeToolSurfaceEnabled });
|
|
7206
|
+
if (!captureRef.value) throw new Error("cron creator authority snapshot did not produce provenance");
|
|
6794
7207
|
options?.signal?.throwIfAborted();
|
|
6795
7208
|
return Object.freeze({
|
|
6796
7209
|
tools: Object.freeze(authorityTools.map((entry) => Object.freeze(entry))),
|
|
@@ -6798,17 +7211,18 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6798
7211
|
...runtimeAuthority ? { runtimeAuthority } : {}
|
|
6799
7212
|
});
|
|
6800
7213
|
} finally {
|
|
6801
|
-
await materialized
|
|
7214
|
+
await materialized?.dispose();
|
|
6802
7215
|
}
|
|
6803
7216
|
};
|
|
6804
7217
|
return {
|
|
6805
7218
|
tools: toolsWithScopedMcp,
|
|
6806
7219
|
registeredTools: registeredWithScopedMcp,
|
|
7220
|
+
requireExplicitMessageTarget,
|
|
6807
7221
|
scopedMcpTools,
|
|
6808
7222
|
configuredMcp,
|
|
7223
|
+
disposeMcpTools,
|
|
6809
7224
|
configuredMcpOwnershipVersion: configuredMcpSurface === "scheduled" ? 1 : void 0,
|
|
6810
|
-
|
|
6811
|
-
cronCreatorToolAllowlistCaptureRef,
|
|
7225
|
+
captureCronCreatorToolAllowlist,
|
|
6812
7226
|
scheduledAppAuthoritySourceRef,
|
|
6813
7227
|
dynamicToolParams,
|
|
6814
7228
|
compactionPlanState,
|
|
@@ -6823,8 +7237,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6823
7237
|
runtimeYieldCompletionClaim
|
|
6824
7238
|
};
|
|
6825
7239
|
} catch (error) {
|
|
6826
|
-
await
|
|
6827
|
-
await configuredMcp?.dispose();
|
|
7240
|
+
await disposeMcpTools();
|
|
6828
7241
|
throw error;
|
|
6829
7242
|
}
|
|
6830
7243
|
}
|
|
@@ -6907,11 +7320,22 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
|
|
|
6907
7320
|
error.name = "AbortError";
|
|
6908
7321
|
throw error;
|
|
6909
7322
|
};
|
|
7323
|
+
const prepareWorkspaceReferences = () => {
|
|
7324
|
+
const references = prepareCodexWorkspaceReferences(resourceState.client, resourceState.thread.threadId, workspaceBootstrapContext.promptContext);
|
|
7325
|
+
prompt.refreshWorkspaceReferences(references.include);
|
|
7326
|
+
return references;
|
|
7327
|
+
};
|
|
6910
7328
|
const startCodexTurn = async () => {
|
|
6911
7329
|
const activeTurnRoute = await ensureCurrentThreadRoute();
|
|
7330
|
+
assertCodexSessionRuntimeOwnership(resourceState.thread, params.expectedSessionRuntimeOwnership);
|
|
6912
7331
|
const turnAppServer = withCodexAppServerFastModeServiceTier(connection.mutable.pluginAppServer, runtimeParams);
|
|
6913
7332
|
connection.mutable.pluginAppServer = turnAppServer;
|
|
6914
|
-
const
|
|
7333
|
+
const references = prepareWorkspaceReferences();
|
|
7334
|
+
const referencesRetained = turnState.codexTurnPromptText.includes(workspaceBootstrapContext.promptContext ?? "");
|
|
7335
|
+
const turnStartParams = buildTurnStartParams({
|
|
7336
|
+
...runtimeParams,
|
|
7337
|
+
images: [...prompt.contextImages, ...runtimeParams.images ?? []]
|
|
7338
|
+
}, {
|
|
6915
7339
|
threadId: resourceState.thread.threadId,
|
|
6916
7340
|
cwd: resourceState.codexExecutionCwd,
|
|
6917
7341
|
appServer: turnAppServer,
|
|
@@ -6928,9 +7352,18 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
|
|
|
6928
7352
|
skillsCollaborationInstructions: context.skillsCollaborationInstructions,
|
|
6929
7353
|
memoryCollaborationInstructions: workspaceBootstrapContext.memoryCollaborationInstructions,
|
|
6930
7354
|
preserveNativeTurnSettings: usesSupervisionConnection,
|
|
7355
|
+
messageToolAvailable: toolBridge.availableTools.some((tool) => tool.name === "message"),
|
|
7356
|
+
requireExplicitMessageTarget: attemptTools.requireExplicitMessageTarget,
|
|
6931
7357
|
sessionStatusAvailable: toolBridge.availableTools.some((tool) => tool.name === "session_status")
|
|
6932
7358
|
});
|
|
6933
7359
|
codexModelCallDiagnostics.setRequestPayloadBytes(utf8JsonByteLength(turnStartParams));
|
|
7360
|
+
recordCodexTrajectoryContext(resources.trajectoryRecorder, {
|
|
7361
|
+
attempt: params,
|
|
7362
|
+
cwd: connection.effectiveCwd,
|
|
7363
|
+
developerInstructions: joinPresentSections(buildRenderedCodexDeveloperInstructions(), attemptTools.configuredMcp?.diagnosticNotice),
|
|
7364
|
+
prompt: turnState.codexTurnPromptText,
|
|
7365
|
+
tools: toolBridge.availableSpecs
|
|
7366
|
+
});
|
|
6934
7367
|
state.latestStartupErrorNotification = void 0;
|
|
6935
7368
|
state.rateLimitsRevisionBeforeLastTurnStart = readCodexRateLimitsRevision(resourceState.client);
|
|
6936
7369
|
activeTurnRoute.armTurn();
|
|
@@ -6949,9 +7382,12 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
|
|
|
6949
7382
|
try {
|
|
6950
7383
|
const startedTurn = assertCodexTurnStartResponse(await resourceState.client.request("turn/start", turnStartParams, {
|
|
6951
7384
|
timeoutMs: params.timeoutMs,
|
|
6952
|
-
signal: runAbortController.signal
|
|
7385
|
+
signal: runAbortController.signal,
|
|
7386
|
+
assertCurrent: connection.assertCurrent
|
|
6953
7387
|
}));
|
|
6954
7388
|
acceptedTurnId = startedTurn.turn.id;
|
|
7389
|
+
connection.assertCurrent();
|
|
7390
|
+
if (referencesRetained) references.accepted();
|
|
6955
7391
|
throwIfTurnStartAcceptedAfterAbort();
|
|
6956
7392
|
return startedTurn;
|
|
6957
7393
|
} catch (error) {
|
|
@@ -6980,6 +7416,7 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
|
|
|
6980
7416
|
if (await waitForActiveNativeTurnCompletion()) await resourceState.turnRoute?.drain();
|
|
6981
7417
|
else if (!runAbortController.signal.aborted) embeddedAgentLog.warn("codex app-server active native turn did not complete before turn/start wait timed out", { threadId: resourceState.thread.threadId });
|
|
6982
7418
|
}
|
|
7419
|
+
prepareWorkspaceReferences();
|
|
6983
7420
|
const buildLlmInputEvent = () => ({
|
|
6984
7421
|
runId: params.runId,
|
|
6985
7422
|
sessionId: params.sessionId,
|
|
@@ -6988,7 +7425,7 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
|
|
|
6988
7425
|
systemPrompt: buildRenderedCodexDeveloperInstructions(),
|
|
6989
7426
|
prompt: turnState.codexTurnPromptText,
|
|
6990
7427
|
historyMessages: prompt.codexModelInputHistoryMessages,
|
|
6991
|
-
imagesCount: params.images?.length ?? 0,
|
|
7428
|
+
imagesCount: prompt.contextImages.length + (params.images?.length ?? 0),
|
|
6992
7429
|
tools
|
|
6993
7430
|
});
|
|
6994
7431
|
return {
|
|
@@ -7004,7 +7441,7 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
|
|
|
7004
7441
|
const { context, turnState, systemPromptReport } = prompt;
|
|
7005
7442
|
const { runtime, historyState, hookContext, hookContextWindowFields, hookRunner } = context;
|
|
7006
7443
|
const { connection, runtimeParams, effectiveRuntimeProviderId, effectiveRuntimeModelId } = runtime;
|
|
7007
|
-
const { params, usesSupervisionConnection, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, attemptStartedAt, startupAuthProfileId
|
|
7444
|
+
const { params, usesSupervisionConnection, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, attemptStartedAt, startupAuthProfileId } = connection;
|
|
7008
7445
|
const { state, turnIdRef } = turnRuntime;
|
|
7009
7446
|
const { waitForActiveNativeTurnCompletion } = notifications;
|
|
7010
7447
|
const { codexModelCallDiagnostics, startCodexTurn, buildLlmInputEvent } = requestRuntime;
|
|
@@ -7040,52 +7477,51 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
|
|
|
7040
7477
|
error: turnStartError,
|
|
7041
7478
|
contextEngineActive: Boolean(activeContextEngine),
|
|
7042
7479
|
thread: resourceState.thread
|
|
7043
|
-
}) && resourceState.restartContextEngineCodexThread) {
|
|
7480
|
+
}) && resourceState.restartContextEngineCodexThread) try {
|
|
7481
|
+
assertCodexBindingMayBeReplaced(resourceState.thread, "retrying an overflow on a fresh native thread", params.expectedSessionRuntimeOwnership);
|
|
7044
7482
|
embeddedAgentLog.warn("codex app-server context-engine turn overflowed on resume; retrying with fresh thread", {
|
|
7045
7483
|
threadId: resourceState.thread.threadId,
|
|
7046
7484
|
error: formatErrorMessage(turnStartError)
|
|
7047
7485
|
});
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
} }
|
|
7067
|
-
});
|
|
7068
|
-
embeddedAgentLog.info("codex app-server cleared stale context-engine projection after overflow retry", {
|
|
7069
|
-
threadId: resourceState.thread.threadId,
|
|
7070
|
-
previousEpoch: retryBinding.contextEngine.projection.epoch
|
|
7071
|
-
});
|
|
7072
|
-
}
|
|
7073
|
-
emitCodexAppServerEvent(params, {
|
|
7074
|
-
stream: "codex_app_server.lifecycle",
|
|
7075
|
-
data: {
|
|
7076
|
-
phase: "thread_ready_retry",
|
|
7077
|
-
threadId: resourceState.thread.threadId
|
|
7078
|
-
}
|
|
7486
|
+
if (!await bindingStore.mutate(bindingIdentity, {
|
|
7487
|
+
kind: "clear",
|
|
7488
|
+
threadId: resourceState.thread.threadId
|
|
7489
|
+
})) embeddedAgentLog.warn("codex app-server preserved newer context-engine binding after resume overflow; skipping fresh retry", {
|
|
7490
|
+
threadId: resourceState.thread.threadId,
|
|
7491
|
+
error: formatErrorMessage(turnStartError)
|
|
7492
|
+
});
|
|
7493
|
+
else {
|
|
7494
|
+
resourceState.thread = await resourceState.restartContextEngineCodexThread();
|
|
7495
|
+
const retryBinding = bindingStore.read(bindingIdentity);
|
|
7496
|
+
if (retryBinding && retryBinding.threadId === resourceState.thread.threadId && retryBinding.contextEngine?.projection) {
|
|
7497
|
+
await bindingStore.mutate(bindingIdentity, {
|
|
7498
|
+
kind: "patch",
|
|
7499
|
+
threadId: retryBinding.threadId,
|
|
7500
|
+
patch: { contextEngine: {
|
|
7501
|
+
...retryBinding.contextEngine,
|
|
7502
|
+
projection: void 0
|
|
7503
|
+
} }
|
|
7079
7504
|
});
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7505
|
+
embeddedAgentLog.info("codex app-server cleared stale context-engine projection after overflow retry", {
|
|
7506
|
+
threadId: resourceState.thread.threadId,
|
|
7507
|
+
previousEpoch: retryBinding.contextEngine.projection.epoch
|
|
7508
|
+
});
|
|
7509
|
+
}
|
|
7510
|
+
emitCodexAppServerEvent(params, {
|
|
7511
|
+
stream: "codex_app_server.lifecycle",
|
|
7512
|
+
data: {
|
|
7513
|
+
phase: "thread_ready_retry",
|
|
7514
|
+
threadId: resourceState.thread.threadId
|
|
7084
7515
|
}
|
|
7516
|
+
});
|
|
7517
|
+
try {
|
|
7518
|
+
turn = await startCodexTurn();
|
|
7519
|
+
} catch (retryError) {
|
|
7520
|
+
turnStartError = retryError;
|
|
7085
7521
|
}
|
|
7086
|
-
} catch (retrySetupError) {
|
|
7087
|
-
turnStartError = retrySetupError;
|
|
7088
7522
|
}
|
|
7523
|
+
} catch (retrySetupError) {
|
|
7524
|
+
turnStartError = retrySetupError;
|
|
7089
7525
|
}
|
|
7090
7526
|
if (turn === void 0) {
|
|
7091
7527
|
const usageLimitError = await formatCodexTurnStartUsageLimitError({
|
|
@@ -7101,7 +7537,7 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
|
|
|
7101
7537
|
phase: "turn_start",
|
|
7102
7538
|
threadId: resourceState.thread.threadId,
|
|
7103
7539
|
error: message
|
|
7104
|
-
});
|
|
7540
|
+
}, params.expectedSessionRuntimeOwnership);
|
|
7105
7541
|
emitCodexAppServerEvent(params, {
|
|
7106
7542
|
stream: "codex_app_server.lifecycle",
|
|
7107
7543
|
data: {
|
|
@@ -7180,7 +7616,6 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
|
|
|
7180
7616
|
log: embeddedAgentLog,
|
|
7181
7617
|
cleanup: async () => trajectoryRecorder?.flush()
|
|
7182
7618
|
});
|
|
7183
|
-
params.abortSignal?.removeEventListener("abort", abortFromUpstream);
|
|
7184
7619
|
await releaseSharedClientLeaseAndRetireOneShotClient();
|
|
7185
7620
|
if (usageLimitError) {
|
|
7186
7621
|
await markCodexAuthProfileBlockedFromRateLimits({
|
|
@@ -7191,7 +7626,7 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
|
|
|
7191
7626
|
return { result: buildCodexTurnStartFailureResult({
|
|
7192
7627
|
params,
|
|
7193
7628
|
message: usageLimitError.message,
|
|
7194
|
-
promptError:
|
|
7629
|
+
promptError: new CodexUsageLimitPromptError(usageLimitError.message),
|
|
7195
7630
|
messagesSnapshot,
|
|
7196
7631
|
systemPromptReport
|
|
7197
7632
|
}) };
|
|
@@ -7299,6 +7734,8 @@ function createCodexAttemptTurnState(resources) {
|
|
|
7299
7734
|
terminalTurnNotificationQueued: false,
|
|
7300
7735
|
sawCodexInterruptMarker: false,
|
|
7301
7736
|
timeout: void 0,
|
|
7737
|
+
settlementWarning: void 0,
|
|
7738
|
+
pendingSettlementStage: void 0,
|
|
7302
7739
|
clientClosedPromptError: void 0,
|
|
7303
7740
|
clientClosedDiagnostic: void 0,
|
|
7304
7741
|
clientClosedAbort: false,
|
|
@@ -7314,6 +7751,7 @@ function createCodexAttemptTurnState(resources) {
|
|
|
7314
7751
|
currentTurnHadNonTerminalDynamicToolResult: false
|
|
7315
7752
|
};
|
|
7316
7753
|
const { promise: completion, resolve: resolveCompletion } = createDeferred();
|
|
7754
|
+
const settlementExpired = createDeferred();
|
|
7317
7755
|
const pendingOpenClawDynamicToolCompletionIds = /* @__PURE__ */ new Set();
|
|
7318
7756
|
const openClawDynamicToolExecutions = createCodexDynamicToolExecutionRegistry();
|
|
7319
7757
|
const activeTurnItemIds = /* @__PURE__ */ new Set();
|
|
@@ -7374,13 +7812,32 @@ function createCodexAttemptTurnState(resources) {
|
|
|
7374
7812
|
signal: runAbortController.signal,
|
|
7375
7813
|
onDeadlineChanged: params.onAttemptDeadlineChanged,
|
|
7376
7814
|
onTimeout: (timeout) => {
|
|
7815
|
+
const pendingStage = state.pendingSettlementStage ?? projectorRef.current?.settlement.pendingStage ?? "notification_queue";
|
|
7816
|
+
if (timeout.kind === "settlement" && projectorRef.current?.recoverCompletedAnswer()) {
|
|
7817
|
+
state.settlementWarning = {
|
|
7818
|
+
pendingStage,
|
|
7819
|
+
elapsedMs: timeout.elapsedMs,
|
|
7820
|
+
timeoutMs: timeout.timeoutMs
|
|
7821
|
+
};
|
|
7822
|
+
state.projectionClosed = true;
|
|
7823
|
+
trajectoryRecorder?.recordEvent("turn.settlement_warning", {
|
|
7824
|
+
threadId: resourceState.thread.threadId,
|
|
7825
|
+
turnId: turnIdRef.current,
|
|
7826
|
+
...state.settlementWarning
|
|
7827
|
+
});
|
|
7828
|
+
embeddedAgentLog.warn("codex app-server retaining completed answer after settlement expiry", state.settlementWarning);
|
|
7829
|
+
completeTurn();
|
|
7830
|
+
settlementExpired.resolve();
|
|
7831
|
+
return;
|
|
7832
|
+
}
|
|
7377
7833
|
state.timeout = timeout;
|
|
7378
7834
|
projectorRef.current?.markTimedOut();
|
|
7379
7835
|
const error = /* @__PURE__ */ new Error(timeout.kind === "execution" ? "codex app-server execution budget timed out" : "codex app-server terminal settlement timed out");
|
|
7380
7836
|
const fields = {
|
|
7381
7837
|
threadId: resourceState.thread.threadId,
|
|
7382
7838
|
turnId: turnIdRef.current,
|
|
7383
|
-
...timeout
|
|
7839
|
+
...timeout,
|
|
7840
|
+
pendingStage
|
|
7384
7841
|
};
|
|
7385
7842
|
trajectoryRecorder?.recordEvent(`turn.${timeout.kind}_timeout`, fields);
|
|
7386
7843
|
embeddedAgentLog.warn(error.message, fields);
|
|
@@ -7391,6 +7848,7 @@ function createCodexAttemptTurnState(resources) {
|
|
|
7391
7848
|
return {
|
|
7392
7849
|
state,
|
|
7393
7850
|
completion,
|
|
7851
|
+
settlementExpired: settlementExpired.promise,
|
|
7394
7852
|
pendingOpenClawDynamicToolCompletionIds,
|
|
7395
7853
|
openClawDynamicToolExecutions,
|
|
7396
7854
|
activeTurnItemIds,
|
|
@@ -7407,35 +7865,47 @@ function createCodexAttemptTurnState(resources) {
|
|
|
7407
7865
|
//#endregion
|
|
7408
7866
|
//#region extensions/codex/src/app-server/run-attempt.ts
|
|
7409
7867
|
async function runCodexAppServerAttempt(params, options) {
|
|
7410
|
-
const
|
|
7868
|
+
const preparation = createCodexAttemptPreparationTiming(params);
|
|
7869
|
+
const connection = await preparation.measure("connection", () => prepareCodexAttemptConnection({
|
|
7411
7870
|
params,
|
|
7412
7871
|
options
|
|
7413
|
-
});
|
|
7414
|
-
const runtime = await prepareCodexAttemptRuntime(connection);
|
|
7415
|
-
const attemptTools = await prepareCodexAttemptTools(runtime);
|
|
7416
|
-
const resources = prepareCodexAttemptResources(await prepareCodexAttemptPrompt(await prepareCodexAttemptContext(runtime, attemptTools)));
|
|
7417
|
-
attemptTools.runtimeYieldCompletionClaim.current = () => resources.state.nativeHookRelay?.hasClaimedDirectChild() ?? false;
|
|
7418
|
-
await startCodexAttemptRuntime(resources);
|
|
7419
|
-
const turnRuntime = createCodexAttemptTurnState(resources);
|
|
7872
|
+
}));
|
|
7420
7873
|
try {
|
|
7421
|
-
const
|
|
7422
|
-
const
|
|
7423
|
-
const { ensureCurrentThreadRoute } = await prepareCodexAttemptRoute(resources, turnRuntime, notifications, createCodexAttemptServerRequestController(resources, turnRuntime, lifecycle).handleServerRequest);
|
|
7424
|
-
const turnRequest = await prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurrentThreadRoute, notifications.waitForActiveNativeTurnCompletion);
|
|
7425
|
-
const turnStart = await startCodexAttemptTurn(resources, turnRuntime, notifications, turnRequest);
|
|
7426
|
-
if ("result" in turnStart) return turnStart.result;
|
|
7427
|
-
const activeTurn = activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notifications, turnStart.turn);
|
|
7428
|
-
let finalizedResult;
|
|
7874
|
+
const runtime = await preparation.measure("runtime", () => prepareCodexAttemptRuntime(connection));
|
|
7875
|
+
const attemptTools = await preparation.measure("tools", () => prepareCodexAttemptTools(runtime));
|
|
7429
7876
|
try {
|
|
7430
|
-
await
|
|
7431
|
-
|
|
7877
|
+
const attemptContext = await preparation.measure("context", () => prepareCodexAttemptContext(runtime, attemptTools));
|
|
7878
|
+
const resources = prepareCodexAttemptResources(await preparation.measure("prompt", () => prepareCodexAttemptPrompt(attemptContext)));
|
|
7879
|
+
attemptTools.runtimeYieldCompletionClaim.current = () => resources.state.nativeHookRelay?.hasClaimedDirectChild() ?? false;
|
|
7880
|
+
await preparation.measure("runtime-start", () => startCodexAttemptRuntime(resources));
|
|
7881
|
+
const turnRuntime = createCodexAttemptTurnState(resources);
|
|
7882
|
+
try {
|
|
7883
|
+
const lifecycle = createCodexAttemptLifecycleController(resources, turnRuntime);
|
|
7884
|
+
const notifications = createCodexAttemptNotificationController(resources, turnRuntime, lifecycle);
|
|
7885
|
+
const serverRequests = createCodexAttemptServerRequestController(resources, turnRuntime, lifecycle);
|
|
7886
|
+
const { ensureCurrentThreadRoute } = await preparation.measure("thread-route", () => prepareCodexAttemptRoute(resources, turnRuntime, notifications, serverRequests.handleServerRequest));
|
|
7887
|
+
const turnRequest = await preparation.measure("turn-request", () => prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurrentThreadRoute, notifications.waitForActiveNativeTurnCompletion));
|
|
7888
|
+
preparation.ready();
|
|
7889
|
+
const turnStart = await startCodexAttemptTurn(resources, turnRuntime, notifications, turnRequest);
|
|
7890
|
+
if ("result" in turnStart) return turnStart.result;
|
|
7891
|
+
const activeTurn = activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notifications, turnStart.turn);
|
|
7892
|
+
let finalizedResult;
|
|
7893
|
+
try {
|
|
7894
|
+
await activeTurn.ready;
|
|
7895
|
+
finalizedResult = await finalizeCodexAttempt(resources, turnRuntime, lifecycle, notifications, turnRequest, activeTurn);
|
|
7896
|
+
} finally {
|
|
7897
|
+
await cleanupCodexAttempt(resources, turnRuntime, lifecycle, turnRequest, activeTurn);
|
|
7898
|
+
}
|
|
7899
|
+
if (resources.state.executionDisconnectError && !connection.terminalState.explicitCancellationObserved) throw resources.state.executionDisconnectError;
|
|
7900
|
+
return finalizedResult;
|
|
7901
|
+
} finally {
|
|
7902
|
+
turnRuntime.deadlines.dispose();
|
|
7903
|
+
}
|
|
7432
7904
|
} finally {
|
|
7433
|
-
await
|
|
7905
|
+
await attemptTools.disposeMcpTools();
|
|
7434
7906
|
}
|
|
7435
|
-
if (resources.state.executionDisconnectError && !connection.terminalState.explicitCancellationObserved) throw resources.state.executionDisconnectError;
|
|
7436
|
-
return finalizedResult;
|
|
7437
7907
|
} finally {
|
|
7438
|
-
|
|
7908
|
+
params.abortSignal?.removeEventListener("abort", connection.abortFromUpstream);
|
|
7439
7909
|
}
|
|
7440
7910
|
}
|
|
7441
7911
|
//#endregion
|