@jskit-ai/assistant-core 0.2.7 → 0.2.9
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/examples/conversation/package.json +5 -5
- package/package.json +18 -7
- package/src/client/browser.js +21 -0
- package/src/client/conversation/AssistantAttachmentQueue.vue +25 -108
- package/src/client/conversation/AssistantComposerActions.vue +1 -1
- package/src/client/conversation/AssistantConversationElement.vue +14 -52
- package/src/client/conversation/AssistantGoalControl.vue +13 -10
- package/src/client/conversation/AssistantPromptInput.vue +6 -91
- package/src/client/conversation/AssistantTranscript.css +505 -0
- package/src/client/conversation/AssistantTranscript.vue +24 -1197
- package/src/client/conversation/attachmentFiles.js +158 -0
- package/src/client/conversation/attachmentQueueItems.js +121 -0
- package/src/client/conversation/attachmentUploadRows.js +265 -0
- package/src/client/conversation/conversationDisplay.js +54 -0
- package/src/client/conversation/messageDelivery.js +13 -9
- package/src/client/conversation/retainedConversation.js +14 -3
- package/src/client/conversation/submitText.js +13 -2
- package/src/client/conversation/transcriptEntries.js +225 -0
- package/src/client/conversation/useAssistantAttachments.js +86 -388
- package/src/client/conversation/useAssistantQuestions.js +16 -3
- package/src/client/conversation/useAssistantSuggestions.js +16 -2
- package/src/client/conversation/useScrollToBottom.js +17 -19
- package/src/client/conversation/useTextareaAutoGrow.js +115 -0
- package/src/client/conversation/useTranscriptScrollFollow.js +525 -0
- package/src/client/lib/assistantApi.js +192 -161
- package/src/client/types.js +110 -0
- package/src/server/conversation/attachments.js +21 -6
- package/src/server/conversation/boundedToolLoop.js +1 -0
- package/src/server/conversation/claudeClient.js +71 -20
- package/src/server/conversation/claudeCommandRun.js +191 -0
- package/src/server/conversation/claudeHistory.js +7 -0
- package/src/server/conversation/claudeNativeTurn.js +708 -0
- package/src/server/conversation/claudeProcess.js +186 -112
- package/src/server/conversation/claudeProcessStart.js +214 -0
- package/src/server/conversation/claudePromptDelivery.js +183 -0
- package/src/server/conversation/claudeSessionCleanup.js +248 -0
- package/src/server/conversation/claudeTools.js +15 -3
- package/src/server/conversation/claudeTurn.js +212 -1388
- package/src/server/conversation/codexAccountReader.js +168 -0
- package/src/server/conversation/codexAuthPreflight.js +5 -4
- package/src/server/conversation/codexClient.js +18 -6
- package/src/server/conversation/codexConfiguration.js +8 -844
- package/src/server/conversation/codexConversationStops.js +377 -0
- package/src/server/conversation/codexConversationStore.js +119 -85
- package/src/server/conversation/codexConversationTurns.js +378 -0
- package/src/server/conversation/codexConversations.js +134 -866
- package/src/server/conversation/codexDetachedConversation.js +203 -0
- package/src/server/conversation/codexDetachedTurn.js +145 -104
- package/src/server/conversation/codexEvents.js +5 -200
- package/src/server/conversation/codexGoalCommands.js +14 -4
- package/src/server/conversation/codexHelperExecution.js +57 -57
- package/src/server/conversation/codexHelperThreadLedger.js +30 -288
- package/src/server/conversation/codexHelperThreadRecord.js +304 -0
- package/src/server/conversation/codexHelperThreadRecovery.js +54 -76
- package/src/server/conversation/codexHelperThreads.js +94 -93
- package/src/server/conversation/codexHistoryAdapter.js +13 -8
- package/src/server/conversation/codexIsolation.js +672 -0
- package/src/server/conversation/codexLiveItems.js +379 -0
- package/src/server/conversation/codexMessageCommands.js +68 -286
- package/src/server/conversation/codexMessageDelivery.js +46 -37
- package/src/server/conversation/codexModelCatalog.js +86 -7
- package/src/server/conversation/codexNotificationObserver.js +81 -88
- package/src/server/conversation/codexNotificationQueue.js +21 -10
- package/src/server/conversation/codexObservationControl.js +105 -89
- package/src/server/conversation/codexOutput.js +84 -419
- package/src/server/conversation/codexProcess.js +29 -1053
- package/src/server/conversation/codexProcessLeader.js +1 -0
- package/src/server/conversation/codexPromptDispatch.js +241 -0
- package/src/server/conversation/codexProvider.js +147 -1807
- package/src/server/conversation/codexProviderAuth.js +348 -0
- package/src/server/conversation/codexProviderInvalidation.js +371 -0
- package/src/server/conversation/codexProviderInventories.js +437 -0
- package/src/server/conversation/codexProviderOwner.js +149 -957
- package/src/server/conversation/codexProviderRelease.js +465 -0
- package/src/server/conversation/codexProviderSelection.js +26 -15
- package/src/server/conversation/codexProviderThreads.js +698 -0
- package/src/server/conversation/codexProviderTurns.js +453 -0
- package/src/server/conversation/codexReasoning.js +32 -23
- package/src/server/conversation/codexRenewalCommands.js +18 -6
- package/src/server/conversation/codexRenewalThreads.js +7 -22
- package/src/server/conversation/codexResultSettlement.js +70 -88
- package/src/server/conversation/codexRunJournal.js +91 -97
- package/src/server/conversation/codexRuntime.js +426 -0
- package/src/server/conversation/codexRuntimeInventory.js +113 -0
- package/src/server/conversation/codexRuntimeLifecycle.js +39 -13
- package/src/server/conversation/codexRuntimeStart.js +431 -0
- package/src/server/conversation/codexRuntimeStop.js +324 -0
- package/src/server/conversation/codexSessionCleanup.js +25 -10
- package/src/server/conversation/codexSessionReconciliation.js +21 -7
- package/src/server/conversation/codexThreadReadiness.js +49 -52
- package/src/server/conversation/codexThreadSnapshot.js +210 -0
- package/src/server/conversation/codexThreadStatus.js +48 -62
- package/src/server/conversation/codexTurn.js +171 -55
- package/src/server/conversation/codexTurnActivity.js +210 -0
- package/src/server/conversation/codexTurnControl.js +44 -48
- package/src/server/conversation/codexTurnEndings.js +610 -0
- package/src/server/conversation/codexTurnRecovery.js +97 -848
- package/src/server/conversation/codexTurnState.js +138 -111
- package/src/server/conversation/completedResponses.js +227 -0
- package/src/server/conversation/configuration.js +2 -2
- package/src/server/conversation/continuity.js +43 -6
- package/src/server/conversation/conversationDelivery.js +394 -0
- package/src/server/conversation/conversationEntries.js +365 -0
- package/src/server/conversation/conversationEvents.js +192 -0
- package/src/server/conversation/conversationGoals.js +187 -0
- package/src/server/conversation/conversationHandles.js +237 -0
- package/src/server/conversation/conversationReads.js +206 -0
- package/src/server/conversation/conversationRefusals.js +58 -0
- package/src/server/conversation/conversationReplacement.js +254 -0
- package/src/server/conversation/conversationSending.js +273 -0
- package/src/server/conversation/conversationStopping.js +121 -0
- package/src/server/conversation/conversationTurnDelivery.js +413 -0
- package/src/server/conversation/conversationTurns.js +511 -0
- package/src/server/conversation/deliveryTiming.js +25 -3
- package/src/server/conversation/fileStorage.js +11 -6
- package/src/server/conversation/hookBridge.js +14 -3
- package/src/server/conversation/index.js +1 -1
- package/src/server/conversation/localExecution.js +82 -625
- package/src/server/conversation/nativeCommandCallbacks.js +10 -0
- package/src/server/conversation/nativeConversationLifecycle.js +379 -0
- package/src/server/conversation/nativeHistoryExport.js +27 -18
- package/src/server/conversation/normalize.js +9 -0
- package/src/server/conversation/openCodeClient.js +295 -366
- package/src/server/conversation/openCodeNativeHistory.js +141 -0
- package/src/server/conversation/openCodeNativeSession.js +79 -0
- package/src/server/conversation/openCodeProcess.js +109 -53
- package/src/server/conversation/openCodeProcessOwner.js +565 -0
- package/src/server/conversation/openCodeRuntime.js +111 -1814
- package/src/server/conversation/openCodeSessionTurns.js +547 -0
- package/src/server/conversation/openCodeTemporaryConversations.js +394 -0
- package/src/server/conversation/openCodeTools.js +28 -14
- package/src/server/conversation/openCodeTurn.js +80 -74
- package/src/server/conversation/openCodeTurnMonitor.js +388 -0
- package/src/server/conversation/processIdentity.js +582 -0
- package/src/server/conversation/provider.js +21 -6
- package/src/server/conversation/providers/api.js +268 -107
- package/src/server/conversation/providers/claude.js +29 -6
- package/src/server/conversation/providers/claudeDriver.js +325 -250
- package/src/server/conversation/providers/codex.js +69 -33
- package/src/server/conversation/providers/codexDriver.js +503 -1081
- package/src/server/conversation/providers/codexDriverConnection.js +331 -0
- package/src/server/conversation/providers/codexDriverTurns.js +464 -0
- package/src/server/conversation/providers/opencode.js +30 -4
- package/src/server/conversation/providers/opencodeDriver.js +321 -659
- package/src/server/conversation/providers/opencodeStandalone.js +475 -0
- package/src/server/conversation/providers/scoped.js +64 -19
- package/src/server/conversation/runtime.js +171 -2863
- package/src/server/conversation/storage.js +91 -50
- package/src/server/conversation/streams.js +15 -2
- package/src/server/conversation/structuredOutput.js +7 -11
- package/src/server/conversation/systemPrompt.js +13 -1
- package/src/server/conversation/tools.js +47 -15
- package/src/server/conversation/transcript.js +49 -20
- package/src/server/hosts/claudeTurn.js +2 -4
- package/src/server/hosts/codexConfiguration.js +6 -8
- package/src/server/hosts/codexEvents.js +4 -2
- package/src/server/hosts/codexProcess.js +1 -1
- package/src/server/hosts/codexProvider.js +11 -9
- package/src/server/hosts/codexTurn.js +3 -3
- package/src/server/hosts/openCodeClient.js +4 -2
- package/src/server/index.js +0 -2
- package/src/server/lib/aiConnectionClient.js +35 -25
- package/src/server/lib/ndjson.js +1 -0
- package/src/server/lib/providers/anthropicClient.js +15 -6
- package/src/server/lib/providers/common.js +10 -6
- package/src/server/lib/providers/openAiCompatibleClient.js +40 -23
- package/src/server/lib/serviceToolCatalog.js +29 -283
- package/src/server/lib/serviceToolEntries.js +270 -0
- package/src/server/types.js +78 -0
- package/src/shared/assistantResource.js +0 -23
- package/src/shared/conversation/answerChoiceSugar.js +2 -14
- package/src/shared/conversation/messageInputSugar.js +18 -0
- package/src/shared/conversation/numberedQuestionSugar.js +6 -16
- package/src/shared/conversation/pagination.js +1 -1
- package/src/shared/conversation/questions.js +1 -0
- package/src/shared/conversation/streaming.js +1 -0
- package/src/shared/index.js +0 -1
- package/src/testing/conversationStorageContract.js +20 -0
- package/test/aiConnectionClient.test.js +42 -1
- package/test/apiConversationDriver.test.js +217 -38
- package/test/assistantBoundedToolLoop.test.js +1 -1
- package/test/claudeConversationSession.test.js +15 -11
- package/test/claudeInstructionResume.test.js +1 -1
- package/test/claudeProcess.test.js +9 -9
- package/test/claudeTurn.test.js +21 -8
- package/test/codexAccountChange.test.js +5 -3
- package/test/codexConversationSession.test.js +22 -21
- package/test/codexEvents.test.js +3 -1
- package/test/codexHelperDeletion.test.js +3 -7
- package/test/codexIsolation.test.js +6 -6
- package/test/codexModelCatalog.test.js +6 -7
- package/test/codexProcess.test.js +3 -3
- package/test/codexThreadSelection.test.js +4 -1
- package/test/codexTurn.test.js +29 -20
- package/test/conversationApiFacilities.test.js +11 -9
- package/test/conversationAttachments.test.js +3 -3
- package/test/conversationConfiguration.test.js +4 -4
- package/test/conversationNativeStorage.test.js +11 -10
- package/test/conversationReplacement.test.js +13 -13
- package/test/conversationRuntime.test.js +9 -5
- package/test/conversationSession.test.js +78 -22
- package/test/conversationTools.test.js +47 -26
- package/test/fileConversationStorage.test.js +10 -3
- package/test/fixtures/codexHelperThreadLedger.js +3 -3
- package/test/frameworkActions.test.js +33 -18
- package/test/localConversationExecution.test.js +4 -4
- package/test/localExecution.test.js +1 -1
- package/test/openCodeConnectionChange.test.js +3 -2
- package/test/openCodeRuntime.test.js +8 -7
- package/test/openCodeTools.test.js +1 -1
- package/test/opencodeConversationSession.test.js +4 -3
- package/test/serviceToolCatalog.test.js +3 -8
- package/src/server/lib/assistantCompletion.js +0 -190
- package/src/server/lib/assistantToolLoop.js +0 -259
|
@@ -1,30 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
codexAppServerThreadStatus,
|
|
7
|
-
codexAppServerReadThreadStatus,
|
|
8
|
-
normalizeCodexRunText,
|
|
9
|
-
codexAppServerAgentRun,
|
|
10
|
-
codexAppServerPendingUserMessageClientIds,
|
|
11
|
-
codexAppServerPendingUserMessageOwnership,
|
|
12
|
-
codexAppServerTurnOwnsActiveGoal,
|
|
13
|
-
codexAppServerTurnCanReceiveProviderCompletion,
|
|
14
|
-
codexAppServerTurnAwaitsProviderIdentity,
|
|
15
|
-
codexAppServerTurnCanReceiveProviderActivity,
|
|
16
|
-
codexAppServerTurnCanAdoptSuccessor,
|
|
17
|
-
codexAppServerTurnKey,
|
|
18
|
-
CODEX_APP_SERVER_RUN_STATE
|
|
19
|
-
} from "./codexTurnState.js";
|
|
20
|
-
import {
|
|
21
|
-
codexAppServerProviderTurnForOperation,
|
|
22
|
-
codexAppServerThreadTurnId,
|
|
23
|
-
codexAppServerThreadError
|
|
24
|
-
} from "./codexEvents.js";
|
|
1
|
+
import { codexAppServerTurnStatusIsActive, codexAppServerTurnStatusIsComplete, codexAppServerTurnStatusIsSuccessfulComplete, codexAppServerTurnStatusIsProviderFailure, codexAppServerThreadStatus, codexAppServerReadThreadStatus, codexAppServerAgentRun, codexAppServerPendingUserMessageOwnership, codexAppServerTurnCanAdoptSuccessor } from "./codexTurnState.js";
|
|
2
|
+
import { codexAppServerProviderTurnForOperation, codexAppServerThreadTurnId, codexAppServerThreadError } from "./codexThreadSnapshot.js";
|
|
3
|
+
import { createCodexTurnActivity } from "./codexTurnActivity.js";
|
|
4
|
+
import { createCodexTurnEndings } from "./codexTurnEndings.js";
|
|
5
|
+
import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
25
6
|
|
|
26
|
-
|
|
27
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Active and finalizing turn recovery: the timers that reread the provider, and the reconciliation of the tracked
|
|
9
|
+
* turn with what the provider reports. Timers and receipts remain owned by the shared journal, output and settlement.
|
|
10
|
+
* @param {object} dependencies
|
|
11
|
+
* @param {import("./codexRunJournal.js").CodexRunJournal} dependencies.journal
|
|
12
|
+
* @param {import("./codexOutput.js").CodexAppServerOutput} dependencies.output
|
|
13
|
+
* @param {import("./codexResultSettlement.js").CodexResultSettlement} dependencies.settlement
|
|
14
|
+
* @param {Set<string>} dependencies.promptDeliveries
|
|
15
|
+
* @param {import("./codexTurn.js").CodexSessionNamespace} dependencies.namespace
|
|
16
|
+
* @param {import("./codexTurn.js").CodexCreateRuntime} dependencies.createRuntime
|
|
17
|
+
* @param {import("./codexTurn.js").CodexCreateStore} dependencies.createStore
|
|
18
|
+
* @param {(input: { sessionId: string, runtime: any, session: object }) => Promise<any>} dependencies.acquireProvider
|
|
19
|
+
* @param {import("./codexTurn.js").CodexTurnStateReader} dependencies.turnState
|
|
20
|
+
* @param {import("./codexTurn.js").CodexAgentRunTurnStateReader} dependencies.turnStateFromAgentRun
|
|
21
|
+
* @param {import("./codexTurn.js").CodexDebugLog} dependencies.debugLog
|
|
22
|
+
* @param {import("./codexTurn.js").CodexDebugError} dependencies.debugError
|
|
23
|
+
* @param {import("./codexTurn.js").CodexCaptureContext} dependencies.captureContext
|
|
24
|
+
* @param {import("./codexTurn.js").CodexRunInContext} dependencies.runInContext
|
|
25
|
+
* @param {number} dependencies.activeReconcileMs
|
|
26
|
+
* @param {boolean} dependencies.finalizingGraceAfterHistoryRead
|
|
27
|
+
* @param {number} dependencies.failureDetailGraceMs
|
|
28
|
+
* @param {import("./codexNotificationQueue.js").CodexAppServerNotificationQueue} dependencies.notificationQueue
|
|
29
|
+
* @param {(session: object) => boolean} dependencies.hasRuntime
|
|
30
|
+
* @param {import("./codexTurn.js").CodexAdmissionRecovery} dependencies.recoverAdmission
|
|
31
|
+
* @param {import("./codexTurn.js").CodexTurnOutcomes} dependencies.turnOutcomes
|
|
32
|
+
* @param {(...details: any[]) => Promise<unknown>} dependencies.outcomeNotice
|
|
33
|
+
* @param {(details: { error?: string }) => string} dependencies.resultDeliveryFailureMessage
|
|
34
|
+
*/
|
|
28
35
|
export function createCodexTurnRecovery({
|
|
29
36
|
journal,
|
|
30
37
|
output,
|
|
@@ -50,135 +57,52 @@ export function createCodexTurnRecovery({
|
|
|
50
57
|
outcomeNotice,
|
|
51
58
|
resultDeliveryFailureMessage
|
|
52
59
|
}) {
|
|
53
|
-
const {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
adoptSuccessorTurn: adoptCodexAppServerSuccessorTurn
|
|
83
|
-
} = settlement;
|
|
84
|
-
const codexAppServerPromptDeliveries = promptDeliveries;
|
|
85
|
-
const retainFinalizingTimer = finalizingGraceAfterHistoryRead || failureDetailGraceMs > 0;
|
|
60
|
+
const activity = createCodexTurnActivity({
|
|
61
|
+
journal,
|
|
62
|
+
output,
|
|
63
|
+
settlement,
|
|
64
|
+
createRuntime,
|
|
65
|
+
createStore,
|
|
66
|
+
debugLog,
|
|
67
|
+
turnState,
|
|
68
|
+
turnStateFromAgentRun,
|
|
69
|
+
scheduleActiveRecovery: scheduleCodexAppServerActiveRecovery
|
|
70
|
+
});
|
|
71
|
+
const endings = createCodexTurnEndings({
|
|
72
|
+
journal,
|
|
73
|
+
output,
|
|
74
|
+
settlement,
|
|
75
|
+
createRuntime,
|
|
76
|
+
debugLog,
|
|
77
|
+
debugError,
|
|
78
|
+
turnState,
|
|
79
|
+
failureDetailGraceMs,
|
|
80
|
+
turnOutcomes,
|
|
81
|
+
outcomeNotice,
|
|
82
|
+
resultDeliveryFailureMessage,
|
|
83
|
+
captureContext,
|
|
84
|
+
runInContext,
|
|
85
|
+
notificationQueue,
|
|
86
|
+
finalizingGraceAfterHistoryRead,
|
|
87
|
+
scheduleActiveRecovery: scheduleCodexAppServerActiveRecovery
|
|
88
|
+
});
|
|
86
89
|
|
|
87
90
|
function scheduleCodexAppServerActiveRecovery(sessionId = "", delayMs = activeReconcileMs) {
|
|
88
|
-
const normalizedSessionId =
|
|
91
|
+
const normalizedSessionId = normalizeText(sessionId);
|
|
89
92
|
const sessionKey = namespace(normalizedSessionId);
|
|
90
93
|
const projectContext = captureContext();
|
|
91
|
-
if (!normalizedSessionId ||
|
|
94
|
+
if (!normalizedSessionId || journal.activeTimers.has(sessionKey)) {
|
|
92
95
|
return;
|
|
93
96
|
}
|
|
94
97
|
const timer = setTimeout(() => {
|
|
95
|
-
|
|
98
|
+
journal.activeTimers.delete(sessionKey);
|
|
96
99
|
void runInContext(
|
|
97
100
|
projectContext,
|
|
98
101
|
() => recoverCodexAppServerActiveTurn(normalizedSessionId)
|
|
99
102
|
);
|
|
100
103
|
}, delayMs);
|
|
101
|
-
timer.unref
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function scheduleCodexAppServerFinalizingRecovery(sessionId = "", threadId = "", turnId = "", {
|
|
106
|
-
completedAt = "",
|
|
107
|
-
status = "completed",
|
|
108
|
-
updatedAt = "",
|
|
109
|
-
failureDetail = null
|
|
110
|
-
} = {}) {
|
|
111
|
-
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
112
|
-
const normalizedThreadId = normalizeCodexRunText(threadId);
|
|
113
|
-
const normalizedTurnId = normalizeCodexRunText(turnId);
|
|
114
|
-
if (!normalizedSessionId || !normalizedThreadId || !normalizedTurnId) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
clearCodexAppServerFinalizingTimer(normalizedSessionId, normalizedThreadId, normalizedTurnId);
|
|
118
|
-
const key = codexAppServerResultFinalizationKey(
|
|
119
|
-
normalizedSessionId,
|
|
120
|
-
normalizedThreadId,
|
|
121
|
-
normalizedTurnId
|
|
122
|
-
);
|
|
123
|
-
const projectContext = captureContext();
|
|
124
|
-
const delayMs = failureDetail
|
|
125
|
-
? Math.max(0, failureDetail.expiresAt - Date.now())
|
|
126
|
-
: codexAppServerFinalizingRemainingMs({ completedAt, state: "finalizing", updatedAt });
|
|
127
|
-
// One record per pending deadline: `recovery` is the in-flight expiry
|
|
128
|
-
// (retained-timer policy only), `expiresAt` the first deadline that a later
|
|
129
|
-
// failure-detail grace may not exceed, `failureDetail` a deferred provider
|
|
130
|
-
// failure, and `startedAt` the post-read clock that rereads must keep.
|
|
131
|
-
const entry = {
|
|
132
|
-
timer: null,
|
|
133
|
-
recovery: null,
|
|
134
|
-
expiresAt: failureDetailGraceMs > 0 ? Date.now() + delayMs : null,
|
|
135
|
-
failureDetail,
|
|
136
|
-
startedAt: !failureDetail && finalizingGraceAfterHistoryRead ? completedAt : ""
|
|
137
|
-
};
|
|
138
|
-
entry.timer = setTimeout(() => {
|
|
139
|
-
if (failureDetail) {
|
|
140
|
-
notificationQueue.run({ projectContext, provider: failureDetail.provider, sessionId: normalizedSessionId }, async () => {
|
|
141
|
-
if (codexAppServerFinalizingTimers.get(key) !== entry) return;
|
|
142
|
-
try {
|
|
143
|
-
return await stopCodexAppServerTurnWithProviderFailure(normalizedSessionId, normalizedThreadId, normalizedTurnId,
|
|
144
|
-
{ ...failureDetail, failureDetailReady: true });
|
|
145
|
-
} finally {
|
|
146
|
-
if (codexAppServerFinalizingTimers.get(key) === entry) {
|
|
147
|
-
clearCodexAppServerFinalizingTimer(normalizedSessionId, normalizedThreadId, normalizedTurnId);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
// The post-read policy keeps its first clock while expiry rereads history.
|
|
154
|
-
if (!retainFinalizingTimer) codexAppServerFinalizingTimers.delete(key);
|
|
155
|
-
const recovery = runInContext(
|
|
156
|
-
projectContext,
|
|
157
|
-
() => recoverCodexAppServerFinalizingTurn(
|
|
158
|
-
normalizedSessionId,
|
|
159
|
-
normalizedThreadId,
|
|
160
|
-
normalizedTurnId,
|
|
161
|
-
{ status, timerRecovery: finalizingGraceAfterHistoryRead }
|
|
162
|
-
)
|
|
163
|
-
);
|
|
164
|
-
if (retainFinalizingTimer) {
|
|
165
|
-
entry.recovery = recovery;
|
|
166
|
-
void recovery.then(
|
|
167
|
-
() => { if (entry.recovery === recovery) entry.recovery = null; },
|
|
168
|
-
error => {
|
|
169
|
-
if (entry.recovery === recovery) entry.recovery = null;
|
|
170
|
-
debugLog("appServerFinalizingRecovery.error", {
|
|
171
|
-
error: debugError(error), sessionId: normalizedSessionId,
|
|
172
|
-
threadId: normalizedThreadId, turnId: normalizedTurnId
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
);
|
|
176
|
-
} else {
|
|
177
|
-
void recovery;
|
|
178
|
-
}
|
|
179
|
-
}, delayMs);
|
|
180
|
-
entry.timer.unref?.();
|
|
181
|
-
codexAppServerFinalizingTimers.set(key, entry);
|
|
104
|
+
timer.unref();
|
|
105
|
+
journal.activeTimers.set(sessionKey, timer);
|
|
182
106
|
}
|
|
183
107
|
|
|
184
108
|
async function reconcileCodexAppServerActiveTurn(session = {}, {
|
|
@@ -186,15 +110,15 @@ export function createCodexTurnRecovery({
|
|
|
186
110
|
runtime = null,
|
|
187
111
|
providerError = null
|
|
188
112
|
} = {}) {
|
|
189
|
-
const sessionId =
|
|
113
|
+
const sessionId = normalizeText(session.sessionId);
|
|
190
114
|
const trackedTurn = turnState(session);
|
|
191
115
|
if (!sessionId || !trackedTurn.active || !trackedTurn.threadId || !hasRuntime(session)) {
|
|
192
116
|
return session;
|
|
193
117
|
}
|
|
194
118
|
const provider = suppliedProvider || await acquireProvider({ sessionId, runtime, session });
|
|
195
|
-
if (
|
|
119
|
+
if (!provider) {
|
|
196
120
|
if (trackedTurn.state === "finalizing") {
|
|
197
|
-
await
|
|
121
|
+
await endings.recoverFinalizingTurn(
|
|
198
122
|
sessionId,
|
|
199
123
|
trackedTurn.threadId,
|
|
200
124
|
trackedTurn.turnId,
|
|
@@ -213,7 +137,7 @@ export function createCodexTurnRecovery({
|
|
|
213
137
|
let thread = await codexAppServerReadThreadStatus(provider, trackedTurn.threadId);
|
|
214
138
|
let status = codexAppServerThreadStatus(thread);
|
|
215
139
|
let providerTurnId = codexAppServerThreadTurnId(thread);
|
|
216
|
-
const promptDeliveryIsLocal =
|
|
140
|
+
const promptDeliveryIsLocal = promptDeliveries.has(
|
|
217
141
|
namespace(sessionId)
|
|
218
142
|
);
|
|
219
143
|
if (
|
|
@@ -224,8 +148,8 @@ export function createCodexTurnRecovery({
|
|
|
224
148
|
const ownership = codexAppServerPendingUserMessageOwnership(
|
|
225
149
|
codexAppServerAgentRun(currentSession)
|
|
226
150
|
);
|
|
227
|
-
if (!ownership
|
|
228
|
-
return
|
|
151
|
+
if (!ownership) {
|
|
152
|
+
return journal.failOrphanedPromptDelivery(
|
|
229
153
|
activeRuntime,
|
|
230
154
|
currentSession,
|
|
231
155
|
currentTurn
|
|
@@ -236,7 +160,7 @@ export function createCodexTurnRecovery({
|
|
|
236
160
|
clientMessageId: ownership.clientId
|
|
237
161
|
});
|
|
238
162
|
if (!ownedProviderTurn) {
|
|
239
|
-
return
|
|
163
|
+
return journal.failOrphanedPromptDelivery(
|
|
240
164
|
activeRuntime,
|
|
241
165
|
currentSession,
|
|
242
166
|
currentTurn
|
|
@@ -249,20 +173,20 @@ export function createCodexTurnRecovery({
|
|
|
249
173
|
status = codexAppServerThreadStatus(thread);
|
|
250
174
|
providerTurnId = codexAppServerThreadTurnId(thread);
|
|
251
175
|
if (!providerTurnId) {
|
|
252
|
-
return
|
|
176
|
+
return journal.failOrphanedPromptDelivery(
|
|
253
177
|
activeRuntime,
|
|
254
178
|
currentSession,
|
|
255
179
|
currentTurn
|
|
256
180
|
);
|
|
257
181
|
}
|
|
258
|
-
await
|
|
182
|
+
await activity.markProviderTurnActive(sessionId, {
|
|
259
183
|
inputSource: ownership.inputSource,
|
|
260
184
|
source: "owned_prompt_recovery",
|
|
261
185
|
status: codexAppServerTurnStatusIsActive(status) ? status : "inProgress",
|
|
262
186
|
threadId: currentTurn.threadId,
|
|
263
187
|
turnId: providerTurnId
|
|
264
188
|
});
|
|
265
|
-
await
|
|
189
|
+
await journal.writeUserMessageOwnership(
|
|
266
190
|
activeRuntime.store,
|
|
267
191
|
sessionId,
|
|
268
192
|
ownership.clientId,
|
|
@@ -285,7 +209,7 @@ export function createCodexTurnRecovery({
|
|
|
285
209
|
providerTurnId &&
|
|
286
210
|
codexAppServerTurnCanAdoptSuccessor(currentTurn, currentTurn.threadId, providerTurnId)
|
|
287
211
|
) {
|
|
288
|
-
const adoption = await
|
|
212
|
+
const adoption = await settlement.adoptSuccessorTurn(sessionId, {
|
|
289
213
|
previousTurnId: currentTurn.turnId,
|
|
290
214
|
source: "active_reconciliation",
|
|
291
215
|
status: "inProgress",
|
|
@@ -302,14 +226,14 @@ export function createCodexTurnRecovery({
|
|
|
302
226
|
}
|
|
303
227
|
}
|
|
304
228
|
if (currentTurn.state === "finalizing") {
|
|
305
|
-
await
|
|
229
|
+
await endings.recoverFinalizingTurn(sessionId, currentTurn.threadId, currentTurn.turnId, {
|
|
306
230
|
status: currentTurn.status || "completed"
|
|
307
231
|
});
|
|
308
232
|
return activeRuntime.getSession(sessionId);
|
|
309
233
|
}
|
|
310
234
|
if (currentTurn.state === "starting") {
|
|
311
235
|
if (codexAppServerTurnStatusIsActive(status) && providerTurnId) {
|
|
312
|
-
await
|
|
236
|
+
await activity.markProviderTurnActive(sessionId, {
|
|
313
237
|
source: "active_reconciliation",
|
|
314
238
|
status,
|
|
315
239
|
threadId: currentTurn.threadId,
|
|
@@ -326,9 +250,9 @@ export function createCodexTurnRecovery({
|
|
|
326
250
|
return currentSession;
|
|
327
251
|
}
|
|
328
252
|
if (!providerTurnId || !codexAppServerTurnStatusIsComplete(status)) {
|
|
329
|
-
return
|
|
253
|
+
return journal.failOrphanedPromptDelivery(activeRuntime, currentSession, currentTurn);
|
|
330
254
|
}
|
|
331
|
-
await
|
|
255
|
+
await activity.markProviderTurnActive(sessionId, {
|
|
332
256
|
source: "active_reconciliation",
|
|
333
257
|
status: "inProgress",
|
|
334
258
|
threadId: currentTurn.threadId,
|
|
@@ -355,14 +279,14 @@ export function createCodexTurnRecovery({
|
|
|
355
279
|
});
|
|
356
280
|
if (codexAppServerTurnStatusIsProviderFailure(status)) {
|
|
357
281
|
const exactError = providerError?.threadId === currentTurn.threadId && providerError?.turnId === completedTurnId;
|
|
358
|
-
await
|
|
282
|
+
await endings.stopTurnWithProviderFailure(sessionId, currentTurn.threadId, completedTurnId, {
|
|
359
283
|
error: exactError ? providerError.error : codexAppServerThreadError(thread),
|
|
360
284
|
failureDetailReady: exactError,
|
|
361
285
|
provider,
|
|
362
286
|
status
|
|
363
287
|
});
|
|
364
288
|
} else if (codexAppServerTurnStatusIsSuccessfulComplete(status)) {
|
|
365
|
-
await
|
|
289
|
+
await endings.completeTurn(sessionId, currentTurn.threadId, completedTurnId, {
|
|
366
290
|
status,
|
|
367
291
|
verifyInactive: false
|
|
368
292
|
});
|
|
@@ -370,338 +294,24 @@ export function createCodexTurnRecovery({
|
|
|
370
294
|
return activeRuntime.getSession(sessionId);
|
|
371
295
|
}
|
|
372
296
|
|
|
373
|
-
async function codexAppServerProviderBlocksTurnRelease(sessionId = "", provider = null, threadId = "", turnId = "", {
|
|
374
|
-
source = ""
|
|
375
|
-
} = {}) {
|
|
376
|
-
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
377
|
-
const normalizedThreadId = normalizeCodexRunText(threadId);
|
|
378
|
-
const normalizedTurnId = normalizeCodexRunText(turnId);
|
|
379
|
-
if (!normalizedSessionId || !normalizedThreadId) {
|
|
380
|
-
return false;
|
|
381
|
-
}
|
|
382
|
-
const runtime = await createRuntime();
|
|
383
|
-
const session = await runtime.getSession(normalizedSessionId);
|
|
384
|
-
const turn = turnState(session);
|
|
385
|
-
if (!turn.active || !codexAppServerTurnCanReceiveProviderActivity(turn, normalizedThreadId, normalizedTurnId)) {
|
|
386
|
-
return false;
|
|
387
|
-
}
|
|
388
|
-
try {
|
|
389
|
-
const providerThread = await codexAppServerReadThreadStatus(provider, normalizedThreadId, {
|
|
390
|
-
observeLatestTurn: true
|
|
391
|
-
});
|
|
392
|
-
if (!providerThread) {
|
|
393
|
-
return false;
|
|
394
|
-
}
|
|
395
|
-
const status = codexAppServerThreadStatus(providerThread);
|
|
396
|
-
const providerTurnId = codexAppServerThreadTurnId(providerThread);
|
|
397
|
-
if (
|
|
398
|
-
providerTurnId &&
|
|
399
|
-
providerTurnId !== normalizeCodexRunText(turn.turnId)
|
|
400
|
-
) {
|
|
401
|
-
debugLog("appServerTurn.releaseAllowedSuccessor", {
|
|
402
|
-
providerTurnId,
|
|
403
|
-
sessionId: normalizedSessionId,
|
|
404
|
-
source: normalizeCodexRunText(source),
|
|
405
|
-
threadId: normalizedThreadId,
|
|
406
|
-
turnId: turn.turnId
|
|
407
|
-
});
|
|
408
|
-
return false;
|
|
409
|
-
}
|
|
410
|
-
if (!codexAppServerTurnStatusIsActive(status)) {
|
|
411
|
-
return false;
|
|
412
|
-
}
|
|
413
|
-
debugLog("appServerTurn.releaseBlockedActive", {
|
|
414
|
-
sessionId: normalizedSessionId,
|
|
415
|
-
source: normalizeCodexRunText(source),
|
|
416
|
-
status,
|
|
417
|
-
threadId: normalizedThreadId,
|
|
418
|
-
turnId: normalizedTurnId || turn.turnId
|
|
419
|
-
});
|
|
420
|
-
scheduleCodexAppServerActiveRecovery(normalizedSessionId);
|
|
421
|
-
return true;
|
|
422
|
-
} catch (error) {
|
|
423
|
-
debugLog("appServerTurn.releaseCheck.error", {
|
|
424
|
-
error: debugError(error),
|
|
425
|
-
sessionId: normalizedSessionId,
|
|
426
|
-
source: normalizeCodexRunText(source),
|
|
427
|
-
threadId: normalizedThreadId,
|
|
428
|
-
turnId: normalizedTurnId || turn.turnId
|
|
429
|
-
});
|
|
430
|
-
return false;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
async function markCodexAppServerTurnActive(sessionId = "", input = {}) {
|
|
435
|
-
if (input.requireTrackedTurn === true) {
|
|
436
|
-
const runtime = await createRuntime();
|
|
437
|
-
const session = await runtime.getSession(sessionId);
|
|
438
|
-
const turn = turnState(session);
|
|
439
|
-
if (!codexAppServerTurnCanReceiveProviderActivity(turn, input.threadId, input.turnId)) {
|
|
440
|
-
debugLog("appServerTurn.active.ignored", {
|
|
441
|
-
currentState: turn.state,
|
|
442
|
-
currentStatus: turn.status,
|
|
443
|
-
currentThreadId: turn.threadId,
|
|
444
|
-
currentTurnId: turn.turnId,
|
|
445
|
-
sessionId: normalizeCodexRunText(sessionId),
|
|
446
|
-
threadId: normalizeCodexRunText(input.threadId),
|
|
447
|
-
turnId: normalizeCodexRunText(input.turnId)
|
|
448
|
-
});
|
|
449
|
-
return {
|
|
450
|
-
ok: true,
|
|
451
|
-
processed: false,
|
|
452
|
-
reason: "untracked_terminal_turn"
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
const status = normalizeCodexRunText(input.status) || "inProgress";
|
|
457
|
-
const result = await publishCodexAppServerAgentRun(sessionId, {
|
|
458
|
-
inputSource: normalizeCodexRunText(input.inputSource),
|
|
459
|
-
phase: input.phase,
|
|
460
|
-
publishReason: "codex-app-server-turn-active",
|
|
461
|
-
observedRun: input.observedRun,
|
|
462
|
-
runState: status === "starting" ? CODEX_APP_SERVER_RUN_STATE.STARTING : CODEX_APP_SERVER_RUN_STATE.ACTIVE,
|
|
463
|
-
status,
|
|
464
|
-
threadId: normalizeCodexRunText(input.threadId),
|
|
465
|
-
turnId: normalizeCodexRunText(input.turnId)
|
|
466
|
-
});
|
|
467
|
-
if (status === "starting") {
|
|
468
|
-
scheduleCodexAppServerActiveRecovery(sessionId);
|
|
469
|
-
} else {
|
|
470
|
-
clearCodexAppServerActiveTimer(sessionId);
|
|
471
|
-
}
|
|
472
|
-
return result;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
async function markCodexAppServerProviderTurnActive(sessionId = "", input = {}) {
|
|
476
|
-
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
477
|
-
const normalizedThreadId = normalizeCodexRunText(input.threadId);
|
|
478
|
-
const normalizedTurnId = normalizeCodexRunText(input.turnId);
|
|
479
|
-
const requestedStatus = normalizeCodexRunText(input.status) || "inProgress";
|
|
480
|
-
const store = await createStore(normalizedSessionId);
|
|
481
|
-
const persistedRun = await readCodexAppServerAgentRunForSession(
|
|
482
|
-
store,
|
|
483
|
-
normalizedSessionId
|
|
484
|
-
);
|
|
485
|
-
const persistedTurn = turnStateFromAgentRun(persistedRun || {});
|
|
486
|
-
const requestedInputSource = normalizeCodexRunText(input.inputSource);
|
|
487
|
-
if (
|
|
488
|
-
persistedTurn.active &&
|
|
489
|
-
persistedTurn.state === "active" &&
|
|
490
|
-
persistedTurn.threadId === normalizedThreadId &&
|
|
491
|
-
persistedTurn.turnId === normalizedTurnId &&
|
|
492
|
-
codexAppServerTurnStatusIsActive(requestedStatus) &&
|
|
493
|
-
(!requestedInputSource || requestedInputSource === persistedTurn.inputSource)
|
|
494
|
-
) {
|
|
495
|
-
clearCodexAppServerActiveTimer(normalizedSessionId);
|
|
496
|
-
return {
|
|
497
|
-
ok: true,
|
|
498
|
-
processed: false,
|
|
499
|
-
reason: "already_active"
|
|
500
|
-
};
|
|
501
|
-
}
|
|
502
|
-
const runtime = await createRuntime();
|
|
503
|
-
let session = await runtime.getSession(normalizedSessionId);
|
|
504
|
-
let turn = turnState(session);
|
|
505
|
-
if (
|
|
506
|
-
input.observedRun &&
|
|
507
|
-
[CODEX_APP_SERVER_RUN_STATE.FAILED, CODEX_APP_SERVER_RUN_STATE.INTERRUPTED].includes(turn.runState) &&
|
|
508
|
-
turn.threadId === normalizedThreadId &&
|
|
509
|
-
turn.turnId === normalizedTurnId &&
|
|
510
|
-
!codexAppServerTurnResultWasProcessed(session, normalizedThreadId, normalizedTurnId)
|
|
511
|
-
) {
|
|
512
|
-
const recovered = await markCodexAppServerTurnActive(normalizedSessionId, {
|
|
513
|
-
inputSource: turn.inputSource,
|
|
514
|
-
observedRun: input.observedRun,
|
|
515
|
-
status: requestedStatus,
|
|
516
|
-
threadId: normalizedThreadId,
|
|
517
|
-
turnId: normalizedTurnId
|
|
518
|
-
});
|
|
519
|
-
if (recovered.processed !== false) {
|
|
520
|
-
codexAppServerCompletedTurns.delete(codexAppServerTurnKey(normalizedThreadId, normalizedTurnId));
|
|
521
|
-
codexAppServerFinalizedTurns.delete(codexAppServerResultFinalizationKey(
|
|
522
|
-
normalizedSessionId, normalizedThreadId, normalizedTurnId
|
|
523
|
-
));
|
|
524
|
-
}
|
|
525
|
-
return recovered;
|
|
526
|
-
}
|
|
527
|
-
if (codexAppServerTurnWasCompleted(session, normalizedThreadId, normalizedTurnId)) {
|
|
528
|
-
debugLog("appServerProviderTurn.completed.ignored", {
|
|
529
|
-
currentState: turn.state,
|
|
530
|
-
currentThreadId: turn.threadId,
|
|
531
|
-
currentTurnId: turn.turnId,
|
|
532
|
-
sessionId: normalizedSessionId,
|
|
533
|
-
threadId: normalizedThreadId,
|
|
534
|
-
turnId: normalizedTurnId
|
|
535
|
-
});
|
|
536
|
-
return {
|
|
537
|
-
ok: true,
|
|
538
|
-
processed: false,
|
|
539
|
-
reason: "completed_turn"
|
|
540
|
-
};
|
|
541
|
-
}
|
|
542
|
-
if (
|
|
543
|
-
turn.state === "finalizing" &&
|
|
544
|
-
codexAppServerTurnCanAdoptSuccessor(turn, normalizedThreadId, normalizedTurnId) &&
|
|
545
|
-
codexAppServerTurnResultWasProcessed(session, normalizedThreadId, turn.turnId)
|
|
546
|
-
) {
|
|
547
|
-
await finalizeCodexAppServerAssistantResult(
|
|
548
|
-
normalizedSessionId,
|
|
549
|
-
normalizedThreadId,
|
|
550
|
-
turn.turnId,
|
|
551
|
-
{
|
|
552
|
-
status: turn.status || "completed"
|
|
553
|
-
}
|
|
554
|
-
);
|
|
555
|
-
session = await runtime.getSession(normalizedSessionId);
|
|
556
|
-
turn = turnState(session);
|
|
557
|
-
}
|
|
558
|
-
const currentRun = codexAppServerAgentRun(session);
|
|
559
|
-
const pendingInputSource = codexAppServerPendingUserMessageClientIds(currentRun).length > 0
|
|
560
|
-
? codexAppServerRunInputSource(currentRun)
|
|
561
|
-
: "";
|
|
562
|
-
const goalInputSource = codexAppServerTurnOwnsActiveGoal(turn, normalizedThreadId)
|
|
563
|
-
? codexAppServerRunInputSource(currentRun)
|
|
564
|
-
: "";
|
|
565
|
-
const inputSource = normalizeCodexRunText(input.inputSource) || pendingInputSource || goalInputSource;
|
|
566
|
-
if (codexAppServerTurnCanReceiveProviderActivity(turn, normalizedThreadId, normalizedTurnId)) {
|
|
567
|
-
return markCodexAppServerTurnActive(normalizedSessionId, {
|
|
568
|
-
inputSource,
|
|
569
|
-
status: requestedStatus,
|
|
570
|
-
threadId: normalizedThreadId,
|
|
571
|
-
turnId: normalizedTurnId
|
|
572
|
-
});
|
|
573
|
-
}
|
|
574
|
-
if (codexAppServerTurnCanAdoptSuccessor(turn, normalizedThreadId, normalizedTurnId)) {
|
|
575
|
-
return adoptCodexAppServerSuccessorTurn(normalizedSessionId, {
|
|
576
|
-
previousTurnId: turn.turnId,
|
|
577
|
-
source: normalizeCodexRunText(input.source) || "provider_activity",
|
|
578
|
-
status: requestedStatus,
|
|
579
|
-
threadId: normalizedThreadId,
|
|
580
|
-
turnId: normalizedTurnId
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
if (turn.active || !normalizedTurnId) {
|
|
584
|
-
debugLog("appServerProviderTurn.active.ignored", {
|
|
585
|
-
currentState: turn.state,
|
|
586
|
-
currentStatus: turn.status,
|
|
587
|
-
currentThreadId: turn.threadId,
|
|
588
|
-
currentTurnId: turn.turnId,
|
|
589
|
-
sessionId: normalizedSessionId,
|
|
590
|
-
threadId: normalizedThreadId,
|
|
591
|
-
turnId: normalizedTurnId
|
|
592
|
-
});
|
|
593
|
-
return {
|
|
594
|
-
ok: true,
|
|
595
|
-
processed: false,
|
|
596
|
-
reason: turn.active ? "active_turn_mismatch" : "missing_turn"
|
|
597
|
-
};
|
|
598
|
-
}
|
|
599
|
-
return markCodexAppServerTurnActive(normalizedSessionId, {
|
|
600
|
-
inputSource: inputSource || "terminal",
|
|
601
|
-
status: requestedStatus,
|
|
602
|
-
threadId: normalizedThreadId,
|
|
603
|
-
turnId: normalizedTurnId
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
async function recoverCodexAppServerFinalizingTurn(sessionId = "", threadId = "", turnId = "", {
|
|
608
|
-
status = "completed", timerRecovery = false
|
|
609
|
-
} = {}) {
|
|
610
|
-
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
611
|
-
const normalizedThreadId = normalizeCodexRunText(threadId);
|
|
612
|
-
const normalizedTurnId = normalizeCodexRunText(turnId);
|
|
613
|
-
const key = codexAppServerResultFinalizationKey(normalizedSessionId, normalizedThreadId, normalizedTurnId);
|
|
614
|
-
const priorTimer = retainFinalizingTimer ? codexAppServerFinalizingTimers.get(key) : null;
|
|
615
|
-
if (!timerRecovery && priorTimer?.recovery) return priorTimer.recovery;
|
|
616
|
-
const runtime = await createRuntime();
|
|
617
|
-
const session = await runtime.getSession(normalizedSessionId);
|
|
618
|
-
const turn = turnState(session);
|
|
619
|
-
if (codexAppServerTurnOwnsActiveGoal(turn, normalizedThreadId)) {
|
|
620
|
-
clearCodexAppServerFinalizingTimer(
|
|
621
|
-
normalizedSessionId,
|
|
622
|
-
normalizedThreadId,
|
|
623
|
-
normalizedTurnId
|
|
624
|
-
);
|
|
625
|
-
return {
|
|
626
|
-
ok: true,
|
|
627
|
-
processed: false,
|
|
628
|
-
reason: "goal_continuation_pending"
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
const result = await finalizeCodexAppServerAssistantResult(
|
|
632
|
-
normalizedSessionId,
|
|
633
|
-
normalizedThreadId,
|
|
634
|
-
normalizedTurnId,
|
|
635
|
-
{
|
|
636
|
-
recoverFromProvider: true,
|
|
637
|
-
status
|
|
638
|
-
}
|
|
639
|
-
);
|
|
640
|
-
if (result?.processed) {
|
|
641
|
-
return result;
|
|
642
|
-
}
|
|
643
|
-
// A later failure owns the same first deadline, even when this successful
|
|
644
|
-
// history read was already in flight under the completion-based clock.
|
|
645
|
-
const currentTimer = codexAppServerFinalizingTimers.get(key);
|
|
646
|
-
if (currentTimer?.failureDetail) return result;
|
|
647
|
-
if (retainFinalizingTimer && priorTimer && !currentTimer) return result;
|
|
648
|
-
let graceTurn = turn;
|
|
649
|
-
if (finalizingGraceAfterHistoryRead) {
|
|
650
|
-
const readReturnedAt = new Date().toISOString();
|
|
651
|
-
const currentTurn = turnState(await runtime.getSession(normalizedSessionId));
|
|
652
|
-
const timer = codexAppServerFinalizingTimers.get(key);
|
|
653
|
-
if (timer?.failureDetail || (priorTimer && !timer)) return result;
|
|
654
|
-
if (currentTurn.state !== "finalizing" || currentTurn.threadId !== normalizedThreadId ||
|
|
655
|
-
currentTurn.turnId !== normalizedTurnId) {
|
|
656
|
-
clearCodexAppServerFinalizingTimer(normalizedSessionId, normalizedThreadId, normalizedTurnId);
|
|
657
|
-
return { ...result, reason: "stale_turn_state" };
|
|
658
|
-
}
|
|
659
|
-
if (codexAppServerTurnOwnsActiveGoal(currentTurn, normalizedThreadId)) {
|
|
660
|
-
clearCodexAppServerFinalizingTimer(normalizedSessionId, normalizedThreadId, normalizedTurnId);
|
|
661
|
-
return { ok: true, processed: false, reason: "goal_continuation_pending" };
|
|
662
|
-
}
|
|
663
|
-
if (!timerRecovery && timer?.recovery) return timer.recovery;
|
|
664
|
-
// This local clock never changes the native completion timestamp.
|
|
665
|
-
graceTurn = { ...currentTurn, completedAt: timer?.startedAt || readReturnedAt };
|
|
666
|
-
}
|
|
667
|
-
if (!codexAppServerFinalizingExpired(graceTurn)) {
|
|
668
|
-
scheduleCodexAppServerFinalizingRecovery(normalizedSessionId, normalizedThreadId, normalizedTurnId, {
|
|
669
|
-
completedAt: graceTurn.completedAt,
|
|
670
|
-
status,
|
|
671
|
-
updatedAt: graceTurn.updatedAt
|
|
672
|
-
});
|
|
673
|
-
return result;
|
|
674
|
-
}
|
|
675
|
-
return stopCodexAppServerTurnWithResultDeliveryFailure(
|
|
676
|
-
normalizedSessionId,
|
|
677
|
-
normalizedThreadId,
|
|
678
|
-
normalizedTurnId,
|
|
679
|
-
{
|
|
680
|
-
error: result?.error,
|
|
681
|
-
reason: result?.reason || "missing_assistant_text",
|
|
682
|
-
status
|
|
683
|
-
}
|
|
684
|
-
);
|
|
685
|
-
}
|
|
686
|
-
|
|
687
297
|
async function recoverCodexAppServerActiveTurn(sessionId = "", {
|
|
688
298
|
provider = null,
|
|
689
299
|
retryOnError = true,
|
|
690
300
|
runtime: suppliedRuntime = null,
|
|
691
301
|
providerError = null
|
|
692
302
|
} = {}) {
|
|
693
|
-
const normalizedSessionId =
|
|
303
|
+
const normalizedSessionId = normalizeText(sessionId);
|
|
694
304
|
if (!normalizedSessionId) {
|
|
695
305
|
return null;
|
|
696
306
|
}
|
|
697
307
|
try {
|
|
698
308
|
const runtime = suppliedRuntime || await createRuntime();
|
|
699
309
|
const storedSession = await runtime.getSession(normalizedSessionId);
|
|
700
|
-
const abandonedClaim = await
|
|
310
|
+
const abandonedClaim = await recoverAdmission(
|
|
701
311
|
runtime,
|
|
702
312
|
storedSession,
|
|
703
313
|
{
|
|
704
|
-
promptDeliveryActive:
|
|
314
|
+
promptDeliveryActive: promptDeliveries.has(
|
|
705
315
|
namespace(normalizedSessionId)
|
|
706
316
|
)
|
|
707
317
|
}
|
|
@@ -736,7 +346,7 @@ export function createCodexTurnRecovery({
|
|
|
736
346
|
.then(() => createStore(normalizedSessionId))
|
|
737
347
|
.catch(() => null);
|
|
738
348
|
const run = store
|
|
739
|
-
? await
|
|
349
|
+
? await output.readAgentRunForSession(store, normalizedSessionId).catch(() => null)
|
|
740
350
|
: null;
|
|
741
351
|
if (turnStateFromAgentRun(run || {}).state === "starting") {
|
|
742
352
|
scheduleCodexAppServerActiveRecovery(normalizedSessionId);
|
|
@@ -745,376 +355,15 @@ export function createCodexTurnRecovery({
|
|
|
745
355
|
}
|
|
746
356
|
}
|
|
747
357
|
|
|
748
|
-
|
|
749
|
-
provider = null,
|
|
750
|
-
status = "completed",
|
|
751
|
-
verifyInactive = true
|
|
752
|
-
} = {}) {
|
|
753
|
-
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
754
|
-
const normalizedThreadId = normalizeCodexRunText(threadId);
|
|
755
|
-
const normalizedTurnId = normalizeCodexRunText(turnId);
|
|
756
|
-
const normalizedStatus = normalizeCodexRunText(status) || "completed";
|
|
757
|
-
const runtime = await createRuntime();
|
|
758
|
-
const session = await runtime.getSession(normalizedSessionId);
|
|
759
|
-
const existingTurn = turnState(session);
|
|
760
|
-
const continuesOwnedGoal = codexAppServerTurnOwnsActiveGoal(
|
|
761
|
-
existingTurn,
|
|
762
|
-
normalizedThreadId
|
|
763
|
-
);
|
|
764
|
-
if (codexAppServerTurnAwaitsProviderIdentity(existingTurn, normalizedThreadId, normalizedTurnId)) {
|
|
765
|
-
return {
|
|
766
|
-
ok: true,
|
|
767
|
-
processed: false,
|
|
768
|
-
reason: "turn_identity_pending"
|
|
769
|
-
};
|
|
770
|
-
}
|
|
771
|
-
if (!normalizedTurnId) {
|
|
772
|
-
if (!codexAppServerTurnCanReceiveProviderCompletion(existingTurn, normalizedThreadId, "")) {
|
|
773
|
-
cleanupCodexAppServerUntrackedTurn(normalizedThreadId, normalizedTurnId);
|
|
774
|
-
debugLog("appServerTurn.complete.stale", {
|
|
775
|
-
currentState: existingTurn.state,
|
|
776
|
-
currentStatus: existingTurn.status,
|
|
777
|
-
currentThreadId: existingTurn.threadId,
|
|
778
|
-
currentTurnId: existingTurn.turnId,
|
|
779
|
-
sessionId: normalizedSessionId,
|
|
780
|
-
status: normalizedStatus,
|
|
781
|
-
threadId: normalizedThreadId,
|
|
782
|
-
turnId: normalizedTurnId
|
|
783
|
-
});
|
|
784
|
-
return {
|
|
785
|
-
ok: true,
|
|
786
|
-
processed: false,
|
|
787
|
-
reason: "stale_turn_state"
|
|
788
|
-
};
|
|
789
|
-
}
|
|
790
|
-
if (verifyInactive && await codexAppServerProviderBlocksTurnRelease(normalizedSessionId, provider, normalizedThreadId, normalizedTurnId, {
|
|
791
|
-
source: "complete_missing_turn"
|
|
792
|
-
})) {
|
|
793
|
-
return {
|
|
794
|
-
ok: true,
|
|
795
|
-
processed: false,
|
|
796
|
-
reason: "provider_still_active",
|
|
797
|
-
status: "inProgress"
|
|
798
|
-
};
|
|
799
|
-
}
|
|
800
|
-
await markCodexAppServerTurnIdle(normalizedSessionId, {
|
|
801
|
-
status: normalizedStatus,
|
|
802
|
-
threadId: normalizedThreadId,
|
|
803
|
-
turnId: normalizedTurnId
|
|
804
|
-
});
|
|
805
|
-
return {
|
|
806
|
-
ok: true,
|
|
807
|
-
processed: false,
|
|
808
|
-
reason: "missing_turn"
|
|
809
|
-
};
|
|
810
|
-
}
|
|
811
|
-
if (!codexAppServerTurnCanReceiveProviderCompletion(existingTurn, normalizedThreadId, normalizedTurnId)) {
|
|
812
|
-
codexAppServerFinalizedTurns.add(codexAppServerResultFinalizationKey(
|
|
813
|
-
normalizedSessionId,
|
|
814
|
-
normalizedThreadId,
|
|
815
|
-
normalizedTurnId
|
|
816
|
-
));
|
|
817
|
-
cleanupCodexAppServerUntrackedTurn(normalizedThreadId, normalizedTurnId);
|
|
818
|
-
debugLog("appServerTurn.complete.stale", {
|
|
819
|
-
currentState: existingTurn.state,
|
|
820
|
-
currentStatus: existingTurn.status,
|
|
821
|
-
currentThreadId: existingTurn.threadId,
|
|
822
|
-
currentTurnId: existingTurn.turnId,
|
|
823
|
-
sessionId: normalizedSessionId,
|
|
824
|
-
status: normalizedStatus,
|
|
825
|
-
threadId: normalizedThreadId,
|
|
826
|
-
turnId: normalizedTurnId
|
|
827
|
-
});
|
|
828
|
-
return {
|
|
829
|
-
ok: true,
|
|
830
|
-
processed: false,
|
|
831
|
-
reason: "stale_turn_state"
|
|
832
|
-
};
|
|
833
|
-
}
|
|
834
|
-
if (verifyInactive && await codexAppServerProviderBlocksTurnRelease(normalizedSessionId, provider, normalizedThreadId, normalizedTurnId, {
|
|
835
|
-
source: "complete"
|
|
836
|
-
})) {
|
|
837
|
-
return {
|
|
838
|
-
ok: true,
|
|
839
|
-
processed: false,
|
|
840
|
-
reason: "provider_still_active",
|
|
841
|
-
status: "inProgress"
|
|
842
|
-
};
|
|
843
|
-
}
|
|
844
|
-
if (codexAppServerRunInputSource(codexAppServerAgentRun(session)) === "terminal") {
|
|
845
|
-
codexAppServerCompletedTurns.add(codexAppServerTurnKey(normalizedThreadId, normalizedTurnId));
|
|
846
|
-
cleanupCodexAppServerUntrackedTurn(normalizedThreadId, normalizedTurnId);
|
|
847
|
-
await markCodexAppServerTurnIdle(normalizedSessionId, {
|
|
848
|
-
status: normalizedStatus,
|
|
849
|
-
threadId: normalizedThreadId,
|
|
850
|
-
turnId: normalizedTurnId
|
|
851
|
-
});
|
|
852
|
-
return {
|
|
853
|
-
ok: true,
|
|
854
|
-
processed: true,
|
|
855
|
-
reason: "terminal_turn_completed"
|
|
856
|
-
};
|
|
857
|
-
}
|
|
858
|
-
const alreadyFinalizing = existingTurn.state === "finalizing" &&
|
|
859
|
-
existingTurn.threadId === normalizedThreadId &&
|
|
860
|
-
existingTurn.turnId === normalizedTurnId;
|
|
861
|
-
codexAppServerCompletedTurns.add(codexAppServerTurnKey(normalizedThreadId, normalizedTurnId));
|
|
862
|
-
if (!alreadyFinalizing) {
|
|
863
|
-
await markCodexAppServerTurnFinalizing(normalizedSessionId, {
|
|
864
|
-
status: normalizedStatus,
|
|
865
|
-
threadId: normalizedThreadId,
|
|
866
|
-
turnId: normalizedTurnId
|
|
867
|
-
});
|
|
868
|
-
}
|
|
869
|
-
if (continuesOwnedGoal) {
|
|
870
|
-
// Keep the outer chat turn active so the next provider turn can adopt
|
|
871
|
-
// its chat ownership without exposing this internal final as an answer.
|
|
872
|
-
clearCodexAppServerFinalizingTimer(
|
|
873
|
-
normalizedSessionId,
|
|
874
|
-
normalizedThreadId,
|
|
875
|
-
normalizedTurnId
|
|
876
|
-
);
|
|
877
|
-
return {
|
|
878
|
-
ok: true,
|
|
879
|
-
processed: true,
|
|
880
|
-
reason: "goal_continuation_pending"
|
|
881
|
-
};
|
|
882
|
-
}
|
|
883
|
-
return recoverCodexAppServerFinalizingTurn(
|
|
884
|
-
normalizedSessionId,
|
|
885
|
-
normalizedThreadId,
|
|
886
|
-
normalizedTurnId,
|
|
887
|
-
{
|
|
888
|
-
status: normalizedStatus
|
|
889
|
-
}
|
|
890
|
-
);
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
function codexAppServerStoppedTurnMessage(status = "", error = "", outcome = "") {
|
|
894
|
-
const normalizedStatus = normalizeCodexRunText(status);
|
|
895
|
-
let base = "Codex app-server failed before completing this turn.";
|
|
896
|
-
if (normalizedStatus === "interrupted") {
|
|
897
|
-
base = outcome === turnOutcomes.CONTROL_RECONFIGURATION
|
|
898
|
-
? "Codex app-server was interrupted while its controls were restored."
|
|
899
|
-
: "Codex app-server was interrupted before completing this turn.";
|
|
900
|
-
}
|
|
901
|
-
const normalizedError = normalizeCodexRunText(error);
|
|
902
|
-
return normalizedError ? `${base} ${normalizedError}` : base;
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
async function stopCodexAppServerTurnWithProviderFailure(sessionId = "", threadId = "", turnId = "", {
|
|
906
|
-
error = "",
|
|
907
|
-
ok = false,
|
|
908
|
-
outcome = "",
|
|
909
|
-
provider = null,
|
|
910
|
-
status = "failed",
|
|
911
|
-
usageLimitExceeded = false,
|
|
912
|
-
verifyInactive = true,
|
|
913
|
-
deferFailureDetails = false,
|
|
914
|
-
failureDetailReady = false
|
|
915
|
-
} = {}) {
|
|
916
|
-
const observedAt = Date.now();
|
|
917
|
-
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
918
|
-
const normalizedThreadId = normalizeCodexRunText(threadId);
|
|
919
|
-
const normalizedTurnId = normalizeCodexRunText(turnId);
|
|
920
|
-
const normalizedStatus = normalizeCodexRunText(status) || "failed";
|
|
921
|
-
let resolvedOutcome = normalizeCodexRunText(outcome);
|
|
922
|
-
if (!resolvedOutcome) {
|
|
923
|
-
if (normalizedStatus === "interrupted") {
|
|
924
|
-
const recorded = provider?.interruptionOutcome?.(normalizedThreadId, normalizedTurnId);
|
|
925
|
-
resolvedOutcome = [turnOutcomes.USER_CANCELLED, turnOutcomes.CONTROL_RECONFIGURATION].includes(recorded)
|
|
926
|
-
? recorded : turnOutcomes.INTERRUPTED;
|
|
927
|
-
} else {
|
|
928
|
-
resolvedOutcome = turnOutcomes.PROVIDER_FAILURE;
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
const runtime = await createRuntime();
|
|
932
|
-
const staleFailure = async () => {
|
|
933
|
-
const turn = turnState(await runtime.getSession(normalizedSessionId));
|
|
934
|
-
if (codexAppServerTurnCanReceiveProviderCompletion(turn, normalizedThreadId, normalizedTurnId)) {
|
|
935
|
-
return null;
|
|
936
|
-
}
|
|
937
|
-
debugLog("appServerTurn.failure.stale", {
|
|
938
|
-
currentState: turn.state,
|
|
939
|
-
currentStatus: turn.status,
|
|
940
|
-
currentThreadId: turn.threadId,
|
|
941
|
-
currentTurnId: turn.turnId,
|
|
942
|
-
sessionId: normalizedSessionId,
|
|
943
|
-
status: normalizedStatus,
|
|
944
|
-
threadId: normalizedThreadId,
|
|
945
|
-
turnId: normalizedTurnId
|
|
946
|
-
});
|
|
947
|
-
return {
|
|
948
|
-
ok: true,
|
|
949
|
-
processed: false,
|
|
950
|
-
reason: "stale_turn_state"
|
|
951
|
-
};
|
|
952
|
-
};
|
|
953
|
-
const staleBeforeRecovery = await staleFailure();
|
|
954
|
-
if (staleBeforeRecovery) {
|
|
955
|
-
return staleBeforeRecovery;
|
|
956
|
-
}
|
|
957
|
-
const key = codexAppServerResultFinalizationKey(normalizedSessionId, normalizedThreadId, normalizedTurnId);
|
|
958
|
-
const pendingTimer = codexAppServerFinalizingTimers.get(key);
|
|
959
|
-
const pendingDetail = pendingTimer?.failureDetail;
|
|
960
|
-
if (failureDetailGraceMs > 0 && !failureDetailReady && (deferFailureDetails || pendingDetail) &&
|
|
961
|
-
![turnOutcomes.USER_CANCELLED, turnOutcomes.CONTROL_RECONFIGURATION].includes(resolvedOutcome)) {
|
|
962
|
-
if (!pendingDetail) {
|
|
963
|
-
scheduleCodexAppServerFinalizingRecovery(normalizedSessionId, normalizedThreadId, normalizedTurnId, {
|
|
964
|
-
failureDetail: { error, ok, outcome: resolvedOutcome, provider, status: normalizedStatus,
|
|
965
|
-
usageLimitExceeded, verifyInactive,
|
|
966
|
-
expiresAt: Math.min(observedAt + failureDetailGraceMs,
|
|
967
|
-
pendingTimer?.expiresAt ?? Infinity) }
|
|
968
|
-
});
|
|
969
|
-
}
|
|
970
|
-
return { ok: true, processed: false, reason: "failure_detail_pending", status: normalizedStatus };
|
|
971
|
-
}
|
|
972
|
-
if (resolvedOutcome === turnOutcomes.PROVIDER_FAILURE) {
|
|
973
|
-
// Saved output is still useful, but cannot turn a known provider failure
|
|
974
|
-
// into successful completion. Persist it without settling the turn;
|
|
975
|
-
// the failure notice and checkpoint below own the terminal outcome.
|
|
976
|
-
await submitCodexAppServerAssistantResult(normalizedSessionId, normalizedThreadId, normalizedTurnId, {
|
|
977
|
-
recoverFromProvider: true
|
|
978
|
-
});
|
|
979
|
-
} else {
|
|
980
|
-
const recovered = await recoverCodexAppServerFinalResponseBeforeOutcome(
|
|
981
|
-
normalizedSessionId,
|
|
982
|
-
normalizedThreadId,
|
|
983
|
-
normalizedTurnId,
|
|
984
|
-
normalizedStatus
|
|
985
|
-
);
|
|
986
|
-
if (recovered?.processed) {
|
|
987
|
-
return recovered;
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
// History recovery awaited the provider. Confirm ownership and activity
|
|
991
|
-
// again before publishing a failure: a successor, Stop or goal
|
|
992
|
-
// continuation may own the run after that gap.
|
|
993
|
-
const staleAfterRecovery = await staleFailure();
|
|
994
|
-
if (staleAfterRecovery) {
|
|
995
|
-
return staleAfterRecovery;
|
|
996
|
-
}
|
|
997
|
-
if (verifyInactive && await codexAppServerProviderBlocksTurnRelease(normalizedSessionId, provider, normalizedThreadId, normalizedTurnId, {
|
|
998
|
-
source: "provider_failure"
|
|
999
|
-
})) {
|
|
1000
|
-
return {
|
|
1001
|
-
ok: true,
|
|
1002
|
-
processed: false,
|
|
1003
|
-
reason: "provider_still_active",
|
|
1004
|
-
status: "inProgress"
|
|
1005
|
-
};
|
|
1006
|
-
}
|
|
1007
|
-
const message = codexAppServerStoppedTurnMessage(normalizedStatus, error, resolvedOutcome);
|
|
1008
|
-
await outcomeNotice(
|
|
1009
|
-
runtime,
|
|
1010
|
-
normalizedSessionId,
|
|
1011
|
-
normalizedThreadId,
|
|
1012
|
-
normalizedTurnId,
|
|
1013
|
-
resolvedOutcome,
|
|
1014
|
-
error,
|
|
1015
|
-
{ usageLimitExceeded }
|
|
1016
|
-
);
|
|
1017
|
-
await markCodexAppServerTurnIdle(normalizedSessionId, {
|
|
1018
|
-
error: message,
|
|
1019
|
-
status: normalizedStatus,
|
|
1020
|
-
threadId: normalizedThreadId,
|
|
1021
|
-
turnId: normalizedTurnId,
|
|
1022
|
-
turnOutcome: resolvedOutcome
|
|
1023
|
-
});
|
|
1024
|
-
cleanupCodexAppServerUntrackedTurn(normalizedThreadId, normalizedTurnId);
|
|
1025
|
-
return {
|
|
1026
|
-
ok,
|
|
1027
|
-
error: message,
|
|
1028
|
-
status: normalizedStatus
|
|
1029
|
-
};
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
async function stopCodexAppServerTurnWithResultDeliveryFailure(sessionId = "", threadId = "", turnId = "", {
|
|
1033
|
-
error = "",
|
|
1034
|
-
reason = "",
|
|
1035
|
-
status = "completed"
|
|
1036
|
-
} = {}) {
|
|
1037
|
-
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
1038
|
-
const normalizedThreadId = normalizeCodexRunText(threadId);
|
|
1039
|
-
const normalizedStatus = normalizeCodexRunText(status) || "completed";
|
|
1040
|
-
const normalizedTurnId = await resolveCodexAppServerTurnId(normalizedSessionId, normalizedThreadId, turnId);
|
|
1041
|
-
const recovered = await recoverCodexAppServerFinalResponseBeforeOutcome(
|
|
1042
|
-
normalizedSessionId,
|
|
1043
|
-
normalizedThreadId,
|
|
1044
|
-
normalizedTurnId,
|
|
1045
|
-
normalizedStatus
|
|
1046
|
-
);
|
|
1047
|
-
if (recovered?.processed) {
|
|
1048
|
-
return recovered;
|
|
1049
|
-
}
|
|
1050
|
-
// The history read can outlive this turn: a successor or Stop may own the
|
|
1051
|
-
// run by now, so the outcome is decided against the run read after it.
|
|
1052
|
-
const runtime = await createRuntime();
|
|
1053
|
-
const currentTurn = turnState(await runtime.getSession(normalizedSessionId));
|
|
1054
|
-
if (!codexAppServerTurnCanReceiveProviderCompletion(currentTurn, normalizedThreadId, normalizedTurnId)) {
|
|
1055
|
-
codexAppServerFinalizedTurns.add(codexAppServerResultFinalizationKey(
|
|
1056
|
-
normalizedSessionId,
|
|
1057
|
-
normalizedThreadId,
|
|
1058
|
-
normalizedTurnId
|
|
1059
|
-
));
|
|
1060
|
-
cleanupCodexAppServerUntrackedTurn(normalizedThreadId, normalizedTurnId);
|
|
1061
|
-
debugLog("appServerAgentResult.missing.stale", {
|
|
1062
|
-
currentState: currentTurn.state,
|
|
1063
|
-
currentStatus: currentTurn.status,
|
|
1064
|
-
currentThreadId: currentTurn.threadId,
|
|
1065
|
-
currentTurnId: currentTurn.turnId,
|
|
1066
|
-
reason: normalizeCodexRunText(reason),
|
|
1067
|
-
sessionId: normalizedSessionId,
|
|
1068
|
-
status: normalizedStatus,
|
|
1069
|
-
threadId: normalizedThreadId,
|
|
1070
|
-
turnId: normalizedTurnId
|
|
1071
|
-
});
|
|
1072
|
-
return {
|
|
1073
|
-
ok: true,
|
|
1074
|
-
processed: false,
|
|
1075
|
-
reason: "stale_turn_state",
|
|
1076
|
-
status: currentTurn.status
|
|
1077
|
-
};
|
|
1078
|
-
}
|
|
1079
|
-
const message = resultDeliveryFailureMessage({
|
|
1080
|
-
error
|
|
1081
|
-
});
|
|
1082
|
-
await outcomeNotice(
|
|
1083
|
-
runtime,
|
|
1084
|
-
normalizedSessionId,
|
|
1085
|
-
normalizedThreadId,
|
|
1086
|
-
normalizedTurnId,
|
|
1087
|
-
turnOutcomes.RESPONSE_DELIVERY_FAILURE
|
|
1088
|
-
);
|
|
1089
|
-
await markCodexAppServerTurnIdle(normalizedSessionId, {
|
|
1090
|
-
error: message,
|
|
1091
|
-
status: normalizedStatus,
|
|
1092
|
-
threadId: normalizedThreadId,
|
|
1093
|
-
turnId: normalizedTurnId,
|
|
1094
|
-
turnOutcome: turnOutcomes.RESPONSE_DELIVERY_FAILURE
|
|
1095
|
-
});
|
|
1096
|
-
cleanupCodexAppServerUntrackedTurn(normalizedThreadId, normalizedTurnId);
|
|
1097
|
-
debugLog("appServerAgentResult.missing", {
|
|
1098
|
-
error: normalizeCodexRunText(error),
|
|
1099
|
-
reason: normalizeCodexRunText(reason),
|
|
1100
|
-
sessionId: normalizedSessionId,
|
|
1101
|
-
threadId: normalizedThreadId,
|
|
1102
|
-
turnId: normalizedTurnId
|
|
1103
|
-
});
|
|
1104
|
-
return {
|
|
1105
|
-
ok: false,
|
|
1106
|
-
error: message,
|
|
1107
|
-
status: normalizedStatus
|
|
1108
|
-
};
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
return {
|
|
358
|
+
return Object.freeze({
|
|
1112
359
|
scheduleActiveRecovery: scheduleCodexAppServerActiveRecovery,
|
|
1113
|
-
markTurnActive:
|
|
1114
|
-
markProviderTurnActive:
|
|
1115
|
-
recoverFinalizingTurn:
|
|
360
|
+
markTurnActive: activity.markTurnActive,
|
|
361
|
+
markProviderTurnActive: activity.markProviderTurnActive,
|
|
362
|
+
recoverFinalizingTurn: endings.recoverFinalizingTurn,
|
|
1116
363
|
recoverActiveTurn: recoverCodexAppServerActiveTurn,
|
|
1117
|
-
completeTurn:
|
|
1118
|
-
stopTurnWithProviderFailure:
|
|
1119
|
-
};
|
|
364
|
+
completeTurn: endings.completeTurn,
|
|
365
|
+
stopTurnWithProviderFailure: endings.stopTurnWithProviderFailure
|
|
366
|
+
});
|
|
1120
367
|
}
|
|
368
|
+
|
|
369
|
+
/** @typedef {ReturnType<typeof createCodexTurnRecovery>} CodexTurnRecovery */
|