@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,28 +1,37 @@
|
|
|
1
|
+
import { codexAppServerErrorMessage, codexAppServerMessageRequiresNewTurn, codexAppServerMessageText, codexAppServerMessageDisplayText, codexPromptInputFromRequest } from "./codexTurnState.js";
|
|
1
2
|
import {
|
|
2
|
-
codexAppServerTurnStatusIsSuccessfulComplete,
|
|
3
|
-
codexAppServerTurnStatusIsProviderFailure,
|
|
4
|
-
normalizeCodexRunText,
|
|
5
|
-
codexAppServerErrorMessage,
|
|
6
|
-
codexAppServerSteerFailure,
|
|
7
|
-
codexAppServerMessageRequiresNewTurn,
|
|
8
|
-
codexAppServerMessageDeferred,
|
|
9
|
-
codexAppServerMessageText,
|
|
10
|
-
codexAppServerMessageDisplayText,
|
|
11
|
-
codexPromptInputFromRequest
|
|
12
|
-
} from "./codexTurnState.js";
|
|
13
|
-
import {
|
|
14
|
-
codexAppServerRequestIsInvalid,
|
|
15
3
|
codexAppServerThreadIsMissing,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
codexAppServerDeliveredTurn,
|
|
19
|
-
sendCodexAppServerPrompt
|
|
20
|
-
} from "./codexProvider.js";
|
|
4
|
+
ensureCodexAppServerThread
|
|
5
|
+
} from "./codexProviderThreads.js";
|
|
21
6
|
import crypto from "node:crypto";
|
|
22
|
-
import { isRecord } from "@jskit-ai/kernel/shared/support/normalize";
|
|
7
|
+
import { isRecord, normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
23
8
|
|
|
24
|
-
|
|
25
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Main message admission, preparation and dispatch. Prompt delivery and receipt state remain the same run-owner
|
|
11
|
+
* references.
|
|
12
|
+
* @param {object} dependencies
|
|
13
|
+
* @param {import("./codexOutput.js").CodexAppServerOutput} dependencies.output
|
|
14
|
+
* @param {import("./codexRunJournal.js").CodexRunJournal} dependencies.journal
|
|
15
|
+
* @param {import("./codexTurnRecovery.js").CodexTurnRecovery} dependencies.recovery
|
|
16
|
+
* @param {import("./codexThreadStatus.js").CodexThreadStatus} dependencies.threadStatus
|
|
17
|
+
* @param {import("./codexProviderSelection.js").CodexProviderSelection} dependencies.selection
|
|
18
|
+
* @param {import("./codexNotificationObserver.js").CodexNotificationObserver} dependencies.observer
|
|
19
|
+
* @param {import("./codexMessageDelivery.js").CodexAppServerMessageDelivery} dependencies.delivery
|
|
20
|
+
* @param {import("./codexPromptDispatch.js").CodexPromptDispatch} dependencies.promptDispatch
|
|
21
|
+
* @param {Set<string>} dependencies.promptDeliveries
|
|
22
|
+
* @param {import("./codexTurn.js").CodexCreateRuntime} dependencies.createRuntime
|
|
23
|
+
* @param {import("./codexTurn.js").CodexDebugError} dependencies.debugError
|
|
24
|
+
* @param {import("./codexTurn.js").CodexDebugLog} dependencies.debugLog
|
|
25
|
+
* @param {string} dependencies.errorPrefix
|
|
26
|
+
* @param {string} dependencies.messageIdPrefix
|
|
27
|
+
* @param {import("./codexTurn.js").CodexMessageMetadataHooks} dependencies.messageMetadata
|
|
28
|
+
* @param {import("./codexTurn.js").CodexSessionNamespace} dependencies.namespace
|
|
29
|
+
* @param {import("./codexTurn.js").CodexProviderSessions} [dependencies.providerSessions]
|
|
30
|
+
* @param {import("./codexTurn.js").CodexAdmissionRecovery} dependencies.recoverAdmission
|
|
31
|
+
* @param {string} dependencies.steerFailedCode
|
|
32
|
+
* @param {string} dependencies.turnAlreadyRunningError
|
|
33
|
+
* @param {import("./codexTurn.js").CodexTurnStateReader} dependencies.turnState
|
|
34
|
+
*/
|
|
26
35
|
export function createCodexMessageCommands({
|
|
27
36
|
output,
|
|
28
37
|
journal,
|
|
@@ -31,7 +40,8 @@ export function createCodexMessageCommands({
|
|
|
31
40
|
selection,
|
|
32
41
|
observer,
|
|
33
42
|
delivery,
|
|
34
|
-
|
|
43
|
+
promptDispatch,
|
|
44
|
+
promptDeliveries,
|
|
35
45
|
createRuntime,
|
|
36
46
|
debugError,
|
|
37
47
|
debugLog,
|
|
@@ -45,37 +55,12 @@ export function createCodexMessageCommands({
|
|
|
45
55
|
turnAlreadyRunningError,
|
|
46
56
|
turnState
|
|
47
57
|
}) {
|
|
48
|
-
const {
|
|
49
|
-
submitAssistantResult: submitCodexAppServerAssistantResult,
|
|
50
|
-
splitReasoningTurn: splitCodexAppServerReasoningTurn
|
|
51
|
-
} = output;
|
|
52
|
-
const {
|
|
53
|
-
recoverAbandonedPromptClaim: recoverAbandonedCodexAppServerPromptClaim,
|
|
54
|
-
claimMessageStart: claimCodexAppServerMessageStart,
|
|
55
|
-
markTurnIdle: markCodexAppServerTurnIdle,
|
|
56
|
-
writeUserMessageOwnership: writeCodexAppServerUserMessageOwnership
|
|
57
|
-
} = journal;
|
|
58
|
-
const {
|
|
59
|
-
stopTurnWithProviderFailure: stopCodexAppServerTurnWithProviderFailure,
|
|
60
|
-
completeTurn: completeCodexAppServerTurn,
|
|
61
|
-
markTurnActive: markCodexAppServerTurnActive
|
|
62
|
-
} = recovery;
|
|
63
|
-
const {
|
|
64
|
-
reconcileThreadStatus: reconcileCodexAppServerThreadStatus
|
|
65
|
-
} = threadStatus;
|
|
66
58
|
const {
|
|
67
59
|
codexAppServerMessageContext,
|
|
68
60
|
codexAppServerSessionObserverOptions,
|
|
69
61
|
sessionConnection,
|
|
70
62
|
rememberManagedSession
|
|
71
63
|
} = selection;
|
|
72
|
-
const {
|
|
73
|
-
subscribeEvents: subscribeCodexAppServerEvents
|
|
74
|
-
} = observer;
|
|
75
|
-
const {
|
|
76
|
-
writeDeliveredUserMessage: writeCodexAppServerDeliveredUserMessage,
|
|
77
|
-
pendingUserMessage: pendingCodexAppServerUserMessage
|
|
78
|
-
} = delivery;
|
|
79
64
|
|
|
80
65
|
async function selectCodexAppServerMessageTurn(sessionId, { messageId = "", startedAt = Date.now() } = {}, context = {}) {
|
|
81
66
|
if (providerSessions) context = codexAppServerMessageContext(sessionId, context);
|
|
@@ -85,9 +70,9 @@ export function createCodexMessageCommands({
|
|
|
85
70
|
if (
|
|
86
71
|
turn.state === "starting" &&
|
|
87
72
|
!turn.turnId &&
|
|
88
|
-
!
|
|
73
|
+
!promptDeliveries.has(namespace(sessionId))
|
|
89
74
|
) {
|
|
90
|
-
const abandonedClaim = await
|
|
75
|
+
const abandonedClaim = await recoverAdmission(
|
|
91
76
|
runtime,
|
|
92
77
|
currentSession,
|
|
93
78
|
{ promptDeliveryActive: false }
|
|
@@ -101,11 +86,11 @@ export function createCodexMessageCommands({
|
|
|
101
86
|
code: `${errorPrefix}codex_observation_lost`
|
|
102
87
|
});
|
|
103
88
|
}
|
|
104
|
-
const recovered = await
|
|
89
|
+
const recovered = await output.submitAssistantResult(sessionId, turn.threadId, turn.turnId, { recoverFromProvider: true });
|
|
105
90
|
if (recovered.reason === "error") throw new Error(recovered.error);
|
|
106
91
|
return { value: codexAppServerMessageRequiresNewTurn({ reason: "observation_lost", threadId: turn.threadId, turnId: turn.turnId }), session: currentSession };
|
|
107
92
|
}
|
|
108
|
-
const threadId =
|
|
93
|
+
const threadId = normalizeText(turn.threadId) || context.threadId(currentSession);
|
|
109
94
|
if (!threadId) {
|
|
110
95
|
debugLog("appServerMessage.newTurn", {
|
|
111
96
|
messageId,
|
|
@@ -125,7 +110,7 @@ export function createCodexMessageCommands({
|
|
|
125
110
|
messageId,
|
|
126
111
|
sessionId,
|
|
127
112
|
threadId,
|
|
128
|
-
turnId:
|
|
113
|
+
turnId: normalizeText(turn.turnId)
|
|
129
114
|
});
|
|
130
115
|
}
|
|
131
116
|
const providerReadyAt = Date.now();
|
|
@@ -135,7 +120,7 @@ export function createCodexMessageCommands({
|
|
|
135
120
|
sessionId
|
|
136
121
|
});
|
|
137
122
|
try {
|
|
138
|
-
await
|
|
123
|
+
await threadStatus.reconcileThreadStatus(sessionId, provider, threadId, {
|
|
139
124
|
source: "message_delivery"
|
|
140
125
|
});
|
|
141
126
|
} catch (error) {
|
|
@@ -148,12 +133,12 @@ export function createCodexMessageCommands({
|
|
|
148
133
|
reason: "provider_thread_missing",
|
|
149
134
|
sessionId,
|
|
150
135
|
threadId,
|
|
151
|
-
turnId:
|
|
136
|
+
turnId: normalizeText(turn.turnId)
|
|
152
137
|
});
|
|
153
138
|
return { value: codexAppServerMessageRequiresNewTurn({
|
|
154
139
|
reason: "provider_thread_missing",
|
|
155
140
|
threadId,
|
|
156
|
-
turnId:
|
|
141
|
+
turnId: normalizeText(turn.turnId)
|
|
157
142
|
}), session: currentSession };
|
|
158
143
|
}
|
|
159
144
|
debugLog("appServerMessage.reconciled", {
|
|
@@ -163,7 +148,7 @@ export function createCodexMessageCommands({
|
|
|
163
148
|
});
|
|
164
149
|
currentSession = await runtime.getSession(sessionId);
|
|
165
150
|
turn = turnState(currentSession);
|
|
166
|
-
const turnId =
|
|
151
|
+
const turnId = normalizeText(turn.turnId);
|
|
167
152
|
const goalAwaitingTurn = !turn.active && turn.goalStatus === "active" && turn.goalThreadId === threadId;
|
|
168
153
|
if (!turn.active && !goalAwaitingTurn) {
|
|
169
154
|
debugLog("appServerMessage.newTurn", {
|
|
@@ -205,7 +190,7 @@ export function createCodexMessageCommands({
|
|
|
205
190
|
const connection = source.provider ? null : sessionConnection(sessionId, source.providerOptions);
|
|
206
191
|
const providerAlreadyAvailable = source.provider
|
|
207
192
|
? source.providerAlreadyAvailable
|
|
208
|
-
: providerSessions.owner.providers.get(connection.providerKey)?.isAvailable
|
|
193
|
+
: providerSessions.owner.providers.get(connection.providerKey)?.isAvailable() === true;
|
|
209
194
|
if (!providerAlreadyAvailable && facility.running) await facility.running();
|
|
210
195
|
let stageStartedAt = Date.now();
|
|
211
196
|
const provider = source.provider || await providerSessions.owner.ensureSession(connection, source.mainThreadId);
|
|
@@ -217,7 +202,7 @@ export function createCodexMessageCommands({
|
|
|
217
202
|
const thread = await ensureCodexAppServerThread({
|
|
218
203
|
...(source.preparation || facility.preparation(currentSession)),
|
|
219
204
|
...(preparation.applicationTools ? { applicationTools: preparation.applicationTools, providerReady: preparation.providerReady } : {}),
|
|
220
|
-
observeThread: threadId =>
|
|
205
|
+
observeThread: threadId => observer.subscribeEvents(sessionId, provider, threadId, observerOptions),
|
|
221
206
|
provider,
|
|
222
207
|
workdir: source.workdir ?? workdir
|
|
223
208
|
});
|
|
@@ -241,7 +226,7 @@ export function createCodexMessageCommands({
|
|
|
241
226
|
durationMs: Date.now() - startedAt, messageId, sessionId, stage: "startup-ready"
|
|
242
227
|
});
|
|
243
228
|
if (!Object.hasOwn(facility, "failureThreadId")) prepared.activeThreadId = thread.threadId;
|
|
244
|
-
|
|
229
|
+
observer.subscribeEvents(sessionId, provider, thread.threadId, observerOptions);
|
|
245
230
|
if (connection) {
|
|
246
231
|
rememberManagedSession(sessionId, providerOptions, {
|
|
247
232
|
executionRoot: prepared.executionRoot, workdir: prepared.workdir, threadId: thread.threadId
|
|
@@ -250,8 +235,8 @@ export function createCodexMessageCommands({
|
|
|
250
235
|
if (facility.ready) await facility.ready();
|
|
251
236
|
return { preparedSession, provider, providerAlreadyAvailable, providerOptions, thread, ...settings };
|
|
252
237
|
} finally {
|
|
253
|
-
// Standalone preparation
|
|
254
|
-
//
|
|
238
|
+
// Standalone preparation keeps the exact binding on failure as well as
|
|
239
|
+
// success; Main records it after the startup gate.
|
|
255
240
|
if (Object.hasOwn(facility, "failureThreadId")) prepared.activeThreadId = facility.failureThreadId;
|
|
256
241
|
}
|
|
257
242
|
}
|
|
@@ -262,7 +247,7 @@ export function createCodexMessageCommands({
|
|
|
262
247
|
? options.agentSettings
|
|
263
248
|
: isRecord(input.agentSettings) ? input.agentSettings : {};
|
|
264
249
|
const actorContext = options.actorContext || null;
|
|
265
|
-
const messageId =
|
|
250
|
+
const messageId = normalizeText(input.messageId) ||
|
|
266
251
|
`${messageIdPrefix}${crypto.randomUUID()}`;
|
|
267
252
|
const userRequest = codexPromptInputFromRequest(input);
|
|
268
253
|
if (!userRequest && options.preparedInput === undefined) {
|
|
@@ -279,14 +264,14 @@ export function createCodexMessageCommands({
|
|
|
279
264
|
return { value: context };
|
|
280
265
|
}
|
|
281
266
|
const { runtime } = context;
|
|
282
|
-
const turnMetadata = { ...input.turnMetadata, ...await messageMetadata.actor
|
|
267
|
+
const turnMetadata = { ...input.turnMetadata, ...await messageMetadata.actor(actorContext) };
|
|
283
268
|
debugLog("appServerPrompt.start", {
|
|
284
269
|
durationMs: Date.now() - startedAt,
|
|
285
270
|
messageId,
|
|
286
271
|
sessionId
|
|
287
272
|
});
|
|
288
273
|
|
|
289
|
-
const claim = await claimCodexAppServerMessageStart(runtime, sessionId, messageId);
|
|
274
|
+
const claim = await journal.claimCodexAppServerMessageStart(runtime, sessionId, messageId);
|
|
290
275
|
if (!claim?.claimed) {
|
|
291
276
|
debugLog("appServerPrompt.claimObserved", {
|
|
292
277
|
code: String(claim?.response?.value?.code || ""),
|
|
@@ -300,9 +285,9 @@ export function createCodexMessageCommands({
|
|
|
300
285
|
} };
|
|
301
286
|
}
|
|
302
287
|
|
|
303
|
-
const normalizedSessionId =
|
|
288
|
+
const normalizedSessionId = normalizeText(sessionId);
|
|
304
289
|
const promptDeliveryKey = namespace(normalizedSessionId);
|
|
305
|
-
|
|
290
|
+
promptDeliveries.add(promptDeliveryKey);
|
|
306
291
|
const prepared = {
|
|
307
292
|
...context, agentSettings, actorContext, messageId, userRequest, startedAt,
|
|
308
293
|
activeThreadId: ""
|
|
@@ -312,12 +297,12 @@ export function createCodexMessageCommands({
|
|
|
312
297
|
try {
|
|
313
298
|
Object.assign(prepared, await prepareCodexAppServerMessageThread(sessionId, input, prepared, prepare));
|
|
314
299
|
const { provider, providerAlreadyAvailable, thread } = prepared;
|
|
315
|
-
await
|
|
300
|
+
await recovery.markTurnActive(sessionId, {
|
|
316
301
|
status: "starting",
|
|
317
302
|
threadId: thread.threadId
|
|
318
303
|
});
|
|
319
304
|
const prompt = await prepare.prepareMessage(input, prepared, { starting: true });
|
|
320
|
-
const started = await
|
|
305
|
+
const started = await promptDispatch.startTurn(sessionId, input, {
|
|
321
306
|
runtime, provider, threadId: thread.threadId, messageId, renderedPrompt: prompt.renderedPrompt, turnMetadata,
|
|
322
307
|
preparedInput: options.preparedInput,
|
|
323
308
|
get turnSettings() { return prompt.turnSettings; }
|
|
@@ -345,7 +330,7 @@ export function createCodexMessageCommands({
|
|
|
345
330
|
}, session: currentSession, nativeIdentity: { threadId: thread.threadId, turnId: deliveredTurnId } };
|
|
346
331
|
} catch (error) {
|
|
347
332
|
if (!turnFailureHandled) {
|
|
348
|
-
await
|
|
333
|
+
await journal.markTurnIdle(sessionId, {
|
|
349
334
|
error: codexAppServerErrorMessage(error, "Codex app-server prompt delivery failed."),
|
|
350
335
|
status: "failed",
|
|
351
336
|
threadId: prepared.activeThreadId
|
|
@@ -353,16 +338,16 @@ export function createCodexMessageCommands({
|
|
|
353
338
|
}
|
|
354
339
|
return await prepare.finishMessage(input, prepared, { error });
|
|
355
340
|
} finally {
|
|
356
|
-
|
|
341
|
+
promptDeliveries.delete(promptDeliveryKey);
|
|
357
342
|
}
|
|
358
343
|
}
|
|
359
344
|
|
|
360
|
-
async function sendCodexAppServerMessage(sessionId, input
|
|
345
|
+
async function sendCodexAppServerMessage(sessionId, input, options = {}, prepare) {
|
|
361
346
|
const startedAt = Date.now();
|
|
362
347
|
const turnOwnership = options.turnOwnership || null;
|
|
363
348
|
const message = codexAppServerMessageText(input);
|
|
364
349
|
const displayMessage = codexAppServerMessageDisplayText(input, message);
|
|
365
|
-
const messageId =
|
|
350
|
+
const messageId = normalizeText(input?.messageId);
|
|
366
351
|
if (!message && options.preparedInput === undefined) {
|
|
367
352
|
return { value: {
|
|
368
353
|
code: steerFailedCode,
|
|
@@ -381,7 +366,6 @@ export function createCodexMessageCommands({
|
|
|
381
366
|
const { runtime, session } = context;
|
|
382
367
|
if (
|
|
383
368
|
messageId &&
|
|
384
|
-
typeof runtime.store.conversationMessageIdExists === "function" &&
|
|
385
369
|
await runtime.store.conversationMessageIdExists(sessionId, messageId)
|
|
386
370
|
) {
|
|
387
371
|
return { value: {
|
|
@@ -392,7 +376,7 @@ export function createCodexMessageCommands({
|
|
|
392
376
|
}, session };
|
|
393
377
|
}
|
|
394
378
|
const actorContext = options.actorContext || null;
|
|
395
|
-
const turnMetadata = { ...input.turnMetadata, ...await messageMetadata.actor
|
|
379
|
+
const turnMetadata = { ...input.turnMetadata, ...await messageMetadata.actor(actorContext) };
|
|
396
380
|
debugLog("appServerMessage.contextReady", {
|
|
397
381
|
durationMs: Date.now() - startedAt,
|
|
398
382
|
messageId,
|
|
@@ -406,7 +390,7 @@ export function createCodexMessageCommands({
|
|
|
406
390
|
const policy = await prepare.prepareMessage(input, prepared, { starting: false, selected });
|
|
407
391
|
if (policy) return policy;
|
|
408
392
|
const clientUserMessageId = messageId || `${messageIdPrefix}${crypto.randomUUID()}`;
|
|
409
|
-
return
|
|
393
|
+
return promptDispatch.steerTurn(sessionId, input, {
|
|
410
394
|
runtime, provider, threadId, turnId, message, displayMessage, messageId, clientUserMessageId, turnMetadata,
|
|
411
395
|
preparedInput: options.preparedInput
|
|
412
396
|
});
|
|
@@ -418,7 +402,7 @@ export function createCodexMessageCommands({
|
|
|
418
402
|
return result;
|
|
419
403
|
}
|
|
420
404
|
const message = codexAppServerMessageText(input);
|
|
421
|
-
const messageId =
|
|
405
|
+
const messageId = normalizeText(input.messageId) ||
|
|
422
406
|
`${messageIdPrefix}${crypto.randomUUID()}`;
|
|
423
407
|
const started = await startCodexAppServerMessage(sessionId, isRecord(input) ? {
|
|
424
408
|
...input,
|
|
@@ -428,27 +412,27 @@ export function createCodexMessageCommands({
|
|
|
428
412
|
message,
|
|
429
413
|
messageId
|
|
430
414
|
}, {
|
|
431
|
-
agentSettings: input
|
|
415
|
+
agentSettings: input.agentSettings || {},
|
|
432
416
|
runtime: options.runtime || null,
|
|
433
417
|
session: options.session || null,
|
|
434
418
|
actorContext: options.actorContext || null,
|
|
435
419
|
preparedInput: options.preparedInput
|
|
436
420
|
}, prepare);
|
|
437
|
-
//
|
|
438
|
-
//
|
|
421
|
+
// An unavailable-worktree result starts its policy operation, releases
|
|
422
|
+
// the prompt marker in finally, and then this awaits the returned value.
|
|
439
423
|
started.value = await started.value;
|
|
440
424
|
if (started.value?.ok === false || started.value?.delivered === false) {
|
|
441
425
|
return started;
|
|
442
426
|
}
|
|
443
427
|
const runtime = await createRuntime(sessionId);
|
|
444
428
|
const displayMessage = codexAppServerMessageDisplayText(input, message);
|
|
445
|
-
const conversationTurn = await
|
|
429
|
+
const conversationTurn = await delivery.writeDeliveredUserMessage(
|
|
446
430
|
runtime,
|
|
447
431
|
sessionId,
|
|
448
432
|
displayMessage || message,
|
|
449
433
|
messageId,
|
|
450
434
|
started.value.turnMetadata || null,
|
|
451
|
-
input
|
|
435
|
+
input.displayAttachments,
|
|
452
436
|
started.nativeIdentity
|
|
453
437
|
);
|
|
454
438
|
return {
|
|
@@ -464,210 +448,8 @@ export function createCodexMessageCommands({
|
|
|
464
448
|
};
|
|
465
449
|
}
|
|
466
450
|
|
|
467
|
-
|
|
468
|
-
const { runtime, provider, threadId, messageId, renderedPrompt, turnMetadata } = context;
|
|
469
|
-
let providerFailure = "";
|
|
470
|
-
let delivery = null;
|
|
471
|
-
const promptSessionId = normalizeCodexRunText(sessionId);
|
|
472
|
-
const clientUserMessageId = messageId;
|
|
473
|
-
await writeCodexAppServerUserMessageOwnership(runtime.store, sessionId, clientUserMessageId, {
|
|
474
|
-
eventKind: "codex-app-server-user-message-owned",
|
|
475
|
-
owned: true
|
|
476
|
-
});
|
|
477
|
-
try {
|
|
478
|
-
await input.onPromptSending?.({ threadId: threadId, displayAttachments: input.displayAttachments, turnMetadata });
|
|
479
|
-
const response = sendCodexAppServerPrompt({
|
|
480
|
-
clientUserMessageId,
|
|
481
|
-
prompt: renderedPrompt,
|
|
482
|
-
attachments: input.attachments,
|
|
483
|
-
provider,
|
|
484
|
-
threadId
|
|
485
|
-
}, context);
|
|
486
|
-
const receipt = pendingCodexAppServerUserMessage(promptSessionId, clientUserMessageId)?.receipt;
|
|
487
|
-
// An exact, persisted user-message receipt confirms delivery too.
|
|
488
|
-
// Finish bookkeeping once; a late RPC reply must not hold admission
|
|
489
|
-
// or change a turn that has already continued or completed.
|
|
490
|
-
delivery = receipt
|
|
491
|
-
? await Promise.race([response, receipt.promise.then((turn) => ({ turn }))])
|
|
492
|
-
: await response;
|
|
493
|
-
} catch (error) {
|
|
494
|
-
if (Number.isInteger(error?.code) && error.code < 0) await input.onPromptRejected?.();
|
|
495
|
-
await writeCodexAppServerUserMessageOwnership(runtime.store, sessionId, clientUserMessageId, {
|
|
496
|
-
eventKind: "codex-app-server-user-message-released",
|
|
497
|
-
owned: false
|
|
498
|
-
});
|
|
499
|
-
await markCodexAppServerTurnIdle(sessionId, {
|
|
500
|
-
error: codexAppServerErrorMessage(error, "Codex app-server prompt delivery failed."),
|
|
501
|
-
status: "failed",
|
|
502
|
-
threadId: threadId
|
|
503
|
-
});
|
|
504
|
-
return { error, turnFailureHandled: true };
|
|
505
|
-
}
|
|
506
|
-
const { turnId: deliveredTurnId, status: deliveredTurnStatus } = codexAppServerDeliveredTurn(delivery);
|
|
507
|
-
if (!deliveredTurnId) {
|
|
508
|
-
throw new Error("Codex app-server accepted the prompt without returning a turn id.");
|
|
509
|
-
}
|
|
510
|
-
pendingCodexAppServerUserMessage(promptSessionId, clientUserMessageId)?.onNativeReceipt?.();
|
|
511
|
-
await markCodexAppServerTurnActive(sessionId, {
|
|
512
|
-
requireTrackedTurn: true,
|
|
513
|
-
status: "inProgress",
|
|
514
|
-
threadId: threadId,
|
|
515
|
-
turnId: deliveredTurnId
|
|
516
|
-
});
|
|
517
|
-
if (codexAppServerTurnStatusIsProviderFailure(deliveredTurnStatus)) {
|
|
518
|
-
providerFailure = `Codex turn ${deliveredTurnStatus}.`;
|
|
519
|
-
await stopCodexAppServerTurnWithProviderFailure(sessionId, threadId, deliveredTurnId, {
|
|
520
|
-
provider,
|
|
521
|
-
status: deliveredTurnStatus
|
|
522
|
-
});
|
|
523
|
-
} else if (codexAppServerTurnStatusIsSuccessfulComplete(deliveredTurnStatus)) {
|
|
524
|
-
const completion = await completeCodexAppServerTurn(sessionId, threadId, deliveredTurnId, {
|
|
525
|
-
provider,
|
|
526
|
-
status: deliveredTurnStatus
|
|
527
|
-
});
|
|
528
|
-
if (completion?.ok === false) {
|
|
529
|
-
providerFailure = normalizeCodexRunText(completion.error) || "Codex completed, but its response could not be processed.";
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
return { delivery, deliveredTurnId, providerFailure };
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
async function steerCodexAppServerTurn(sessionId, input = {}, context = {}) {
|
|
536
|
-
const { runtime, provider, threadId, turnId, message, displayMessage, messageId, clientUserMessageId, turnMetadata } = context;
|
|
537
|
-
let currentSession;
|
|
538
|
-
await writeCodexAppServerUserMessageOwnership(runtime.store, sessionId, clientUserMessageId, {
|
|
539
|
-
eventKind: "codex-app-server-user-message-owned",
|
|
540
|
-
owned: true
|
|
541
|
-
});
|
|
542
|
-
debugLog("appServerMessage.activeTurn.start", {
|
|
543
|
-
messageId,
|
|
544
|
-
sessionId,
|
|
545
|
-
threadId,
|
|
546
|
-
turnId
|
|
547
|
-
});
|
|
548
|
-
async function recoverAfterSteerFailure(error = null) {
|
|
549
|
-
await writeCodexAppServerUserMessageOwnership(runtime.store, sessionId, clientUserMessageId, {
|
|
550
|
-
eventKind: "codex-app-server-user-message-released",
|
|
551
|
-
owned: false
|
|
552
|
-
});
|
|
553
|
-
await reconcileCodexAppServerThreadStatus(sessionId, provider, threadId, {
|
|
554
|
-
source: "message_delivery_steer_race"
|
|
555
|
-
}).catch(() => null);
|
|
556
|
-
currentSession = await runtime.getSession(sessionId);
|
|
557
|
-
const currentTurn = turnState(currentSession);
|
|
558
|
-
const sameTurnIsActive = currentTurn.active === true &&
|
|
559
|
-
normalizeCodexRunText(currentTurn.threadId) === threadId &&
|
|
560
|
-
normalizeCodexRunText(currentTurn.turnId) === turnId &&
|
|
561
|
-
currentTurn.state !== "finalizing";
|
|
562
|
-
if (sameTurnIsActive) {
|
|
563
|
-
return codexAppServerRequestIsInvalid(error, "turn/steer")
|
|
564
|
-
? { value: codexAppServerMessageDeferred({ threadId, turnId }, steerFailedCode), session: currentSession }
|
|
565
|
-
: null;
|
|
566
|
-
}
|
|
567
|
-
debugLog("appServerMessage.newTurn", {
|
|
568
|
-
error: debugError(error),
|
|
569
|
-
messageId,
|
|
570
|
-
reason: "active_turn_completed_before_delivery",
|
|
571
|
-
sessionId,
|
|
572
|
-
threadId,
|
|
573
|
-
turnId
|
|
574
|
-
});
|
|
575
|
-
return { value: codexAppServerMessageRequiresNewTurn({
|
|
576
|
-
reason: "active_turn_completed_before_delivery",
|
|
577
|
-
threadId,
|
|
578
|
-
turnId
|
|
579
|
-
}), session: currentSession };
|
|
580
|
-
}
|
|
581
|
-
let result;
|
|
582
|
-
try {
|
|
583
|
-
await input.onPromptSending?.({ threadId, displayAttachments: input.displayAttachments, turnMetadata });
|
|
584
|
-
const response = provider.steerTurn(
|
|
585
|
-
threadId,
|
|
586
|
-
turnId,
|
|
587
|
-
context.preparedInput === undefined
|
|
588
|
-
? input.attachments?.some((attachment) => attachment.contentType?.startsWith("image/"))
|
|
589
|
-
? [message, ...codexLocalImageInput(input.attachments)]
|
|
590
|
-
: message
|
|
591
|
-
: context.preparedInput,
|
|
592
|
-
{
|
|
593
|
-
clientUserMessageId
|
|
594
|
-
}
|
|
595
|
-
);
|
|
596
|
-
const receipt = pendingCodexAppServerUserMessage(sessionId, clientUserMessageId)?.receipt;
|
|
597
|
-
result = receipt ? await Promise.race([response, receipt.promise]) : await response;
|
|
598
|
-
} catch (error) {
|
|
599
|
-
if (Number.isInteger(error?.code) && error.code < 0) await input.onPromptRejected?.();
|
|
600
|
-
const recovered = await recoverAfterSteerFailure(error);
|
|
601
|
-
if (recovered) {
|
|
602
|
-
return recovered;
|
|
603
|
-
}
|
|
604
|
-
debugLog("appServerMessage.activeTurn.error", {
|
|
605
|
-
error: debugError(error),
|
|
606
|
-
messageId,
|
|
607
|
-
sessionId,
|
|
608
|
-
threadId,
|
|
609
|
-
turnId
|
|
610
|
-
});
|
|
611
|
-
throw error;
|
|
612
|
-
}
|
|
613
|
-
const steerFailure = codexAppServerSteerFailure(result, steerFailedCode);
|
|
614
|
-
if (steerFailure) {
|
|
615
|
-
const recovered = await recoverAfterSteerFailure(result);
|
|
616
|
-
if (recovered) {
|
|
617
|
-
return recovered;
|
|
618
|
-
}
|
|
619
|
-
debugLog("appServerMessage.activeTurn.failed", {
|
|
620
|
-
error: steerFailure.error,
|
|
621
|
-
messageId,
|
|
622
|
-
operationOutcome: steerFailure.operationOutcome,
|
|
623
|
-
sessionId,
|
|
624
|
-
threadId,
|
|
625
|
-
turnId
|
|
626
|
-
});
|
|
627
|
-
return { value: {
|
|
628
|
-
...steerFailure,
|
|
629
|
-
result,
|
|
630
|
-
threadId,
|
|
631
|
-
turnId
|
|
632
|
-
} };
|
|
633
|
-
}
|
|
634
|
-
pendingCodexAppServerUserMessage(sessionId, clientUserMessageId)?.onNativeReceipt?.();
|
|
635
|
-
const conversationTurn = await writeCodexAppServerDeliveredUserMessage(
|
|
636
|
-
runtime,
|
|
637
|
-
sessionId,
|
|
638
|
-
displayMessage || message,
|
|
639
|
-
messageId,
|
|
640
|
-
turnMetadata,
|
|
641
|
-
input?.displayAttachments,
|
|
642
|
-
{ threadId, turnId }
|
|
643
|
-
);
|
|
644
|
-
splitCodexAppServerReasoningTurn(threadId, turnId);
|
|
645
|
-
currentSession = await runtime.getSession(sessionId);
|
|
646
|
-
debugLog("appServerMessage.activeTurn.done", {
|
|
647
|
-
conversationTurnId: normalizeCodexRunText(conversationTurn?.turnId || conversationTurn?.id),
|
|
648
|
-
messageId,
|
|
649
|
-
sessionId,
|
|
650
|
-
threadId,
|
|
651
|
-
turnId
|
|
652
|
-
});
|
|
653
|
-
return { value: {
|
|
654
|
-
conversationTurn,
|
|
655
|
-
conversationTurns: [conversationTurn],
|
|
656
|
-
delivered: true,
|
|
657
|
-
deliveryMode: "active_turn",
|
|
658
|
-
newTurnRequired: false,
|
|
659
|
-
ok: true,
|
|
660
|
-
operationOutcome: "delivered_to_active_turn",
|
|
661
|
-
result,
|
|
662
|
-
threadId,
|
|
663
|
-
turnId
|
|
664
|
-
}, session: currentSession };
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
return {
|
|
451
|
+
return Object.freeze({
|
|
668
452
|
selectMessageTurn: selectCodexAppServerMessageTurn,
|
|
669
|
-
dispatchMessage: dispatchCodexAppServerMessage
|
|
670
|
-
|
|
671
|
-
steerTurn: steerCodexAppServerTurn
|
|
672
|
-
};
|
|
453
|
+
dispatchMessage: dispatchCodexAppServerMessage
|
|
454
|
+
});
|
|
673
455
|
}
|