@sentry/junior 0.144.0 → 0.145.0
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/dist/{agent-hooks-GCUTGKY3.js → agent-hooks-L7D2BDVV.js} +10 -10
- package/dist/api/conversations/detail.d.ts +1 -0
- package/dist/api/schema/conversation.d.ts +2 -0
- package/dist/api/schema.js +1 -1
- package/dist/api.js +40 -22
- package/dist/app.js +335 -409
- package/dist/{catalog-runtime-DWVYKDC6.js → catalog-runtime-QLAC4Q3W.js} +5 -5
- package/dist/chat/agent/request.d.ts +1 -1
- package/dist/chat/agent/resume.d.ts +6 -15
- package/dist/chat/agent/tools.d.ts +1 -1
- package/dist/chat/agent-dispatch/types.d.ts +1 -1
- package/dist/chat/app/conversation-work.d.ts +24 -0
- package/dist/chat/conversations/projection.d.ts +11 -3
- package/dist/chat/conversations/store.d.ts +1 -1
- package/dist/chat/runtime/agent-run-outcome.d.ts +1 -1
- package/dist/chat/runtime/reply-executor.d.ts +5 -5
- package/dist/chat/runtime/slack-resume.d.ts +12 -4
- package/dist/chat/state/locks.d.ts +28 -0
- package/dist/chat/task-execution/checkpoint.d.ts +86 -0
- package/dist/chat/task-execution/paused-turn.d.ts +29 -0
- package/dist/chat/task-execution/queue-signing.d.ts +1 -0
- package/dist/chat/task-execution/queue.d.ts +7 -1
- package/dist/chat/task-execution/slack-work.d.ts +1 -1
- package/dist/chat/task-execution/state.d.ts +4 -4
- package/dist/chat/task-execution/store.d.ts +2 -2
- package/dist/chat/task-execution/turn-cursor-keys.d.ts +6 -0
- package/dist/chat/{state/turn-session.d.ts → task-execution/turn-cursor.d.ts} +52 -42
- package/dist/chat/task-execution/turn-wake.d.ts +29 -0
- package/dist/chat/tools/types.d.ts +1 -1
- package/dist/{chunk-HNO2E5WB.js → chunk-27TEJTZO.js} +1 -1
- package/dist/{chunk-RIFJUJSI.js → chunk-2LWPFSB4.js} +1 -1
- package/dist/{chunk-SBZP2J5Q.js → chunk-2UH3JI64.js} +10 -9
- package/dist/{chunk-QUZJDAQQ.js → chunk-2XET6PKP.js} +93 -89
- package/dist/{chunk-SUK7NC5A.js → chunk-5PNPQYTO.js} +2 -2
- package/dist/{chunk-SSDTQDYQ.js → chunk-64SBYW2O.js} +132 -127
- package/dist/{chunk-DVO5VKYQ.js → chunk-B46ZMVOV.js} +5 -5
- package/dist/{chunk-A67GZN73.js → chunk-CD2XFGYQ.js} +1 -1
- package/dist/{chunk-WTX2RFJG.js → chunk-DS3J6WGY.js} +1 -1
- package/dist/{chunk-PKH6762I.js → chunk-DXEQAIUV.js} +1 -1
- package/dist/{chunk-WSOLZJJS.js → chunk-EIX2LQ6L.js} +3 -3
- package/dist/{chunk-KQBXT5B7.js → chunk-FUBRJA5F.js} +6 -6
- package/dist/{chunk-I44JB7HQ.js → chunk-GDV5LXRA.js} +1 -1
- package/dist/{chunk-7KAW7UF4.js → chunk-GUWLDMGF.js} +4 -4
- package/dist/{chunk-PELZ2ZSY.js → chunk-HISR3DTV.js} +33 -61
- package/dist/{chunk-HD6BHR25.js → chunk-HLOUZC5C.js} +32 -34
- package/dist/{chunk-BBCWYXHB.js → chunk-I47UGQPJ.js} +7 -7
- package/dist/{chunk-IUFM5JWV.js → chunk-JAL3CH4G.js} +3 -0
- package/dist/{chunk-E7HCWOHG.js → chunk-JLMVCNXL.js} +2 -1
- package/dist/{chunk-STFCL3K4.js → chunk-JTGS3ZZE.js} +1 -1
- package/dist/{chunk-GKA74DRA.js → chunk-LVVSIMBB.js} +1 -1
- package/dist/{chunk-SHEEZSLY.js → chunk-PJ4NMVQB.js} +2 -2
- package/dist/{chunk-W7JFV5SB.js → chunk-QJBDABQA.js} +14 -17
- package/dist/{chunk-UDQMY6RS.js → chunk-QUG4JSZK.js} +43 -1
- package/dist/{chunk-4X5KM7Z6.js → chunk-RUSS62EN.js} +14 -14
- package/dist/{chunk-ZF3N3JD6.js → chunk-SIN3MXH6.js} +1 -1
- package/dist/{chunk-QE3TICD4.js → chunk-TZRXYWRE.js} +2 -2
- package/dist/{chunk-CNTWB2SM.js → chunk-VTDMB7XX.js} +1 -1
- package/dist/{chunk-LDWNYCZ6.js → chunk-WF5HVH3M.js} +1 -1
- package/dist/{chunk-KCBZSJRU.js → chunk-WR76IVA5.js} +5 -2
- package/dist/{chunk-3GU4PWA3.js → chunk-XFKIRN3Q.js} +29 -29
- package/dist/{chunk-ZZCTGAIT.js → chunk-YD54Q45G.js} +4 -4
- package/dist/{chunk-BEGGFVFR.js → chunk-ZIAMN2UW.js} +407 -523
- package/dist/{chunk-44RJWAND.js → chunk-ZIMRGFYL.js} +6 -6
- package/dist/{chunk-54JMYQYS.js → chunk-ZYAJMESY.js} +2 -2
- package/dist/cli/chat.js +32 -32
- package/dist/cli/check.js +6 -6
- package/dist/cli/plugins.js +13 -13
- package/dist/cli/snapshot-create.js +9 -9
- package/dist/cli/upgrade.js +7 -7
- package/dist/{db-EFLHTBU6.js → db-62PW6LM3.js} +7 -7
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +4 -4
- package/dist/{oauth-callback-server-RO3IQKWM.js → oauth-callback-server-6NZNHJAM.js} +25 -25
- package/dist/{runner-LOWW7JKA.js → runner-GCRPG3GQ.js} +19 -18
- package/dist/{skills-ZLMUG7AE.js → skills-2S3MDFIQ.js} +6 -6
- package/dist/spawn-7WK37BTD.js +39 -0
- package/dist/{validation-MAKEZNTS.js → validation-HAOLCJ5A.js} +6 -6
- package/dist/version.js +1 -1
- package/dist/{work-5OAGC3I4.js → work-R4XYKMUW.js} +17 -16
- package/dist/worker-U2UCVR7M.js +24 -0
- package/package.json +4 -4
- package/dist/chat/agent/session.d.ts +0 -19
- package/dist/chat/runtime/agent-continue-runner.d.ts +0 -37
- package/dist/chat/services/agent-continue.d.ts +0 -29
- package/dist/chat/services/turn-session-record.d.ts +0 -164
- package/dist/chat/state/turn-session-keys.d.ts +0 -6
- package/dist/spawn-R3LUV6RF.js +0 -38
- package/dist/worker-KTGGRTTP.js +0 -24
package/dist/app.js
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
processConversationWork
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RUSS62EN.js";
|
|
4
4
|
import {
|
|
5
5
|
bindSpawnAgent
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LVVSIMBB.js";
|
|
7
7
|
import {
|
|
8
8
|
createAgentInvocationWorker,
|
|
9
9
|
enqueueAgentInvocation,
|
|
10
10
|
listPendingAgentInvocationMailboxAppends,
|
|
11
11
|
routeAgentInvocationWork
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-HISR3DTV.js";
|
|
13
13
|
import {
|
|
14
14
|
GET as GET2,
|
|
15
15
|
GET2 as GET3,
|
|
16
|
-
ResumeTurnBusyError,
|
|
17
16
|
buildAuthPauseResponse,
|
|
18
17
|
buildSlackOutputMessage,
|
|
19
18
|
createSlackAdapterAssistantStatusSession,
|
|
20
19
|
getAssistantThreadContext,
|
|
21
|
-
getAwaitingAgentContinueRequest,
|
|
22
20
|
getChannelId,
|
|
23
21
|
getMessageTs,
|
|
22
|
+
getPausedTurnRequest,
|
|
24
23
|
getRunId,
|
|
25
24
|
getSlackApiErrorCode,
|
|
26
25
|
getSlackErrorObservabilityAttributes,
|
|
@@ -33,13 +32,13 @@ import {
|
|
|
33
32
|
receiveLocalOAuthCredential,
|
|
34
33
|
resumeSlackTurn,
|
|
35
34
|
runWithTurnRequestDeadline,
|
|
36
|
-
scheduleAgentContinue,
|
|
37
35
|
sendSlackReply,
|
|
38
36
|
shouldKeepProcessingReactionForToolInvocation,
|
|
39
37
|
splitSlackReplyText,
|
|
40
38
|
startSlackProcessingReaction,
|
|
41
|
-
stripLeadingBotMention
|
|
42
|
-
|
|
39
|
+
stripLeadingBotMention,
|
|
40
|
+
wakePausedTurn
|
|
41
|
+
} from "./chunk-2XET6PKP.js";
|
|
43
42
|
import "./chunk-FA6POGLH.js";
|
|
44
43
|
import {
|
|
45
44
|
CONVERSATION_WORK_STALE_ENQUEUE_MS,
|
|
@@ -51,7 +50,7 @@ import {
|
|
|
51
50
|
isInvalidConversationRecordError,
|
|
52
51
|
listActiveConversationIds,
|
|
53
52
|
removeActiveConversation
|
|
54
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-HLOUZC5C.js";
|
|
55
54
|
import {
|
|
56
55
|
buildConversationContext,
|
|
57
56
|
buildDeliveredTurnStatePatch,
|
|
@@ -90,8 +89,9 @@ import {
|
|
|
90
89
|
requireTurnFailureEventId,
|
|
91
90
|
resolveTurnSessionRouting,
|
|
92
91
|
scheduleSessionCompletedPluginTasks,
|
|
92
|
+
turnHasReply,
|
|
93
93
|
upsertConversationMessage
|
|
94
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-QJBDABQA.js";
|
|
95
95
|
import {
|
|
96
96
|
ConversationTurnLifecycleService
|
|
97
97
|
} from "./chunk-Q6QZTTLS.js";
|
|
@@ -100,21 +100,21 @@ import {
|
|
|
100
100
|
conversationVisibilityFromSlackChannelType,
|
|
101
101
|
resolveSlackChannelTypeFromMessage,
|
|
102
102
|
resolveSlackConversationContext
|
|
103
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-PJ4NMVQB.js";
|
|
104
104
|
import "./chunk-4CODA7P5.js";
|
|
105
105
|
import {
|
|
106
106
|
recordTaskExecution
|
|
107
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-EIX2LQ6L.js";
|
|
108
108
|
import "./chunk-UTL3MHPC.js";
|
|
109
109
|
import {
|
|
110
110
|
getVercelConversationWorkQueue,
|
|
111
111
|
resolveConversationWorkQueueTopic,
|
|
112
112
|
verifyConversationQueueMessage
|
|
113
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-WR76IVA5.js";
|
|
114
114
|
import {
|
|
115
115
|
conversationQueueMessageSchema,
|
|
116
116
|
isConversationQueueMessageRejectedError
|
|
117
|
-
} from "./chunk-
|
|
117
|
+
} from "./chunk-JAL3CH4G.js";
|
|
118
118
|
import {
|
|
119
119
|
PLUGIN_TASK_QUEUE_TOPIC,
|
|
120
120
|
createVercelQueueClient,
|
|
@@ -123,7 +123,7 @@ import {
|
|
|
123
123
|
import {
|
|
124
124
|
validatePluginEgressCredentialHooks,
|
|
125
125
|
validatePluginRegistrations
|
|
126
|
-
} from "./chunk-
|
|
126
|
+
} from "./chunk-WF5HVH3M.js";
|
|
127
127
|
import {
|
|
128
128
|
defineJuniorPlugins,
|
|
129
129
|
pluginCatalogConfigFromEnv,
|
|
@@ -156,18 +156,18 @@ import {
|
|
|
156
156
|
setConfigDefaults,
|
|
157
157
|
shouldEmitDevAgentTrace,
|
|
158
158
|
shouldPropagateSandboxEgressTrace
|
|
159
|
-
} from "./chunk-
|
|
159
|
+
} from "./chunk-64SBYW2O.js";
|
|
160
160
|
import {
|
|
161
161
|
AuthorizationFlowDisabledError,
|
|
162
162
|
PluginCredentialFailureError
|
|
163
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-B46ZMVOV.js";
|
|
164
164
|
import "./chunk-DIB4GX3G.js";
|
|
165
165
|
import {
|
|
166
166
|
createUserTokenStore,
|
|
167
167
|
deleteMcpAuthSessionsForUserProvider,
|
|
168
168
|
deleteMcpServerSessionId,
|
|
169
169
|
deleteMcpStoredOAuthCredentials
|
|
170
|
-
} from "./chunk-
|
|
170
|
+
} from "./chunk-I47UGQPJ.js";
|
|
171
171
|
import {
|
|
172
172
|
RetryableDeliveryError
|
|
173
173
|
} from "./chunk-R776HKPK.js";
|
|
@@ -175,16 +175,16 @@ import {
|
|
|
175
175
|
formatProviderLabel,
|
|
176
176
|
postSlackMessage,
|
|
177
177
|
startOAuthFlow
|
|
178
|
-
} from "./chunk-
|
|
178
|
+
} from "./chunk-FUBRJA5F.js";
|
|
179
179
|
import {
|
|
180
180
|
estimateTextTokens
|
|
181
|
-
} from "./chunk-
|
|
181
|
+
} from "./chunk-VTDMB7XX.js";
|
|
182
182
|
import {
|
|
183
183
|
ConversationTurnBoundaryError,
|
|
184
184
|
CooperativeTurnYieldError,
|
|
185
185
|
TurnInputCommitLostError,
|
|
186
186
|
TurnInputDeferredError,
|
|
187
|
-
|
|
187
|
+
abandonTurnRecord,
|
|
188
188
|
buildDeterministicAssistantMessageId,
|
|
189
189
|
buildDeterministicTurnId,
|
|
190
190
|
clearPendingAuth,
|
|
@@ -192,24 +192,26 @@ import {
|
|
|
192
192
|
coerceThreadConversationState,
|
|
193
193
|
commitAcceptedReply,
|
|
194
194
|
commitMessages,
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
getAgentTurnSessionRecord,
|
|
198
|
-
getAgentTurnSessionRecordForResume,
|
|
195
|
+
completeTurnRecord,
|
|
196
|
+
failTurnRecord,
|
|
199
197
|
getAssistantReplyText,
|
|
200
198
|
getChannelConfigurationService,
|
|
201
199
|
getChannelConfigurationServiceById,
|
|
202
200
|
getConversationTurnBoundaryError,
|
|
203
201
|
getPersistedSandboxState,
|
|
204
202
|
getPersistedThreadState,
|
|
203
|
+
getTurnRecord,
|
|
204
|
+
getTurnRecordForResume,
|
|
205
205
|
hydrateConversationMessages,
|
|
206
206
|
isCooperativeTurnYieldError,
|
|
207
207
|
isTurnInputCommitLostError,
|
|
208
208
|
isTurnInputDeferredError,
|
|
209
|
-
|
|
209
|
+
listTurnSummaries,
|
|
210
210
|
loadConversationProjection,
|
|
211
211
|
loadProjection,
|
|
212
|
+
loadTurnCheckpoint,
|
|
212
213
|
markTurnClosed,
|
|
214
|
+
markTurnCompleted,
|
|
213
215
|
markTurnFailed,
|
|
214
216
|
mergeArtifactsState,
|
|
215
217
|
persistConversationMessageSummaries,
|
|
@@ -218,12 +220,12 @@ import {
|
|
|
218
220
|
persistThreadState,
|
|
219
221
|
persistThreadStateById,
|
|
220
222
|
persistWithRetry,
|
|
221
|
-
|
|
222
|
-
|
|
223
|
+
recordTurnSummary,
|
|
224
|
+
saveTurnCheckpoint,
|
|
223
225
|
startActiveTurn,
|
|
224
226
|
stripRuntimeTurnContext,
|
|
225
227
|
trimTrailingAssistantMessages
|
|
226
|
-
} from "./chunk-
|
|
228
|
+
} from "./chunk-ZIAMN2UW.js";
|
|
227
229
|
import "./chunk-3Y47VMHV.js";
|
|
228
230
|
import "./chunk-HUO3UTAQ.js";
|
|
229
231
|
import {
|
|
@@ -233,17 +235,17 @@ import {
|
|
|
233
235
|
import {
|
|
234
236
|
getSandboxResourceConfig,
|
|
235
237
|
setSandboxResourceConfig
|
|
236
|
-
} from "./chunk-
|
|
238
|
+
} from "./chunk-GUWLDMGF.js";
|
|
237
239
|
import {
|
|
238
240
|
createSchedulerSqlStore,
|
|
239
241
|
findMatchingEventTasks,
|
|
240
242
|
logScheduledTaskRunSkipped,
|
|
241
243
|
scheduledTaskRunAttributes
|
|
242
|
-
} from "./chunk-
|
|
244
|
+
} from "./chunk-YD54Q45G.js";
|
|
243
245
|
import {
|
|
244
246
|
parseSlackThreadId
|
|
245
|
-
} from "./chunk-
|
|
246
|
-
import "./chunk-
|
|
247
|
+
} from "./chunk-DXEQAIUV.js";
|
|
248
|
+
import "./chunk-ZYAJMESY.js";
|
|
247
249
|
import "./chunk-HLXXQI5Q.js";
|
|
248
250
|
import "./chunk-PDO5BLNM.js";
|
|
249
251
|
import "./chunk-UIE3R5XU.js";
|
|
@@ -263,7 +265,7 @@ import {
|
|
|
263
265
|
verifyEventTaskCredentialSubject,
|
|
264
266
|
verifyScheduledTaskCredentialSubject,
|
|
265
267
|
verifySlackDirectCredentialSubject
|
|
266
|
-
} from "./chunk-
|
|
268
|
+
} from "./chunk-ZIMRGFYL.js";
|
|
267
269
|
import {
|
|
268
270
|
SlackActionError,
|
|
269
271
|
downloadPrivateSlackFile,
|
|
@@ -273,7 +275,7 @@ import {
|
|
|
273
275
|
normalizeSlackConversationId,
|
|
274
276
|
runWithSlackInstallationToken,
|
|
275
277
|
runWithWorkspaceTeamId
|
|
276
|
-
} from "./chunk-
|
|
278
|
+
} from "./chunk-TZRXYWRE.js";
|
|
277
279
|
import {
|
|
278
280
|
contextProvenance,
|
|
279
281
|
createSlackDestination,
|
|
@@ -285,20 +287,19 @@ import {
|
|
|
285
287
|
requireSlackDestination,
|
|
286
288
|
withConversationEventLock,
|
|
287
289
|
withConversationMutationLock
|
|
288
|
-
} from "./chunk-
|
|
290
|
+
} from "./chunk-2UH3JI64.js";
|
|
289
291
|
import {
|
|
290
292
|
juniorAgentBindings,
|
|
291
293
|
juniorAgentInvocations,
|
|
292
294
|
juniorConversationEvents,
|
|
293
295
|
juniorConversations
|
|
294
|
-
} from "./chunk-
|
|
295
|
-
import
|
|
296
|
-
sleep
|
|
297
|
-
} from "./chunk-EM225ITJ.js";
|
|
296
|
+
} from "./chunk-27TEJTZO.js";
|
|
297
|
+
import "./chunk-EM225ITJ.js";
|
|
298
298
|
import {
|
|
299
299
|
acquireActiveLock,
|
|
300
|
-
getStateAdapter
|
|
301
|
-
|
|
300
|
+
getStateAdapter,
|
|
301
|
+
withActiveLock
|
|
302
|
+
} from "./chunk-QUG4JSZK.js";
|
|
302
303
|
import {
|
|
303
304
|
STANDARD_MODEL_PROFILE,
|
|
304
305
|
botConfig,
|
|
@@ -316,16 +317,16 @@ import {
|
|
|
316
317
|
modelIdForProfile,
|
|
317
318
|
setSlackReactionConfig,
|
|
318
319
|
standardModelId
|
|
319
|
-
} from "./chunk-
|
|
320
|
+
} from "./chunk-XFKIRN3Q.js";
|
|
320
321
|
import {
|
|
321
322
|
juniorDestinations
|
|
322
323
|
} from "./chunk-VFUK3X5B.js";
|
|
323
|
-
import "./chunk-
|
|
324
|
-
import "./chunk-
|
|
324
|
+
import "./chunk-JTGS3ZZE.js";
|
|
325
|
+
import "./chunk-5PNPQYTO.js";
|
|
325
326
|
import {
|
|
326
327
|
pluginCatalogRuntime
|
|
327
|
-
} from "./chunk-
|
|
328
|
-
import "./chunk-
|
|
328
|
+
} from "./chunk-SIN3MXH6.js";
|
|
329
|
+
import "./chunk-CD2XFGYQ.js";
|
|
329
330
|
import {
|
|
330
331
|
credentialContextForActor
|
|
331
332
|
} from "./chunk-RUIXF3YQ.js";
|
|
@@ -357,7 +358,7 @@ import {
|
|
|
357
358
|
withContext,
|
|
358
359
|
withLogContext,
|
|
359
360
|
withSpan
|
|
360
|
-
} from "./chunk-
|
|
361
|
+
} from "./chunk-2LWPFSB4.js";
|
|
361
362
|
import {
|
|
362
363
|
continueTrace
|
|
363
364
|
} from "./chunk-6GWA276C.js";
|
|
@@ -365,10 +366,10 @@ import "./chunk-OOUNJNMR.js";
|
|
|
365
366
|
import "./chunk-H4HBKISO.js";
|
|
366
367
|
import {
|
|
367
368
|
JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE
|
|
368
|
-
} from "./chunk-
|
|
369
|
+
} from "./chunk-DS3J6WGY.js";
|
|
369
370
|
import {
|
|
370
371
|
JUNIOR_VERSION
|
|
371
|
-
} from "./chunk-
|
|
372
|
+
} from "./chunk-GDV5LXRA.js";
|
|
372
373
|
import "./chunk-MLKGABMK.js";
|
|
373
374
|
|
|
374
375
|
// src/app.ts
|
|
@@ -533,12 +534,10 @@ async function resolveAgentDispatchId(context) {
|
|
|
533
534
|
if (context.attempt.messages.length > 0) {
|
|
534
535
|
return void 0;
|
|
535
536
|
}
|
|
536
|
-
const summaries = await
|
|
537
|
-
context.conversationId
|
|
538
|
-
);
|
|
537
|
+
const summaries = await listTurnSummaries(context.conversationId);
|
|
539
538
|
const activeDispatchIds = new Set(
|
|
540
539
|
summaries.filter(
|
|
541
|
-
(summary) => (summary.state === "
|
|
540
|
+
(summary) => (summary.state === "paused" || summary.state === "running") && Boolean(summary.dispatchId)
|
|
542
541
|
).map((summary) => summary.dispatchId).filter((id) => Boolean(id))
|
|
543
542
|
);
|
|
544
543
|
if (activeDispatchIds.size > 1) {
|
|
@@ -585,8 +584,10 @@ function createAgentDispatchWorkRouter(options) {
|
|
|
585
584
|
async function readDispatchTurnResult(dispatch2) {
|
|
586
585
|
const conversationId = getDispatchConversationId(dispatch2);
|
|
587
586
|
const turnId = getDispatchTurnId(dispatch2.id);
|
|
588
|
-
const storedSession = await
|
|
589
|
-
const summary = (await
|
|
587
|
+
const storedSession = await getTurnRecord(conversationId, turnId);
|
|
588
|
+
const summary = (await listTurnSummaries(conversationId)).find(
|
|
589
|
+
(candidate) => candidate.turnId === turnId
|
|
590
|
+
);
|
|
590
591
|
const session = storedSession ?? summary;
|
|
591
592
|
const dispatchOutcome = summary?.dispatchOutcome ?? storedSession?.dispatchOutcome;
|
|
592
593
|
const resultMessageTs = summary?.resultMessageId ?? storedSession?.resultMessageId;
|
|
@@ -607,7 +608,7 @@ async function readDispatchTurnResult(dispatch2) {
|
|
|
607
608
|
if (!session) {
|
|
608
609
|
return {};
|
|
609
610
|
}
|
|
610
|
-
if (session.state === "
|
|
611
|
+
if (session.state === "paused") {
|
|
611
612
|
return { hasResumableRun: true, outcome: "awaiting_resume" };
|
|
612
613
|
}
|
|
613
614
|
if (session.state === "running") {
|
|
@@ -652,15 +653,15 @@ function getDispatchBlockingError(error) {
|
|
|
652
653
|
async function persistBlockedDispatchTurn(dispatch2, error) {
|
|
653
654
|
const conversationId = getDispatchConversationId(dispatch2);
|
|
654
655
|
const sessionId = getDispatchTurnId(dispatch2.id);
|
|
655
|
-
const session = await
|
|
656
|
-
await
|
|
656
|
+
const session = await getTurnRecord(conversationId, sessionId);
|
|
657
|
+
await recordTurnSummary({
|
|
657
658
|
actor: dispatch2.actor,
|
|
658
659
|
conversationId,
|
|
659
660
|
destination: dispatch2.destination,
|
|
660
661
|
destinationVisibility: dispatch2.destinationVisibility,
|
|
661
662
|
dispatchId: dispatch2.id,
|
|
662
663
|
dispatchOutcome: "blocked",
|
|
663
|
-
sessionId,
|
|
664
|
+
turnId: sessionId,
|
|
664
665
|
sliceId: session?.sliceId ?? 1,
|
|
665
666
|
source: dispatch2.source,
|
|
666
667
|
state: "failed",
|
|
@@ -880,7 +881,9 @@ async function recoverConversationWork(args) {
|
|
|
880
881
|
}
|
|
881
882
|
if (recovery === "stopped") {
|
|
882
883
|
logException(
|
|
883
|
-
new Error(
|
|
884
|
+
new Error(
|
|
885
|
+
"Conversation work stopped after repeated failed attempts"
|
|
886
|
+
),
|
|
884
887
|
"conversation.work.retry.exhausted",
|
|
885
888
|
{
|
|
886
889
|
"app.run.id": work.execution.runId ?? "unknown",
|
|
@@ -3098,14 +3101,14 @@ function createSlackConversationWorker(options) {
|
|
|
3098
3101
|
if (records.length === 0) {
|
|
3099
3102
|
const destination = requireSlackDestination(
|
|
3100
3103
|
context.destination,
|
|
3101
|
-
"Slack
|
|
3104
|
+
"Slack paused-turn recovery"
|
|
3102
3105
|
);
|
|
3103
3106
|
await runWithSlackInstallation({
|
|
3104
3107
|
adapter,
|
|
3105
3108
|
installation: { teamId: destination.teamId },
|
|
3106
3109
|
state,
|
|
3107
3110
|
task: async () => {
|
|
3108
|
-
await options.
|
|
3111
|
+
await options.runNextPausedTurn(context.conversationId, {
|
|
3109
3112
|
shouldYield: context.shouldYield
|
|
3110
3113
|
});
|
|
3111
3114
|
}
|
|
@@ -5945,9 +5948,9 @@ function createJuniorRuntimeServices(overrides = {}) {
|
|
|
5945
5948
|
replyExecutor: {
|
|
5946
5949
|
contextCompactor: overrides.replyExecutor?.contextCompactor ?? contextCompactor,
|
|
5947
5950
|
agentRunner,
|
|
5948
|
-
|
|
5951
|
+
getPausedTurnRequest: overrides.replyExecutor?.getPausedTurnRequest ?? getPausedTurnRequest,
|
|
5949
5952
|
lookupSlackUser: overrides.replyExecutor?.lookupSlackUser ?? lookupSlackUser,
|
|
5950
|
-
|
|
5953
|
+
wakePausedTurn: overrides.replyExecutor?.wakePausedTurn ?? wakePausedTurn,
|
|
5951
5954
|
scheduleSessionCompletedPluginTasks: overrides.replyExecutor?.scheduleSessionCompletedPluginTasks ?? (async (params) => {
|
|
5952
5955
|
await scheduleSessionCompletedPluginTasks(params);
|
|
5953
5956
|
}),
|
|
@@ -6183,7 +6186,7 @@ async function loadPiMessagesForTurn(args) {
|
|
|
6183
6186
|
return {};
|
|
6184
6187
|
}
|
|
6185
6188
|
if (args.activeTurnId) {
|
|
6186
|
-
const sessionRecord = await
|
|
6189
|
+
const sessionRecord = await getTurnRecord(
|
|
6187
6190
|
args.conversationId,
|
|
6188
6191
|
args.activeTurnId
|
|
6189
6192
|
);
|
|
@@ -6473,20 +6476,20 @@ function createReplyToThread(deps) {
|
|
|
6473
6476
|
return;
|
|
6474
6477
|
}
|
|
6475
6478
|
if (conversationId && activeTurnId) {
|
|
6476
|
-
const
|
|
6479
|
+
const pausedTurn = await deps.services.getPausedTurnRequest({
|
|
6477
6480
|
conversationId,
|
|
6478
|
-
|
|
6481
|
+
turnId: activeTurnId
|
|
6479
6482
|
});
|
|
6480
|
-
if (
|
|
6481
|
-
if (!await appendParkedTurnInput(
|
|
6483
|
+
if (pausedTurn) {
|
|
6484
|
+
if (!await appendParkedTurnInput(pausedTurn.turnId)) {
|
|
6482
6485
|
throw new TurnInputDeferredError();
|
|
6483
6486
|
}
|
|
6484
6487
|
try {
|
|
6485
|
-
await deps.services.
|
|
6488
|
+
await deps.services.wakePausedTurn(pausedTurn);
|
|
6486
6489
|
} catch (error) {
|
|
6487
6490
|
logException(error, "agent.continue.schedule.failed", {
|
|
6488
|
-
"app.ai.resume_session_version":
|
|
6489
|
-
"app.ai.resume_session_id":
|
|
6491
|
+
"app.ai.resume_session_version": pausedTurn.expectedVersion,
|
|
6492
|
+
"app.ai.resume_session_id": pausedTurn.turnId,
|
|
6490
6493
|
...messageTs ? { "messaging.message.id": messageTs } : {}
|
|
6491
6494
|
});
|
|
6492
6495
|
throw error;
|
|
@@ -6498,15 +6501,15 @@ function createReplyToThread(deps) {
|
|
|
6498
6501
|
await options.ack?.();
|
|
6499
6502
|
return;
|
|
6500
6503
|
}
|
|
6501
|
-
const sessionRecord = await
|
|
6504
|
+
const sessionRecord = await getTurnRecord(
|
|
6502
6505
|
conversationId,
|
|
6503
6506
|
activeTurnId
|
|
6504
6507
|
);
|
|
6505
|
-
if (sessionRecord?.state === "
|
|
6508
|
+
if (sessionRecord?.state === "paused") {
|
|
6506
6509
|
if (sessionRecord.resumeReason === "auth") {
|
|
6507
|
-
await
|
|
6510
|
+
await abandonTurnRecord({
|
|
6508
6511
|
conversationId,
|
|
6509
|
-
|
|
6512
|
+
turnId: activeTurnId,
|
|
6510
6513
|
errorMessage: "Auth-parked session superseded by a new user message"
|
|
6511
6514
|
});
|
|
6512
6515
|
markTurnClosed({
|
|
@@ -6516,11 +6519,11 @@ function createReplyToThread(deps) {
|
|
|
6516
6519
|
});
|
|
6517
6520
|
activeTurnId = void 0;
|
|
6518
6521
|
} else {
|
|
6519
|
-
await
|
|
6522
|
+
await failTurnRecord({
|
|
6520
6523
|
conversationId,
|
|
6521
6524
|
expectedVersion: sessionRecord.version,
|
|
6522
|
-
|
|
6523
|
-
errorMessage: "Awaiting
|
|
6525
|
+
turnId: activeTurnId,
|
|
6526
|
+
errorMessage: "Awaiting paused-turn metadata could not be materialized"
|
|
6524
6527
|
});
|
|
6525
6528
|
markTurnFailed({
|
|
6526
6529
|
conversation: preparedState.conversation,
|
|
@@ -6590,10 +6593,10 @@ function createReplyToThread(deps) {
|
|
|
6590
6593
|
}
|
|
6591
6594
|
if (conversationId) {
|
|
6592
6595
|
const turnStartedAtMs = message.metadata.dateSent.getTime();
|
|
6593
|
-
void
|
|
6596
|
+
void recordTurnSummary({
|
|
6594
6597
|
channelName,
|
|
6595
6598
|
conversationId,
|
|
6596
|
-
|
|
6599
|
+
turnId,
|
|
6597
6600
|
sliceId: 1,
|
|
6598
6601
|
startedAtMs: turnStartedAtMs,
|
|
6599
6602
|
state: "running",
|
|
@@ -6669,7 +6672,7 @@ function createReplyToThread(deps) {
|
|
|
6669
6672
|
if (!dispatchId) {
|
|
6670
6673
|
return;
|
|
6671
6674
|
}
|
|
6672
|
-
await
|
|
6675
|
+
await recordTurnSummary({
|
|
6673
6676
|
channelName,
|
|
6674
6677
|
conversationId,
|
|
6675
6678
|
destination,
|
|
@@ -6677,7 +6680,7 @@ function createReplyToThread(deps) {
|
|
|
6677
6680
|
dispatchId,
|
|
6678
6681
|
dispatchOutcome,
|
|
6679
6682
|
...acceptedDeliveryId ? { resultMessageId: acceptedDeliveryId } : {},
|
|
6680
|
-
|
|
6683
|
+
turnId,
|
|
6681
6684
|
sliceId: 1,
|
|
6682
6685
|
source,
|
|
6683
6686
|
startedAtMs: message.metadata.dateSent.getTime(),
|
|
@@ -6687,7 +6690,7 @@ function createReplyToThread(deps) {
|
|
|
6687
6690
|
};
|
|
6688
6691
|
let latestArtifacts = preparedState.artifacts;
|
|
6689
6692
|
let assistantTitleArtifacts = {};
|
|
6690
|
-
let
|
|
6693
|
+
let turnWakeError;
|
|
6691
6694
|
let boundaryFailureCode = "agent_run_failed";
|
|
6692
6695
|
let finalizedFailureEventId;
|
|
6693
6696
|
let terminalDispatchFailureOutcome;
|
|
@@ -6789,14 +6792,14 @@ function createReplyToThread(deps) {
|
|
|
6789
6792
|
if (slackTs && options.execution?.dispatch?.id) {
|
|
6790
6793
|
try {
|
|
6791
6794
|
await persistWithRetry(
|
|
6792
|
-
() =>
|
|
6795
|
+
() => recordTurnSummary({
|
|
6793
6796
|
channelName,
|
|
6794
6797
|
conversationId,
|
|
6795
6798
|
destination,
|
|
6796
6799
|
destinationVisibility,
|
|
6797
6800
|
dispatchId: options.execution?.dispatch?.id,
|
|
6798
6801
|
resultMessageId: slackTs,
|
|
6799
|
-
|
|
6802
|
+
turnId,
|
|
6800
6803
|
sliceId: 1,
|
|
6801
6804
|
source,
|
|
6802
6805
|
startedAtMs: message.metadata.dateSent.getTime(),
|
|
@@ -7063,14 +7066,14 @@ function createReplyToThread(deps) {
|
|
|
7063
7066
|
}
|
|
7064
7067
|
if (!destination || !conversationId) {
|
|
7065
7068
|
throw new Error(
|
|
7066
|
-
"
|
|
7069
|
+
"Paused turn requires a destination and conversation id"
|
|
7067
7070
|
);
|
|
7068
7071
|
}
|
|
7069
7072
|
try {
|
|
7070
|
-
await deps.services.
|
|
7073
|
+
await deps.services.wakePausedTurn({
|
|
7071
7074
|
conversationId,
|
|
7072
7075
|
destination,
|
|
7073
|
-
|
|
7076
|
+
turnId,
|
|
7074
7077
|
expectedVersion: outcome.resumeVersion
|
|
7075
7078
|
});
|
|
7076
7079
|
shouldPersistFailureState = false;
|
|
@@ -7080,7 +7083,7 @@ function createReplyToThread(deps) {
|
|
|
7080
7083
|
"app.ai.resume_session_version": outcome.resumeVersion
|
|
7081
7084
|
});
|
|
7082
7085
|
shouldPersistFailureState = true;
|
|
7083
|
-
|
|
7086
|
+
turnWakeError = scheduleError;
|
|
7084
7087
|
throw scheduleError;
|
|
7085
7088
|
}
|
|
7086
7089
|
return;
|
|
@@ -7122,16 +7125,17 @@ function createReplyToThread(deps) {
|
|
|
7122
7125
|
}
|
|
7123
7126
|
try {
|
|
7124
7127
|
if (conversationId && reply.piMessages?.length) {
|
|
7125
|
-
await
|
|
7128
|
+
await saveTurnCheckpoint({
|
|
7129
|
+
mode: "completed",
|
|
7126
7130
|
channelName,
|
|
7127
7131
|
conversationId,
|
|
7132
|
+
turnId,
|
|
7128
7133
|
durationMs: reply.diagnostics.durationMs,
|
|
7129
7134
|
usage: reply.diagnostics.usage,
|
|
7130
7135
|
reasoningLevel: reply.diagnostics.reasoningLevel,
|
|
7131
7136
|
destination,
|
|
7132
7137
|
destinationVisibility,
|
|
7133
7138
|
source,
|
|
7134
|
-
sessionId: turnId,
|
|
7135
7139
|
sliceId: 1,
|
|
7136
7140
|
dispatchOutcome: reply.diagnostics.outcome === "success" ? "completed" : "failed",
|
|
7137
7141
|
...options.execution?.dispatch && turnResult.errorMessage ? { errorMessage: turnResult.errorMessage } : {},
|
|
@@ -7143,12 +7147,12 @@ function createReplyToThread(deps) {
|
|
|
7143
7147
|
dispatchId: options.execution?.dispatch?.id
|
|
7144
7148
|
});
|
|
7145
7149
|
} else if (conversationId) {
|
|
7146
|
-
await
|
|
7150
|
+
await recordTurnSummary({
|
|
7147
7151
|
channelName,
|
|
7148
7152
|
conversationId,
|
|
7149
7153
|
cumulativeDurationMs: reply.diagnostics.durationMs,
|
|
7150
7154
|
cumulativeUsage: reply.diagnostics.usage,
|
|
7151
|
-
|
|
7155
|
+
turnId,
|
|
7152
7156
|
sliceId: 1,
|
|
7153
7157
|
startedAtMs: message.metadata.dateSent.getTime(),
|
|
7154
7158
|
state: "completed",
|
|
@@ -7262,7 +7266,7 @@ function createReplyToThread(deps) {
|
|
|
7262
7266
|
shouldPersistFailureState = false;
|
|
7263
7267
|
throw error;
|
|
7264
7268
|
}
|
|
7265
|
-
if (error ===
|
|
7269
|
+
if (error === turnWakeError) {
|
|
7266
7270
|
shouldPersistFailureState = true;
|
|
7267
7271
|
}
|
|
7268
7272
|
shouldPersistFailureState = true;
|
|
@@ -7285,15 +7289,12 @@ function createReplyToThread(deps) {
|
|
|
7285
7289
|
const recoveryText = buildCanvasRecoveryReply(createdCanvasUrl);
|
|
7286
7290
|
await deliverAssistantMessage(recoveryText, dispatchOutcome);
|
|
7287
7291
|
if (conversationId) {
|
|
7288
|
-
const sessionRecord = await
|
|
7289
|
-
conversationId,
|
|
7290
|
-
turnId
|
|
7291
|
-
);
|
|
7292
|
+
const sessionRecord = await getTurnRecord(conversationId, turnId);
|
|
7292
7293
|
if (sessionRecord) {
|
|
7293
|
-
await
|
|
7294
|
+
await failTurnRecord({
|
|
7294
7295
|
conversationId,
|
|
7295
7296
|
expectedVersion: sessionRecord.version,
|
|
7296
|
-
|
|
7297
|
+
turnId,
|
|
7297
7298
|
errorMessage
|
|
7298
7299
|
});
|
|
7299
7300
|
}
|
|
@@ -7343,10 +7344,10 @@ function createReplyToThread(deps) {
|
|
|
7343
7344
|
});
|
|
7344
7345
|
if (conversationId) {
|
|
7345
7346
|
try {
|
|
7346
|
-
await
|
|
7347
|
+
await recordTurnSummary({
|
|
7347
7348
|
channelName,
|
|
7348
7349
|
conversationId,
|
|
7349
|
-
|
|
7350
|
+
turnId,
|
|
7350
7351
|
sliceId: 1,
|
|
7351
7352
|
startedAtMs: message.metadata.dateSent.getTime(),
|
|
7352
7353
|
state: "failed",
|
|
@@ -7361,15 +7362,15 @@ function createReplyToThread(deps) {
|
|
|
7361
7362
|
} : {},
|
|
7362
7363
|
traceId: getActiveTraceId()
|
|
7363
7364
|
});
|
|
7364
|
-
const sessionRecord = await
|
|
7365
|
+
const sessionRecord = await getTurnRecord(
|
|
7365
7366
|
conversationId,
|
|
7366
7367
|
turnId
|
|
7367
7368
|
);
|
|
7368
7369
|
if (sessionRecord) {
|
|
7369
|
-
await
|
|
7370
|
+
await failTurnRecord({
|
|
7370
7371
|
conversationId,
|
|
7371
7372
|
expectedVersion: sessionRecord.version,
|
|
7372
|
-
|
|
7373
|
+
turnId,
|
|
7373
7374
|
errorMessage: "Agent turn failed before assistant output handling completed"
|
|
7374
7375
|
});
|
|
7375
7376
|
}
|
|
@@ -7871,39 +7872,33 @@ function createJuniorSlackAdapter(config) {
|
|
|
7871
7872
|
return createSlackAdapter(config);
|
|
7872
7873
|
}
|
|
7873
7874
|
|
|
7874
|
-
// src/chat/
|
|
7875
|
-
var AGENT_CONTINUE_LOCK_RETRY_DELAYS_MS = [250, 1e3, 2e3];
|
|
7875
|
+
// src/chat/task-execution/paused-turn.ts
|
|
7876
7876
|
async function persistCompletedReplyState(args) {
|
|
7877
|
-
const currentState = await getPersistedThreadState(
|
|
7878
|
-
args.sessionRecord.conversationId
|
|
7879
|
-
);
|
|
7877
|
+
const currentState = await getPersistedThreadState(args.turn.conversationId);
|
|
7880
7878
|
const conversation = coerceThreadConversationState(currentState);
|
|
7881
7879
|
await hydrateConversationMessages({
|
|
7882
7880
|
conversation,
|
|
7883
|
-
conversationId: args.
|
|
7881
|
+
conversationId: args.turn.conversationId
|
|
7884
7882
|
});
|
|
7885
7883
|
const artifacts = coerceThreadArtifactsState(currentState);
|
|
7886
|
-
const userMessage = getTurnUserMessage(
|
|
7887
|
-
conversation,
|
|
7888
|
-
args.sessionRecord.sessionId
|
|
7889
|
-
);
|
|
7884
|
+
const userMessage = getTurnUserMessage(conversation, args.turn.turnId);
|
|
7890
7885
|
const statePatch = buildDeliveredTurnStatePatch({
|
|
7891
7886
|
artifacts,
|
|
7892
7887
|
conversation,
|
|
7893
7888
|
reply: args.reply,
|
|
7894
|
-
sessionId: args.
|
|
7889
|
+
sessionId: args.turn.turnId,
|
|
7895
7890
|
userMessageId: userMessage?.id
|
|
7896
7891
|
});
|
|
7897
|
-
await persistThreadStateById(args.
|
|
7892
|
+
await persistThreadStateById(args.turn.conversationId, {
|
|
7898
7893
|
...statePatch
|
|
7899
7894
|
});
|
|
7900
7895
|
}
|
|
7901
|
-
async function
|
|
7896
|
+
async function failTurnBestEffort(args) {
|
|
7902
7897
|
try {
|
|
7903
|
-
await
|
|
7904
|
-
conversationId: args.
|
|
7905
|
-
expectedVersion: args.
|
|
7906
|
-
|
|
7898
|
+
await failTurnRecord({
|
|
7899
|
+
conversationId: args.turn.conversationId,
|
|
7900
|
+
expectedVersion: args.turn.version,
|
|
7901
|
+
turnId: args.turn.turnId,
|
|
7907
7902
|
errorMessage: args.errorMessage
|
|
7908
7903
|
});
|
|
7909
7904
|
} catch (error) {
|
|
@@ -7911,51 +7906,49 @@ async function failSessionRecordBestEffort(args) {
|
|
|
7911
7906
|
error,
|
|
7912
7907
|
"agent.continue.session_record.failure_persistence.failed",
|
|
7913
7908
|
{
|
|
7914
|
-
"app.ai.conversation_id": args.
|
|
7915
|
-
"app.ai.session_id": args.
|
|
7909
|
+
"app.ai.conversation_id": args.turn.conversationId,
|
|
7910
|
+
"app.ai.session_id": args.turn.turnId
|
|
7916
7911
|
}
|
|
7917
7912
|
);
|
|
7918
7913
|
}
|
|
7919
7914
|
}
|
|
7920
|
-
async function persistFailedReplyState(
|
|
7921
|
-
const currentState = await getPersistedThreadState(
|
|
7922
|
-
sessionRecord.conversationId
|
|
7923
|
-
);
|
|
7915
|
+
async function persistFailedReplyState(turn, errorMessage = "Paused agent run failed while continuing") {
|
|
7916
|
+
const currentState = await getPersistedThreadState(turn.conversationId);
|
|
7924
7917
|
const conversation = coerceThreadConversationState(currentState);
|
|
7925
7918
|
await hydrateConversationMessages({
|
|
7926
7919
|
conversation,
|
|
7927
|
-
conversationId:
|
|
7920
|
+
conversationId: turn.conversationId
|
|
7928
7921
|
});
|
|
7929
|
-
clearPendingAuth(conversation,
|
|
7922
|
+
clearPendingAuth(conversation, turn.turnId);
|
|
7930
7923
|
markTurnFailed({
|
|
7931
7924
|
conversation,
|
|
7932
7925
|
nowMs: Date.now(),
|
|
7933
|
-
sessionId:
|
|
7934
|
-
userMessageId: getTurnUserMessage(conversation,
|
|
7926
|
+
sessionId: turn.turnId,
|
|
7927
|
+
userMessageId: getTurnUserMessage(conversation, turn.turnId)?.id,
|
|
7935
7928
|
markConversationMessage
|
|
7936
7929
|
});
|
|
7937
|
-
await
|
|
7938
|
-
|
|
7930
|
+
await failTurnBestEffort({
|
|
7931
|
+
turn,
|
|
7939
7932
|
errorMessage
|
|
7940
7933
|
});
|
|
7941
|
-
await persistThreadStateById(
|
|
7934
|
+
await persistThreadStateById(turn.conversationId, {
|
|
7942
7935
|
conversation
|
|
7943
7936
|
});
|
|
7944
7937
|
}
|
|
7945
|
-
async function
|
|
7938
|
+
async function failPausedTurnStart(args) {
|
|
7946
7939
|
try {
|
|
7947
|
-
await persistFailedReplyState(args.
|
|
7940
|
+
await persistFailedReplyState(args.turn, args.errorMessage);
|
|
7948
7941
|
} catch (persistError) {
|
|
7949
|
-
await
|
|
7950
|
-
|
|
7951
|
-
errorMessage: "Paused
|
|
7942
|
+
await failTurnBestEffort({
|
|
7943
|
+
turn: args.turn,
|
|
7944
|
+
errorMessage: "Paused turn failed before it could run"
|
|
7952
7945
|
});
|
|
7953
7946
|
logException(
|
|
7954
7947
|
persistError,
|
|
7955
7948
|
"agent.continue.startup_failure_persist.failed",
|
|
7956
7949
|
{
|
|
7957
|
-
"app.ai.conversation_id": args.
|
|
7958
|
-
"app.ai.session_id": args.
|
|
7950
|
+
"app.ai.conversation_id": args.turn.conversationId,
|
|
7951
|
+
"app.ai.session_id": args.turn.turnId
|
|
7959
7952
|
}
|
|
7960
7953
|
);
|
|
7961
7954
|
}
|
|
@@ -8012,74 +8005,78 @@ async function resolveResumeExecutionIdentity(args) {
|
|
|
8012
8005
|
credentialContext: credentialContextForActor(actor)
|
|
8013
8006
|
};
|
|
8014
8007
|
}
|
|
8015
|
-
function
|
|
8016
|
-
return summary.state === "
|
|
8008
|
+
function isPausedTurn(summary) {
|
|
8009
|
+
return summary.state === "paused" && (summary.resumeReason === "timeout" || summary.resumeReason === "yield" || summary.resumeReason === "retry");
|
|
8017
8010
|
}
|
|
8018
|
-
async function
|
|
8019
|
-
await
|
|
8011
|
+
async function failPausedTurn(args) {
|
|
8012
|
+
const failed = await failTurnRecord({
|
|
8020
8013
|
conversationId: args.conversationId,
|
|
8021
8014
|
expectedVersion: args.expectedVersion ?? args.summary.version,
|
|
8022
|
-
|
|
8015
|
+
turnId: args.summary.turnId,
|
|
8023
8016
|
errorMessage: args.errorMessage
|
|
8024
8017
|
});
|
|
8025
|
-
if (
|
|
8018
|
+
if (!failed) return;
|
|
8019
|
+
if (failed.dispatchId) {
|
|
8026
8020
|
try {
|
|
8027
8021
|
const routing = await resolveTurnSessionRouting({
|
|
8028
8022
|
conversationId: args.conversationId
|
|
8029
8023
|
});
|
|
8030
|
-
await
|
|
8024
|
+
await recordTurnSummary({
|
|
8031
8025
|
conversationId: args.conversationId,
|
|
8032
8026
|
destination: routing.destination,
|
|
8033
|
-
dispatchId:
|
|
8027
|
+
dispatchId: failed.dispatchId,
|
|
8034
8028
|
dispatchOutcome: "failed",
|
|
8035
|
-
|
|
8036
|
-
sliceId:
|
|
8029
|
+
turnId: failed.turnId,
|
|
8030
|
+
sliceId: failed.sliceId,
|
|
8037
8031
|
source: routing.source,
|
|
8038
8032
|
state: "failed",
|
|
8039
|
-
surface:
|
|
8033
|
+
surface: failed.surface
|
|
8040
8034
|
});
|
|
8041
8035
|
} catch (error) {
|
|
8042
8036
|
logException(error, "agent.continue.dispatch_failure_summary.failed", {
|
|
8043
8037
|
"app.ai.conversation_id": args.conversationId,
|
|
8044
|
-
"app.ai.session_id": args.summary.
|
|
8038
|
+
"app.ai.session_id": args.summary.turnId
|
|
8045
8039
|
});
|
|
8046
8040
|
}
|
|
8047
8041
|
}
|
|
8048
8042
|
}
|
|
8049
|
-
async function
|
|
8043
|
+
async function runPausedTurn(payload, options, runOptions = {}) {
|
|
8050
8044
|
return withLogContext(
|
|
8051
8045
|
{ conversationId: payload.conversationId },
|
|
8052
|
-
() =>
|
|
8046
|
+
() => runPausedTurnInContext(payload, options, runOptions)
|
|
8053
8047
|
);
|
|
8054
8048
|
}
|
|
8055
|
-
async function
|
|
8049
|
+
async function runPausedTurnInContext(payload, options, runOptions) {
|
|
8056
8050
|
const thread = parseSlackThreadId(payload.conversationId);
|
|
8057
8051
|
const destination = requireSlackDestination(
|
|
8058
8052
|
payload.destination,
|
|
8059
|
-
"
|
|
8053
|
+
"Paused turn"
|
|
8060
8054
|
);
|
|
8061
|
-
const
|
|
8055
|
+
const wakePausedTurn2 = options.wakePausedTurn ?? wakePausedTurn;
|
|
8062
8056
|
const resumeTurn = options.resumeTurn ?? resumeSlackTurn;
|
|
8063
8057
|
return await resumeTurn({
|
|
8064
8058
|
messageText: "",
|
|
8065
8059
|
conversationId: payload.conversationId,
|
|
8066
|
-
turnId: payload.
|
|
8060
|
+
turnId: payload.turnId,
|
|
8067
8061
|
channelId: thread?.channelId ?? destination.channelId,
|
|
8068
8062
|
...thread?.threadTs ? { threadTs: thread.threadTs } : {},
|
|
8069
8063
|
lockKey: payload.conversationId,
|
|
8064
|
+
// Queue continue runs under the conversation work lease already.
|
|
8065
|
+
ownsConversationLease: true,
|
|
8070
8066
|
agentRunner: options.agentRunner,
|
|
8071
8067
|
scheduleSessionCompletedPluginTasks: options.scheduleSessionCompletedPluginTasks,
|
|
8072
8068
|
beforeStart: async () => {
|
|
8073
|
-
let
|
|
8069
|
+
let turn;
|
|
8074
8070
|
try {
|
|
8075
|
-
|
|
8076
|
-
payload.conversationId,
|
|
8077
|
-
payload.
|
|
8078
|
-
);
|
|
8079
|
-
|
|
8071
|
+
const checkpoint = await loadTurnCheckpoint({
|
|
8072
|
+
conversationId: payload.conversationId,
|
|
8073
|
+
turnId: payload.turnId
|
|
8074
|
+
});
|
|
8075
|
+
turn = checkpoint.record;
|
|
8076
|
+
if (!turn || turn.state !== "paused" || turn.resumeReason !== "timeout" && turn.resumeReason !== "yield" && turn.resumeReason !== "retry" || turn.version !== payload.expectedVersion) {
|
|
8080
8077
|
return false;
|
|
8081
8078
|
}
|
|
8082
|
-
const
|
|
8079
|
+
const activeTurn = turn;
|
|
8083
8080
|
const currentState = await getPersistedThreadState(
|
|
8084
8081
|
payload.conversationId
|
|
8085
8082
|
);
|
|
@@ -8089,20 +8086,20 @@ async function continueSlackAgentRunInContext(payload, options, runOptions) {
|
|
|
8089
8086
|
conversationId: payload.conversationId
|
|
8090
8087
|
});
|
|
8091
8088
|
const artifacts = coerceThreadArtifactsState(currentState);
|
|
8092
|
-
const dispatchId =
|
|
8089
|
+
const dispatchId = activeTurn.dispatchId ?? options.routingContext?.dispatch?.id;
|
|
8093
8090
|
const dispatchUserMessage = dispatchId ? conversation.messages.find(
|
|
8094
8091
|
(message) => message.role === "user" && options.inputMessageIds?.includes(message.id)
|
|
8095
8092
|
) : void 0;
|
|
8096
|
-
const userMessage = getTurnUserMessage(conversation, payload.
|
|
8093
|
+
const userMessage = getTurnUserMessage(conversation, payload.turnId) ?? dispatchUserMessage;
|
|
8097
8094
|
if (!userMessage) {
|
|
8098
|
-
await
|
|
8095
|
+
await failStrandedTurnWithFallback({
|
|
8099
8096
|
conversationId: payload.conversationId,
|
|
8100
|
-
errorMessage: `Unable to locate the persisted user message for
|
|
8101
|
-
|
|
8097
|
+
errorMessage: `Unable to locate the persisted user message for paused turn "${payload.turnId}"`,
|
|
8098
|
+
turn: activeTurn
|
|
8102
8099
|
});
|
|
8103
8100
|
return false;
|
|
8104
8101
|
}
|
|
8105
|
-
if (conversation.processing.activeTurnId !== payload.
|
|
8102
|
+
if (conversation.processing.activeTurnId !== payload.turnId) {
|
|
8106
8103
|
return false;
|
|
8107
8104
|
}
|
|
8108
8105
|
const identity = await resolveResumeExecutionIdentity({
|
|
@@ -8112,10 +8109,10 @@ async function continueSlackAgentRunInContext(payload, options, runOptions) {
|
|
|
8112
8109
|
userMessage
|
|
8113
8110
|
});
|
|
8114
8111
|
if (!identity) {
|
|
8115
|
-
await
|
|
8112
|
+
await failStrandedTurnWithFallback({
|
|
8116
8113
|
conversationId: payload.conversationId,
|
|
8117
|
-
errorMessage: "Unable to rebuild Slack actor for
|
|
8118
|
-
|
|
8114
|
+
errorMessage: "Unable to rebuild the Slack actor for the paused turn",
|
|
8115
|
+
turn: activeTurn
|
|
8119
8116
|
});
|
|
8120
8117
|
return false;
|
|
8121
8118
|
}
|
|
@@ -8132,22 +8129,20 @@ async function continueSlackAgentRunInContext(payload, options, runOptions) {
|
|
|
8132
8129
|
});
|
|
8133
8130
|
const source = routing.source;
|
|
8134
8131
|
const routingDestination = routing.destination;
|
|
8135
|
-
const turnMessages =
|
|
8136
|
-
activeSessionRecord.turnStartMessageIndex
|
|
8137
|
-
);
|
|
8132
|
+
const turnMessages = activeTurn.turnStartMessageIndex === void 0 ? [] : activeTurn.piMessages.slice(activeTurn.turnStartMessageIndex);
|
|
8138
8133
|
const recordDispatchOutcome = async (dispatchOutcome) => {
|
|
8139
8134
|
const dispatchId2 = options.routingContext?.dispatch?.id;
|
|
8140
8135
|
if (!dispatchId2) {
|
|
8141
8136
|
return;
|
|
8142
8137
|
}
|
|
8143
|
-
await
|
|
8138
|
+
await recordTurnSummary({
|
|
8144
8139
|
conversationId: payload.conversationId,
|
|
8145
8140
|
destination: routingDestination,
|
|
8146
8141
|
destinationVisibility: options.routingContext?.destinationVisibility,
|
|
8147
8142
|
dispatchId: dispatchId2,
|
|
8148
8143
|
dispatchOutcome,
|
|
8149
|
-
|
|
8150
|
-
sliceId:
|
|
8144
|
+
turnId: payload.turnId,
|
|
8145
|
+
sliceId: activeTurn.sliceId,
|
|
8151
8146
|
source,
|
|
8152
8147
|
state: "failed",
|
|
8153
8148
|
surface: options.routingContext?.surface ?? "slack"
|
|
@@ -8155,7 +8150,7 @@ async function continueSlackAgentRunInContext(payload, options, runOptions) {
|
|
|
8155
8150
|
};
|
|
8156
8151
|
return {
|
|
8157
8152
|
messageText: userMessage.text,
|
|
8158
|
-
sliceId:
|
|
8153
|
+
sliceId: activeTurn.sliceId,
|
|
8159
8154
|
messageTs: getTurnUserSlackMessageTs(userMessage),
|
|
8160
8155
|
inputMessageIds: [userMessage.id],
|
|
8161
8156
|
initialStatus: latestReportedProgress(turnMessages),
|
|
@@ -8166,7 +8161,7 @@ async function continueSlackAgentRunInContext(payload, options, runOptions) {
|
|
|
8166
8161
|
// exact dispatch session so unrelated conversation input cannot
|
|
8167
8162
|
// gain system authority. Interactive turns retain their merged
|
|
8168
8163
|
// projection so queued steering remains visible.
|
|
8169
|
-
piMessages: dispatchId ?
|
|
8164
|
+
piMessages: dispatchId ? activeTurn.piMessages : await loadProjection({
|
|
8170
8165
|
conversationId: payload.conversationId
|
|
8171
8166
|
}),
|
|
8172
8167
|
...getTurnUserReplyAttachmentContext(userMessage)
|
|
@@ -8199,51 +8194,51 @@ async function continueSlackAgentRunInContext(payload, options, runOptions) {
|
|
|
8199
8194
|
},
|
|
8200
8195
|
commitResult: async (reply) => {
|
|
8201
8196
|
await persistCompletedReplyState({
|
|
8202
|
-
|
|
8197
|
+
turn: activeTurn,
|
|
8203
8198
|
reply
|
|
8204
8199
|
});
|
|
8205
8200
|
},
|
|
8206
8201
|
onFailure: async (error) => {
|
|
8207
8202
|
await persistFailedReplyState(
|
|
8208
|
-
|
|
8203
|
+
activeTurn,
|
|
8209
8204
|
error instanceof Error ? error.message : String(error)
|
|
8210
8205
|
);
|
|
8211
8206
|
await recordDispatchOutcome("failed");
|
|
8212
8207
|
},
|
|
8213
8208
|
onPostDeliveryCommitFailure: async () => {
|
|
8214
|
-
await
|
|
8215
|
-
conversationId:
|
|
8216
|
-
expectedVersion:
|
|
8217
|
-
|
|
8209
|
+
await failTurnRecord({
|
|
8210
|
+
conversationId: activeTurn.conversationId,
|
|
8211
|
+
expectedVersion: activeTurn.version,
|
|
8212
|
+
turnId: activeTurn.turnId,
|
|
8218
8213
|
errorMessage: "Continued agent reply was delivered but completion state did not persist"
|
|
8219
8214
|
});
|
|
8220
8215
|
await recordDispatchOutcome("failed");
|
|
8221
8216
|
},
|
|
8222
8217
|
onAuthPause: async () => {
|
|
8223
8218
|
await persistAuthPauseTurnState({
|
|
8224
|
-
sessionId: payload.
|
|
8219
|
+
sessionId: payload.turnId,
|
|
8225
8220
|
threadStateId: payload.conversationId
|
|
8226
8221
|
});
|
|
8227
8222
|
await recordDispatchOutcome("blocked");
|
|
8228
8223
|
logWarn("agent.continue.reparked_for_auth", {
|
|
8229
8224
|
"app.ai.conversation_id": payload.conversationId,
|
|
8230
|
-
"app.ai.session_id": payload.
|
|
8225
|
+
"app.ai.session_id": payload.turnId
|
|
8231
8226
|
});
|
|
8232
8227
|
},
|
|
8233
8228
|
onSuspend: async (resumeVersion) => {
|
|
8234
|
-
await
|
|
8229
|
+
await wakePausedTurn2({
|
|
8235
8230
|
conversationId: payload.conversationId,
|
|
8236
8231
|
destination: payload.destination,
|
|
8237
|
-
|
|
8232
|
+
turnId: payload.turnId,
|
|
8238
8233
|
expectedVersion: resumeVersion
|
|
8239
8234
|
});
|
|
8240
8235
|
}
|
|
8241
8236
|
};
|
|
8242
8237
|
} catch (error) {
|
|
8243
|
-
if (
|
|
8244
|
-
await
|
|
8238
|
+
if (turn) {
|
|
8239
|
+
await failPausedTurnStart({
|
|
8245
8240
|
errorMessage: error instanceof Error ? error.message : String(error),
|
|
8246
|
-
|
|
8241
|
+
turn
|
|
8247
8242
|
});
|
|
8248
8243
|
}
|
|
8249
8244
|
throw error;
|
|
@@ -8251,13 +8246,14 @@ async function continueSlackAgentRunInContext(payload, options, runOptions) {
|
|
|
8251
8246
|
}
|
|
8252
8247
|
});
|
|
8253
8248
|
}
|
|
8254
|
-
async function
|
|
8255
|
-
await
|
|
8249
|
+
async function failStrandedTurnWithFallback(args) {
|
|
8250
|
+
const failed = await failTurnRecord({
|
|
8256
8251
|
conversationId: args.conversationId,
|
|
8257
|
-
expectedVersion: args.
|
|
8258
|
-
|
|
8252
|
+
expectedVersion: args.turn.version,
|
|
8253
|
+
turnId: args.turn.turnId,
|
|
8259
8254
|
errorMessage: args.errorMessage
|
|
8260
8255
|
});
|
|
8256
|
+
if (!failed) return false;
|
|
8261
8257
|
const currentState = await getPersistedThreadState(args.conversationId);
|
|
8262
8258
|
const conversation = coerceThreadConversationState(currentState);
|
|
8263
8259
|
await hydrateConversationMessages({
|
|
@@ -8267,18 +8263,15 @@ async function failStrandedSessionWithFallback(args) {
|
|
|
8267
8263
|
markTurnFailed({
|
|
8268
8264
|
conversation,
|
|
8269
8265
|
nowMs: Date.now(),
|
|
8270
|
-
sessionId:
|
|
8271
|
-
userMessageId: getTurnUserMessage(
|
|
8272
|
-
conversation,
|
|
8273
|
-
args.sessionRecord.sessionId
|
|
8274
|
-
)?.id,
|
|
8266
|
+
sessionId: failed.turnId,
|
|
8267
|
+
userMessageId: getTurnUserMessage(conversation, failed.turnId)?.id,
|
|
8275
8268
|
markConversationMessage
|
|
8276
8269
|
});
|
|
8277
8270
|
await persistThreadStateById(args.conversationId, { conversation });
|
|
8278
8271
|
const eventName = "agent.turn.stranded_session.failed";
|
|
8279
8272
|
const eventId = logException(new Error(args.errorMessage), eventName, {
|
|
8280
8273
|
"app.ai.conversation_id": args.conversationId,
|
|
8281
|
-
"app.ai.session_id":
|
|
8274
|
+
"app.ai.session_id": failed.turnId
|
|
8282
8275
|
});
|
|
8283
8276
|
let routing;
|
|
8284
8277
|
try {
|
|
@@ -8288,25 +8281,25 @@ async function failStrandedSessionWithFallback(args) {
|
|
|
8288
8281
|
} catch (error) {
|
|
8289
8282
|
logException(error, "agent.turn.stranded_session.routing_unavailable", {
|
|
8290
8283
|
"app.ai.conversation_id": args.conversationId,
|
|
8291
|
-
"app.ai.session_id":
|
|
8284
|
+
"app.ai.session_id": failed.turnId
|
|
8292
8285
|
});
|
|
8293
|
-
return;
|
|
8286
|
+
return true;
|
|
8294
8287
|
}
|
|
8295
|
-
if (
|
|
8296
|
-
await
|
|
8288
|
+
if (failed.dispatchId) {
|
|
8289
|
+
await recordTurnSummary({
|
|
8297
8290
|
conversationId: args.conversationId,
|
|
8298
8291
|
destination: routing.destination,
|
|
8299
|
-
dispatchId:
|
|
8292
|
+
dispatchId: failed.dispatchId,
|
|
8300
8293
|
dispatchOutcome: "failed",
|
|
8301
|
-
|
|
8302
|
-
sliceId:
|
|
8294
|
+
turnId: failed.turnId,
|
|
8295
|
+
sliceId: failed.sliceId,
|
|
8303
8296
|
source: routing.source,
|
|
8304
8297
|
state: "failed",
|
|
8305
|
-
surface:
|
|
8298
|
+
surface: failed.surface
|
|
8306
8299
|
});
|
|
8307
8300
|
}
|
|
8308
8301
|
const thread = parseSlackThreadId(args.conversationId);
|
|
8309
|
-
const channelId = thread?.channelId ?? requireSlackDestination(routing.destination, "Stranded
|
|
8302
|
+
const channelId = thread?.channelId ?? requireSlackDestination(routing.destination, "Stranded paused turn").channelId;
|
|
8310
8303
|
await postSlackMessage({
|
|
8311
8304
|
channelId,
|
|
8312
8305
|
...thread?.threadTs ? { threadTs: thread.threadTs } : {},
|
|
@@ -8314,173 +8307,154 @@ async function failStrandedSessionWithFallback(args) {
|
|
|
8314
8307
|
requireTurnFailureEventId(eventId, eventName)
|
|
8315
8308
|
)
|
|
8316
8309
|
});
|
|
8310
|
+
return true;
|
|
8317
8311
|
}
|
|
8318
|
-
async function
|
|
8319
|
-
const stateAdapter = getStateAdapter();
|
|
8320
|
-
await stateAdapter.connect();
|
|
8321
|
-
const probe = await acquireActiveLock(stateAdapter, args.conversationId);
|
|
8322
|
-
if (!probe) {
|
|
8323
|
-
return false;
|
|
8324
|
-
}
|
|
8325
|
-
await stateAdapter.releaseLock(probe);
|
|
8326
|
-
const sessionRecord = await getAgentTurnSessionRecordForResume(
|
|
8327
|
-
args.conversationId,
|
|
8328
|
-
args.summary.sessionId
|
|
8329
|
-
);
|
|
8330
|
-
if (!sessionRecord || sessionRecord.state !== "running") {
|
|
8331
|
-
return false;
|
|
8332
|
-
}
|
|
8333
|
-
const recoveryProjection = await loadConversationProjection({
|
|
8334
|
-
conversationId: args.conversationId
|
|
8335
|
-
});
|
|
8336
|
-
const modelProfile = recoveryProjection.modelProfile;
|
|
8337
|
-
const modelId = modelIdForProfile(botConfig, modelProfile);
|
|
8338
|
-
let routing;
|
|
8339
|
-
try {
|
|
8340
|
-
routing = await resolveTurnSessionRouting({
|
|
8341
|
-
conversationId: args.conversationId
|
|
8342
|
-
});
|
|
8343
|
-
} catch (error) {
|
|
8344
|
-
await failStrandedSessionWithFallback({
|
|
8345
|
-
conversationId: args.conversationId,
|
|
8346
|
-
errorMessage: error instanceof Error ? error.message : String(error),
|
|
8347
|
-
sessionRecord
|
|
8348
|
-
});
|
|
8349
|
-
return false;
|
|
8350
|
-
}
|
|
8351
|
-
const parked = await persistYieldSessionRecord({
|
|
8352
|
-
channelName: sessionRecord.channelName,
|
|
8353
|
-
conversationId: args.conversationId,
|
|
8354
|
-
sessionId: sessionRecord.sessionId,
|
|
8355
|
-
currentSliceId: sessionRecord.sliceId,
|
|
8356
|
-
destination: routing.destination,
|
|
8357
|
-
source: routing.source,
|
|
8358
|
-
messages: sessionRecord.piMessages,
|
|
8359
|
-
errorMessage: "Recovered running session after hard worker death",
|
|
8360
|
-
modelId,
|
|
8361
|
-
surface: sessionRecord.surface
|
|
8362
|
-
});
|
|
8363
|
-
if (!parked) {
|
|
8364
|
-
await failStrandedSessionWithFallback({
|
|
8365
|
-
conversationId: args.conversationId,
|
|
8366
|
-
errorMessage: "Stranded running session had no resumable boundary after worker death",
|
|
8367
|
-
sessionRecord
|
|
8368
|
-
});
|
|
8369
|
-
return false;
|
|
8370
|
-
}
|
|
8371
|
-
const request = await getAwaitingAgentContinueRequest({
|
|
8372
|
-
conversationId: args.conversationId,
|
|
8373
|
-
sessionId: sessionRecord.sessionId
|
|
8374
|
-
});
|
|
8375
|
-
if (!request) {
|
|
8376
|
-
await failStrandedSessionWithFallback({
|
|
8377
|
-
conversationId: args.conversationId,
|
|
8378
|
-
errorMessage: "Stranded running session could not materialize continuation metadata",
|
|
8379
|
-
sessionRecord: parked
|
|
8380
|
-
});
|
|
8381
|
-
return false;
|
|
8382
|
-
}
|
|
8383
|
-
if (await continueSlackAgentRunWithLockRetry(
|
|
8384
|
-
request,
|
|
8385
|
-
args.options,
|
|
8386
|
-
args.runOptions
|
|
8387
|
-
)) {
|
|
8388
|
-
return true;
|
|
8389
|
-
}
|
|
8390
|
-
await failUnresumableContinuation({
|
|
8391
|
-
conversationId: args.conversationId,
|
|
8392
|
-
expectedVersion: request.expectedVersion,
|
|
8393
|
-
summary: args.summary,
|
|
8394
|
-
errorMessage: "Awaiting agent continuation was stale before it could run"
|
|
8395
|
-
});
|
|
8396
|
-
return false;
|
|
8397
|
-
}
|
|
8398
|
-
async function resumeAwaitingSlackContinuation(conversationId, options, runOptions = {}) {
|
|
8312
|
+
async function runNextPausedTurn(conversationId, options, runOptions = {}) {
|
|
8399
8313
|
return withLogContext(
|
|
8400
8314
|
{ conversationId },
|
|
8401
|
-
() =>
|
|
8402
|
-
conversationId,
|
|
8403
|
-
options,
|
|
8404
|
-
runOptions
|
|
8405
|
-
)
|
|
8315
|
+
() => runNextPausedTurnInContext(conversationId, options, runOptions)
|
|
8406
8316
|
);
|
|
8407
8317
|
}
|
|
8408
|
-
async function
|
|
8409
|
-
const summaries = await
|
|
8318
|
+
async function runNextPausedTurnInContext(conversationId, options, runOptions) {
|
|
8319
|
+
const summaries = await listTurnSummaries(conversationId);
|
|
8320
|
+
const persisted = await getPersistedThreadState(conversationId);
|
|
8321
|
+
const conversation = coerceThreadConversationState(persisted);
|
|
8322
|
+
await hydrateConversationMessages({ conversation, conversationId });
|
|
8410
8323
|
const newest = summaries[0];
|
|
8411
|
-
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
|
|
8324
|
+
const running = newest ? await getTurnRecord(conversationId, newest.turnId) : void 0;
|
|
8325
|
+
if (running?.state === "running") {
|
|
8326
|
+
if (turnHasReply(conversation, running.turnId)) {
|
|
8327
|
+
const acceptedReply = [...conversation.messages].reverse().find(
|
|
8328
|
+
(message) => message.role === "assistant" && message.id.startsWith(`${running.turnId}:assistant:`)
|
|
8329
|
+
);
|
|
8330
|
+
const completed = await completeTurnRecord({
|
|
8331
|
+
conversationId,
|
|
8332
|
+
expectedVersion: running.version,
|
|
8333
|
+
resultMessageId: acceptedReply?.meta?.slackTs,
|
|
8334
|
+
turnId: running.turnId
|
|
8335
|
+
});
|
|
8336
|
+
if (!completed) return false;
|
|
8337
|
+
markTurnCompleted({
|
|
8338
|
+
conversation,
|
|
8339
|
+
nowMs: Date.now(),
|
|
8340
|
+
sessionId: running.turnId
|
|
8341
|
+
});
|
|
8342
|
+
await persistThreadStateById(conversationId, { conversation });
|
|
8343
|
+
return false;
|
|
8344
|
+
}
|
|
8345
|
+
const state = getStateAdapter();
|
|
8346
|
+
await state.connect();
|
|
8347
|
+
await withActiveLock(state, conversationId, async () => {
|
|
8348
|
+
const record = await getTurnRecordForResume(
|
|
8349
|
+
conversationId,
|
|
8350
|
+
running.turnId
|
|
8351
|
+
);
|
|
8352
|
+
if (!record || record.state !== "running") return;
|
|
8353
|
+
await failStrandedTurnWithFallback({
|
|
8354
|
+
conversationId,
|
|
8355
|
+
errorMessage: "Turn lost its worker before reaching a safe boundary",
|
|
8356
|
+
turn: record
|
|
8357
|
+
});
|
|
8417
8358
|
});
|
|
8359
|
+
return false;
|
|
8418
8360
|
}
|
|
8419
8361
|
for (const summary of summaries) {
|
|
8420
|
-
if (!
|
|
8362
|
+
if (!isPausedTurn(summary)) {
|
|
8421
8363
|
continue;
|
|
8422
8364
|
}
|
|
8423
|
-
const request = await
|
|
8365
|
+
const request = await getPausedTurnRequest({
|
|
8424
8366
|
conversationId,
|
|
8425
|
-
|
|
8367
|
+
turnId: summary.turnId
|
|
8426
8368
|
});
|
|
8427
8369
|
if (!request) {
|
|
8428
|
-
await
|
|
8370
|
+
await failPausedTurn({
|
|
8429
8371
|
conversationId,
|
|
8430
8372
|
summary,
|
|
8431
|
-
errorMessage: "Awaiting
|
|
8373
|
+
errorMessage: "Awaiting paused-turn metadata could not be materialized"
|
|
8432
8374
|
});
|
|
8433
8375
|
continue;
|
|
8434
8376
|
}
|
|
8435
|
-
if (await
|
|
8377
|
+
if (await runPausedTurn(request, options, runOptions)) {
|
|
8436
8378
|
return true;
|
|
8437
8379
|
}
|
|
8438
|
-
await
|
|
8380
|
+
await failPausedTurn({
|
|
8439
8381
|
conversationId,
|
|
8440
8382
|
expectedVersion: request.expectedVersion,
|
|
8441
8383
|
summary,
|
|
8442
|
-
errorMessage: "Awaiting
|
|
8384
|
+
errorMessage: "Awaiting paused turn was stale before it could run"
|
|
8443
8385
|
});
|
|
8444
8386
|
}
|
|
8445
8387
|
return false;
|
|
8446
8388
|
}
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
|
|
8457
|
-
|
|
8458
|
-
|
|
8459
|
-
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
throw error;
|
|
8464
|
-
}
|
|
8465
|
-
if (typeof delayMs !== "number") {
|
|
8466
|
-
logWarn("agent.continue.lock.busy", {
|
|
8467
|
-
"app.ai.conversation_id": payload.conversationId,
|
|
8468
|
-
"app.ai.session_id": payload.sessionId,
|
|
8469
|
-
"app.ai.resume_lock_retry_count": attempt
|
|
8470
|
-
});
|
|
8471
|
-
await scheduleAgentContinue2(payload);
|
|
8472
|
-
return true;
|
|
8473
|
-
}
|
|
8474
|
-
logWarn("agent.continue.lock.retrying", {
|
|
8475
|
-
"app.ai.conversation_id": payload.conversationId,
|
|
8476
|
-
"app.ai.session_id": payload.sessionId,
|
|
8477
|
-
"app.ai.resume_lock_retry_attempt": attempt + 1,
|
|
8478
|
-
"app.ai.resume_lock_retry_delay_ms": delayMs
|
|
8479
|
-
});
|
|
8480
|
-
await sleep(delayMs);
|
|
8389
|
+
|
|
8390
|
+
// src/chat/app/conversation-work.ts
|
|
8391
|
+
function createConversationWork(options) {
|
|
8392
|
+
const services = {
|
|
8393
|
+
...options.services,
|
|
8394
|
+
replyExecutor: {
|
|
8395
|
+
...options.services?.replyExecutor,
|
|
8396
|
+
agentRunner: options.agentRunner,
|
|
8397
|
+
getPausedTurnRequest: options.services?.replyExecutor?.getPausedTurnRequest ?? (async (request) => await getPausedTurnRequest({
|
|
8398
|
+
...request,
|
|
8399
|
+
conversationStore: options.conversationStore
|
|
8400
|
+
})),
|
|
8401
|
+
wakePausedTurn: options.services?.replyExecutor?.wakePausedTurn ?? (async (request) => await wakePausedTurn(request, {
|
|
8402
|
+
queue: options.queue,
|
|
8403
|
+
state: options.state
|
|
8404
|
+
}))
|
|
8481
8405
|
}
|
|
8482
|
-
}
|
|
8483
|
-
|
|
8406
|
+
};
|
|
8407
|
+
const runtime = createSlackRuntime({
|
|
8408
|
+
getSlackAdapter: options.getSlackAdapter,
|
|
8409
|
+
services
|
|
8410
|
+
});
|
|
8411
|
+
const slackWorker = createSlackConversationWorker({
|
|
8412
|
+
getSlackAdapter: options.getSlackAdapter,
|
|
8413
|
+
conversationStore: options.conversationStore,
|
|
8414
|
+
runNextPausedTurn: async (conversationId, runOptions) => await runNextPausedTurn(
|
|
8415
|
+
conversationId,
|
|
8416
|
+
{
|
|
8417
|
+
agentRunner: options.agentRunner,
|
|
8418
|
+
scheduleSessionCompletedPluginTasks: services.replyExecutor?.scheduleSessionCompletedPluginTasks,
|
|
8419
|
+
wakePausedTurn: services.replyExecutor?.wakePausedTurn
|
|
8420
|
+
},
|
|
8421
|
+
runOptions
|
|
8422
|
+
),
|
|
8423
|
+
runtime,
|
|
8424
|
+
state: options.state
|
|
8425
|
+
});
|
|
8426
|
+
const dispatchWorker = createAgentDispatchConversationWorker({
|
|
8427
|
+
resumeTurn: async (dispatch2, hooks) => {
|
|
8428
|
+
await runNextPausedTurn(
|
|
8429
|
+
getDispatchConversationId(dispatch2),
|
|
8430
|
+
{
|
|
8431
|
+
agentRunner: options.agentRunner,
|
|
8432
|
+
inputMessageIds: getDispatchInputMessageIds(dispatch2.id),
|
|
8433
|
+
routingContext: buildDispatchRoutingContext(dispatch2),
|
|
8434
|
+
scheduleSessionCompletedPluginTasks: services.replyExecutor?.scheduleSessionCompletedPluginTasks,
|
|
8435
|
+
wakePausedTurn: services.replyExecutor?.wakePausedTurn
|
|
8436
|
+
},
|
|
8437
|
+
{ shouldYield: hooks.shouldYield }
|
|
8438
|
+
);
|
|
8439
|
+
},
|
|
8440
|
+
runTurn: runtime.runDispatchTurn
|
|
8441
|
+
});
|
|
8442
|
+
const providerWorker = createAgentDispatchWorkRouter({
|
|
8443
|
+
dispatchWorker,
|
|
8444
|
+
fallbackWorker: slackWorker
|
|
8445
|
+
});
|
|
8446
|
+
return {
|
|
8447
|
+
conversationStore: options.conversationStore,
|
|
8448
|
+
queue: options.queue,
|
|
8449
|
+
run: routeAgentInvocationWork({
|
|
8450
|
+
invocationWorker: createAgentInvocationWorker({
|
|
8451
|
+
agentRunner: options.agentRunner
|
|
8452
|
+
}),
|
|
8453
|
+
fallbackWorker: providerWorker
|
|
8454
|
+
}),
|
|
8455
|
+
runtime,
|
|
8456
|
+
state: options.state
|
|
8457
|
+
};
|
|
8484
8458
|
}
|
|
8485
8459
|
|
|
8486
8460
|
// src/chat/app/production.ts
|
|
@@ -8524,61 +8498,13 @@ function createProductionSlackWebhookServices(options) {
|
|
|
8524
8498
|
}
|
|
8525
8499
|
function createProductionConversationWorkOptions(options) {
|
|
8526
8500
|
const conversationStore = getProductionConversationStore();
|
|
8527
|
-
|
|
8528
|
-
|
|
8529
|
-
...options.services,
|
|
8530
|
-
replyExecutor: {
|
|
8531
|
-
...options.services?.replyExecutor,
|
|
8532
|
-
agentRunner
|
|
8533
|
-
}
|
|
8534
|
-
};
|
|
8535
|
-
const runtime = createSlackRuntime({
|
|
8536
|
-
getSlackAdapter: getProductionSlackAdapter,
|
|
8537
|
-
services
|
|
8538
|
-
});
|
|
8539
|
-
const queue = getVercelConversationWorkQueue();
|
|
8540
|
-
const slackWorker = createSlackConversationWorker({
|
|
8541
|
-
getSlackAdapter: getProductionSlackAdapter,
|
|
8501
|
+
return createConversationWork({
|
|
8502
|
+
agentRunner: options.agentRunner,
|
|
8542
8503
|
conversationStore,
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
agentRunner,
|
|
8547
|
-
scheduleSessionCompletedPluginTasks: services.replyExecutor?.scheduleSessionCompletedPluginTasks
|
|
8548
|
-
},
|
|
8549
|
-
runOptions
|
|
8550
|
-
),
|
|
8551
|
-
runtime
|
|
8552
|
-
});
|
|
8553
|
-
const dispatchWorker = createAgentDispatchConversationWorker({
|
|
8554
|
-
resumeTurn: async (dispatch2, hooks) => {
|
|
8555
|
-
await resumeAwaitingSlackContinuation(
|
|
8556
|
-
getDispatchConversationId(dispatch2),
|
|
8557
|
-
{
|
|
8558
|
-
agentRunner,
|
|
8559
|
-
inputMessageIds: getDispatchInputMessageIds(dispatch2.id),
|
|
8560
|
-
routingContext: buildDispatchRoutingContext(dispatch2),
|
|
8561
|
-
scheduleSessionCompletedPluginTasks: services.replyExecutor?.scheduleSessionCompletedPluginTasks
|
|
8562
|
-
},
|
|
8563
|
-
{ shouldYield: hooks.shouldYield }
|
|
8564
|
-
);
|
|
8565
|
-
},
|
|
8566
|
-
runTurn: runtime.runDispatchTurn
|
|
8567
|
-
});
|
|
8568
|
-
const providerWorker = createAgentDispatchWorkRouter({
|
|
8569
|
-
dispatchWorker,
|
|
8570
|
-
fallbackWorker: slackWorker
|
|
8504
|
+
getSlackAdapter: getProductionSlackAdapter,
|
|
8505
|
+
queue: getVercelConversationWorkQueue(),
|
|
8506
|
+
services: options.services
|
|
8571
8507
|
});
|
|
8572
|
-
return {
|
|
8573
|
-
conversationStore,
|
|
8574
|
-
queue,
|
|
8575
|
-
run: routeAgentInvocationWork({
|
|
8576
|
-
invocationWorker: createAgentInvocationWorker({
|
|
8577
|
-
agentRunner
|
|
8578
|
-
}),
|
|
8579
|
-
fallbackWorker: providerWorker
|
|
8580
|
-
})
|
|
8581
|
-
};
|
|
8582
8508
|
}
|
|
8583
8509
|
|
|
8584
8510
|
// src/chat/resource-events/ingest.ts
|