@jskit-ai/assistant-core 0.1.199 → 0.1.201

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.
Files changed (164) hide show
  1. package/examples/conversation/README.md +8 -1
  2. package/examples/conversation/package.json +5 -5
  3. package/fixtures/responsive-assistant/App.vue +4 -1
  4. package/package.json +99 -36
  5. package/src/client/conversation/AssistantConversationElement.vue +27 -4
  6. package/src/client/conversation/AssistantConversationStatus.vue +24 -0
  7. package/src/client/conversation/AssistantGoalControl.vue +8 -5
  8. package/src/client/conversation/AssistantTranscript.vue +10 -3
  9. package/src/client/conversation/index.js +2 -0
  10. package/src/client/conversation/messageDelivery.js +115 -32
  11. package/src/client/conversation/retainedConversation.js +32 -0
  12. package/src/client/conversation/useAssistantQuestions.js +76 -0
  13. package/src/client/lib/assistantApi.js +72 -2
  14. package/src/server/conversation/agentRun.js +222 -0
  15. package/src/server/conversation/attachments.js +93 -0
  16. package/src/server/conversation/claudeClient.js +221 -0
  17. package/src/server/conversation/claudeHistory.js +256 -0
  18. package/src/server/conversation/claudeProcess.js +327 -0
  19. package/src/server/conversation/claudeTools.js +42 -0
  20. package/src/server/conversation/claudeTurn.js +1082 -0
  21. package/src/server/conversation/codexConfiguration.js +1183 -0
  22. package/src/server/conversation/codexConversations.js +1082 -0
  23. package/src/server/conversation/codexDetachedTurn.js +332 -0
  24. package/src/server/conversation/codexEvents.js +194 -1
  25. package/src/server/conversation/codexGoalCommands.js +124 -0
  26. package/src/server/conversation/codexHelperExecution.js +306 -0
  27. package/src/server/conversation/codexHelperThreadLedger.js +804 -0
  28. package/src/server/conversation/codexHelperThreadRecovery.js +395 -0
  29. package/src/server/conversation/codexHelperThreads.js +638 -0
  30. package/src/server/conversation/codexHistoryAdapter.js +369 -0
  31. package/src/server/conversation/codexMessageCommands.js +663 -0
  32. package/src/server/conversation/codexMessageDelivery.js +211 -0
  33. package/src/server/conversation/codexNativeHistoryExport.js +95 -0
  34. package/src/server/conversation/codexNotificationObserver.js +482 -0
  35. package/src/server/conversation/codexNotificationQueue.js +103 -0
  36. package/src/server/conversation/codexObservationControl.js +174 -0
  37. package/src/server/conversation/codexOutput.js +931 -0
  38. package/src/server/conversation/codexProcess.js +1559 -0
  39. package/src/server/conversation/codexProcessLeader.js +14 -0
  40. package/src/server/conversation/codexProvider.js +2710 -0
  41. package/src/server/conversation/codexProviderOwner.js +1058 -0
  42. package/src/server/conversation/codexProviderSelection.js +218 -0
  43. package/src/server/conversation/codexReasoning.js +314 -0
  44. package/src/server/conversation/codexRenewalCommands.js +290 -0
  45. package/src/server/conversation/codexResultSettlement.js +409 -0
  46. package/src/server/conversation/codexRunJournal.js +658 -0
  47. package/src/server/conversation/codexRuntimeLifecycle.js +288 -0
  48. package/src/server/conversation/codexSessionCleanup.js +96 -0
  49. package/src/server/conversation/codexSessionReconciliation.js +284 -0
  50. package/src/server/conversation/codexThreadReadiness.js +397 -0
  51. package/src/server/conversation/codexThreadStatus.js +354 -0
  52. package/src/server/conversation/codexTurn.js +701 -255
  53. package/src/server/conversation/codexTurnControl.js +317 -0
  54. package/src/server/conversation/codexTurnRecovery.js +990 -0
  55. package/src/server/conversation/codexTurnState.js +549 -0
  56. package/src/server/conversation/commandHook.js +18 -0
  57. package/src/server/conversation/commandWrapper.js +37 -0
  58. package/src/server/conversation/configuration.js +43 -0
  59. package/src/server/conversation/continuity.js +289 -0
  60. package/src/server/conversation/fileStorage.js +55 -0
  61. package/src/server/conversation/hookBridge.js +19 -0
  62. package/src/server/conversation/index.js +13 -0
  63. package/src/server/conversation/localExecution.js +665 -0
  64. package/src/server/conversation/memoryStorage.js +7 -72
  65. package/src/server/conversation/nativeHistoryExport.js +90 -0
  66. package/src/server/conversation/nativeStorage.js +23 -0
  67. package/src/server/conversation/openCodeClient.js +209 -19
  68. package/src/server/conversation/openCodePlugin.js +84 -0
  69. package/src/server/conversation/openCodeProcess.js +476 -0
  70. package/src/server/conversation/openCodeRuntime.js +1578 -0
  71. package/src/server/conversation/openCodeTools.js +60 -0
  72. package/src/server/conversation/openCodeTurn.js +557 -0
  73. package/src/server/conversation/provider.js +30 -0
  74. package/src/server/conversation/providers/api.js +136 -0
  75. package/src/server/conversation/providers/claude.js +63 -0
  76. package/src/server/conversation/providers/claudeDriver.js +425 -0
  77. package/src/server/conversation/providers/codex.js +248 -0
  78. package/src/server/conversation/providers/codexDriver.js +1078 -0
  79. package/src/server/conversation/providers/opencode.js +49 -0
  80. package/src/server/conversation/providers/opencodeDriver.js +650 -0
  81. package/src/server/conversation/providers/scoped.js +312 -0
  82. package/src/server/conversation/runtime.js +2220 -0
  83. package/src/server/conversation/runtimeStateUpgrade.js +125 -0
  84. package/src/server/conversation/storage.js +184 -0
  85. package/src/server/conversation/streams.js +7 -2
  86. package/src/server/conversation/structuredOutput.js +240 -0
  87. package/src/server/conversation/systemPrompt.js +54 -0
  88. package/src/server/conversation/tools.js +84 -0
  89. package/src/server/conversation/transcript.js +5 -4
  90. package/src/server/hosts/claudeHistory.js +5 -0
  91. package/src/server/hosts/claudeProcess.js +11 -0
  92. package/src/server/hosts/claudeTurn.js +4 -0
  93. package/src/server/hosts/codexConfiguration.js +20 -0
  94. package/src/server/hosts/codexEvents.js +13 -0
  95. package/src/server/hosts/codexProcess.js +12 -0
  96. package/src/server/hosts/codexProvider.js +23 -0
  97. package/src/server/hosts/codexTurn.js +20 -0
  98. package/src/server/hosts/nativeHistory.js +3 -0
  99. package/src/server/hosts/openCodeClient.js +3 -0
  100. package/src/server/hosts/openCodeProcess.js +23 -0
  101. package/src/server/hosts/openCodeTurn.js +7 -0
  102. package/src/server/index.js +2 -0
  103. package/src/server/lib/aiConnectionClient.js +13 -6
  104. package/src/server/lib/assistantCompletion.js +190 -0
  105. package/src/server/lib/assistantToolLoop.js +314 -0
  106. package/src/server/lib/serviceToolCatalog.js +25 -10
  107. package/src/shared/assistantResponseText.js +29 -0
  108. package/src/shared/conversation/attachments.js +19 -0
  109. package/src/shared/conversation/index.js +3 -0
  110. package/src/shared/conversation/pagination.js +78 -0
  111. package/src/shared/conversation/patches.js +150 -0
  112. package/src/shared/conversation/questions.js +48 -0
  113. package/src/shared/conversation/streaming.js +7 -4
  114. package/src/shared/index.js +2 -0
  115. package/src/shared/nativeProviders.js +45 -0
  116. package/src/testing/conversationStorageContract.js +31 -1
  117. package/src/testing/nativeCodex.js +11 -0
  118. package/src/testing/nativeOpenCode.js +3 -0
  119. package/test/aiConnectionClient.test.js +2 -0
  120. package/test/apiConversationDriver.test.js +73 -0
  121. package/test/assistantApiSurfaceHeader.test.js +85 -0
  122. package/test/assistantBoundedToolLoop.test.js +285 -0
  123. package/test/assistantScroll.browser.test.js +16 -0
  124. package/test/claudeClient.test.js +189 -0
  125. package/test/claudeConversationSession.test.js +1173 -0
  126. package/test/claudeInstructionResume.test.js +82 -0
  127. package/test/claudeProcess.test.js +204 -0
  128. package/test/claudeTurn.test.js +253 -0
  129. package/test/codexConversationSession.test.js +2122 -0
  130. package/test/codexGoal.test.js +37 -0
  131. package/test/codexHelperDeletion.test.js +163 -0
  132. package/test/codexHelperThreadLedger.test.js +494 -0
  133. package/test/codexHistoryAdapter.test.js +541 -0
  134. package/test/codexInteractiveArguments.test.js +30 -0
  135. package/test/codexIsolation.test.js +756 -0
  136. package/test/codexModelCatalog.test.js +362 -0
  137. package/test/codexNativeHistoryExport.test.js +81 -0
  138. package/test/codexThreadSelection.test.js +136 -0
  139. package/test/codexTurn.test.js +2158 -0
  140. package/test/conversation.test.js +110 -0
  141. package/test/conversationAgentRun.test.js +326 -0
  142. package/test/conversationApiFacilities.test.js +90 -0
  143. package/test/conversationAttachments.test.js +238 -0
  144. package/test/conversationCommandWrapper.test.js +48 -0
  145. package/test/conversationConfiguration.test.js +174 -0
  146. package/test/conversationNativeStorage.test.js +25 -0
  147. package/test/conversationReplacement.test.js +172 -0
  148. package/test/conversationRuntime.test.js +241 -0
  149. package/test/conversationRuntimeStateUpgrade.test.js +144 -0
  150. package/test/conversationSession.test.js +1080 -0
  151. package/test/conversationStreaming.test.js +68 -0
  152. package/test/conversationSystemPrompt.test.js +84 -0
  153. package/test/conversationTools.test.js +416 -0
  154. package/test/fileConversationStorage.test.js +73 -0
  155. package/test/fixtures/codexHelperThreadLedger.js +39 -0
  156. package/test/localConversationExecution.test.js +90 -0
  157. package/test/messageDelivery.test.js +234 -1
  158. package/test/nativeConversationRetirement.test.js +215 -0
  159. package/test/openCodeClient.test.js +515 -0
  160. package/test/openCodeProcess.test.js +177 -0
  161. package/test/openCodeRuntime.test.js +322 -0
  162. package/test/openCodeTools.test.js +287 -0
  163. package/test/opencodeConversationSession.test.js +789 -0
  164. package/test/serviceToolCatalog.test.js +24 -0
