@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.
- package/examples/conversation/README.md +8 -1
- package/examples/conversation/package.json +5 -5
- package/fixtures/responsive-assistant/App.vue +4 -1
- package/package.json +99 -36
- package/src/client/conversation/AssistantConversationElement.vue +27 -4
- package/src/client/conversation/AssistantConversationStatus.vue +24 -0
- package/src/client/conversation/AssistantGoalControl.vue +8 -5
- package/src/client/conversation/AssistantTranscript.vue +10 -3
- package/src/client/conversation/index.js +2 -0
- package/src/client/conversation/messageDelivery.js +115 -32
- package/src/client/conversation/retainedConversation.js +32 -0
- package/src/client/conversation/useAssistantQuestions.js +76 -0
- package/src/client/lib/assistantApi.js +72 -2
- package/src/server/conversation/agentRun.js +222 -0
- package/src/server/conversation/attachments.js +93 -0
- package/src/server/conversation/claudeClient.js +221 -0
- package/src/server/conversation/claudeHistory.js +256 -0
- package/src/server/conversation/claudeProcess.js +327 -0
- package/src/server/conversation/claudeTools.js +42 -0
- package/src/server/conversation/claudeTurn.js +1082 -0
- package/src/server/conversation/codexConfiguration.js +1183 -0
- package/src/server/conversation/codexConversations.js +1082 -0
- package/src/server/conversation/codexDetachedTurn.js +332 -0
- package/src/server/conversation/codexEvents.js +194 -1
- package/src/server/conversation/codexGoalCommands.js +124 -0
- package/src/server/conversation/codexHelperExecution.js +306 -0
- package/src/server/conversation/codexHelperThreadLedger.js +804 -0
- package/src/server/conversation/codexHelperThreadRecovery.js +395 -0
- package/src/server/conversation/codexHelperThreads.js +638 -0
- package/src/server/conversation/codexHistoryAdapter.js +369 -0
- package/src/server/conversation/codexMessageCommands.js +663 -0
- package/src/server/conversation/codexMessageDelivery.js +211 -0
- package/src/server/conversation/codexNativeHistoryExport.js +95 -0
- package/src/server/conversation/codexNotificationObserver.js +482 -0
- package/src/server/conversation/codexNotificationQueue.js +103 -0
- package/src/server/conversation/codexObservationControl.js +174 -0
- package/src/server/conversation/codexOutput.js +931 -0
- package/src/server/conversation/codexProcess.js +1559 -0
- package/src/server/conversation/codexProcessLeader.js +14 -0
- package/src/server/conversation/codexProvider.js +2710 -0
- package/src/server/conversation/codexProviderOwner.js +1058 -0
- package/src/server/conversation/codexProviderSelection.js +218 -0
- package/src/server/conversation/codexReasoning.js +314 -0
- package/src/server/conversation/codexRenewalCommands.js +290 -0
- package/src/server/conversation/codexResultSettlement.js +409 -0
- package/src/server/conversation/codexRunJournal.js +658 -0
- package/src/server/conversation/codexRuntimeLifecycle.js +288 -0
- package/src/server/conversation/codexSessionCleanup.js +96 -0
- package/src/server/conversation/codexSessionReconciliation.js +284 -0
- package/src/server/conversation/codexThreadReadiness.js +397 -0
- package/src/server/conversation/codexThreadStatus.js +354 -0
- package/src/server/conversation/codexTurn.js +701 -255
- package/src/server/conversation/codexTurnControl.js +317 -0
- package/src/server/conversation/codexTurnRecovery.js +990 -0
- package/src/server/conversation/codexTurnState.js +549 -0
- package/src/server/conversation/commandHook.js +18 -0
- package/src/server/conversation/commandWrapper.js +37 -0
- package/src/server/conversation/configuration.js +43 -0
- package/src/server/conversation/continuity.js +289 -0
- package/src/server/conversation/fileStorage.js +55 -0
- package/src/server/conversation/hookBridge.js +19 -0
- package/src/server/conversation/index.js +13 -0
- package/src/server/conversation/localExecution.js +665 -0
- package/src/server/conversation/memoryStorage.js +7 -72
- package/src/server/conversation/nativeHistoryExport.js +90 -0
- package/src/server/conversation/nativeStorage.js +23 -0
- package/src/server/conversation/openCodeClient.js +209 -19
- package/src/server/conversation/openCodePlugin.js +84 -0
- package/src/server/conversation/openCodeProcess.js +476 -0
- package/src/server/conversation/openCodeRuntime.js +1578 -0
- package/src/server/conversation/openCodeTools.js +60 -0
- package/src/server/conversation/openCodeTurn.js +557 -0
- package/src/server/conversation/provider.js +30 -0
- package/src/server/conversation/providers/api.js +136 -0
- package/src/server/conversation/providers/claude.js +63 -0
- package/src/server/conversation/providers/claudeDriver.js +425 -0
- package/src/server/conversation/providers/codex.js +248 -0
- package/src/server/conversation/providers/codexDriver.js +1078 -0
- package/src/server/conversation/providers/opencode.js +49 -0
- package/src/server/conversation/providers/opencodeDriver.js +650 -0
- package/src/server/conversation/providers/scoped.js +312 -0
- package/src/server/conversation/runtime.js +2220 -0
- package/src/server/conversation/runtimeStateUpgrade.js +125 -0
- package/src/server/conversation/storage.js +184 -0
- package/src/server/conversation/streams.js +7 -2
- package/src/server/conversation/structuredOutput.js +240 -0
- package/src/server/conversation/systemPrompt.js +54 -0
- package/src/server/conversation/tools.js +84 -0
- package/src/server/conversation/transcript.js +5 -4
- package/src/server/hosts/claudeHistory.js +5 -0
- package/src/server/hosts/claudeProcess.js +11 -0
- package/src/server/hosts/claudeTurn.js +4 -0
- package/src/server/hosts/codexConfiguration.js +20 -0
- package/src/server/hosts/codexEvents.js +13 -0
- package/src/server/hosts/codexProcess.js +12 -0
- package/src/server/hosts/codexProvider.js +23 -0
- package/src/server/hosts/codexTurn.js +20 -0
- package/src/server/hosts/nativeHistory.js +3 -0
- package/src/server/hosts/openCodeClient.js +3 -0
- package/src/server/hosts/openCodeProcess.js +23 -0
- package/src/server/hosts/openCodeTurn.js +7 -0
- package/src/server/index.js +2 -0
- package/src/server/lib/aiConnectionClient.js +13 -6
- package/src/server/lib/assistantCompletion.js +190 -0
- package/src/server/lib/assistantToolLoop.js +314 -0
- package/src/server/lib/serviceToolCatalog.js +25 -10
- package/src/shared/assistantResponseText.js +29 -0
- package/src/shared/conversation/attachments.js +19 -0
- package/src/shared/conversation/index.js +3 -0
- package/src/shared/conversation/pagination.js +78 -0
- package/src/shared/conversation/patches.js +150 -0
- package/src/shared/conversation/questions.js +48 -0
- package/src/shared/conversation/streaming.js +7 -4
- package/src/shared/index.js +2 -0
- package/src/shared/nativeProviders.js +45 -0
- package/src/testing/conversationStorageContract.js +31 -1
- package/src/testing/nativeCodex.js +11 -0
- package/src/testing/nativeOpenCode.js +3 -0
- package/test/aiConnectionClient.test.js +2 -0
- package/test/apiConversationDriver.test.js +73 -0
- package/test/assistantApiSurfaceHeader.test.js +85 -0
- package/test/assistantBoundedToolLoop.test.js +285 -0
- package/test/assistantScroll.browser.test.js +16 -0
- package/test/claudeClient.test.js +189 -0
- package/test/claudeConversationSession.test.js +1173 -0
- package/test/claudeInstructionResume.test.js +82 -0
- package/test/claudeProcess.test.js +204 -0
- package/test/claudeTurn.test.js +253 -0
- package/test/codexConversationSession.test.js +2122 -0
- package/test/codexGoal.test.js +37 -0
- package/test/codexHelperDeletion.test.js +163 -0
- package/test/codexHelperThreadLedger.test.js +494 -0
- package/test/codexHistoryAdapter.test.js +541 -0
- package/test/codexInteractiveArguments.test.js +30 -0
- package/test/codexIsolation.test.js +756 -0
- package/test/codexModelCatalog.test.js +362 -0
- package/test/codexNativeHistoryExport.test.js +81 -0
- package/test/codexThreadSelection.test.js +136 -0
- package/test/codexTurn.test.js +2158 -0
- package/test/conversation.test.js +110 -0
- package/test/conversationAgentRun.test.js +326 -0
- package/test/conversationApiFacilities.test.js +90 -0
- package/test/conversationAttachments.test.js +238 -0
- package/test/conversationCommandWrapper.test.js +48 -0
- package/test/conversationConfiguration.test.js +174 -0
- package/test/conversationNativeStorage.test.js +25 -0
- package/test/conversationReplacement.test.js +172 -0
- package/test/conversationRuntime.test.js +241 -0
- package/test/conversationRuntimeStateUpgrade.test.js +144 -0
- package/test/conversationSession.test.js +1080 -0
- package/test/conversationStreaming.test.js +68 -0
- package/test/conversationSystemPrompt.test.js +84 -0
- package/test/conversationTools.test.js +416 -0
- package/test/fileConversationStorage.test.js +73 -0
- package/test/fixtures/codexHelperThreadLedger.js +39 -0
- package/test/localConversationExecution.test.js +90 -0
- package/test/messageDelivery.test.js +234 -1
- package/test/nativeConversationRetirement.test.js +215 -0
- package/test/openCodeClient.test.js +515 -0
- package/test/openCodeProcess.test.js +177 -0
- package/test/openCodeRuntime.test.js +322 -0
- package/test/openCodeTools.test.js +287 -0
- package/test/opencodeConversationSession.test.js +789 -0
- package/test/serviceToolCatalog.test.js +24 -0
|
@@ -0,0 +1,658 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeCodexRunText,
|
|
3
|
+
codexAppServerRunStateIsActive,
|
|
4
|
+
codexAppServerAgentRun,
|
|
5
|
+
codexAppServerPendingUserMessageClientIds,
|
|
6
|
+
codexAppServerProcessedResultEvent,
|
|
7
|
+
codexAppServerTurnCanReceiveProviderActivity,
|
|
8
|
+
codexAppServerTurnKey,
|
|
9
|
+
codexAppServerAgentRunPatch,
|
|
10
|
+
codexAppServerRunIdentityForPatch,
|
|
11
|
+
codexAppServerRunPatchIsStaleAfterTerminalState,
|
|
12
|
+
CODEX_APP_SERVER_AGENT_RUN_ID,
|
|
13
|
+
CODEX_AGENT_PROVIDER,
|
|
14
|
+
CODEX_APP_SERVER_RUN_STATE,
|
|
15
|
+
CODEX_APP_SERVER_ACTIVE_RUN_STATES,
|
|
16
|
+
codexAppServerRunInputSource
|
|
17
|
+
} from "./codexTurnState.js";
|
|
18
|
+
import crypto from "node:crypto";
|
|
19
|
+
import { isPlainObject } from "./normalize.js";
|
|
20
|
+
|
|
21
|
+
const CODEX_APP_SERVER_PROMPT_CLAIM_GRACE_MS = 15000;
|
|
22
|
+
|
|
23
|
+
// Original native run claims, guarded journal writes and status retirement.
|
|
24
|
+
// The containing run owner shares these exact Sets and Maps by reference.
|
|
25
|
+
export function createCodexRunJournal({
|
|
26
|
+
namespace,
|
|
27
|
+
normalizeRunState,
|
|
28
|
+
turnState,
|
|
29
|
+
createRuntime,
|
|
30
|
+
publish,
|
|
31
|
+
checkpoint,
|
|
32
|
+
debugLog,
|
|
33
|
+
output,
|
|
34
|
+
messageIdPrefix,
|
|
35
|
+
sessionIdRequiredError,
|
|
36
|
+
turnClaimsUnsupportedError,
|
|
37
|
+
turnAlreadyRunningError,
|
|
38
|
+
errorPrefix,
|
|
39
|
+
idlePublishPayload,
|
|
40
|
+
finalizingGraceMs,
|
|
41
|
+
admissionTaskFinished,
|
|
42
|
+
orphanedPromptMessage
|
|
43
|
+
}) {
|
|
44
|
+
const codexAppServerCompletedTurns = new Set();
|
|
45
|
+
const codexAppServerProcessedTurns = new Set();
|
|
46
|
+
const codexAppServerActiveTimers = new Map();
|
|
47
|
+
const codexAppServerFinalizingTimers = new Map();
|
|
48
|
+
const agentRunPatch = input => codexAppServerAgentRunPatch(input, normalizeRunState);
|
|
49
|
+
const runIdentityForPatch = (session, input) => codexAppServerRunIdentityForPatch(session, input, normalizeRunState);
|
|
50
|
+
const runPatchIsStaleAfterTerminalState = (turn, patch) => codexAppServerRunPatchIsStaleAfterTerminalState(turn, patch, normalizeRunState);
|
|
51
|
+
const {
|
|
52
|
+
resultFinalizationKey: codexAppServerResultFinalizationKey,
|
|
53
|
+
readAgentRunForSession: readCodexAppServerAgentRunForSession
|
|
54
|
+
} = output;
|
|
55
|
+
|
|
56
|
+
function codexAppServerTurnResultWasProcessed(session = {}, threadId = "", turnId = "") {
|
|
57
|
+
const normalizedThreadId = normalizeCodexRunText(threadId);
|
|
58
|
+
const normalizedTurnId = normalizeCodexRunText(turnId);
|
|
59
|
+
if (!normalizedThreadId || !normalizedTurnId) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
return codexAppServerProcessedTurns.has(codexAppServerResultFinalizationKey(
|
|
63
|
+
session.sessionId,
|
|
64
|
+
normalizedThreadId,
|
|
65
|
+
normalizedTurnId
|
|
66
|
+
)) || Boolean(codexAppServerProcessedResultEvent(session, normalizedThreadId, normalizedTurnId));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function claimCodexAppServerTurnStart(runtime, sessionId = "", outerTurnId = "", {
|
|
70
|
+
inputSource = "chat"
|
|
71
|
+
} = {}) {
|
|
72
|
+
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
73
|
+
const normalizedOuterTurnId = normalizeCodexRunText(outerTurnId);
|
|
74
|
+
let claimResult = null;
|
|
75
|
+
const mutationResult = await runtime.store.mutateSession(normalizedSessionId, async () => {
|
|
76
|
+
const currentSession = await runtime.getSession(normalizedSessionId);
|
|
77
|
+
const currentTurn = turnState(currentSession);
|
|
78
|
+
if (currentTurn.active) {
|
|
79
|
+
claimResult = {
|
|
80
|
+
claimed: false,
|
|
81
|
+
session: currentSession
|
|
82
|
+
};
|
|
83
|
+
return claimResult;
|
|
84
|
+
}
|
|
85
|
+
const updatedAt = new Date().toISOString();
|
|
86
|
+
const runPatch = agentRunPatch({
|
|
87
|
+
inputSource: normalizeCodexRunText(inputSource) || "chat",
|
|
88
|
+
outerTurnId: normalizedOuterTurnId,
|
|
89
|
+
runState: CODEX_APP_SERVER_RUN_STATE.STARTING,
|
|
90
|
+
session: currentSession,
|
|
91
|
+
status: "starting",
|
|
92
|
+
updatedAt
|
|
93
|
+
});
|
|
94
|
+
runPatch.providerGoalStatus = "";
|
|
95
|
+
runPatch.providerGoalThreadId = "";
|
|
96
|
+
runPatch.providerGoalUpdatedAt = "";
|
|
97
|
+
await runtime.store.writeAgentRunEvent(normalizedSessionId, CODEX_APP_SERVER_AGENT_RUN_ID, {
|
|
98
|
+
event: {
|
|
99
|
+
kind: "codex-app-server-turn-claimed",
|
|
100
|
+
message: "",
|
|
101
|
+
state: runPatch.state
|
|
102
|
+
},
|
|
103
|
+
patch: runPatch
|
|
104
|
+
});
|
|
105
|
+
claimResult = {
|
|
106
|
+
claimed: true,
|
|
107
|
+
session: await runtime.getSession(normalizedSessionId)
|
|
108
|
+
};
|
|
109
|
+
return claimResult;
|
|
110
|
+
});
|
|
111
|
+
return claimResult || mutationResult;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function claimCodexAppServerMessageStart(runtime, sessionId = "", outerTurnId = "", {
|
|
115
|
+
inputSource = "chat"
|
|
116
|
+
} = {}) {
|
|
117
|
+
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
118
|
+
const normalizedOuterTurnId = normalizeCodexRunText(outerTurnId) ||
|
|
119
|
+
`${messageIdPrefix}${crypto.randomUUID()}`;
|
|
120
|
+
if (!normalizedSessionId) {
|
|
121
|
+
return {
|
|
122
|
+
claimed: false,
|
|
123
|
+
response: { value: {
|
|
124
|
+
ok: false,
|
|
125
|
+
error: sessionIdRequiredError
|
|
126
|
+
} }
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
if (typeof runtime?.store?.mutateSession !== "function" || typeof runtime?.getSession !== "function") {
|
|
130
|
+
throw new Error(turnClaimsUnsupportedError);
|
|
131
|
+
}
|
|
132
|
+
const result = await claimCodexAppServerTurnStart(runtime, normalizedSessionId, normalizedOuterTurnId, { inputSource });
|
|
133
|
+
if (result?.claimed === false && result.session) {
|
|
134
|
+
const turn = turnState(result.session);
|
|
135
|
+
return { ...result, response: { value: {
|
|
136
|
+
ok: false,
|
|
137
|
+
code: `${errorPrefix}agent_turn_already_running`,
|
|
138
|
+
error: turnAlreadyRunningError,
|
|
139
|
+
operationOutcome: "agent_already_running",
|
|
140
|
+
refreshRecommended: true,
|
|
141
|
+
threadId: normalizeCodexRunText(turn.threadId),
|
|
142
|
+
turnId: normalizeCodexRunText(turn.turnId)
|
|
143
|
+
}, session: result.session } };
|
|
144
|
+
}
|
|
145
|
+
if (result?.claimed) {
|
|
146
|
+
await publish(normalizedSessionId, {
|
|
147
|
+
reason: "codex-app-server-turn-claimed",
|
|
148
|
+
session: result.session,
|
|
149
|
+
payload: codexAppServerAgentRunRealtimePayload(codexAppServerAgentRun(result.session))
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async function writeCodexAppServerAgentRun(runtime, sessionId = "", {
|
|
156
|
+
error = "",
|
|
157
|
+
inputSource = "",
|
|
158
|
+
phase,
|
|
159
|
+
publishReason = "",
|
|
160
|
+
observedRun = null,
|
|
161
|
+
runState = CODEX_APP_SERVER_RUN_STATE.COMPLETED,
|
|
162
|
+
status = "",
|
|
163
|
+
threadId = "",
|
|
164
|
+
turnId = "",
|
|
165
|
+
updatedAt = ""
|
|
166
|
+
} = {}) {
|
|
167
|
+
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
168
|
+
let runPatch = null;
|
|
169
|
+
let conversationStream = null;
|
|
170
|
+
let wrote = false;
|
|
171
|
+
let stale = null;
|
|
172
|
+
const updatedSession = await runtime.store.mutateSession(normalizedSessionId, async () => {
|
|
173
|
+
const currentSession = typeof runtime?.getSession === "function"
|
|
174
|
+
? await runtime.getSession(normalizedSessionId).catch(() => null)
|
|
175
|
+
: null;
|
|
176
|
+
const identity = runIdentityForPatch(currentSession || {}, {
|
|
177
|
+
threadId,
|
|
178
|
+
turnId
|
|
179
|
+
});
|
|
180
|
+
runPatch = agentRunPatch({
|
|
181
|
+
error,
|
|
182
|
+
inputSource,
|
|
183
|
+
phase,
|
|
184
|
+
runState,
|
|
185
|
+
session: currentSession || {},
|
|
186
|
+
status,
|
|
187
|
+
threadId: identity.threadId,
|
|
188
|
+
turnId: identity.turnId,
|
|
189
|
+
updatedAt: normalizeCodexRunText(updatedAt) || new Date().toISOString()
|
|
190
|
+
});
|
|
191
|
+
const currentTurn = turnState(currentSession || {});
|
|
192
|
+
if (
|
|
193
|
+
codexAppServerRunStateIsActive(runPatch.state) &&
|
|
194
|
+
currentTurn.threadId === normalizeCodexRunText(runPatch.providerThreadId) &&
|
|
195
|
+
currentTurn.turnId === normalizeCodexRunText(runPatch.providerTurnId) &&
|
|
196
|
+
currentTurn.startedAt
|
|
197
|
+
) {
|
|
198
|
+
runPatch.startedAt = currentTurn.startedAt;
|
|
199
|
+
}
|
|
200
|
+
// The observation is valid only for the durable run read before the RPC.
|
|
201
|
+
// A later Stop, Pause, completion or successor wins under this same lock.
|
|
202
|
+
const canRecoverStoppedTurn = observedRun &&
|
|
203
|
+
currentTurn.status !== "observation_lost" &&
|
|
204
|
+
(codexAppServerAgentRun(currentSession)?.events?.length || 0) === (observedRun.events?.length || 0) &&
|
|
205
|
+
!codexAppServerTurnResultWasProcessed(currentSession, runPatch.providerThreadId, runPatch.providerTurnId) &&
|
|
206
|
+
[CODEX_APP_SERVER_RUN_STATE.FAILED, CODEX_APP_SERVER_RUN_STATE.INTERRUPTED].includes(currentTurn.runState) &&
|
|
207
|
+
currentTurn.threadId === runPatch.providerThreadId &&
|
|
208
|
+
currentTurn.turnId === runPatch.providerTurnId &&
|
|
209
|
+
runPatch.state === CODEX_APP_SERVER_RUN_STATE.ACTIVE;
|
|
210
|
+
if (
|
|
211
|
+
(currentTurn.status === "observation_lost" && status !== "observation_lost") ||
|
|
212
|
+
(phase !== undefined && (!normalizeCodexRunText(turnId) ||
|
|
213
|
+
!codexAppServerTurnCanReceiveProviderActivity(currentTurn, threadId, turnId))) ||
|
|
214
|
+
(observedRun && !canRecoverStoppedTurn) ||
|
|
215
|
+
(!canRecoverStoppedTurn && runPatchIsStaleAfterTerminalState(currentTurn, runPatch))
|
|
216
|
+
) {
|
|
217
|
+
stale = {
|
|
218
|
+
currentState: currentTurn.state,
|
|
219
|
+
currentStatus: currentTurn.status,
|
|
220
|
+
currentThreadId: currentTurn.threadId,
|
|
221
|
+
currentTurnId: currentTurn.turnId,
|
|
222
|
+
patchState: runPatch.state,
|
|
223
|
+
patchStatus: runPatch.providerStatus,
|
|
224
|
+
patchThreadId: runPatch.providerThreadId,
|
|
225
|
+
patchTurnId: runPatch.providerTurnId
|
|
226
|
+
};
|
|
227
|
+
debugLog("appServerAgentRun.staleTerminalPatch", {
|
|
228
|
+
...stale,
|
|
229
|
+
publishReason,
|
|
230
|
+
sessionId: normalizedSessionId
|
|
231
|
+
});
|
|
232
|
+
return currentSession;
|
|
233
|
+
}
|
|
234
|
+
await runtime.store.writeAgentRunEvent(normalizedSessionId, CODEX_APP_SERVER_AGENT_RUN_ID, {
|
|
235
|
+
event: {
|
|
236
|
+
kind: publishReason || "codex-app-server-turn-state",
|
|
237
|
+
message: normalizeCodexRunText(error),
|
|
238
|
+
state: runPatch.state
|
|
239
|
+
},
|
|
240
|
+
patch: runPatch
|
|
241
|
+
});
|
|
242
|
+
if (!codexAppServerRunStateIsActive(runPatch.state)) {
|
|
243
|
+
conversationStream = runtime.store.clearConversationStream(normalizedSessionId);
|
|
244
|
+
}
|
|
245
|
+
wrote = true;
|
|
246
|
+
return runtime.getSession(normalizedSessionId);
|
|
247
|
+
});
|
|
248
|
+
return { wrote, stale, runPatch, conversationStream, updatedSession };
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function clearCodexAppServerActiveTimer(sessionId = "") {
|
|
252
|
+
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
253
|
+
const sessionKey = namespace(normalizedSessionId);
|
|
254
|
+
const timer = codexAppServerActiveTimers.get(sessionKey);
|
|
255
|
+
if (timer) {
|
|
256
|
+
clearTimeout(timer);
|
|
257
|
+
codexAppServerActiveTimers.delete(sessionKey);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function clearCodexAppServerFinalizingTimer(sessionId = "", threadId = "", turnId = "") {
|
|
262
|
+
const key = codexAppServerResultFinalizationKey(sessionId, threadId, turnId);
|
|
263
|
+
const timer = codexAppServerFinalizingTimers.get(key);
|
|
264
|
+
if (timer) {
|
|
265
|
+
clearTimeout(timer);
|
|
266
|
+
codexAppServerFinalizingTimers.delete(key);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function clearCodexAppServerSessionRecoveryTimers(sessionId = "") {
|
|
271
|
+
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
272
|
+
clearCodexAppServerActiveTimer(normalizedSessionId);
|
|
273
|
+
const finalizingKeyPrefix = `${namespace(normalizedSessionId)}:`;
|
|
274
|
+
for (const [key, timer] of codexAppServerFinalizingTimers.entries()) {
|
|
275
|
+
if (key.startsWith(finalizingKeyPrefix)) {
|
|
276
|
+
clearTimeout(timer);
|
|
277
|
+
codexAppServerFinalizingTimers.delete(key);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function terminalCodexAppServerAgentRunState(status = "") {
|
|
283
|
+
const normalizedStatus = normalizeCodexRunText(status);
|
|
284
|
+
if (normalizedStatus === "interrupted") {
|
|
285
|
+
return CODEX_APP_SERVER_RUN_STATE.INTERRUPTED;
|
|
286
|
+
}
|
|
287
|
+
if (normalizedStatus === "failed") {
|
|
288
|
+
return CODEX_APP_SERVER_RUN_STATE.FAILED;
|
|
289
|
+
}
|
|
290
|
+
return CODEX_APP_SERVER_RUN_STATE.COMPLETED;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function codexAppServerAgentRunRealtimePayload(runPatch = {}) {
|
|
294
|
+
const runState = normalizeRunState(runPatch.state);
|
|
295
|
+
const active = codexAppServerRunStateIsActive(runState);
|
|
296
|
+
const state = runState === CODEX_APP_SERVER_RUN_STATE.FINALIZING
|
|
297
|
+
? "finalizing"
|
|
298
|
+
: runState === CODEX_APP_SERVER_RUN_STATE.STARTING
|
|
299
|
+
? "starting"
|
|
300
|
+
: active
|
|
301
|
+
? "active"
|
|
302
|
+
: "idle";
|
|
303
|
+
const turn = {
|
|
304
|
+
active,
|
|
305
|
+
completedAt: normalizeCodexRunText(runPatch.finishedAt),
|
|
306
|
+
error: normalizeCodexRunText(runPatch.error),
|
|
307
|
+
inputSource: normalizeCodexRunText(runPatch.inputSource),
|
|
308
|
+
outerTurnId: normalizeCodexRunText(runPatch.outerTurnId),
|
|
309
|
+
phase: active && runPatch.providerStatus !== "observation_lost" ? normalizeCodexRunText(runPatch.providerPhase) : "",
|
|
310
|
+
runId: CODEX_APP_SERVER_AGENT_RUN_ID,
|
|
311
|
+
runState,
|
|
312
|
+
startedAt: normalizeCodexRunText(runPatch.startedAt),
|
|
313
|
+
state,
|
|
314
|
+
status: normalizeCodexRunText(runPatch.providerStatus || runState),
|
|
315
|
+
threadId: normalizeCodexRunText(runPatch.providerThreadId),
|
|
316
|
+
turnId: normalizeCodexRunText(runPatch.providerTurnId),
|
|
317
|
+
updatedAt: normalizeCodexRunText(runPatch.updatedAt)
|
|
318
|
+
};
|
|
319
|
+
return {
|
|
320
|
+
agentRun: {
|
|
321
|
+
active,
|
|
322
|
+
id: CODEX_APP_SERVER_AGENT_RUN_ID,
|
|
323
|
+
inputSource: turn.inputSource,
|
|
324
|
+
outerTurnId: turn.outerTurnId,
|
|
325
|
+
provider: CODEX_AGENT_PROVIDER,
|
|
326
|
+
providerInterface: "codex_app_server",
|
|
327
|
+
providerStatus: turn.status,
|
|
328
|
+
providerThreadId: turn.threadId,
|
|
329
|
+
providerTurnId: turn.turnId,
|
|
330
|
+
state: runState,
|
|
331
|
+
updatedAt: turn.updatedAt
|
|
332
|
+
},
|
|
333
|
+
agentSession: {
|
|
334
|
+
providerId: CODEX_AGENT_PROVIDER,
|
|
335
|
+
thread: {
|
|
336
|
+
id: turn.threadId
|
|
337
|
+
},
|
|
338
|
+
transportId: "codex_app_server",
|
|
339
|
+
turn: {
|
|
340
|
+
active: turn.active,
|
|
341
|
+
completedAt: turn.completedAt,
|
|
342
|
+
error: turn.error,
|
|
343
|
+
id: turn.turnId,
|
|
344
|
+
inputSource: turn.inputSource,
|
|
345
|
+
outerTurnId: turn.outerTurnId,
|
|
346
|
+
phase: turn.phase,
|
|
347
|
+
runState: turn.runState,
|
|
348
|
+
startedAt: turn.startedAt,
|
|
349
|
+
state: turn.state,
|
|
350
|
+
status: turn.status,
|
|
351
|
+
updatedAt: turn.updatedAt
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
async function publishCodexAppServerAgentRun(sessionId = "", {
|
|
358
|
+
error = "",
|
|
359
|
+
inputSource = "",
|
|
360
|
+
phase,
|
|
361
|
+
publishPayload = null,
|
|
362
|
+
publishReason = "",
|
|
363
|
+
observedRun = null,
|
|
364
|
+
runState = CODEX_APP_SERVER_RUN_STATE.COMPLETED,
|
|
365
|
+
status = "",
|
|
366
|
+
threadId = "",
|
|
367
|
+
turnId = "",
|
|
368
|
+
updatedAt = ""
|
|
369
|
+
} = {}) {
|
|
370
|
+
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
371
|
+
if (!normalizedSessionId) {
|
|
372
|
+
return {
|
|
373
|
+
ok: false,
|
|
374
|
+
error: sessionIdRequiredError
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
const runtime = await createRuntime();
|
|
378
|
+
const { wrote, stale, runPatch, conversationStream, updatedSession } = await writeCodexAppServerAgentRun(runtime, normalizedSessionId, {
|
|
379
|
+
error, inputSource, phase, publishReason, observedRun, runState, status, threadId, turnId, updatedAt
|
|
380
|
+
});
|
|
381
|
+
if (!wrote) {
|
|
382
|
+
return {
|
|
383
|
+
ok: true,
|
|
384
|
+
processed: false,
|
|
385
|
+
reason: "stale_terminal_turn_state",
|
|
386
|
+
stale
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
await publish(normalizedSessionId, {
|
|
390
|
+
payload: {
|
|
391
|
+
...codexAppServerAgentRunRealtimePayload(runPatch),
|
|
392
|
+
...(conversationStream ? { conversationStream } : {}),
|
|
393
|
+
...(isPlainObject(publishPayload) ? publishPayload : {})
|
|
394
|
+
},
|
|
395
|
+
reason: publishReason || "codex-app-server-turn-state",
|
|
396
|
+
session: updatedSession
|
|
397
|
+
});
|
|
398
|
+
return {
|
|
399
|
+
ok: true
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
async function markCodexAppServerTurnFinalizing(sessionId = "", input = {}) {
|
|
404
|
+
const result = await publishCodexAppServerAgentRun(sessionId, {
|
|
405
|
+
error: normalizeCodexRunText(input.error),
|
|
406
|
+
publishReason: "codex-app-server-turn-finalizing",
|
|
407
|
+
runState: CODEX_APP_SERVER_RUN_STATE.FINALIZING,
|
|
408
|
+
status: normalizeCodexRunText(input.status) || "completed",
|
|
409
|
+
threadId: normalizeCodexRunText(input.threadId),
|
|
410
|
+
turnId: normalizeCodexRunText(input.turnId)
|
|
411
|
+
});
|
|
412
|
+
clearCodexAppServerActiveTimer(sessionId);
|
|
413
|
+
return result;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
async function markCodexAppServerTurnIdle(sessionId = "", input = {}) {
|
|
417
|
+
const status = normalizeCodexRunText(input.status) || "completed";
|
|
418
|
+
const result = await publishCodexAppServerAgentRun(sessionId, {
|
|
419
|
+
error: normalizeCodexRunText(input.error),
|
|
420
|
+
publishPayload: idlePublishPayload,
|
|
421
|
+
publishReason: "codex-app-server-turn-idle",
|
|
422
|
+
runState: terminalCodexAppServerAgentRunState(status),
|
|
423
|
+
status,
|
|
424
|
+
threadId: normalizeCodexRunText(input.threadId),
|
|
425
|
+
turnId: normalizeCodexRunText(input.turnId)
|
|
426
|
+
});
|
|
427
|
+
clearCodexAppServerActiveTimer(sessionId);
|
|
428
|
+
clearCodexAppServerFinalizingTimer(sessionId, input.threadId, input.turnId);
|
|
429
|
+
if (result?.processed === false) {
|
|
430
|
+
return result;
|
|
431
|
+
}
|
|
432
|
+
return {
|
|
433
|
+
...result,
|
|
434
|
+
checkpoint: await checkpoint(sessionId, {
|
|
435
|
+
status,
|
|
436
|
+
turnOutcome: normalizeCodexRunText(input.turnOutcome),
|
|
437
|
+
threadId: normalizeCodexRunText(input.threadId),
|
|
438
|
+
turnId: normalizeCodexRunText(input.turnId)
|
|
439
|
+
})
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
async function currentCodexAppServerTurnId(sessionId = "", threadId = "") {
|
|
444
|
+
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
445
|
+
const normalizedThreadId = normalizeCodexRunText(threadId);
|
|
446
|
+
if (!normalizedSessionId) {
|
|
447
|
+
return "";
|
|
448
|
+
}
|
|
449
|
+
const runtime = await createRuntime();
|
|
450
|
+
const session = await runtime.getSession(normalizedSessionId);
|
|
451
|
+
const turn = turnState(session);
|
|
452
|
+
if (!turn.active) {
|
|
453
|
+
return "";
|
|
454
|
+
}
|
|
455
|
+
if (normalizedThreadId && turn.threadId && turn.threadId !== normalizedThreadId) {
|
|
456
|
+
return "";
|
|
457
|
+
}
|
|
458
|
+
return turn.turnId;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
async function resolveCodexAppServerTurnId(sessionId = "", threadId = "", turnId = "") {
|
|
462
|
+
return normalizeCodexRunText(turnId) || await currentCodexAppServerTurnId(sessionId, threadId);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function codexAppServerDateValueMs(value = "") {
|
|
466
|
+
const parsed = Date.parse(normalizeCodexRunText(value));
|
|
467
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
function codexAppServerFinalizingExpired(turn = {}, nowMs = Date.now()) {
|
|
471
|
+
if (normalizeCodexRunText(turn.state) !== "finalizing") {
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
const referenceMs = codexAppServerDateValueMs(turn.completedAt) || codexAppServerDateValueMs(turn.updatedAt);
|
|
475
|
+
return Boolean(referenceMs && nowMs - referenceMs >= finalizingGraceMs);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function codexAppServerFinalizingRemainingMs(turn = {}, nowMs = Date.now()) {
|
|
479
|
+
const referenceMs = codexAppServerDateValueMs(turn.completedAt) || codexAppServerDateValueMs(turn.updatedAt);
|
|
480
|
+
if (!referenceMs) {
|
|
481
|
+
return finalizingGraceMs;
|
|
482
|
+
}
|
|
483
|
+
return Math.max(0, finalizingGraceMs - (nowMs - referenceMs));
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function codexAppServerTurnWasCompleted(session = {}, threadId = "", turnId = "") {
|
|
487
|
+
const normalizedThreadId = normalizeCodexRunText(threadId);
|
|
488
|
+
const normalizedTurnId = normalizeCodexRunText(turnId);
|
|
489
|
+
if (!normalizedThreadId || !normalizedTurnId) {
|
|
490
|
+
return false;
|
|
491
|
+
}
|
|
492
|
+
return codexAppServerCompletedTurns.has(codexAppServerTurnKey(
|
|
493
|
+
normalizedThreadId,
|
|
494
|
+
normalizedTurnId
|
|
495
|
+
)) || codexAppServerTurnResultWasProcessed(session, normalizedThreadId, normalizedTurnId);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
async function failOrphanedCodexAppServerPromptDelivery(runtime, session = {}, turn = {}) {
|
|
499
|
+
const sessionId = normalizeCodexRunText(session.sessionId);
|
|
500
|
+
if (!sessionId) {
|
|
501
|
+
return session;
|
|
502
|
+
}
|
|
503
|
+
const error = orphanedPromptMessage;
|
|
504
|
+
const updatedAt = new Date().toISOString();
|
|
505
|
+
const runPatch = agentRunPatch({
|
|
506
|
+
error,
|
|
507
|
+
inputSource: turn.inputSource,
|
|
508
|
+
runState: CODEX_APP_SERVER_RUN_STATE.FAILED,
|
|
509
|
+
session,
|
|
510
|
+
status: "delivery_failed",
|
|
511
|
+
threadId: turn.threadId,
|
|
512
|
+
turnId: turn.turnId,
|
|
513
|
+
updatedAt
|
|
514
|
+
});
|
|
515
|
+
delete runPatch.pendingUserMessageClientIds;
|
|
516
|
+
const updatedSession = await runtime.store.mutateSession(sessionId, async () => {
|
|
517
|
+
await runtime.store.writeAgentRunEvent(sessionId, CODEX_APP_SERVER_AGENT_RUN_ID, {
|
|
518
|
+
event: {
|
|
519
|
+
kind: "codex-prompt-delivery-abandoned",
|
|
520
|
+
message: error,
|
|
521
|
+
state: CODEX_APP_SERVER_RUN_STATE.FAILED
|
|
522
|
+
},
|
|
523
|
+
patch: runPatch
|
|
524
|
+
});
|
|
525
|
+
return runtime.getSession(sessionId);
|
|
526
|
+
});
|
|
527
|
+
await publish(sessionId, {
|
|
528
|
+
payload: codexAppServerAgentRunRealtimePayload(runPatch),
|
|
529
|
+
reason: "codex-prompt-delivery-abandoned",
|
|
530
|
+
session: updatedSession
|
|
531
|
+
});
|
|
532
|
+
debugLog("appServerPrompt.orphaned", {
|
|
533
|
+
sessionId,
|
|
534
|
+
threadId: turn.threadId
|
|
535
|
+
});
|
|
536
|
+
return runtime.getSession(sessionId);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
async function writeCodexAppServerUserMessageOwnership(store, sessionId = "", clientId = "", {
|
|
540
|
+
eventKind = "codex-app-server-user-message-ownership-updated",
|
|
541
|
+
owned = false
|
|
542
|
+
} = {}) {
|
|
543
|
+
const normalizedSessionId = normalizeCodexRunText(sessionId);
|
|
544
|
+
const normalizedClientId = normalizeCodexRunText(clientId);
|
|
545
|
+
if (!normalizedSessionId || !normalizedClientId) {
|
|
546
|
+
return false;
|
|
547
|
+
}
|
|
548
|
+
let wasOwned = false;
|
|
549
|
+
await store.mutateSession(normalizedSessionId, async () => {
|
|
550
|
+
const run = await readCodexAppServerAgentRunForSession(store, normalizedSessionId);
|
|
551
|
+
const currentIds = codexAppServerPendingUserMessageClientIds(run);
|
|
552
|
+
wasOwned = currentIds.indexOf(normalizedClientId) >= 0;
|
|
553
|
+
if (wasOwned === owned) {
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
const pendingUserMessageClientIds = owned
|
|
557
|
+
? [...currentIds, normalizedClientId]
|
|
558
|
+
: currentIds.filter((id) => id !== normalizedClientId);
|
|
559
|
+
await store.writeAgentRunEvent(normalizedSessionId, CODEX_APP_SERVER_AGENT_RUN_ID, {
|
|
560
|
+
event: {
|
|
561
|
+
clientId: normalizedClientId,
|
|
562
|
+
kind: eventKind,
|
|
563
|
+
message: ""
|
|
564
|
+
},
|
|
565
|
+
patch: {
|
|
566
|
+
pendingUserMessageClientIds
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
});
|
|
570
|
+
return wasOwned;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
function abandonedCodexAppServerPromptClaim(session = {}, {
|
|
574
|
+
nowMs = Date.now(),
|
|
575
|
+
promptDeliveryActive = false
|
|
576
|
+
} = {}) {
|
|
577
|
+
const run = codexAppServerAgentRun(session);
|
|
578
|
+
if (!run) {
|
|
579
|
+
return null;
|
|
580
|
+
}
|
|
581
|
+
const runUpdatedMs = codexAppServerDateValueMs(run.updatedAt || run.startedAt || run.at);
|
|
582
|
+
const claimExpired = Boolean(
|
|
583
|
+
runUpdatedMs &&
|
|
584
|
+
nowMs - runUpdatedMs >= CODEX_APP_SERVER_PROMPT_CLAIM_GRACE_MS
|
|
585
|
+
);
|
|
586
|
+
return (
|
|
587
|
+
(run.active === true || CODEX_APP_SERVER_ACTIVE_RUN_STATES.has(normalizeRunState(run.state))) &&
|
|
588
|
+
normalizeCodexRunText(run.state) === CODEX_APP_SERVER_RUN_STATE.STARTING &&
|
|
589
|
+
!normalizeCodexRunText(run.providerThreadId) &&
|
|
590
|
+
!normalizeCodexRunText(run.providerTurnId) &&
|
|
591
|
+
promptDeliveryActive !== true &&
|
|
592
|
+
(admissionTaskFinished(session, run) || claimExpired)
|
|
593
|
+
) ? run : null;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
async function recoverAbandonedCodexAppServerPromptClaim(runtime, session = {}, options = {}) {
|
|
597
|
+
const run = abandonedCodexAppServerPromptClaim(session, options);
|
|
598
|
+
if (!run || !session?.sessionId || typeof runtime?.store?.writeAgentRunEvent !== "function") {
|
|
599
|
+
return {
|
|
600
|
+
recovered: false,
|
|
601
|
+
session
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
const error = "Codex app-server prompt delivery ended before a provider turn was created.";
|
|
605
|
+
await runtime.store.writeAgentRunEvent(session.sessionId, CODEX_APP_SERVER_AGENT_RUN_ID, {
|
|
606
|
+
event: {
|
|
607
|
+
kind: "codex-prompt-delivery-abandoned",
|
|
608
|
+
message: error,
|
|
609
|
+
state: CODEX_APP_SERVER_RUN_STATE.FAILED
|
|
610
|
+
},
|
|
611
|
+
patch: {
|
|
612
|
+
error,
|
|
613
|
+
provider: CODEX_AGENT_PROVIDER,
|
|
614
|
+
providerInterface: "codex_app_server",
|
|
615
|
+
providerStatus: "delivery_failed",
|
|
616
|
+
providerThreadId: "",
|
|
617
|
+
providerTurnId: "",
|
|
618
|
+
state: CODEX_APP_SERVER_RUN_STATE.FAILED,
|
|
619
|
+
updatedAt: new Date().toISOString()
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
debugLog("appServerPrompt.abandoned", {
|
|
623
|
+
runUpdatedAt: normalizeCodexRunText(run.updatedAt),
|
|
624
|
+
sessionId: session.sessionId
|
|
625
|
+
});
|
|
626
|
+
return {
|
|
627
|
+
recovered: true,
|
|
628
|
+
session: await runtime.getSession(session.sessionId)
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
return {
|
|
633
|
+
completedTurns: codexAppServerCompletedTurns,
|
|
634
|
+
processedTurns: codexAppServerProcessedTurns,
|
|
635
|
+
activeTimers: codexAppServerActiveTimers,
|
|
636
|
+
finalizingTimers: codexAppServerFinalizingTimers,
|
|
637
|
+
agentRunPatch,
|
|
638
|
+
turnResultWasProcessed: codexAppServerTurnResultWasProcessed,
|
|
639
|
+
claimTurnStart: claimCodexAppServerTurnStart,
|
|
640
|
+
claimMessageStart: claimCodexAppServerMessageStart,
|
|
641
|
+
writeAgentRun: writeCodexAppServerAgentRun,
|
|
642
|
+
clearActiveTimer: clearCodexAppServerActiveTimer,
|
|
643
|
+
clearFinalizingTimer: clearCodexAppServerFinalizingTimer,
|
|
644
|
+
clearSessionRecoveryTimers: clearCodexAppServerSessionRecoveryTimers,
|
|
645
|
+
agentRunRealtimePayload: codexAppServerAgentRunRealtimePayload,
|
|
646
|
+
publishAgentRun: publishCodexAppServerAgentRun,
|
|
647
|
+
markTurnFinalizing: markCodexAppServerTurnFinalizing,
|
|
648
|
+
markTurnIdle: markCodexAppServerTurnIdle,
|
|
649
|
+
resolveTurnId: resolveCodexAppServerTurnId,
|
|
650
|
+
finalizingExpired: codexAppServerFinalizingExpired,
|
|
651
|
+
finalizingRemainingMs: codexAppServerFinalizingRemainingMs,
|
|
652
|
+
turnWasCompleted: codexAppServerTurnWasCompleted,
|
|
653
|
+
runInputSource: codexAppServerRunInputSource,
|
|
654
|
+
writeUserMessageOwnership: writeCodexAppServerUserMessageOwnership,
|
|
655
|
+
recoverAbandonedPromptClaim: recoverAbandonedCodexAppServerPromptClaim,
|
|
656
|
+
failOrphanedPromptDelivery: failOrphanedCodexAppServerPromptDelivery
|
|
657
|
+
};
|
|
658
|
+
}
|