


























@@ -888,7 +888,6 @@ export async function runCodexAppServerAttempt(
888888let turnCompletionLastActivityReason = "startup";
889889let turnCompletionLastActivityDetails: Record<string, unknown> | undefined;
890890let activeAppServerTurnRequests = 0;
891-let sawTurnScopedRequestResponse = false;
892891893892const clearTurnCompletionIdleTimer = () => {
894893if (turnCompletionIdleTimer) {
@@ -1149,9 +1148,7 @@ export async function runCodexAppServerAttempt(
11491148// See openclaw/openclaw#67996.
11501149const isTurnCompletion = notification.method === "turn/completed" && isCurrentTurnNotification;
11511150const isTurnAbortMarker =
1152-isCurrentTurnNotification &&
1153-sawTurnScopedRequestResponse &&
1154-isCodexTurnAbortMarkerNotification(notification);
1151+isCurrentTurnNotification && isCodexTurnAbortMarkerNotification(notification);
11551152const isTurnTerminal = isTurnCompletion || isTurnAbortMarker;
11561153try {
11571154await projector.handleNotification(notification);
@@ -1314,9 +1311,6 @@ export async function runCodexAppServerAttempt(
13141311return response as JsonValue;
13151312} finally {
13161313activeAppServerTurnRequests = Math.max(0, activeAppServerTurnRequests - 1);
1317-if (armCompletionWatchOnResponse) {
1318-sawTurnScopedRequestResponse = true;
1319-}
13201314touchTurnCompletionActivity(`request:${request.method}:response`, {
13211315arm: armCompletionWatchOnResponse,
13221316});
@@ -2356,6 +2350,13 @@ function readNestedTurnId(record: JsonObject): string | undefined {
23562350return isJsonObject(turn) ? readString(turn, "id") : undefined;
23572351}
235823522353+const CODEX_TURN_ABORT_MARKER_START = "<turn_aborted>";
2354+const CODEX_TURN_ABORT_MARKER_END = "</turn_aborted>";
2355+const CODEX_INTERRUPTED_USER_GUIDANCE =
2356+"The user interrupted the previous turn on purpose. Any running unified exec processes may still be running in the background. If any tools/commands were aborted, they may have partially executed.";
2357+const CODEX_INTERRUPTED_DEVELOPER_GUIDANCE =
2358+"The previous turn was interrupted on purpose. Any running unified exec processes may still be running in the background. If any tools/commands were aborted, they may have partially executed.";
2359+23592360function isCodexTurnAbortMarkerNotification(notification: CodexServerNotification): boolean {
23602361if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) {
23612362return false;
@@ -2366,7 +2367,23 @@ function isCodexTurnAbortMarkerNotification(notification: CodexServerNotificatio
23662367return false;
23672368}
23682369const text = extractRawResponseItemText(item).trim();
2369-return text.startsWith("<turn_aborted>") && text.includes("</turn_aborted>");
2370+const markerBody = readCodexTurnAbortMarkerBody(text);
2371+return (
2372+markerBody === CODEX_INTERRUPTED_USER_GUIDANCE ||
2373+markerBody === CODEX_INTERRUPTED_DEVELOPER_GUIDANCE
2374+);
2375+}
2376+2377+function readCodexTurnAbortMarkerBody(text: string): string | undefined {
2378+if (
2379+!text.startsWith(CODEX_TURN_ABORT_MARKER_START) ||
2380+!text.endsWith(CODEX_TURN_ABORT_MARKER_END)
2381+) {
2382+return undefined;
2383+}
2384+return text
2385+.slice(CODEX_TURN_ABORT_MARKER_START.length, -CODEX_TURN_ABORT_MARKER_END.length)
2386+.trim();
23702387}
2371238823722389function extractRawResponseItemText(item: JsonObject): string {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。