@@ -1,280 +1,726 @@
1
- import { normalizeText, isPlainObject } from "./normalize.js";
2
- import { classifyCodexAppServerEvent, codexAppServerNotificationParams, codexAppServerNotificationThreadId, codexAppServerNotificationTurnId, codexAppServerNotificationTurnStatus, codexAppServerNotificationError, codexAppServerStatusFromValue, codexAppServerProviderThreadAssistantSegments } from "./codexEvents.js";
3
- const CODEX_APP_SERVER_DETACHED_TURN_TIMEOUT_MS = 180_000;
4
- const CODEX_APP_SERVER_DETACHED_FAILURE_DETAIL_GRACE_MS = 500;
1
+ import { createCodexSessionReconciliation } from "./codexSessionReconciliation.js";
2
+ import { createCodexRuntimeLifecycle } from "./codexRuntimeLifecycle.js";
3
+ import { createCodexSessionCleanup } from "./codexSessionCleanup.js";
4
+ import { createCodexMessageCommands } from "./codexMessageCommands.js";
5
+ import { createCodexTurnControl } from "./codexTurnControl.js";
6
+ import { createCodexObservationControl } from "./codexObservationControl.js";
7
+ import { createCodexThreadReadiness } from "./codexThreadReadiness.js";
8
+ import { createCodexNotificationObserver } from "./codexNotificationObserver.js";
9
+ import { createCodexThreadStatus } from "./codexThreadStatus.js";
10
+ import { createCodexTurnRecovery } from "./codexTurnRecovery.js";
11
+ import { createCodexResultSettlement } from "./codexResultSettlement.js";
12
+ import { createCodexRunJournal } from "./codexRunJournal.js";
13
+ import { createCodexRenewalCommands } from "./codexRenewalCommands.js";
14
+ import { createCodexGoalCommands } from "./codexGoalCommands.js";
15
+ import { createCodexProviderSelection } from "./codexProviderSelection.js";
16
+ import { createCodexAppServerMessageDelivery } from "./codexMessageDelivery.js";
17
+ import { createCodexConversationCommands } from "./codexConversations.js";
18
+ import { createCodexAppServerOutput } from "./codexOutput.js";
19
+ import {
20
+ normalizeCodexRunText,
21
+ normalizeCodexAppServerRunState,
22
+ codexAppServerTurnStateFromAgentRun,
23
+ codexAppServerTurnState
24
+ } from "./codexTurnState.js";
5
25
 
6
- function codexAppServerTurnStatusIsActive(status = "") {
7
- return normalizeText(status) === "inProgress";
8
- }
26
+ import { createCodexAppServerNotificationQueue } from "./codexNotificationQueue.js";
27
+ export {
28
+ CODEX_APP_SERVER_RUN_STATE,
29
+ normalizeCodexAppServerRunState,
30
+ codexAppServerRunStateIsActive,
31
+ codexAppServerRunStateIsTerminal,
32
+ codexAppServerAgentRun,
33
+ codexAppServerPendingUserMessageClientIds,
34
+ codexAppServerPendingUserMessageOwnership,
35
+ codexAppServerProcessedResultEvent,
36
+ codexAppServerTurnStateFromAgentRun,
37
+ codexAppServerTurnState,
38
+ codexAppServerTurnOwnsActiveGoal,
39
+ codexAppServerTurnMatches,
40
+ codexAppServerTurnCanReceiveProviderCompletion,
41
+ codexAppServerTurnAwaitsProviderIdentity,
42
+ codexAppServerTurnCanReceiveProviderActivity,
43
+ codexAppServerTurnCanAdoptSuccessor,
44
+ codexAppServerTurnKey,
45
+ codexAppServerAgentRunPatch,
46
+ codexAppServerRunIdentityForPatch,
47
+ codexAppServerRunPatchIsStaleAfterTerminalState,
48
+ codexAppServerSteerFailure,
49
+ codexAppServerMessageRequiresNewTurn,
50
+ codexAppServerInterruptFailure,
51
+ codexAppServerInterruptUnavailableResponse,
52
+ codexAppServerFrozenTurnInterruptResponse,
53
+ codexAppServerConversationTurnIsActive,
54
+ codexAppServerMessageText,
55
+ codexAppServerMessageDisplayText,
56
+ codexAppServerThreadStatus,
57
+ codexAppServerReadThreadStatus,
58
+ codexAppServerTurnStatusIsActive,
59
+ codexAppServerTurnStatusIsComplete,
60
+ codexAppServerTurnStatusIsSuccessfulComplete,
61
+ codexAppServerTurnStatusIsProviderFailure
62
+ } from "./codexTurnState.js";
63
+ export { createCodexAppServerDetachedTurnWatcher, waitForCodexAppServerTurn } from "./codexDetachedTurn.js";
64
+ export { createCodexAppServerNotificationQueue } from "./codexNotificationQueue.js";
65
+ import {
66
+ assertCodexAppServerHelperAccountIdentity,
67
+ createCodexHelperOwnershipError,
68
+ readCodexAppServerAccountIdentity
69
+ } from "./codexHelperExecution.js";
70
+ export { sendPreparedCodexAppServerHelperTurn } from "./codexHelperExecution.js";
71
+ import { createCodexHelperThreadLifecycle } from "./codexHelperThreads.js";
72
+ export { codexAppServerThreadIsMissing } from "./codexProvider.js";
9
73
 
