






















@@ -1038,6 +1038,7 @@ export async function runCodexAppServerAttempt(
10381038let timedOut = false;
10391039let turnCompletionIdleTimedOut = false;
10401040let turnCompletionIdleTimeoutMessage: string | undefined;
1041+let clientClosedPromptError: string | undefined;
10411042let lifecycleStarted = false;
10421043let lifecycleTerminalEmitted = false;
10431044let resolveCompletion: (() => void) | undefined;
@@ -1758,6 +1759,7 @@ export async function runCodexAppServerAttempt(
17581759}
17591760}
17601761});
1762+let closeCleanup: (() => void) | undefined;
1761176317621764const forceContextEngineCompactionForCodexOverflow = async (error: unknown): Promise<boolean> => {
17631765if (!activeContextEngine?.info.ownsCompaction) {
@@ -2016,6 +2018,30 @@ export async function runCodexAppServerAttempt(
20162018nativePostToolUseRelayEnabled:
20172019nativeHookRelay?.allowedEvents.includes("post_tool_use") === true,
20182020});
2021+closeCleanup = (
2022+client as {
2023+addCloseHandler?: (handler: (client: CodexAppServerClient) => void) => () => void;
2024+}
2025+).addCloseHandler?.(() => {
2026+if (completed || runAbortController.signal.aborted) {
2027+return;
2028+}
2029+clientClosedPromptError = "codex app-server client closed before turn completed";
2030+trajectoryRecorder?.recordEvent("turn.client_closed", {
2031+threadId: thread.threadId,
2032+turnId: activeTurnId,
2033+});
2034+embeddedAgentLog.warn("codex app-server client closed before turn completed", {
2035+threadId: thread.threadId,
2036+turnId: activeTurnId,
2037+});
2038+completed = true;
2039+clearTurnAttemptIdleTimer();
2040+clearTurnCompletionIdleTimer();
2041+clearTurnAssistantCompletionIdleTimer();
2042+clearTurnTerminalIdleTimer();
2043+resolveCompletion?.();
2044+});
20192045emitLifecycleStart();
20202046const activeProjector = projector;
20212047turnTerminalIdleWatchArmed = true;
@@ -2081,11 +2107,13 @@ export async function runCodexAppServerAttempt(
20812107await completion;
20822108const result = activeProjector.buildResult(toolBridge.telemetry, { yieldDetected });
20832109const finalAborted = result.aborted || runAbortController.signal.aborted;
2084-let finalPromptError = turnCompletionIdleTimedOut
2085- ? turnCompletionIdleTimeoutMessage
2086- : timedOut
2087- ? "codex app-server attempt timed out"
2088- : result.promptError;
2110+let finalPromptError =
2111+clientClosedPromptError ??
2112+(turnCompletionIdleTimedOut
2113+ ? turnCompletionIdleTimeoutMessage
2114+ : timedOut
2115+ ? "codex app-server attempt timed out"
2116+ : result.promptError);
20892117const finalPromptErrorMessage =
20902118typeof finalPromptError === "string"
20912119 ? finalPromptError
@@ -2104,7 +2132,8 @@ export async function runCodexAppServerAttempt(
21042132signal: runAbortController.signal,
21052133});
21062134}
2107-const finalPromptErrorSource = timedOut ? "prompt" : result.promptErrorSource;
2135+const finalPromptErrorSource =
2136+timedOut || clientClosedPromptError ? "prompt" : result.promptErrorSource;
21082137recordCodexTrajectoryCompletion(trajectoryRecorder, {
21092138attempt: params,
21102139 result,
@@ -2247,6 +2276,7 @@ export async function runCodexAppServerAttempt(
22472276clearTurnTerminalIdleTimer();
22482277notificationCleanup();
22492278requestCleanup();
2279+closeCleanup?.();
22502280nativeHookRelay?.unregister();
22512281runAbortController.signal.removeEventListener("abort", abortListener);
22522282params.abortSignal?.removeEventListener("abort", abortFromUpstream);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。