10
- function codexAppServerTurnStatusIsComplete(status = "") {
11
- return ["completed", "interrupted", "failed"].includes(normalizeText(status));
12
- }
74
+ export function createCodexAppServerRunOwner({
75
+ namespace = normalizeCodexRunText,
76
+ normalizeRunState = normalizeCodexAppServerRunState,
77
+ debugLog = () => {},
78
+ debugError = error => normalizeCodexRunText(error?.message || error),
79
+ createRuntime,
80
+ createStore,
81
+ publish = async () => null,
82
+ acquireProvider = async () => null,
83
+ providerSessions = null,
84
+ serverClosingError = null,
85
+ helperThreads = null,
86
+ modelCatalogCacheMs = 30_000,
87
+ conversationPreparation = null,
88
+ storeReadError = "The session store does not support agent-run reads.",
89
+ sessionIdRequiredError = "A session ID is required.",
90
+ turnClaimsUnsupportedError = "The session runtime does not support Codex turn claims.",
91
+ turnAlreadyRunningError = "Codex is already working on this session.",
92
+ messageIdPrefix = "codex:",
93
+ idlePublishPayload = null,
94
+ checkpoint = async () => null,
95
+ messageMetadata = {},
96
+ deliveryStateMetadataKey = "assistant_delivery",
97
+ hasRuntime = () => true,
98
+ recoverAdmission = null,
99
+ admissionTaskFinished = () => false,
100
+ outcomeNotice = async () => null,
101
+ resultDeliveryFailureMessage = ({ error = "" } = {}) => {
102
+ const detail = normalizeCodexRunText(error);
103
+ if (!detail) return "Codex app-server finished this turn, but the assistant result text was not received.";
104
+ const punctuation = [".", "!", "?"].some(character => detail.endsWith(character)) ? "" : ".";
105
+ return "Codex completed, but its response could not be processed: " + detail + punctuation;
106
+ },
107
+ orphanedPromptMessage = "The application restarted before Codex confirmed the message. Your message is safe; retry it.",
108
+ onNotificationSignal = async () => null,
109
+ captureContext = () => null,
110
+ runInContext = (_context, operation) => operation(),
111
+ notificationQueue = null,
112
+ activeReconcileMs = 2000,
113
+ steerFailedCode = "codex_turn_steer_failed",
114
+ interruptFailedCode = "codex_turn_interrupt_failed",
115
+ errorPrefix = ""
116
+ } = {}) {
117
+ if (providerSessions && (serverClosingError || !providerSessions.managed)) {
118
+ providerSessions = { ...providerSessions, managed: providerSessions.managed || new Map() };
119
+ }
120
+ const liveProgressMaxLength = 320;
121
+ const turnOutcomes = { PROVIDER_FAILURE: "provider_failure", RESPONSE_DELIVERY_FAILURE: "response_delivery_failure", SERVICE_RESTART: "service_restart", USER_CANCELLED: "user_cancelled" };
122
+ const finalizingGraceMs = 10000;
123
+ const snapshotRecoveryItemLimit = 25;
124
+ const helperOwnershipError = createCodexHelperOwnershipError({ errorPrefix });
125
+ const helperLifecycle = helperThreads ? createCodexHelperThreadLifecycle({
126
+ providerOwner: providerSessions.owner,
127
+ ...helperThreads,
128
+ errorPrefix
129
+ }) : null;
130
+ const codexAppServerNotificationQueue = notificationQueue || createCodexAppServerNotificationQueue({
131
+ namespace, runInContext,
132
+ isClosing: () => runOwner.runtimeLifecycle?.closing === true,
133
+ reportError: (error, context) => debugLog("appServerNotification.error", {
134
+ error: debugError(error), method: normalizeCodexRunText(context.method),
135
+ sessionId: normalizeCodexRunText(context.sessionId),
136
+ threadId: normalizeCodexRunText(context.threadId), turnId: normalizeCodexRunText(context.turnId)
137
+ })
138
+ });
139
+ const codexAppServerPromptDeliveries = new Set();
140
+ const turnState = session => codexAppServerTurnState(session, normalizeRunState);
141
+ const turnStateFromAgentRun = run => codexAppServerTurnStateFromAgentRun(run, normalizeRunState);
13
142
 
14
- function codexAppServerTurnStatusIsSuccessfulComplete(status = "") {
15
- return normalizeText(status) === "completed";
16
- }
143
+ const codexProviderSelection = createCodexProviderSelection({
144
+ providerSessions,
145
+ turnState,
146
+ helperLifecycle,
147
+ helperOwnershipError,
148
+ modelCatalogCacheMs,
149
+ errorPrefix
150
+ });
151
+ const {
152
+ ensureCodexAppServerProviderForActiveTurn,
153
+ acquireCodexAppServerOutputProvider,
154
+ codexAppServerRuntimeForVisibleTerminal,
155
+ codexAppServerMessageContext,
156
+ codexAppServerControlContext,
157
+ codexAppServerObservationRecoveryContext
158
+ } = codexProviderSelection;
159
+ const acquireOutputProvider = providerSessions?.outputContext
160
+ ? async ({ sessionId, runtime, session }) => {
161
+ const prepared = providerSessions.outputContext({ sessionId, runtime, session });
162
+ if (!prepared) return null;
163
+ return acquireCodexAppServerOutputProvider(
164
+ sessionId, session, prepared.managedIdentity, prepared.providerOptions
165
+ );
166
+ }
167
+ : acquireProvider;
17
168
 
18
- function codexAppServerTurnStatusIsProviderFailure(status = "") {
19
- return ["failed", "interrupted"].includes(normalizeText(status));
20
- }
169
+ const codexAppServerOutput = createCodexAppServerOutput({
170
+ namespace,
171
+ createRuntime,
172
+ createStore,
173
+ publish,
174
+ acquireProvider: acquireOutputProvider,
175
+ turnState,
176
+ turnStateFromAgentRun,
177
+ debugLog,
178
+ debugError,
179
+ liveProgressMaxLength,
180
+ storeReadError,
181
+ messageMetadata,
182
+ snapshotRecoveryItemLimit
183
+ });
184
+ const {
185
+ finalizedTurns: codexAppServerFinalizedTurns,
186
+ finalAssistantResults: codexAppServerFinalAssistantResults,
187
+ reasoningTurns: codexAppServerReasoningTurns,
188
+ reasoningPersistQueues: codexAppServerReasoningPersistQueues,
189
+ liveProgressItems: codexAppServerLiveProgressItems,
190
+ liveProgressFingerprints: codexAppServerLiveProgressFingerprints,
191
+ mirroredTerminalItems: codexAppServerMirroredTerminalItems,
192
+ resultFinalizationKey: codexAppServerResultFinalizationKey,
193
+ liveProgressCandidate: codexAppServerLiveProgressCandidate,
194
+ conversationMessageId: codexAppServerConversationMessageId,
195
+ readAgentRunForSession: readCodexAppServerAgentRunForSession,
196
+ readFinalAssistantResult: readCodexAppServerFinalAssistantResult,
197
+ persistAssistantReply: persistCodexAppServerAssistantReply,
198
+ recordFinalAssistantResult: recordCodexAppServerFinalAssistantResult,
199
+ recordReasoningForSession: recordCodexAppServerReasoningForSession,
200
+ flushReasoningPersist: flushCodexAppServerReasoningPersist,
201
+ splitReasoningTurn: splitCodexAppServerReasoningTurn,
202
+ cleanupUntrackedTurn: cleanupCodexAppServerUntrackedTurn,
203
+ streamMessage: codexAppServerStreamMessage,
204
+ writeStream: writeCodexAppServerStream,
205
+ writeLiveProgress: writeCodexAppServerLiveProgress,
206
+ submitAssistantResult: submitCodexAppServerAssistantResult,
207
+ reconcileObservedTurnItems: reconcileCodexAppServerObservedTurnItems
208
+ } = codexAppServerOutput;
21
209
 
22
- function codexAppServerTurnTokenUsage(notification = {}) {
23
- if (normalizeText(notification.method) !== "thread/tokenUsage/updated") {
24
- return null;
25
- }
26
- const params = codexAppServerNotificationParams(notification);
27
- const tokenUsage = isPlainObject(params.tokenUsage) ? params.tokenUsage : {};
28
- const turnUsage = isPlainObject(tokenUsage.last) ? tokenUsage.last : tokenUsage;
29
- const snapshot = {};
30
- for (const field of [
31
- "cachedInputTokens",
32
- "cacheWriteInputTokens",
33
- "inputTokens",
34
- "outputTokens",
35
- "reasoningOutputTokens",
36
- "totalTokens"
37
- ]) {
38
- const value = Number(turnUsage[field]);
39
- if (Number.isSafeInteger(value) && value >= 0) {
40
- snapshot[field] = value;
41
- }
42
- }
43
- return Object.keys(snapshot).length ? Object.freeze(snapshot) : null;
44
- }
210
+ const codexRunJournal = createCodexRunJournal({
211
+ namespace,
212
+ normalizeRunState,
213
+ turnState,
214
+ createRuntime,
215
+ publish,
216
+ checkpoint,
217
+ debugLog,
218
+ output: codexAppServerOutput,
219
+ messageIdPrefix,
220
+ sessionIdRequiredError,
221
+ turnClaimsUnsupportedError,
222
+ turnAlreadyRunningError,
223
+ errorPrefix,
224
+ idlePublishPayload,
225
+ finalizingGraceMs,
226
+ admissionTaskFinished,
227
+ orphanedPromptMessage
228
+ });
229
+ const {
230
+ completedTurns: codexAppServerCompletedTurns,
231
+ processedTurns: codexAppServerProcessedTurns,
232
+ activeTimers: codexAppServerActiveTimers,
233
+ finalizingTimers: codexAppServerFinalizingTimers,
234
+ turnResultWasProcessed: codexAppServerTurnResultWasProcessed,
235
+ claimTurnStart: claimCodexAppServerTurnStart,
236
+ claimMessageStart: claimCodexAppServerMessageStart,
237
+ writeAgentRun: writeCodexAppServerAgentRun,
238
+ clearActiveTimer: clearCodexAppServerActiveTimer,
239
+ clearFinalizingTimer: clearCodexAppServerFinalizingTimer,
240
+ clearSessionRecoveryTimers: clearCodexAppServerSessionRecoveryTimers,
241
+ agentRunRealtimePayload: codexAppServerAgentRunRealtimePayload,
242
+ publishAgentRun: publishCodexAppServerAgentRun,
243
+ markTurnFinalizing: markCodexAppServerTurnFinalizing,
244
+ markTurnIdle: markCodexAppServerTurnIdle,
245
+ resolveTurnId: resolveCodexAppServerTurnId,
246
+ writeUserMessageOwnership: writeCodexAppServerUserMessageOwnership
247
+ } = codexRunJournal;
45
248
 
46
- function createCodexAppServerDetachedTurnWatcher(provider = null, threadId = "", {
47
- includeThreadHistory = true,
48
- onEvent = null,
49
- timeoutMs = CODEX_APP_SERVER_DETACHED_TURN_TIMEOUT_MS
50
- } = {}) {
51
- const normalizedThreadId = normalizeText(threadId);
52
- let targetTurnId = "";
53
- let finalText = "";
54
- let usage = null;
55
- let failureDetailTimeout = null;
56
- let settled = false;
57
- let timeout = null;
58
- let connectionCheck = null;
59
- let unsubscribe = null;
60
- let pendingCompletionStatus = "";
61
- let pendingFailure = null;
62
- let resolveWaiter = null;
63
- let rejectWaiter = null;
249
+ const codexResultSettlement = createCodexResultSettlement({
250
+ journal: codexRunJournal,
251
+ output: codexAppServerOutput,
252
+ createRuntime,
253
+ publish,
254
+ debugLog,
255
+ debugError,
256
+ turnState
257
+ });
258
+ const {
259
+ resultFinalizations: codexAppServerResultFinalizations,
260
+ finalizeAssistantResult: finalizeCodexAppServerAssistantResult,
261
+ recoverFinalResponseBeforeOutcome: recoverCodexAppServerFinalResponseBeforeOutcome,
262
+ adoptSuccessorTurn: adoptCodexAppServerSuccessorTurn
263
+ } = codexResultSettlement;
64
264
 
65
- function cleanup() {
66
- clearTimeout(timeout);
67
- timeout = null;
68
- clearInterval(connectionCheck);
69
- connectionCheck = null;
70
- clearTimeout(failureDetailTimeout);
71
- failureDetailTimeout = null;
72
- unsubscribe?.();
73
- unsubscribe = null;
74
- }
265
+ const codexTurnRecovery = createCodexTurnRecovery({
266
+ journal: codexRunJournal,
267
+ output: codexAppServerOutput,
268
+ settlement: codexResultSettlement,
269
+ promptDeliveries: codexAppServerPromptDeliveries,
270
+ namespace,
271
+ createRuntime,
272
+ createStore,
273
+ acquireProvider: acquireOutputProvider,
274
+ turnState,
275
+ turnStateFromAgentRun,
276
+ debugLog,
277
+ debugError,
278
+ captureContext,
279
+ runInContext,
280
+ activeReconcileMs,
281
+ hasRuntime,
282
+ recoverAdmission,
283
+ turnOutcomes,
284
+ outcomeNotice,
285
+ resultDeliveryFailureMessage
286
+ });
287
+ const {
288
+ scheduleActiveRecovery: scheduleCodexAppServerActiveRecovery,
289
+ markTurnActive: markCodexAppServerTurnActive,
290
+ recoverActiveTurn: recoverCodexAppServerActiveTurn,
291
+ completeTurn: completeCodexAppServerTurn,
292
+ stopTurnWithProviderFailure: stopCodexAppServerTurnWithProviderFailure
293
+ } = codexTurnRecovery;
75
294
 
76
- function finish(result = {}) {
77
- if (settled) {
78
- return;
79
- }
80
- settled = true;
81
- cleanup();
82
- resolveWaiter?.(result);
83
- }
295
+ const codexThreadStatus = createCodexThreadStatus({
296
+ journal: codexRunJournal,
297
+ settlement: codexResultSettlement,
298
+ recovery: codexTurnRecovery,
299
+ output: codexAppServerOutput,
300
+ createRuntime,
301
+ turnState,
302
+ turnOutcomes,
303
+ debugLog,
304
+ debugError
305
+ });
306
+ const {
307
+ reconcileThreadStatus: reconcileCodexAppServerThreadStatus,
308
+ reconcileLoadedThreadStatus: reconcileCodexAppServerLoadedThreadStatus
309
+ } = codexThreadStatus;
84
310
 
85
- function fail(error) {
86
- if (settled) {
87
- return;
88
- }
89
- settled = true;
90
- cleanup();
91
- rejectWaiter?.(error);
92
- }
311
+ const codexMessageDelivery = createCodexAppServerMessageDelivery({
312
+ namespace,
313
+ publish,
314
+ messageMetadata,
315
+ createStore,
316
+ turnStateFromAgentRun,
317
+ deliveryStateMetadataKey,
318
+ output: codexAppServerOutput,
319
+ journal: codexRunJournal,
320
+ recovery: codexTurnRecovery
321
+ });
322
+ const {
323
+ messageDeliveries: codexAppServerMessageDeliveries,
324
+ pendingUserMessages: codexAppServerPendingUserMessages,
325
+ withMessageDelivery: withCodexAppServerMessageDelivery,
326
+ writeDeliveredUserMessage: writeCodexAppServerDeliveredUserMessage,
327
+ mirrorTerminalUserMessage: mirrorCodexAppServerTerminalUserMessage
328
+ } = codexMessageDelivery;
93
329
 
94
- function emitWatcherEvent(classification = {}) {
95
- if (typeof onEvent !== "function" || !classification?.kind) {
96
- return;
97
- }
98
- onEvent({
99
- ...classification,
100
- threadId: classification.threadId || normalizedThreadId,
101
- turnId: classification.turnId || targetTurnId
102
- });
103
- }
330
+ const codexNotificationObserver = createCodexNotificationObserver({
331
+ journal: codexRunJournal,
332
+ recovery: codexTurnRecovery,
333
+ threadStatus: codexThreadStatus,
334
+ output: codexAppServerOutput,
335
+ delivery: codexMessageDelivery,
336
+ notificationQueue: codexAppServerNotificationQueue,
337
+ namespace,
338
+ createRuntime,
339
+ createStore,
340
+ publish,
341
+ captureContext,
342
+ debugLog,
343
+ onNotificationSignal,
344
+ turnStateFromAgentRun
345
+ });
346
+ const {
347
+ eventSubscriptions: codexAppServerEventSubscriptions,
348
+ automaticHookThreads: codexAppServerAutomaticHookThreads,
349
+ eventSubscriptionKey: codexAppServerEventSubscriptionKey,
350
+ eventSubscriptionIsCurrent: codexAppServerEventSubscriptionIsCurrent,
351
+ unsubscribeEventSubscription: unsubscribeCodexAppServerEventSubscription,
352
+ reconcileGoalUpdated: reconcileCodexAppServerGoalUpdated,
353
+ subscribeEvents: subscribeCodexAppServerEvents
354
+ } = codexNotificationObserver;
104
355
 
105
- async function resultFromThread() {
106
- if (
107
- !includeThreadHistory ||
108
- !normalizedThreadId ||
109
- !targetTurnId ||
110
- typeof provider?.readThread !== "function"
111
- ) {
112
- return {
113
- status: "",
114
- statusType: "",
115
- text: ""
116
- };
117
- }
118
- const thread = await provider.readThread(normalizedThreadId);
119
- const rawStatus = thread.raw?.status || thread.response?.thread?.status;
120
- return {
121
- status: codexAppServerStatusFromValue(rawStatus),
122
- statusType: normalizeText(typeof rawStatus === "string" ? rawStatus : rawStatus?.type),
123
- text: codexAppServerProviderThreadAssistantSegments(thread, targetTurnId)
124
- .map((segment) => segment.text)
125
- .join("\n\n")
126
- };
127
- }
356
+ const codexThreadReadiness = createCodexThreadReadiness({
357
+ providerSessions,
358
+ selection: codexProviderSelection,
359
+ observer: codexNotificationObserver,
360
+ threadStatus: codexThreadStatus,
361
+ recovery: codexTurnRecovery,
362
+ turnState,
363
+ debugLog,
364
+ debugError
365
+ });
366
+ const {
367
+ threadReconciliations: codexAppServerThreadReconciliations,
368
+ ensureThreadReady: ensureCodexAppServerThreadReady,
369
+ reconcileThread: reconcileCodexAppServerThreadForSession,
370
+ waitForThreadReconciliations: waitForOtherCodexAppServerThreadReconciliations,
371
+ checkManagedConnection: checkCodexAppServerManagedConnection,
372
+ restoreLoadedThread: restoreCodexAppServerLoadedThread
373
+ } = codexThreadReadiness;
128
374
 
129
- function failAfterDetailGrace(error) {
130
- if (settled || failureDetailTimeout) {
131
- return;
132
- }
133
- failureDetailTimeout = setTimeout(() => {
134
- failureDetailTimeout = null;
135
- fail(error);
136
- }, CODEX_APP_SERVER_DETACHED_FAILURE_DETAIL_GRACE_MS);
375
+ const codexConversations = createCodexConversationCommands({
376
+ checkpoint,
377
+ codexAppServerConversationMessageId,
378
+ codexAppServerStreamMessage,
379
+ conversationPreparation,
380
+ ensureCodexAppServerProviderForActiveTurn,
381
+ errorPrefix,
382
+ helperLifecycle,
383
+ helperOwnershipError,
384
+ interruptFailedCode,
385
+ namespace,
386
+ providerSessions,
387
+ steerFailedCode
388
+ });
389
+ const {
390
+ codexAppServerConversations,
391
+ codexAppServerConversationTurnStarts,
392
+ codexAppServerConversation,
393
+ withCodexAppServerConversationTurnStart,
394
+ observeCodexConversation,
395
+ readPersistentCodexConversation,
396
+ codexAppServerEphemeralConversationSnapshot,
397
+ prepareCodexAppServerConversationThread,
398
+ codexAppServerConversationContext,
399
+ codexAppServerEphemeralScopeContext,
400
+ createCodexAppServerConversation,
401
+ startCodexAppServerConversationTurn,
402
+ readCodexAppServerConversation,
403
+ waitForCodexAppServerConversationTurn,
404
+ stopCodexAppServerConversation,
405
+ deleteScopedCodexAppServerConversation,
406
+ closeCodexAppServerConversations,
407
+ interruptDetachedCodexAppServerConversationTurn,
408
+ deleteDetachedCodexAppServerConversationThread,
409
+ steerCodexAppServerConversationTurn,
410
+ acquireCodexAppServerDetachedThread,
411
+ codexAppServerDetachedThreadId,
412
+ dispatchCodexAppServerDetachedTurn,
413
+ runDetachedCodexAppServerTurn,
414
+ interruptCodexAppServerConversation,
415
+ stopPersistentCodexConversation
416
+ } = codexConversations;
417
+
418
+ const codexObservationControl = createCodexObservationControl({
419
+ conversations: codexConversations,
420
+ output: codexAppServerOutput,
421
+ journal: codexRunJournal,
422
+ namespace,
423
+ createRuntime,
424
+ publish,
425
+ runInContext,
426
+ turnState,
427
+ errorPrefix
428
+ });
429
+ const {
430
+ assertThreadCanResume: assertCodexAppServerThreadCanResume,
431
+ createObservation: createCodexAppServerObservation,
432
+ recoverObservationLoss: recoverCodexAppServerObservationLoss
433
+ } = codexObservationControl;
434
+
435
+ const codexTurnControl = createCodexTurnControl({
436
+ journal: codexRunJournal,
437
+ settlement: codexResultSettlement,
438
+ recovery: codexTurnRecovery,
439
+ threadStatus: codexThreadStatus,
440
+ debugError,
441
+ debugLog,
442
+ errorPrefix,
443
+ interruptFailedCode,
444
+ turnOutcomes,
445
+ turnState
446
+ });
447
+ const { interruptTurn: interruptCodexAppServerTurn } = codexTurnControl;
448
+
449
+ const codexMessageCommands = createCodexMessageCommands({
450
+ output: codexAppServerOutput,
451
+ journal: codexRunJournal,
452
+ recovery: codexTurnRecovery,
453
+ threadStatus: codexThreadStatus,
454
+ selection: codexProviderSelection,
455
+ observer: codexNotificationObserver,
456
+ delivery: codexMessageDelivery,
457
+ promptDeliveries: codexAppServerPromptDeliveries,
458
+ createRuntime,
459
+ debugError,
460
+ debugLog,
461
+ errorPrefix,
462
+ messageIdPrefix,
463
+ messageMetadata,
464
+ namespace,
465
+ providerSessions,
466
+ recoverAdmission,
467
+ steerFailedCode,
468
+ turnAlreadyRunningError,
469
+ turnState
470
+ });
471
+ const {
472
+ selectMessageTurn: selectCodexAppServerMessageTurn,
473
+ dispatchMessage: dispatchCodexAppServerMessage,
474
+ startTurn: startCodexAppServerTurn,
475
+ steerTurn: steerCodexAppServerTurn
476
+ } = codexMessageCommands;
477
+
478
+ const {
479
+ runCodexAppServerRenewalHandover,
480
+ runCodexAppServerRenewalSeed
481
+ } = createCodexRenewalCommands({
482
+ claimCodexAppServerTurnStart,
483
+ codexAppServerNotificationQueue,
484
+ completeCodexAppServerTurn,
485
+ errorPrefix,
486
+ markCodexAppServerTurnActive,
487
+ markCodexAppServerTurnIdle,
488
+ observer: codexNotificationObserver,
489
+ selection: codexProviderSelection,
490
+ turnAlreadyRunningError,
491
+ writeCodexAppServerUserMessageOwnership
492
+ });
493
+
494
+ const {
495
+ prepareCodexAppServerGoalContext,
496
+ validateCodexAppServerGoalInput,
497
+ updateCodexAppServerGoal
498
+ } = createCodexGoalCommands({
499
+ conversationContext: codexAppServerConversationContext,
500
+ ensureThreadReady: ensureCodexAppServerThreadReady,
501
+ publish,
502
+ readCodexAppServerAgentRunForSession,
503
+ reconcileCodexAppServerGoalUpdated,
504
+ submitCodexAppServerAssistantResult,
505
+ subscribeCodexAppServerEvents,
506
+ turnState
507
+ });
508
+
509
+ function recoverSessionObservationLoss(sessionId, runtime, session, preparation) {
510
+ return recoverCodexAppServerObservationLoss(runtime, session,
511
+ codexAppServerObservationRecoveryContext(sessionId, preparation));
137
512
  }
138
513
 
139
- async function finishFromCompletion(status = "completed") {
140
- try {
141
- if (!targetTurnId) {
142
- pendingCompletionStatus = normalizeText(status) || "completed";
143
- return;
514
+ async function ensureSessionReadiness(sessionId, prepared) {
515
+ if (Object.hasOwn(prepared, "value")) return prepared.value;
516
+ let session = prepared.session;
517
+ let turn = turnState(session);
518
+ if (turn.status === "observation_lost") {
519
+ if (turn.active) {
520
+ session = await prepared.recovery(recoverSessionObservationLoss);
521
+ turn = turnState(session);
144
522
  }
145
- const authoritative = await resultFromThread().catch(() => ({
146
- status: "",
147
- statusType: "",
148
- text: ""
149
- }));
150
- finalText = authoritative.text || finalText;
151
- if (!finalText) {
152
- pendingCompletionStatus = normalizeText(status) || "completed";
153
- const systemError = authoritative.statusType === "systemError" || authoritative.status === "failed";
154
- failAfterDetailGrace(new Error(systemError
155
- ? "Codex app-server thread entered a system error before producing an assistant response."
156
- : "Codex app-server completed without producing an assistant response."));
157
- return;
523
+ if (!turn.active) {
524
+ const recovered = await submitCodexAppServerAssistantResult(sessionId, turn.threadId, turn.turnId, { recoverFromProvider: true });
525
+ if (recovered.reason === "error") throw new Error(recovered.error);
158
526
  }
159
- finish({
160
- status,
161
- text: finalText,
162
- threadId: normalizedThreadId,
163
- turnId: targetTurnId,
164
- usage
165
- });
166
- } catch (error) {
167
- fail(error);
527
+ // A verified stop is a usable composer state, not a reconnect loop.
528
+ return prepared.stopped(session, turn);
168
529
  }
530
+ const connection = prepared.connection;
531
+ const { workdir, threadId } = connection;
532
+ if (threadId && connection.available && turnState(session).state !== "starting") {
533
+ const providerKey = codexProviderSelection.managedProviderKeyForThread(sessionId, workdir, threadId);
534
+ if (providerKey !== null) {
535
+ const observed = await checkCodexAppServerManagedConnection(providerKey, { reconnect: false });
536
+ if (!observed.requiresPreparation) {
537
+ return prepared.ready(threadId);
538
+ }
539
+ }
540
+ }
541
+ return prepared.prepare(ensureCodexAppServerThreadReady);
169
542
  }
170
543
 
171
- function notificationMatches(notification = {}) {
172
- const notificationThreadId = codexAppServerNotificationThreadId(notification);
173
- if (notificationThreadId && notificationThreadId !== normalizedThreadId) {
174
- return false;
544
+ async function readExecutionProfileModelCatalog(sessionId, preparation) {
545
+ if (preparation.assistantScope) {
546
+ const context = await codexAppServerEphemeralScopeContext(
547
+ sessionId, { agentSettings: preparation.agentSettings }, preparation.assistantScope
548
+ );
549
+ if (context.ok === false) return context;
550
+ return codexProviderSelection.readExecutionProfileModelCatalog(sessionId, {
551
+ assistantScope: preparation.assistantScope,
552
+ get provider() { return context.provider; },
553
+ signal: preparation.signal
554
+ });
175
555
  }
176
- const notificationTurnId = codexAppServerNotificationTurnId(notification);
177
- return !targetTurnId || !notificationTurnId || notificationTurnId === targetTurnId;
556
+ return codexProviderSelection.readExecutionProfileModelCatalog(sessionId, preparation);
178
557
  }
179
558
 
180
- return {
181
- async completeNow(status = "completed") {
182
- await finishFromCompletion(status);
183
- },
184
- failNow(error) {
185
- fail(error);
186
- },
187
- failAfterDetailGrace(error) {
188
- failAfterDetailGrace(error);
189
- },
190
- setTurnId(turnId = "") {
191
- targetTurnId = normalizeText(turnId);
192
- if (pendingFailure) {
193
- failAfterDetailGrace(pendingFailure);
194
- return;
195
- }
196
- if (pendingCompletionStatus) {
197
- const status = pendingCompletionStatus;
198
- pendingCompletionStatus = "";
199
- void finishFromCompletion(status);
200
- }
201
- },
202
- wait() {
203
- if (settled) {
204
- return Promise.reject(new Error("Codex app-server detached turn watcher was already settled."));
205
- }
206
- return new Promise((resolve, reject) => {
207
- resolveWaiter = resolve;
208
- rejectWaiter = reject;
209
- if (timeoutMs > 0) {
210
- timeout = setTimeout(() => {
211
- fail(new Error("Timed out waiting for Codex app-server response."));
212
- }, timeoutMs);
213
- } else {
214
- // Interactive repair turns may take longer than bounded helper jobs.
215
- // Retain their watcher until completion, interruption, or connection loss.
216
- const generation = provider?.currentConnectionGeneration?.();
217
- connectionCheck = setInterval(() => {
218
- if (provider?.isAvailable?.() === false ||
219
- provider?.currentConnectionGeneration?.() !== generation) {
220
- fail(new Error("Connection to Codex was lost while the temporary AI was working."));
221
- }
222
- }, 1000);
223
- connectionCheck.unref?.();
224
- }
225
- unsubscribe = typeof provider?.subscribe === "function"
226
- ? provider.subscribe((notification = {}) => {
227
- if (!notificationMatches(notification)) {
228
- return;
229
- }
230
- usage = codexAppServerTurnTokenUsage(notification) || usage;
231
- const classification = classifyCodexAppServerEvent(notification);
232
- emitWatcherEvent(classification);
233
- if (
234
- classification.kind === "provider_error" &&
235
- classification.text &&
236
- codexAppServerNotificationParams(notification).willRetry !== true
237
- ) {
238
- const error = new Error(classification.text);
239
- if (!targetTurnId) {
240
- pendingFailure = error;
241
- return;
242
- }
243
- fail(error);
244
- return;
245
- }
246
- if (classification.kind === "final_assistant_result" && classification.text) {
247
- finalText = classification.text;
248
- if (pendingCompletionStatus && targetTurnId) {
249
- const status = pendingCompletionStatus;
250
- pendingCompletionStatus = "";
251
- clearTimeout(failureDetailTimeout);
252
- failureDetailTimeout = null;
253
- void finishFromCompletion(status);
254
- }
255
- }
256
- const method = normalizeText(notification.method);
257
- if (method !== "turn/completed" && method !== "thread/status/changed") {
258
- return;
259
- }
260
- const status = codexAppServerNotificationTurnStatus(notification) || "completed";
261
- if (codexAppServerTurnStatusIsProviderFailure(status)) {
262
- const error = new Error(codexAppServerNotificationError(notification) || `Codex app-server turn ${status}.`);
263
- if (!targetTurnId) {
264
- pendingFailure = error;
265
- return;
266
- }
267
- failAfterDetailGrace(error);
268
- return;
269
- }
270
- if (codexAppServerTurnStatusIsSuccessfulComplete(status)) {
271
- void finishFromCompletion(status);
272
- }
273
- })
274
- : null;
559
+ const runOwner = {
560
+ helperThreads: helperLifecycle,
561
+ readAccountIdentity: provider => readCodexAppServerAccountIdentity(provider, helperOwnershipError),
562
+ assertAccountIdentity: (provider, expectedSignature) => assertCodexAppServerHelperAccountIdentity(
563
+ provider, expectedSignature, helperOwnershipError
564
+ ),
565
+ checkManagedConnection: checkCodexAppServerManagedConnection,
566
+ ensureSessionReadiness,
567
+ recoverSessionObservationLoss,
568
+ restoreLoadedThread: restoreCodexAppServerLoadedThread,
569
+ reconcileThread: reconcileCodexAppServerThreadForSession,
570
+ threadReconciliations: codexAppServerThreadReconciliations,
571
+ waitForThreadReconciliations: waitForOtherCodexAppServerThreadReconciliations,
572
+ conversations: codexAppServerConversations,
573
+ hasActiveTemporaryConversation: codexConversations.hasActiveConversation,
574
+ readExecutionProfileModelCatalog,
575
+ readProviderAccountIdentity: codexProviderSelection.readProviderAccountIdentity,
576
+ conversationTurnStarts: codexAppServerConversationTurnStarts,
577
+ conversation: codexAppServerConversation,
578
+ conversationSnapshot: codexAppServerEphemeralConversationSnapshot,
579
+ withConversationTurnStart: withCodexAppServerConversationTurnStart,
580
+ observeConversation: observeCodexConversation,
581
+ readPersistentConversation: readPersistentCodexConversation,
582
+ createConversation: createCodexAppServerConversation,
583
+ steerConversationTurn: steerCodexAppServerConversationTurn,
584
+ startConversationTurn: startCodexAppServerConversationTurn,
585
+ acquireDetachedThread: acquireCodexAppServerDetachedThread,
586
+ detachedThreadId: codexAppServerDetachedThreadId,
587
+ dispatchDetachedTurn: dispatchCodexAppServerDetachedTurn,
588
+ runDetachedTurn: runDetachedCodexAppServerTurn,
589
+ interruptConversation: interruptCodexAppServerConversation,
590
+ deleteConversation: deleteScopedCodexAppServerConversation,
591
+ readConversation: readCodexAppServerConversation,
592
+ stopConversation: stopCodexAppServerConversation,
593
+ closeConversations: closeCodexAppServerConversations,
594
+ conversationContext: codexAppServerConversationContext,
595
+ ephemeralScopeContext: codexAppServerEphemeralScopeContext,
596
+ prepareConversationThread: prepareCodexAppServerConversationThread,
597
+ interruptDetachedTurn: interruptDetachedCodexAppServerConversationTurn,
598
+ deleteDetachedThread: deleteDetachedCodexAppServerConversationThread,
599
+ stopPersistentConversation: stopPersistentCodexConversation,
600
+ waitForConversationTurn: waitForCodexAppServerConversationTurn,
601
+ withMessageDelivery: withCodexAppServerMessageDelivery,
602
+ dispatchMessage: dispatchCodexAppServerMessage,
603
+ ensureThreadReady: ensureCodexAppServerThreadReady,
604
+ messageContext: codexAppServerMessageContext,
605
+ outputProvider: acquireCodexAppServerOutputProvider,
606
+ runtimeForVisibleTerminal: codexAppServerRuntimeForVisibleTerminal,
607
+ controlContext: codexAppServerControlContext,
608
+ observationRecoveryContext: codexAppServerObservationRecoveryContext,
609
+ claimMessageStart: claimCodexAppServerMessageStart,
610
+ assertThreadCanResume: assertCodexAppServerThreadCanResume,
611
+ createObservation(sessionId, context = {}) {
612
+ if (!providerSessions) return createCodexAppServerObservation(sessionId, context);
613
+ const { providerKey } = context;
614
+ return createCodexAppServerObservation(sessionId, {
615
+ ...context,
616
+ retireProvider: () => runOwner.runtimeLifecycle.retireProvider(providerKey)
275
617
  });
276
- }
618
+ },
619
+ selectMessageTurn: selectCodexAppServerMessageTurn,
620
+ interruptTurn: interruptCodexAppServerTurn,
621
+ recoverObservationLoss: recoverCodexAppServerObservationLoss,
622
+ runRenewalHandover: runCodexAppServerRenewalHandover,
623
+ runRenewalSeed: runCodexAppServerRenewalSeed,
624
+ startTurn: startCodexAppServerTurn,
625
+ steerTurn: steerCodexAppServerTurn,
626
+ prepareGoalContext: prepareCodexAppServerGoalContext,
627
+ validateGoalInput: validateCodexAppServerGoalInput,
628
+ updateGoal: updateCodexAppServerGoal,
629
+ notificationQueue: codexAppServerNotificationQueue,
630
+ messageDeliveries: codexAppServerMessageDeliveries,
631
+ pendingUserMessages: codexAppServerPendingUserMessages,
632
+ eventSubscriptions: codexAppServerEventSubscriptions,
633
+ completedTurns: codexAppServerCompletedTurns,
634
+ promptDeliveries: codexAppServerPromptDeliveries,
635
+ automaticHookThreads: codexAppServerAutomaticHookThreads,
636
+ eventSubscriptionKey: codexAppServerEventSubscriptionKey,
637
+ eventSubscriptionIsCurrent: codexAppServerEventSubscriptionIsCurrent,
638
+ unsubscribeEventSubscription: unsubscribeCodexAppServerEventSubscription,
639
+ scheduleActiveRecovery: scheduleCodexAppServerActiveRecovery,
640
+ reconcileThreadStatus: reconcileCodexAppServerThreadStatus,
641
+ reconcileLoadedThreadStatus: reconcileCodexAppServerLoadedThreadStatus,
642
+ writeUserMessageOwnership: writeCodexAppServerUserMessageOwnership,
643
+ mirrorTerminalUserMessage: mirrorCodexAppServerTerminalUserMessage,
644
+ reconcileObservedTurnItems: reconcileCodexAppServerObservedTurnItems,
645
+ markTurnActive: markCodexAppServerTurnActive,
646
+ adoptSuccessorTurn: adoptCodexAppServerSuccessorTurn,
647
+ recoverActiveTurn: recoverCodexAppServerActiveTurn,
648
+ completeTurn: completeCodexAppServerTurn,
649
+ stopTurnWithProviderFailure: stopCodexAppServerTurnWithProviderFailure,
650
+ reconcileGoalUpdated: reconcileCodexAppServerGoalUpdated,
651
+ writeDeliveredUserMessage: writeCodexAppServerDeliveredUserMessage,
652
+ subscribeEvents: subscribeCodexAppServerEvents,
653
+ activeTimers: codexAppServerActiveTimers,
654
+ finalizingTimers: codexAppServerFinalizingTimers,
655
+ resultFinalizations: codexAppServerResultFinalizations,
656
+ clearActiveTimer: clearCodexAppServerActiveTimer,
657
+ clearFinalizingTimer: clearCodexAppServerFinalizingTimer,
658
+ clearSessionRecoveryTimers: clearCodexAppServerSessionRecoveryTimers,
659
+ agentRunRealtimePayload: codexAppServerAgentRunRealtimePayload,
660
+ publishAgentRun: publishCodexAppServerAgentRun,
661
+ markTurnFinalizing: markCodexAppServerTurnFinalizing,
662
+ markTurnIdle: markCodexAppServerTurnIdle,
663
+ resolveTurnId: resolveCodexAppServerTurnId,
664
+ finalizeAssistantResult: finalizeCodexAppServerAssistantResult,
665
+ recoverFinalResponseBeforeOutcome: recoverCodexAppServerFinalResponseBeforeOutcome,
666
+ finalizedTurns: codexAppServerFinalizedTurns,
667
+ finalAssistantResults: codexAppServerFinalAssistantResults,
668
+ reasoningTurns: codexAppServerReasoningTurns,
669
+ reasoningPersistQueues: codexAppServerReasoningPersistQueues,
670
+ liveProgressItems: codexAppServerLiveProgressItems,
671
+ liveProgressFingerprints: codexAppServerLiveProgressFingerprints,
672
+ mirroredTerminalItems: codexAppServerMirroredTerminalItems,
673
+ liveProgressCandidate: codexAppServerLiveProgressCandidate,
674
+ conversationMessageId: codexAppServerConversationMessageId,
675
+ readAgentRunForSession: readCodexAppServerAgentRunForSession,
676
+ readFinalAssistantResult: readCodexAppServerFinalAssistantResult,
677
+ persistAssistantReply: persistCodexAppServerAssistantReply,
678
+ recordFinalAssistantResult: recordCodexAppServerFinalAssistantResult,
679
+ recordReasoningForSession: recordCodexAppServerReasoningForSession,
680
+ flushReasoningPersist: flushCodexAppServerReasoningPersist,
681
+ splitReasoningTurn: splitCodexAppServerReasoningTurn,
682
+ cleanupUntrackedTurn: cleanupCodexAppServerUntrackedTurn,
683
+ writeStream: writeCodexAppServerStream,
684
+ writeLiveProgress: writeCodexAppServerLiveProgress,
685
+ submitAssistantResult: submitCodexAppServerAssistantResult,
686
+ processedTurns: codexAppServerProcessedTurns,
687
+ resultFinalizationKey: codexAppServerResultFinalizationKey,
688
+ turnResultWasProcessed: codexAppServerTurnResultWasProcessed,
689
+ claimTurnStart: claimCodexAppServerTurnStart,
690
+ writeAgentRun: writeCodexAppServerAgentRun
277
691
  };
692
+ const cleanup = createCodexSessionCleanup({
693
+ namespace,
694
+ runOwner,
695
+ providerSessions,
696
+ helperLifecycle,
697
+ journal: codexRunJournal,
698
+ conversations: codexConversations,
699
+ debugLog,
700
+ debugError
701
+ });
702
+ runOwner.closeSession = cleanup.closeSession;
703
+ runOwner.closeProject = cleanup.closeProject;
704
+ if (providerSessions) {
705
+ runOwner.runtimeLifecycle = createCodexRuntimeLifecycle({
706
+ runOwner,
707
+ providerSessions,
708
+ helperLifecycle,
709
+ captureContext,
710
+ runInContext,
711
+ debugLog,
712
+ debugError,
713
+ closingError: serverClosingError
714
+ });
715
+ if (serverClosingError) {
716
+ providerSessions.owner.attachRuntimeLifecycle(runOwner.runtimeLifecycle);
717
+ providerSessions.assertOpen = runOwner.runtimeLifecycle.assertOpen;
718
+ }
719
+ runOwner.invalidateRuntimes = runOwner.runtimeLifecycle.invalidateRuntimes;
720
+ Object.assign(runOwner, createCodexSessionReconciliation({
721
+ runOwner, providerSessions, helperLifecycle, lifecycle: runOwner.runtimeLifecycle,
722
+ createRuntime, namespace, turnState, sessionIdRequiredError, debugLog, debugError
723
+ }));
724
+ }
725
+ return runOwner;
278
726
  }
279
-
280
- export { createCodexAppServerDetachedTurnWatcher, codexAppServerTurnStatusIsActive, codexAppServerTurnStatusIsComplete, codexAppServerTurnStatusIsSuccessfulComplete, codexAppServerTurnStatusIsProviderFailure };