@sentry/junior 0.184.0 → 0.185.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.
Files changed (111) hide show
  1. package/dist/{agent-hooks-XTZVALGQ.js → agent-hooks-NGZQLL5O.js} +13 -11
  2. package/dist/api/acp/schema.d.ts +20 -2
  3. package/dist/api/code/overview.d.ts +39 -0
  4. package/dist/api/locations/detail.d.ts +1 -1
  5. package/dist/api/people/code.d.ts +22 -0
  6. package/dist/api/schema/code.d.ts +46 -0
  7. package/dist/api/schema/conversation.d.ts +100 -20
  8. package/dist/api/schema/location.d.ts +1 -1
  9. package/dist/api/schema/person.d.ts +1 -1
  10. package/dist/api/schema.d.ts +4 -4
  11. package/dist/api/schema.js +12 -1
  12. package/dist/api.js +358 -76
  13. package/dist/app.js +406 -377
  14. package/dist/{catalog-runtime-5357XR4F.js → catalog-runtime-AAEAO2RL.js} +4 -4
  15. package/dist/chat/api-turns/accepted-reply.d.ts +11 -0
  16. package/dist/chat/api-turns/cancellation.d.ts +3 -5
  17. package/dist/chat/api-turns/work.d.ts +4 -9
  18. package/dist/chat/app/conversation-work.d.ts +1 -1
  19. package/dist/chat/app/factory.d.ts +4 -0
  20. package/dist/chat/app/services.d.ts +4 -3
  21. package/dist/chat/conversations/history.d.ts +83 -9
  22. package/dist/chat/conversations/turn-lifecycle.d.ts +4 -3
  23. package/dist/chat/providers/slack/input.d.ts +32 -0
  24. package/dist/chat/{runtime → providers/slack}/processing-reaction.d.ts +6 -8
  25. package/dist/chat/{runtime/slack-resume.d.ts → providers/slack/resume.d.ts} +16 -19
  26. package/dist/chat/providers/slack/runtime.d.ts +1 -10
  27. package/dist/chat/providers/slack/turn.d.ts +11 -24
  28. package/dist/chat/resource-events/store.d.ts +1 -1
  29. package/dist/chat/resource-events/tool-support.d.ts +0 -5
  30. package/dist/chat/runtime/turn-execution.d.ts +7 -2
  31. package/dist/chat/sandbox/egress/credentials.d.ts +3 -3
  32. package/dist/chat/sandbox/egress/session.d.ts +5 -6
  33. package/dist/chat/scheduled-tasks/tool-support.d.ts +5 -5
  34. package/dist/chat/scheduled-tasks/tools/create.d.ts +2 -2
  35. package/dist/chat/scheduled-tasks/tools/delete.d.ts +2 -2
  36. package/dist/chat/scheduled-tasks/tools/list.d.ts +2 -2
  37. package/dist/chat/scheduled-tasks/tools/run-now.d.ts +2 -2
  38. package/dist/chat/scheduled-tasks/tools/update.d.ts +2 -2
  39. package/dist/chat/scheduled-tasks/types.d.ts +1 -1
  40. package/dist/chat/services/provider-retry.d.ts +2 -0
  41. package/dist/chat/services/turn-failure-response.d.ts +4 -0
  42. package/dist/chat/task-execution/paused-turn.d.ts +0 -2
  43. package/dist/chat/task-execution/state.d.ts +2 -2
  44. package/dist/chat/task-execution/store.d.ts +1 -1
  45. package/dist/chat/task-execution/turn-wake.d.ts +12 -0
  46. package/dist/chat/tool-support/action-review.d.ts +1 -1
  47. package/dist/chat/tools/resource-events.d.ts +1 -1
  48. package/dist/chat/tools/search-conversation-events.d.ts +1 -1
  49. package/dist/chat/tools/types.d.ts +1 -1
  50. package/dist/chat/tools/watch-resource-events.d.ts +2 -2
  51. package/dist/{chunk-FKEZZMXS.js → chunk-4HA36IWS.js} +9 -94
  52. package/dist/{chunk-WVIA7V3M.js → chunk-4K25ODAO.js} +27 -1
  53. package/dist/{chunk-UF6BUA5W.js → chunk-4S47VHJR.js} +3 -3
  54. package/dist/{chunk-JNO2GUDS.js → chunk-6DOAUXLD.js} +231 -198
  55. package/dist/{chunk-M3QYTBQ6.js → chunk-6Q7YZLCL.js} +2 -1
  56. package/dist/{chunk-6VOYP4M6.js → chunk-7GAP2XG4.js} +1 -1
  57. package/dist/{chunk-LHXIZLFF.js → chunk-7MHNIGHP.js} +1 -1
  58. package/dist/{chunk-IZDYYYGP.js → chunk-ABAX75GG.js} +10 -384
  59. package/dist/{chunk-WQFEWULF.js → chunk-ATUWN6Z3.js} +2 -2
  60. package/dist/{chunk-4RONS3WR.js → chunk-C6TS47CQ.js} +4 -4
  61. package/dist/chunk-D4YV5TDV.js +45 -0
  62. package/dist/{chunk-Z3QAXJR7.js → chunk-D63IUQQE.js} +4 -4
  63. package/dist/{chunk-M5YWNMTE.js → chunk-DAPC2HTM.js} +24 -6
  64. package/dist/{chunk-BHYRYYLY.js → chunk-EIJCPJOY.js} +1 -1
  65. package/dist/{chunk-SHJK75Z2.js → chunk-EJYP3NQ4.js} +4 -4
  66. package/dist/{chunk-K7VDC2QW.js → chunk-EWEH2PJW.js} +6 -6
  67. package/dist/{chunk-6WGC3SO4.js → chunk-FFHXG2FX.js} +13 -11
  68. package/dist/{chunk-MLSQX2EX.js → chunk-FTVMXDNN.js} +1 -1
  69. package/dist/chunk-GFBR4S3Q.js +406 -0
  70. package/dist/{chunk-PJPRXO2T.js → chunk-GJTIZQGJ.js} +1 -1
  71. package/dist/{chunk-BT53RIGJ.js → chunk-HJPC32TQ.js} +12 -50
  72. package/dist/{chunk-RF6J3DIO.js → chunk-INQHUE72.js} +84 -1
  73. package/dist/{chunk-6UDPINOX.js → chunk-LRI5IRGY.js} +19 -44
  74. package/dist/{chunk-BCHYQS4B.js → chunk-LVK4WJKM.js} +1 -1
  75. package/dist/{chunk-UBOIHNTH.js → chunk-MWOH6CIK.js} +178 -148
  76. package/dist/{chunk-3S7ULUWW.js → chunk-OMQ2J6F6.js} +1 -1
  77. package/dist/{chunk-DUKIDPF6.js → chunk-PNYJOEVV.js} +1 -1
  78. package/dist/{chunk-MAPJFUMV.js → chunk-QCT4226Q.js} +3 -3
  79. package/dist/{chunk-HIPUIPJM.js → chunk-QZKHHG3B.js} +34 -8
  80. package/dist/{chunk-QABCY33S.js → chunk-TVVAMOLS.js} +2 -2
  81. package/dist/{chunk-JA43DV4Y.js → chunk-U4CTAVWN.js} +1 -1
  82. package/dist/{chunk-LCP4EDKR.js → chunk-UUULGCKK.js} +1 -1
  83. package/dist/{chunk-4CNDGK25.js → chunk-VH4IU3UC.js} +928 -984
  84. package/dist/chunk-W7GCLNIV.js +58 -0
  85. package/dist/{chunk-2ZQPVX7C.js → chunk-WLKWN4CD.js} +22 -12
  86. package/dist/{chunk-ACPDVEJO.js → chunk-X2SS6BF7.js} +198 -209
  87. package/dist/{chunk-YKX6MTLU.js → chunk-X7NCJQAA.js} +1 -1
  88. package/dist/{chunk-E57WPXWY.js → chunk-Y5G23T2D.js} +5 -5
  89. package/dist/{chunk-HUXFMDBZ.js → chunk-ZIF2S464.js} +1 -1
  90. package/dist/{chunk-JM2COLGC.js → chunk-ZKKGFUWM.js} +6 -6
  91. package/dist/cli/chat.js +35 -33
  92. package/dist/cli/check.js +5 -5
  93. package/dist/cli/plugins.js +14 -12
  94. package/dist/cli/snapshot-create.js +10 -9
  95. package/dist/cli/upgrade.js +7 -6
  96. package/dist/{db-MA52H62H.js → db-TRJ77FAU.js} +8 -6
  97. package/dist/instrumentation.js +3 -3
  98. package/dist/nitro.js +7 -6
  99. package/dist/{oauth-callback-server-DXGHKN6S.js → oauth-callback-server-XD5SV3MS.js} +30 -27
  100. package/dist/{runner-4IXUAQNK.js → runner-KFX7NG6D.js} +24 -19
  101. package/dist/{skills-X3DY7AXO.js → skills-J2AH26CW.js} +5 -5
  102. package/dist/spawn-VU3CSRI6.js +41 -0
  103. package/dist/task-runner-5JG3VIIY.js +34 -0
  104. package/dist/{validation-Z6JXSTJS.js → validation-O5J4VOPF.js} +5 -5
  105. package/dist/version.js +1 -1
  106. package/dist/{work-OKWRFBDW.js → work-ECPQTG3U.js} +24 -19
  107. package/dist/worker-RS3DXUDO.js +24 -0
  108. package/package.json +4 -4
  109. package/dist/spawn-43WGS6CH.js +0 -37
  110. package/dist/task-runner-VDRKITPV.js +0 -32
  111. package/dist/worker-B236AE72.js +0 -22
package/dist/app.js CHANGED
@@ -1,20 +1,21 @@
1
1
  import {
2
2
  processConversationWork
3
- } from "./chunk-4RONS3WR.js";
3
+ } from "./chunk-C6TS47CQ.js";
4
4
  import {
5
5
  bindSpawnAgent
6
- } from "./chunk-QABCY33S.js";
6
+ } from "./chunk-TVVAMOLS.js";
7
7
  import {
8
8
  createAgentInvocationWorker,
9
9
  enqueueAgentInvocation,
10
10
  listPendingAgentInvocationMailboxAppends,
11
11
  routeAgentInvocationWork
12
- } from "./chunk-BT53RIGJ.js";
12
+ } from "./chunk-HJPC32TQ.js";
13
13
  import {
14
14
  GET as GET2,
15
15
  GET2 as GET3,
16
16
  buildAuthPauseResponse,
17
17
  buildSlackOutputMessage,
18
+ createPausedTurns,
18
19
  createSlackAdapterAssistantStatusSession,
19
20
  getAssistantThreadContext,
20
21
  getChannelId,
@@ -33,10 +34,10 @@ import {
33
34
  sendSlackReply,
34
35
  shouldKeepProcessingReactionForToolInvocation,
35
36
  splitSlackReplyText,
36
- startSlackProcessingReaction,
37
+ startProcessingReaction,
37
38
  stripLeadingBotMention,
38
39
  wakePausedTurn
39
- } from "./chunk-ACPDVEJO.js";
40
+ } from "./chunk-X2SS6BF7.js";
40
41
  import "./chunk-FA6POGLH.js";
41
42
  import {
42
43
  GET,
@@ -53,8 +54,12 @@ import {
53
54
  resolveSlackConversationContext,
54
55
  routeApiTurnWork,
55
56
  webActorFromEmail
56
- } from "./chunk-UBOIHNTH.js";
57
- import "./chunk-LCP4EDKR.js";
57
+ } from "./chunk-MWOH6CIK.js";
58
+ import "./chunk-UUULGCKK.js";
59
+ import {
60
+ AgentRunError,
61
+ executeTurn
62
+ } from "./chunk-W7GCLNIV.js";
58
63
  import {
59
64
  buildDeliveredTurnStatePatch,
60
65
  completeAuthPauseTurn,
@@ -65,7 +70,7 @@ import {
65
70
  getTurnUserSlackMessageTs,
66
71
  persistAuthPauseTurnState,
67
72
  requireTurnFailureEventId
68
- } from "./chunk-M5YWNMTE.js";
73
+ } from "./chunk-DAPC2HTM.js";
69
74
  import {
70
75
  claimDispatchMailboxAppend,
71
76
  confirmDispatchMailboxAppend,
@@ -85,10 +90,10 @@ import {
85
90
  recordTaskExecution,
86
91
  resolveTurnSessionRouting,
87
92
  scheduleSessionCompletedPluginTasks
88
- } from "./chunk-6WGC3SO4.js";
93
+ } from "./chunk-FFHXG2FX.js";
89
94
  import {
90
95
  ConversationTurnLifecycleService
91
- } from "./chunk-M3QYTBQ6.js";
96
+ } from "./chunk-6Q7YZLCL.js";
92
97
  import {
93
98
  coerceThreadConversationState,
94
99
  getLocationConfigurationService,
@@ -97,17 +102,17 @@ import {
97
102
  persistThreadRuntimeState,
98
103
  persistThreadState,
99
104
  persistThreadStateById
100
- } from "./chunk-E57WPXWY.js";
105
+ } from "./chunk-Y5G23T2D.js";
101
106
  import "./chunk-UTL3MHPC.js";
102
107
  import {
103
108
  createVercelPluginTaskCallback,
104
109
  queueCallback,
105
110
  registerVercelPluginTaskDevConsumer
106
- } from "./chunk-UF6BUA5W.js";
111
+ } from "./chunk-4S47VHJR.js";
107
112
  import {
108
113
  validatePluginEgressCredentialHooks,
109
114
  validatePluginRegistrations
110
- } from "./chunk-HUXFMDBZ.js";
115
+ } from "./chunk-ZIF2S464.js";
111
116
  import {
112
117
  defineJuniorPlugins,
113
118
  pluginCatalogConfigFromEnv,
@@ -155,36 +160,28 @@ import {
155
160
  unpublishedArtifactHeaders,
156
161
  verifySlackSignature,
157
162
  withNormalizedThreadId
158
- } from "./chunk-JNO2GUDS.js";
163
+ } from "./chunk-6DOAUXLD.js";
159
164
  import {
160
165
  AuthorizationFlowDisabledError,
161
166
  PluginCredentialFailureError
162
- } from "./chunk-K7VDC2QW.js";
167
+ } from "./chunk-EWEH2PJW.js";
163
168
  import "./chunk-6Y5B5PEX.js";
164
169
  import "./chunk-DIB4GX3G.js";
165
170
  import {
166
- createAgentRunner,
167
171
  createUserTokenStore,
168
172
  deleteMcpAuthSessionsForUserProvider,
169
173
  deleteMcpServerSessionId,
170
174
  deleteMcpStoredOAuthCredentials
171
- } from "./chunk-FKEZZMXS.js";
172
- import {
173
- RetryableDeliveryError
174
- } from "./chunk-RF6J3DIO.js";
175
+ } from "./chunk-4HA36IWS.js";
175
176
  import {
176
177
  formatProviderLabel,
177
178
  postSlackMessage,
178
179
  startOAuthFlow
179
- } from "./chunk-JM2COLGC.js";
180
- import {
181
- getExperimentalFeatures,
182
- isExperimentalFeatureEnabled,
183
- setExperimentalFeatures
184
- } from "./chunk-2LYHWMR4.js";
180
+ } from "./chunk-ZKKGFUWM.js";
185
181
  import {
186
182
  collectAttachmentGarbage,
187
183
  collectEventTaskMatchKeys,
184
+ createResourceEventTeamIdResolver,
188
185
  findMatchingEventTasks,
189
186
  getResourceEventCatalog,
190
187
  listScheduledTasks,
@@ -197,10 +194,14 @@ import {
197
194
  scheduledRunId,
198
195
  scheduledRunSchema,
199
196
  withScheduledTaskLock
200
- } from "./chunk-HIPUIPJM.js";
197
+ } from "./chunk-QZKHHG3B.js";
201
198
  import {
202
199
  parseSlackThreadId
203
- } from "./chunk-YKX6MTLU.js";
200
+ } from "./chunk-X7NCJQAA.js";
201
+ import {
202
+ RetryableDeliveryError,
203
+ createAgentRunner
204
+ } from "./chunk-INQHUE72.js";
204
205
  import {
205
206
  CONVERSATION_WORK_STALE_ENQUEUE_MS,
206
207
  appendAndEnqueueInboundMessage,
@@ -215,7 +216,7 @@ import {
215
216
  removeActiveConversation,
216
217
  requestConversationWork,
217
218
  stopConversationWork
218
- } from "./chunk-Z3QAXJR7.js";
219
+ } from "./chunk-D63IUQQE.js";
219
220
  import {
220
221
  ConversationTurnBoundaryError,
221
222
  CooperativeTurnYieldError,
@@ -233,7 +234,7 @@ import {
233
234
  markTurnCompleted,
234
235
  markTurnFailed,
235
236
  startActiveTurn
236
- } from "./chunk-JA43DV4Y.js";
237
+ } from "./chunk-U4CTAVWN.js";
237
238
  import {
238
239
  abandonTurnRecord,
239
240
  appendThreadContextMessages,
@@ -269,11 +270,16 @@ import {
269
270
  trimTrailingAssistantMessages,
270
271
  turnHasReply,
271
272
  upsertConversationMessage
272
- } from "./chunk-2ZQPVX7C.js";
273
+ } from "./chunk-WLKWN4CD.js";
274
+ import {
275
+ getExperimentalFeatures,
276
+ isExperimentalFeatureEnabled,
277
+ setExperimentalFeatures
278
+ } from "./chunk-2LYHWMR4.js";
273
279
  import {
274
280
  getSandboxResourceConfig,
275
281
  setSandboxResourceConfig
276
- } from "./chunk-MAPJFUMV.js";
282
+ } from "./chunk-QCT4226Q.js";
277
283
  import "./chunk-PDO5BLNM.js";
278
284
  import "./chunk-UIE3R5XU.js";
279
285
  import {
@@ -292,7 +298,7 @@ import {
292
298
  import "./chunk-7H2VZTWN.js";
293
299
  import {
294
300
  getTurnRequestDeadline
295
- } from "./chunk-MLSQX2EX.js";
301
+ } from "./chunk-FTVMXDNN.js";
296
302
  import {
297
303
  SlackActionError,
298
304
  bindEventTaskCredentialSubject,
@@ -302,7 +308,6 @@ import {
302
308
  collectResourceEventMatchKeys,
303
309
  createPluginLogger,
304
310
  createPluginState,
305
- createResourceEventTeamIdResolver,
306
311
  downloadPrivateSlackFile,
307
312
  getPluginApiRoutes,
308
313
  getPluginRoutes,
@@ -318,20 +323,18 @@ import {
318
323
  verifyEventTaskCredentialSubject,
319
324
  verifyScheduledTaskCredentialSubject,
320
325
  verifySlackDirectCredentialSubject
321
- } from "./chunk-4CNDGK25.js";
326
+ } from "./chunk-VH4IU3UC.js";
322
327
  import "./chunk-3Y47VMHV.js";
323
328
  import {
324
- contextProvenance,
325
329
  deleteProviderIdentityForSlackUser,
326
330
  getConversationEventStore,
327
331
  getConversationStore,
328
332
  getDb,
329
333
  getSqlExecutor,
330
- instructionProvenanceFor,
331
334
  requireSlackDestination,
332
335
  withConversationEventLock,
333
336
  withConversationMutationLock
334
- } from "./chunk-IZDYYYGP.js";
337
+ } from "./chunk-ABAX75GG.js";
335
338
  import {
336
339
  juniorAgentBindings,
337
340
  juniorAgentInvocations,
@@ -339,13 +342,17 @@ import {
339
342
  juniorConversations,
340
343
  juniorSchedulerRuns,
341
344
  juniorSchedulerTasks
342
- } from "./chunk-BCHYQS4B.js";
343
- import "./chunk-SHJK75Z2.js";
345
+ } from "./chunk-LVK4WJKM.js";
346
+ import "./chunk-EJYP3NQ4.js";
344
347
  import {
345
348
  acquireActiveLock,
346
349
  getStateAdapter,
347
350
  withActiveLock
348
- } from "./chunk-DUKIDPF6.js";
351
+ } from "./chunk-PNYJOEVV.js";
352
+ import {
353
+ contextProvenance,
354
+ instructionProvenanceFor
355
+ } from "./chunk-GFBR4S3Q.js";
349
356
  import {
350
357
  juniorDestinations
351
358
  } from "./chunk-VFUK3X5B.js";
@@ -354,7 +361,6 @@ import {
354
361
  completeObject,
355
362
  completeText,
356
363
  configureFunctionMaxDurationSeconds,
357
- defaultModelId,
358
364
  escapeXml,
359
365
  getChatConfig,
360
366
  getSlackBotToken,
@@ -363,16 +369,19 @@ import {
363
369
  getSlackReactionConfig,
364
370
  getSlackSigningSecret,
365
371
  isProviderRetryError,
366
- modelIdForProfile,
367
372
  setProfiles,
368
373
  setSlackReactionConfig
369
- } from "./chunk-6UDPINOX.js";
370
- import "./chunk-BHYRYYLY.js";
371
- import "./chunk-WQFEWULF.js";
374
+ } from "./chunk-LRI5IRGY.js";
375
+ import {
376
+ defaultModelId,
377
+ modelIdForProfile
378
+ } from "./chunk-D4YV5TDV.js";
379
+ import "./chunk-EIJCPJOY.js";
380
+ import "./chunk-ATUWN6Z3.js";
372
381
  import {
373
382
  pluginCatalogRuntime
374
- } from "./chunk-PJPRXO2T.js";
375
- import "./chunk-LHXIZLFF.js";
383
+ } from "./chunk-GJTIZQGJ.js";
384
+ import "./chunk-7MHNIGHP.js";
376
385
  import {
377
386
  credentialContextForActor
378
387
  } from "./chunk-CEMMLV5L.js";
@@ -407,13 +416,13 @@ import {
407
416
  withContext,
408
417
  withLogContext,
409
418
  withSpan
410
- } from "./chunk-3S7ULUWW.js";
419
+ } from "./chunk-OMQ2J6F6.js";
411
420
  import {
412
421
  continueTrace
413
422
  } from "./chunk-PEQXYSSE.js";
414
423
  import {
415
424
  JUNIOR_VERSION
416
- } from "./chunk-6VOYP4M6.js";
425
+ } from "./chunk-7GAP2XG4.js";
417
426
 
418
427
  // src/app.ts
419
428
  import { createRequire } from "module";
@@ -4218,9 +4227,10 @@ function shouldRethrowTurnControlError(error) {
4218
4227
  function getQueuedMessages(context, options) {
4219
4228
  return (context?.skipped ?? []).map((message) => {
4220
4229
  const content = parseContent(message);
4221
- const stripped = options.stripLeadingBotMention(
4230
+ const stripped = stripLeadingBotMention(
4222
4231
  stripLeadingSteeringOverride(content.topLevelText),
4223
4232
  {
4233
+ botUserId: options.botUserId,
4224
4234
  stripLeadingSlackMentionToken: options.explicitMention || Boolean(message.isMention)
4225
4235
  }
4226
4236
  );
@@ -4295,7 +4305,7 @@ function createSlackTurnRuntime(deps) {
4295
4305
  return true;
4296
4306
  };
4297
4307
  const failConversationTurn = async (args) => {
4298
- const conversationId = deps.getThreadId(args.thread, args.message) ?? deps.getRunId(args.thread, args.message);
4308
+ const conversationId = getThreadId(args.thread, args.message) ?? getRunId(args.thread, args.message);
4299
4309
  if (!conversationId) {
4300
4310
  return;
4301
4311
  }
@@ -4328,7 +4338,7 @@ function createSlackTurnRuntime(deps) {
4328
4338
  const processingReactionByMessage = /* @__PURE__ */ new Map();
4329
4339
  return {
4330
4340
  start: async (context, targetMessage) => {
4331
- const channelId = deps.getChannelId(thread, targetMessage);
4341
+ const channelId = getChannelId(thread, targetMessage);
4332
4342
  const messageTs = getMessageTs(targetMessage);
4333
4343
  const reactionKey = channelId && messageTs ? `${channelId}:${messageTs}` : void 0;
4334
4344
  if (reactionKey) {
@@ -4337,10 +4347,9 @@ function createSlackTurnRuntime(deps) {
4337
4347
  return existing;
4338
4348
  }
4339
4349
  }
4340
- const started = await startSlackProcessingReaction({
4350
+ const started = await startProcessingReaction({
4341
4351
  thread,
4342
- message: targetMessage,
4343
- logException: deps.logException
4352
+ message: targetMessage
4344
4353
  });
4345
4354
  processingReactions.push(started);
4346
4355
  if (reactionKey) {
@@ -4356,7 +4365,7 @@ function createSlackTurnRuntime(deps) {
4356
4365
  try {
4357
4366
  await args.thread.post(buildTurnFailureResponse(args.eventId));
4358
4367
  } catch (postError) {
4359
- deps.logException(postError, args.postFailureEventName, {
4368
+ logException(postError, args.postFailureEventName, {
4360
4369
  "app.slack.reply_stage": "error_fallback_post",
4361
4370
  "app.error.original_event_id": args.eventId,
4362
4371
  ...getSlackErrorObservabilityAttributes(postError)
@@ -4367,15 +4376,16 @@ function createSlackTurnRuntime(deps) {
4367
4376
  const decideSteeringMessage = async (thread, candidate, conversationContext) => {
4368
4377
  const { message } = candidate;
4369
4378
  const context = {
4370
- threadId: deps.getThreadId(thread, message),
4379
+ threadId: getThreadId(thread, message),
4371
4380
  actorId: message.author.userId,
4372
- channelId: deps.getChannelId(thread, message),
4373
- runId: deps.getRunId(thread, message)
4381
+ channelId: getChannelId(thread, message),
4382
+ runId: getRunId(thread, message)
4374
4383
  };
4375
4384
  const content = parseContent(message);
4376
- const strippedUserText = deps.stripLeadingBotMention(
4385
+ const strippedUserText = stripLeadingBotMention(
4377
4386
  stripLeadingSteeringOverride(content.topLevelText),
4378
4387
  {
4388
+ botUserId: deps.getBotUserId(),
4379
4389
  stripLeadingSlackMentionToken: Boolean(message.isMention)
4380
4390
  }
4381
4391
  );
@@ -4407,7 +4417,7 @@ function createSlackTurnRuntime(deps) {
4407
4417
  runId: args.context.runId
4408
4418
  }),
4409
4419
  () => {
4410
- deps.logWarn("subscribed_message.reply.skipped", {
4420
+ logWarn("subscribed_message.reply.skipped", {
4411
4421
  "app.decision.reason": args.decision.reason
4412
4422
  });
4413
4423
  }
@@ -4503,7 +4513,7 @@ function createSlackTurnRuntime(deps) {
4503
4513
  }
4504
4514
  } catch (error) {
4505
4515
  withLogContext(args.context, () => {
4506
- deps.logException(error, "agent.turn.steering_flush.failed");
4516
+ logException(error, "agent.turn.steering_flush.failed");
4507
4517
  });
4508
4518
  }
4509
4519
  };
@@ -4520,18 +4530,18 @@ function createSlackTurnRuntime(deps) {
4520
4530
  thread,
4521
4531
  pending: skippedSteeringMessages,
4522
4532
  context: logContext({
4523
- threadId: deps.getThreadId(thread, message),
4533
+ threadId: getThreadId(thread, message),
4524
4534
  actorId: message.author.userId,
4525
4535
  actorUserName: actorUserName(message),
4526
- channelId: deps.getChannelId(thread, message),
4527
- runId: deps.getRunId(thread, message)
4536
+ channelId: getChannelId(thread, message),
4537
+ runId: getRunId(thread, message)
4528
4538
  })
4529
4539
  });
4530
4540
  };
4531
4541
  try {
4532
- const threadId = deps.getThreadId(thread, message);
4533
- const channelId = deps.getChannelId(thread, message);
4534
- const runId = deps.getRunId(thread, message);
4542
+ const threadId = getThreadId(thread, message);
4543
+ const channelId = getChannelId(thread, message);
4544
+ const runId = getRunId(thread, message);
4535
4545
  const context = logContext({
4536
4546
  threadId,
4537
4547
  channelId,
@@ -4544,11 +4554,11 @@ function createSlackTurnRuntime(deps) {
4544
4554
  processingReaction,
4545
4555
  hooks
4546
4556
  );
4547
- await deps.withSpan("chat.turn", "chat.turn", context, async () => {
4557
+ await withSpan("chat.turn", "chat.turn", context, async () => {
4548
4558
  await thread.subscribe();
4549
4559
  const queuedMessages = getQueuedMessages(hooks.messageContext, {
4550
- explicitMention: true,
4551
- stripLeadingBotMention: deps.stripLeadingBotMention
4560
+ botUserId: deps.getBotUserId(),
4561
+ explicitMention: true
4552
4562
  });
4553
4563
  let queuedProcessingReactionsStarted = false;
4554
4564
  const startQueuedProcessingReactions = async () => {
@@ -4568,6 +4578,7 @@ function createSlackTurnRuntime(deps) {
4568
4578
  await startQueuedProcessingReactions();
4569
4579
  };
4570
4580
  const drainSteeringMessages = createAcceptedSteeringDrain(hooks, {
4581
+ botUserId: deps.getBotUserId(),
4571
4582
  explicitMention: true,
4572
4583
  onAcceptedForProcessing: async (messages) => {
4573
4584
  await Promise.all(
@@ -4586,8 +4597,7 @@ function createSlackTurnRuntime(deps) {
4586
4597
  conversationContext: drainContext?.conversationContext,
4587
4598
  messages,
4588
4599
  thread
4589
- }),
4590
- stripLeadingBotMention: deps.stripLeadingBotMention
4600
+ })
4591
4601
  });
4592
4602
  await deps.executeSlackTurn(thread, message, {
4593
4603
  explicitMention: true,
@@ -4606,11 +4616,11 @@ function createSlackTurnRuntime(deps) {
4606
4616
  });
4607
4617
  } catch (error) {
4608
4618
  const failureLogContext = logContext({
4609
- threadId: deps.getThreadId(thread, message),
4619
+ threadId: getThreadId(thread, message),
4610
4620
  actorId: message.author.userId,
4611
4621
  actorUserName: actorUserName(message),
4612
- channelId: deps.getChannelId(thread, message),
4613
- runId: deps.getRunId(thread, message)
4622
+ channelId: getChannelId(thread, message),
4623
+ runId: getRunId(thread, message)
4614
4624
  });
4615
4625
  const classifiedFailure = getConversationTurnBoundaryError(error);
4616
4626
  const failureCause = classifiedFailure?.cause ?? error;
@@ -4623,7 +4633,7 @@ function createSlackTurnRuntime(deps) {
4623
4633
  const failureCode = classifiedFailure?.failureCode ?? "agent_run_failed";
4624
4634
  if (failureCause instanceof SlackActionError && failureCause.code === "read_only_channel") {
4625
4635
  withLogContext(failureLogContext, () => {
4626
- deps.logWarn("mention.handler.skipped", {
4636
+ logWarn("mention.handler.skipped", {
4627
4637
  "app.decision.reason": "read_only_channel"
4628
4638
  });
4629
4639
  });
@@ -4631,7 +4641,7 @@ function createSlackTurnRuntime(deps) {
4631
4641
  }
4632
4642
  const eventId = classifiedFailure?.eventId ?? withLogContext(
4633
4643
  failureLogContext,
4634
- () => deps.logException(failureCause, "mention.handler.failed")
4644
+ () => logException(failureCause, "mention.handler.failed")
4635
4645
  );
4636
4646
  if (!acked && hooks.isFinalAttempt === false) {
4637
4647
  return;
@@ -4669,11 +4679,11 @@ function createSlackTurnRuntime(deps) {
4669
4679
  thread,
4670
4680
  pending: skippedSteeringMessages,
4671
4681
  context: logContext({
4672
- threadId: deps.getThreadId(thread, message),
4682
+ threadId: getThreadId(thread, message),
4673
4683
  actorId: message.author.userId,
4674
4684
  actorUserName: actorUserName(message),
4675
- channelId: deps.getChannelId(thread, message),
4676
- runId: deps.getRunId(thread, message)
4685
+ channelId: getChannelId(thread, message),
4686
+ runId: getRunId(thread, message)
4677
4687
  })
4678
4688
  });
4679
4689
  await processingReactions.stopAll();
@@ -4692,18 +4702,18 @@ function createSlackTurnRuntime(deps) {
4692
4702
  thread,
4693
4703
  pending: skippedSteeringMessages,
4694
4704
  context: logContext({
4695
- threadId: deps.getThreadId(thread, message),
4705
+ threadId: getThreadId(thread, message),
4696
4706
  actorId: message.author.userId,
4697
4707
  actorUserName: actorUserName(message),
4698
- channelId: deps.getChannelId(thread, message),
4699
- runId: deps.getRunId(thread, message)
4708
+ channelId: getChannelId(thread, message),
4709
+ runId: getRunId(thread, message)
4700
4710
  })
4701
4711
  });
4702
4712
  };
4703
4713
  try {
4704
- const threadId = deps.getThreadId(thread, message);
4705
- const channelId = deps.getChannelId(thread, message);
4706
- const runId = deps.getRunId(thread, message);
4714
+ const threadId = getThreadId(thread, message);
4715
+ const channelId = getChannelId(thread, message);
4716
+ const runId = getRunId(thread, message);
4707
4717
  const isResourceEventNotification = isResourceEventSlackMessage(message);
4708
4718
  const actorId = isResourceEventNotification ? void 0 : message.author.userId;
4709
4719
  const turnContext = logContext({
@@ -4713,11 +4723,12 @@ function createSlackTurnRuntime(deps) {
4713
4723
  channelId,
4714
4724
  runId
4715
4725
  });
4716
- await deps.withSpan("chat.turn", "chat.turn", turnContext, async () => {
4726
+ await withSpan("chat.turn", "chat.turn", turnContext, async () => {
4717
4727
  const content = parseContent(message);
4718
- const strippedUserText = deps.stripLeadingBotMention(
4728
+ const strippedUserText = stripLeadingBotMention(
4719
4729
  stripLeadingSteeringOverride(content.topLevelText),
4720
4730
  {
4731
+ botUserId: deps.getBotUserId(),
4721
4732
  stripLeadingSlackMentionToken: Boolean(message.isMention)
4722
4733
  }
4723
4734
  );
@@ -4732,8 +4743,8 @@ function createSlackTurnRuntime(deps) {
4732
4743
  runId
4733
4744
  };
4734
4745
  const queuedMessages = getQueuedMessages(hooks.messageContext, {
4735
- explicitMention: Boolean(message.isMention),
4736
- stripLeadingBotMention: deps.stripLeadingBotMention
4746
+ botUserId: deps.getBotUserId(),
4747
+ explicitMention: Boolean(message.isMention)
4737
4748
  });
4738
4749
  const combinedText = combineTurnText(queuedMessages, currentText);
4739
4750
  const turnIsExplicitMention = Boolean(message.isMention) || queuedMessages.some((queued) => queued.explicitMention);
@@ -4833,6 +4844,7 @@ function createSlackTurnRuntime(deps) {
4833
4844
  }
4834
4845
  const conversationContext = deps.getPreparedConversationContext(preparedState);
4835
4846
  const drainSteeringMessages = createAcceptedSteeringDrain(hooks, {
4847
+ botUserId: deps.getBotUserId(),
4836
4848
  explicitMention: Boolean(message.isMention),
4837
4849
  onAcceptedForProcessing: async (messages) => {
4838
4850
  await Promise.all(
@@ -4851,8 +4863,7 @@ function createSlackTurnRuntime(deps) {
4851
4863
  conversationContext: drainContext?.conversationContext ?? conversationContext,
4852
4864
  messages,
4853
4865
  thread
4854
- }),
4855
- stripLeadingBotMention: deps.stripLeadingBotMention
4866
+ })
4856
4867
  });
4857
4868
  processingReaction = await processingReactions.start(
4858
4869
  turnContext,
@@ -4897,11 +4908,11 @@ function createSlackTurnRuntime(deps) {
4897
4908
  });
4898
4909
  } catch (error) {
4899
4910
  const failureLogContext = logContext({
4900
- threadId: deps.getThreadId(thread, message),
4911
+ threadId: getThreadId(thread, message),
4901
4912
  actorId: message.author.userId,
4902
4913
  actorUserName: actorUserName(message),
4903
- channelId: deps.getChannelId(thread, message),
4904
- runId: deps.getRunId(thread, message)
4914
+ channelId: getChannelId(thread, message),
4915
+ runId: getRunId(thread, message)
4905
4916
  });
4906
4917
  const classifiedFailure = getConversationTurnBoundaryError(error);
4907
4918
  const failureCause = classifiedFailure?.cause ?? error;
@@ -4914,7 +4925,7 @@ function createSlackTurnRuntime(deps) {
4914
4925
  const failureCode = classifiedFailure?.failureCode ?? "agent_run_failed";
4915
4926
  if (failureCause instanceof SlackActionError && failureCause.code === "read_only_channel") {
4916
4927
  withLogContext(failureLogContext, () => {
4917
- deps.logWarn("subscribed_message.handler.skipped", {
4928
+ logWarn("subscribed_message.handler.skipped", {
4918
4929
  "app.decision.reason": "read_only_channel"
4919
4930
  });
4920
4931
  });
@@ -4922,10 +4933,7 @@ function createSlackTurnRuntime(deps) {
4922
4933
  }
4923
4934
  const eventId = classifiedFailure?.eventId ?? withLogContext(
4924
4935
  failureLogContext,
4925
- () => deps.logException(
4926
- failureCause,
4927
- "subscribed_message.handler.failed"
4928
- )
4936
+ () => logException(failureCause, "subscribed_message.handler.failed")
4929
4937
  );
4930
4938
  if (!acked && hooks.isFinalAttempt === false) {
4931
4939
  return;
@@ -4963,11 +4971,11 @@ function createSlackTurnRuntime(deps) {
4963
4971
  thread,
4964
4972
  pending: skippedSteeringMessages,
4965
4973
  context: logContext({
4966
- threadId: deps.getThreadId(thread, message),
4974
+ threadId: getThreadId(thread, message),
4967
4975
  actorId: message.author.userId,
4968
4976
  actorUserName: actorUserName(message),
4969
- channelId: deps.getChannelId(thread, message),
4970
- runId: deps.getRunId(thread, message)
4977
+ channelId: getChannelId(thread, message),
4978
+ runId: getRunId(thread, message)
4971
4979
  })
4972
4980
  });
4973
4981
  await processingReactions.stopAll();
@@ -4990,7 +4998,7 @@ function createSlackTurnRuntime(deps) {
4990
4998
  sourceChannelId: event.context?.channelId
4991
4999
  });
4992
5000
  } catch (error) {
4993
- deps.logException(error, "assistant.thread.initialization.failed");
5001
+ logException(error, "assistant.thread.initialization.failed");
4994
5002
  }
4995
5003
  }
4996
5004
  );
@@ -5011,7 +5019,7 @@ function createSlackTurnRuntime(deps) {
5011
5019
  sourceChannelId: event.context?.channelId
5012
5020
  });
5013
5021
  } catch (error) {
5014
- deps.logException(error, "assistant.context.refresh.failed");
5022
+ logException(error, "assistant.context.refresh.failed");
5015
5023
  }
5016
5024
  }
5017
5025
  );
@@ -5493,24 +5501,14 @@ function createJuniorRuntimeServices(overrides = {}) {
5493
5501
  listThreadReplies: overrides.visionContext?.listThreadReplies ?? listThreadReplies,
5494
5502
  downloadFile: overrides.visionContext?.downloadFile ?? downloadPrivateSlackFile
5495
5503
  });
5496
- const agentRunner = overrides.replyExecutor?.agentRunner ?? createAgentRunner(executeAgentRun, {
5504
+ const agentRunner = overrides.agentRunner ?? createAgentRunner(executeAgentRun, {
5497
5505
  bindSpawnAgent: (request) => bindSpawnAgent(request, { queue: getVercelConversationWorkQueue }),
5498
5506
  tracePropagation: overrides.sandbox?.tracePropagation
5499
5507
  });
5500
5508
  return {
5501
5509
  conversationMemory,
5502
5510
  contextCompactor,
5503
- replyExecutor: {
5504
- contextCompactor: overrides.replyExecutor?.contextCompactor ?? contextCompactor,
5505
- agentRunner,
5506
- getPausedTurnRequest: overrides.replyExecutor?.getPausedTurnRequest ?? getPausedTurnRequest,
5507
- lookupSlackUser: overrides.replyExecutor?.lookupSlackUser ?? lookupSlackUser,
5508
- wakePausedTurn: overrides.replyExecutor?.wakePausedTurn ?? wakePausedTurn,
5509
- scheduleSessionCompletedPluginTasks: overrides.replyExecutor?.scheduleSessionCompletedPluginTasks ?? (async (params) => {
5510
- await scheduleSessionCompletedPluginTasks(params);
5511
- }),
5512
- turnLifecycle: overrides.replyExecutor?.turnLifecycle ?? new ConversationTurnLifecycleService(getConversationEventStore())
5513
- },
5511
+ executeTurn: async (run, saveResult, timeoutMs) => await executeTurn(agentRunner, run, saveResult, timeoutMs),
5514
5512
  subscribedReplyPolicy: createSubscribedReplyPolicy({
5515
5513
  completeObject: overrides.subscribedReplyPolicy?.completeObject ?? completeObject
5516
5514
  }),
@@ -5616,11 +5614,8 @@ async function maybeApplyProviderDefaultConfigRequest(args) {
5616
5614
  };
5617
5615
  }
5618
5616
 
5619
- // src/chat/providers/slack/turn.ts
5620
- async function persistThreadRuntimeStateWithRetry(thread, patch) {
5621
- await persistWithRetry(() => persistThreadRuntimeState(thread, patch));
5622
- }
5623
- function parkedInputKey(message) {
5617
+ // src/chat/providers/slack/input.ts
5618
+ function steeringMessageKey(message) {
5624
5619
  if (message.role !== "user") {
5625
5620
  return void 0;
5626
5621
  }
@@ -5629,19 +5624,19 @@ function parkedInputKey(message) {
5629
5624
  return `${message.timestamp}:${text}`;
5630
5625
  }
5631
5626
  function renderRecentThreadMessageLines(conversationContext, messages) {
5632
- const passiveMessages = messages.filter((queued) => {
5627
+ const messagesForContext = messages.filter((queued) => {
5633
5628
  if (queued.explicitMention) {
5634
5629
  return false;
5635
5630
  }
5636
- const slackTs = queuedInstructionActor(queued)?.slackTs;
5631
+ const slackTs = inboundMessageActor(queued)?.slackTs;
5637
5632
  return !slackTs || !conversationContext?.includes(`slack_ts="${slackTs}"`);
5638
5633
  });
5639
- if (passiveMessages.length === 0) {
5634
+ if (messagesForContext.length === 0) {
5640
5635
  return [];
5641
5636
  }
5642
5637
  const lines = [];
5643
- for (const queued of passiveMessages) {
5644
- const actor = queuedInstructionActor(queued);
5638
+ for (const queued of messagesForContext) {
5639
+ const actor = inboundMessageActor(queued);
5645
5640
  const author = escapeXml(actor?.authorName ?? "user");
5646
5641
  const attrs = [
5647
5642
  `role="user"`,
@@ -5658,14 +5653,13 @@ function renderRecentThreadMessageLines(conversationContext, messages) {
5658
5653
  }
5659
5654
  return lines;
5660
5655
  }
5661
- function appendRecentThreadMessagesToContext(conversationContext, messages, options) {
5662
- const baseContext = options?.includeConversationContext === false ? void 0 : conversationContext;
5656
+ function appendRecentMessagesToContext(conversationContext, messages) {
5663
5657
  return appendThreadContextMessages(
5664
- baseContext,
5658
+ conversationContext,
5665
5659
  renderRecentThreadMessageLines(conversationContext, messages)
5666
5660
  );
5667
5661
  }
5668
- function queuedInstructionActor(queued) {
5662
+ function inboundMessageActor(queued) {
5669
5663
  const actor = getMessageActorIdentity(queued.message);
5670
5664
  const authorId = actor?.userId ?? parseActorUserId(queued.message.author.userId);
5671
5665
  const authorName = actor?.fullName ?? actor?.userName;
@@ -5676,7 +5670,7 @@ function queuedInstructionActor(queued) {
5676
5670
  ...slackTs ? { slackTs } : void 0
5677
5671
  };
5678
5672
  }
5679
- function queuedInstructionProvenance(queued, teamId) {
5673
+ function inboundMessageProvenance(queued, teamId) {
5680
5674
  if (isResourceEventSlackMessage(queued.message)) {
5681
5675
  return contextProvenance;
5682
5676
  }
@@ -5703,12 +5697,57 @@ async function resolveChannelName(thread) {
5703
5697
  return void 0;
5704
5698
  }
5705
5699
  }
5706
- function collectTurnAttachments(message, queuedMessages) {
5700
+ function collectAttachments(message, batchedMessages) {
5707
5701
  return [
5708
- ...(queuedMessages ?? []).flatMap((queued) => queued.message.attachments),
5702
+ ...(batchedMessages ?? []).flatMap((queued) => queued.message.attachments),
5709
5703
  ...message.attachments
5710
5704
  ];
5711
5705
  }
5706
+ async function saveSteeringMessages(args) {
5707
+ if (args.messages.length === 0) {
5708
+ return true;
5709
+ }
5710
+ const state = getStateAdapter();
5711
+ await state.connect();
5712
+ const lock = await acquireActiveLock(state, args.conversationId);
5713
+ if (!lock) {
5714
+ return false;
5715
+ }
5716
+ try {
5717
+ const projection = await loadConversationProjection({
5718
+ conversationId: args.conversationId
5719
+ });
5720
+ const savedKeys = new Set(
5721
+ projection.messages.map(steeringMessageKey).filter((key) => key !== void 0)
5722
+ );
5723
+ const missing = args.messages.filter((entry) => {
5724
+ const key = steeringMessageKey(entry.message);
5725
+ return key === void 0 || !savedKeys.has(key);
5726
+ });
5727
+ if (missing.length === 0) {
5728
+ return true;
5729
+ }
5730
+ await commitMessages({
5731
+ conversationId: args.conversationId,
5732
+ messages: [
5733
+ ...projection.messages,
5734
+ ...missing.map((entry) => entry.message)
5735
+ ],
5736
+ provenance: [
5737
+ ...projection.provenance,
5738
+ ...missing.map((entry) => entry.provenance)
5739
+ ]
5740
+ });
5741
+ return true;
5742
+ } finally {
5743
+ await state.releaseLock(lock);
5744
+ }
5745
+ }
5746
+
5747
+ // src/chat/providers/slack/turn.ts
5748
+ async function persistThreadRuntimeStateWithRetry(thread, patch) {
5749
+ await persistWithRetry(() => persistThreadRuntimeState(thread, patch));
5750
+ }
5712
5751
  async function loadPiMessagesForTurn(args) {
5713
5752
  if (!args.conversationId) {
5714
5753
  return {};
@@ -5810,7 +5849,7 @@ function createSlackTurn(deps) {
5810
5849
  (queued) => ensureSlackMessageActorIdentity(
5811
5850
  queued.message,
5812
5851
  teamId,
5813
- deps.services.lookupSlackUser
5852
+ lookupSlackUser
5814
5853
  )
5815
5854
  )
5816
5855
  );
@@ -5827,7 +5866,7 @@ function createSlackTurn(deps) {
5827
5866
  executionActor = await ensureSlackMessageActorIdentity(
5828
5867
  message,
5829
5868
  teamId,
5830
- deps.services.lookupSlackUser
5869
+ lookupSlackUser
5831
5870
  );
5832
5871
  if (executionActor) {
5833
5872
  credentialContext = credentialContextForActor(executionActor);
@@ -5905,8 +5944,8 @@ function createSlackTurn(deps) {
5905
5944
  queuedMessages.map(async (queued) => {
5906
5945
  const attachments = queued.message.attachments;
5907
5946
  return {
5908
- actor: queuedInstructionActor(queued),
5909
- provenance: queuedInstructionProvenance(queued, teamId),
5947
+ actor: inboundMessageActor(queued),
5948
+ provenance: inboundMessageProvenance(queued, teamId),
5910
5949
  text: queued.userText,
5911
5950
  timestampMs: queued.message.metadata.dateSent.getTime(),
5912
5951
  omittedImageAttachmentCount: !isVisionEnabled() && hasPotentialImageAttachment(attachments) ? countPotentialImageAttachments(attachments) : 0,
@@ -5922,51 +5961,11 @@ function createSlackTurn(deps) {
5922
5961
  })
5923
5962
  );
5924
5963
  };
5925
- const drainParkedInputToEventLog = async (pairs) => {
5926
- if (!conversationId || pairs.length === 0) {
5927
- return true;
5928
- }
5929
- const stateAdapter = getStateAdapter();
5930
- await stateAdapter.connect();
5931
- const lock = await acquireActiveLock(stateAdapter, conversationId);
5932
- if (!lock) {
5933
- return false;
5934
- }
5935
- try {
5936
- const projection = await loadConversationProjection({
5937
- conversationId
5938
- });
5939
- const appendedKeys = new Set(
5940
- projection.messages.map(parkedInputKey).filter((key) => key !== void 0)
5941
- );
5942
- const missing = pairs.filter((pair) => {
5943
- const key = parkedInputKey(pair.message);
5944
- return key === void 0 || !appendedKeys.has(key);
5945
- });
5946
- if (missing.length === 0) {
5947
- return true;
5948
- }
5949
- await commitMessages({
5950
- conversationId,
5951
- messages: [
5952
- ...projection.messages,
5953
- ...missing.map((pair) => pair.message)
5954
- ],
5955
- provenance: [
5956
- ...projection.provenance,
5957
- ...missing.map((pair) => pair.provenance)
5958
- ]
5959
- });
5960
- return true;
5961
- } finally {
5962
- await stateAdapter.releaseLock(lock);
5963
- }
5964
- };
5965
- const appendParkedTurnInput = async (parkedSessionId) => {
5964
+ const saveMessagesForPausedTurn = async (pausedTurnId) => {
5966
5965
  if (!conversationId) {
5967
5966
  return true;
5968
5967
  }
5969
- const parkedMessages = [
5968
+ const messagesForPausedTurn = [
5970
5969
  ...options.queuedMessages ?? [],
5971
5970
  {
5972
5971
  explicitMention: Boolean(
@@ -5977,18 +5976,21 @@ function createSlackTurn(deps) {
5977
5976
  userText: currentText.userText
5978
5977
  }
5979
5978
  ].filter(
5980
- // Redelivery of the parked turn's own message must not duplicate
5979
+ // Redelivery of the paused Turn's own message must not duplicate
5981
5980
  // the prompt that already started the session.
5982
- (queued) => buildDeterministicTurnId(queued.message.id) !== parkedSessionId
5981
+ (queued) => buildDeterministicTurnId(queued.message.id) !== pausedTurnId
5983
5982
  );
5984
- if (parkedMessages.length === 0) {
5983
+ if (messagesForPausedTurn.length === 0) {
5985
5984
  return true;
5986
5985
  }
5987
- const parkedPairs = (await resolveSteeringMessages(parkedMessages)).map((steering) => ({
5986
+ const steeringMessages = (await resolveSteeringMessages(messagesForPausedTurn)).map((steering) => ({
5988
5987
  message: buildSteeringPiMessage(steering),
5989
5988
  provenance: steering.provenance
5990
5989
  }));
5991
- return drainParkedInputToEventLog(parkedPairs);
5990
+ return saveSteeringMessages({
5991
+ conversationId,
5992
+ messages: steeringMessages
5993
+ });
5992
5994
  };
5993
5995
  if (preparedState.userMessageAlreadyReplied) {
5994
5996
  const deliveredMessage = [...preparedState.conversation.messages].reverse().find(
@@ -6005,16 +6007,16 @@ function createSlackTurn(deps) {
6005
6007
  return;
6006
6008
  }
6007
6009
  if (conversationId && activeTurnId) {
6008
- const pausedTurn = await deps.services.getPausedTurnRequest({
6010
+ const pausedTurn = await deps.pausedTurns.get({
6009
6011
  conversationId,
6010
6012
  turnId: activeTurnId
6011
6013
  });
6012
6014
  if (pausedTurn) {
6013
- if (!await appendParkedTurnInput(pausedTurn.turnId)) {
6015
+ if (!await saveMessagesForPausedTurn(pausedTurn.turnId)) {
6014
6016
  throw new TurnInputDeferredError();
6015
6017
  }
6016
6018
  try {
6017
- await deps.services.wakePausedTurn(pausedTurn);
6019
+ await deps.pausedTurns.wake(pausedTurn);
6018
6020
  } catch (error) {
6019
6021
  logException(error, "agent.continue.schedule.failed", {
6020
6022
  "app.ai.resume_session_version": pausedTurn.expectedVersion,
@@ -6039,6 +6041,7 @@ function createSlackTurn(deps) {
6039
6041
  await abandonTurnRecord({
6040
6042
  conversationId,
6041
6043
  turnId: activeTurnId,
6044
+ // TODO(dcramer): Rename this legacy text in Slack and Conversation API Turn records together.
6042
6045
  errorMessage: "Auth-parked session superseded by a new user message"
6043
6046
  });
6044
6047
  markTurnClosed({
@@ -6108,7 +6111,7 @@ function createSlackTurn(deps) {
6108
6111
  nextTurnId: turnId
6109
6112
  });
6110
6113
  if (conversationId && preparedState.userMessageId) {
6111
- await deps.services.turnLifecycle.start({
6114
+ await deps.turnLifecycle.start({
6112
6115
  conversationId,
6113
6116
  createdAtMs: Date.now(),
6114
6117
  inputMessageIds: [
@@ -6168,7 +6171,7 @@ function createSlackTurn(deps) {
6168
6171
  if (actor?.userName) {
6169
6172
  setTags({ userName: actor.userName });
6170
6173
  }
6171
- const turnAttachments = collectTurnAttachments(
6174
+ const turnAttachments = collectAttachments(
6172
6175
  message,
6173
6176
  options.queuedMessages
6174
6177
  );
@@ -6197,7 +6200,6 @@ function createSlackTurn(deps) {
6197
6200
  let runResultHandled = false;
6198
6201
  let assistantMessageDelivered = false;
6199
6202
  let acceptedDeliveryId;
6200
- let lifecycleTerminalized = false;
6201
6203
  let turnCompletionNotified = false;
6202
6204
  const recordDispatchOutcome = async (dispatchOutcome, state) => {
6203
6205
  const dispatchId = options.execution?.dispatch?.id;
@@ -6222,7 +6224,6 @@ function createSlackTurn(deps) {
6222
6224
  };
6223
6225
  let turnWakeError;
6224
6226
  let boundaryFailureCode = "agent_run_failed";
6225
- let finalizedFailureEventId;
6226
6227
  let terminalDispatchFailureOutcome;
6227
6228
  const notifyTurnCompleted = async () => {
6228
6229
  if (turnCompletionNotified) {
@@ -6354,7 +6355,7 @@ function createSlackTurn(deps) {
6354
6355
  });
6355
6356
  let piMessages = loadedPiMessages.piMessages;
6356
6357
  if (conversationId && loadedPiMessages.canCompact && piMessages?.length) {
6357
- const compaction = await deps.services.contextCompactor.maybeCompact({
6358
+ const compaction = await deps.contextCompactor.maybeCompact({
6358
6359
  conversation: preparedState.conversation,
6359
6360
  conversationContext: preparedState.conversationContext,
6360
6361
  conversationId,
@@ -6379,7 +6380,7 @@ function createSlackTurn(deps) {
6379
6380
  }
6380
6381
  }
6381
6382
  const hasDurablePromptHistory = Boolean(piMessages?.length);
6382
- const batchedInstructions = (await resolveSteeringMessages(
6383
+ const batchedSteeringMessages = (await resolveSteeringMessages(
6383
6384
  (options.queuedMessages ?? []).filter(
6384
6385
  (queued) => queued.explicitMention
6385
6386
  )
@@ -6387,20 +6388,23 @@ function createSlackTurn(deps) {
6387
6388
  message: buildSteeringPiMessage(steering),
6388
6389
  provenance: steering.provenance
6389
6390
  }));
6390
- if (!await drainParkedInputToEventLog(batchedInstructions)) {
6391
+ if (!await saveSteeringMessages({
6392
+ conversationId,
6393
+ messages: batchedSteeringMessages
6394
+ })) {
6391
6395
  shouldPersistFailureState = false;
6392
6396
  throw new TurnInputDeferredError();
6393
6397
  }
6394
- if (batchedInstructions.length > 0) {
6398
+ if (batchedSteeringMessages.length > 0) {
6395
6399
  const presentKeys = new Set(
6396
- (piMessages ?? []).map(parkedInputKey).filter((key) => key !== void 0)
6400
+ (piMessages ?? []).map(steeringMessageKey).filter((key) => key !== void 0)
6397
6401
  );
6398
- const newlyBatched = batchedInstructions.map((entry) => entry.message).filter((batchedMessage) => {
6399
- const key = parkedInputKey(batchedMessage);
6402
+ const newSteeringMessages = batchedSteeringMessages.map((entry) => entry.message).filter((batchedMessage) => {
6403
+ const key = steeringMessageKey(batchedMessage);
6400
6404
  return key === void 0 || !presentKeys.has(key);
6401
6405
  });
6402
- if (newlyBatched.length > 0) {
6403
- piMessages = [...piMessages ?? [], ...newlyBatched];
6406
+ if (newSteeringMessages.length > 0) {
6407
+ piMessages = [...piMessages ?? [], ...newSteeringMessages];
6404
6408
  }
6405
6409
  }
6406
6410
  status.update();
@@ -6420,7 +6424,7 @@ function createSlackTurn(deps) {
6420
6424
  const toolChannelId = channelId;
6421
6425
  const activeInstructionAuthorId = actor?.userId ?? parseActorUserId(message.author.userId);
6422
6426
  const activeInstructionAuthorName = actor?.fullName ?? actor?.userName;
6423
- const promptConversationContext = appendRecentThreadMessagesToContext(
6427
+ const promptConversationContext = appendRecentMessagesToContext(
6424
6428
  preparedState.conversationContext,
6425
6429
  options.queuedMessages ?? []
6426
6430
  );
@@ -6435,7 +6439,7 @@ function createSlackTurn(deps) {
6435
6439
  );
6436
6440
  return acceptedMessages ?? await resolveSteeringMessages(drained);
6437
6441
  } : void 0;
6438
- const outcome = await deps.services.agentRunner.run({
6442
+ const run = {
6439
6443
  conversationId,
6440
6444
  turnId,
6441
6445
  ...runId ? { runId } : void 0,
@@ -6507,7 +6511,121 @@ function createSlackTurn(deps) {
6507
6511
  });
6508
6512
  }
6509
6513
  }
6510
- });
6514
+ };
6515
+ let completedResult;
6516
+ const saveResult = async (result) => {
6517
+ let finalResult = result;
6518
+ setTags({ modelId: finalResult.diagnostics.modelId });
6519
+ const diagnosticsAttributes = getAgentTurnDiagnosticsAttributes(finalResult);
6520
+ setSpanAttributes(diagnosticsAttributes);
6521
+ let failureEventId;
6522
+ let failureReason;
6523
+ if (finalResult.diagnostics.outcome !== "success") {
6524
+ const finalized = finalizeFailedTurnReplyWithEvent({
6525
+ reply: finalResult,
6526
+ logException
6527
+ });
6528
+ finalResult = finalized.reply;
6529
+ failureEventId = finalized.eventId;
6530
+ failureReason = finalized.failureReason;
6531
+ await deliverAssistantMessage(finalResult.text);
6532
+ }
6533
+ const turnResult = finalResult.diagnostics.outcome === "success" ? { outcome: "completed" } : {
6534
+ errorMessage: finalResult.diagnostics.errorMessage ?? `Agent turn ended with ${finalResult.diagnostics.outcome}.`,
6535
+ outcome: "failed"
6536
+ };
6537
+ runResultHandled = true;
6538
+ shouldPersistFailureState = false;
6539
+ boundaryFailureCode = "agent_run_failed";
6540
+ const completedState = buildDeliveredTurnStatePatch({
6541
+ conversation: preparedState.conversation,
6542
+ reply: finalResult,
6543
+ sessionId: turnId,
6544
+ userMessageId: preparedState.userMessageId
6545
+ });
6546
+ let saveFailed = false;
6547
+ let saveFailureEventId;
6548
+ try {
6549
+ if (conversationId && finalResult.piMessages?.length) {
6550
+ await saveTurnCheckpoint({
6551
+ mode: "completed",
6552
+ channelName,
6553
+ conversationId,
6554
+ turnId,
6555
+ durationMs: finalResult.diagnostics.durationMs,
6556
+ usage: finalResult.diagnostics.usage,
6557
+ destination,
6558
+ destinationVisibility,
6559
+ source,
6560
+ sliceId: 1,
6561
+ dispatchOutcome: finalResult.diagnostics.outcome === "success" ? "completed" : "failed",
6562
+ ...options.execution?.dispatch && turnResult.errorMessage ? { errorMessage: turnResult.errorMessage } : void 0,
6563
+ ...acceptedDeliveryId ? { resultMessageId: acceptedDeliveryId } : void 0,
6564
+ messages: finalResult.piMessages,
6565
+ actor: executionActor,
6566
+ surface: options.execution?.surface ?? "slack",
6567
+ dispatchId: options.execution?.dispatch?.id
6568
+ });
6569
+ } else if (conversationId) {
6570
+ await recordTurnSummary({
6571
+ channelName,
6572
+ conversationId,
6573
+ cumulativeDurationMs: finalResult.diagnostics.durationMs,
6574
+ cumulativeUsage: finalResult.diagnostics.usage,
6575
+ turnId,
6576
+ sliceId: 1,
6577
+ startedAtMs: message.metadata.dateSent.getTime(),
6578
+ state: "completed",
6579
+ actor: executionActor,
6580
+ destination,
6581
+ destinationVisibility,
6582
+ source,
6583
+ surface: options.execution?.surface ?? "slack",
6584
+ dispatchId: options.execution?.dispatch?.id,
6585
+ dispatchOutcome: finalResult.diagnostics.outcome === "success" ? "completed" : "failed",
6586
+ ...acceptedDeliveryId ? { resultMessageId: acceptedDeliveryId } : void 0,
6587
+ traceId: getActiveTraceId()
6588
+ });
6589
+ }
6590
+ await persistWithRetry(
6591
+ () => persistConversationMessages({
6592
+ conversation: completedState.conversation,
6593
+ conversationId
6594
+ })
6595
+ );
6596
+ await persistThreadRuntimeStateWithRetry(thread, completedState);
6597
+ } catch (saveError) {
6598
+ saveFailed = true;
6599
+ saveFailureEventId = logException(
6600
+ saveError,
6601
+ "slack.reply.post_delivery_commit.failed",
6602
+ messageTs ? { "messaging.message.id": messageTs } : {}
6603
+ );
6604
+ }
6605
+ preparedState.conversation = completedState.conversation;
6606
+ persistedAtLeastOnce = true;
6607
+ options.onTurnOutcome?.(turnResult);
6608
+ completedResult = finalResult;
6609
+ if (saveFailed) {
6610
+ return {
6611
+ ...saveFailureEventId ? { eventId: saveFailureEventId } : void 0,
6612
+ failureCode: "persistence_failed",
6613
+ outcome: "failed"
6614
+ };
6615
+ }
6616
+ if (finalResult.diagnostics.outcome === "success") {
6617
+ return {
6618
+ outcome: assistantMessageDelivered ? "success" : "no_reply"
6619
+ };
6620
+ }
6621
+ return {
6622
+ ...failureEventId ? { eventId: failureEventId } : void 0,
6623
+ failureCode: "model_execution_failed",
6624
+ ...failureReason ? { failureReason } : void 0,
6625
+ outcome: "failed"
6626
+ };
6627
+ };
6628
+ const outcome = await deps.executeTurn(run, saveResult);
6511
6629
  if (outcome.status === "awaiting_auth") {
6512
6630
  await recordDispatchOutcome("blocked", "failed");
6513
6631
  options.onTurnOutcome?.({ outcome: "blocked" });
@@ -6530,14 +6648,13 @@ function createSlackTurn(deps) {
6530
6648
  conversation: preparedState.conversation
6531
6649
  });
6532
6650
  if (conversationId) {
6533
- await deps.services.turnLifecycle.fail({
6651
+ await deps.turnLifecycle.fail({
6534
6652
  conversationId,
6535
6653
  createdAtMs: Date.now(),
6536
6654
  ...authFailureEventId ? { eventId: authFailureEventId } : void 0,
6537
6655
  failureCode: "agent_run_failed",
6538
6656
  turnId
6539
6657
  });
6540
- lifecycleTerminalized = true;
6541
6658
  }
6542
6659
  persistedAtLeastOnce = true;
6543
6660
  shouldPersistFailureState = false;
@@ -6570,7 +6687,7 @@ function createSlackTurn(deps) {
6570
6687
  );
6571
6688
  }
6572
6689
  try {
6573
- await deps.services.wakePausedTurn({
6690
+ await deps.pausedTurns.wake({
6574
6691
  conversationId,
6575
6692
  destination,
6576
6693
  turnId,
@@ -6588,134 +6705,26 @@ function createSlackTurn(deps) {
6588
6705
  }
6589
6706
  return;
6590
6707
  }
6591
- let reply = outcome.result;
6592
- setTags({ modelId: reply.diagnostics.modelId });
6593
- const diagnosticsAttributes = getAgentTurnDiagnosticsAttributes(reply);
6594
- setSpanAttributes(diagnosticsAttributes);
6595
- if (reply.diagnostics.outcome !== "success") {
6596
- const finalized = finalizeFailedTurnReplyWithEvent({
6597
- reply,
6598
- logException
6599
- });
6600
- reply = finalized.reply;
6601
- finalizedFailureEventId = finalized.eventId;
6602
- await deliverAssistantMessage(reply.text);
6603
- }
6604
- const turnResult = reply.diagnostics.outcome === "success" ? { outcome: "completed" } : {
6605
- errorMessage: reply.diagnostics.errorMessage ?? `Agent turn ended with ${reply.diagnostics.outcome}.`,
6606
- outcome: "failed"
6607
- };
6608
- runResultHandled = true;
6609
- shouldPersistFailureState = false;
6610
- boundaryFailureCode = "agent_run_failed";
6611
- const completedState = buildDeliveredTurnStatePatch({
6612
- conversation: preparedState.conversation,
6613
- reply,
6614
- sessionId: turnId,
6615
- userMessageId: preparedState.userMessageId
6616
- });
6617
- try {
6618
- if (conversationId && reply.piMessages?.length) {
6619
- await saveTurnCheckpoint({
6620
- mode: "completed",
6621
- channelName,
6622
- conversationId,
6623
- turnId,
6624
- durationMs: reply.diagnostics.durationMs,
6625
- usage: reply.diagnostics.usage,
6626
- destination,
6627
- destinationVisibility,
6628
- source,
6629
- sliceId: 1,
6630
- dispatchOutcome: reply.diagnostics.outcome === "success" ? "completed" : "failed",
6631
- ...options.execution?.dispatch && turnResult.errorMessage ? { errorMessage: turnResult.errorMessage } : void 0,
6632
- ...acceptedDeliveryId ? { resultMessageId: acceptedDeliveryId } : void 0,
6633
- messages: reply.piMessages,
6634
- actor: executionActor,
6635
- surface: options.execution?.surface ?? "slack",
6636
- dispatchId: options.execution?.dispatch?.id
6637
- });
6638
- } else if (conversationId) {
6639
- await recordTurnSummary({
6640
- channelName,
6641
- conversationId,
6642
- cumulativeDurationMs: reply.diagnostics.durationMs,
6643
- cumulativeUsage: reply.diagnostics.usage,
6644
- turnId,
6645
- sliceId: 1,
6646
- startedAtMs: message.metadata.dateSent.getTime(),
6647
- state: "completed",
6648
- actor: executionActor,
6649
- destination,
6650
- destinationVisibility,
6651
- source,
6652
- surface: options.execution?.surface ?? "slack",
6653
- dispatchId: options.execution?.dispatch?.id,
6654
- dispatchOutcome: reply.diagnostics.outcome === "success" ? "completed" : "failed",
6655
- ...acceptedDeliveryId ? { resultMessageId: acceptedDeliveryId } : void 0,
6656
- traceId: getActiveTraceId()
6657
- });
6658
- }
6659
- await persistWithRetry(
6660
- () => persistConversationMessages({
6661
- conversation: completedState.conversation,
6662
- conversationId
6663
- })
6664
- );
6665
- await persistThreadRuntimeStateWithRetry(thread, completedState);
6666
- } catch (commitError) {
6667
- const persistenceEventId = logException(
6668
- commitError,
6669
- "slack.reply.post_delivery_commit.failed",
6670
- messageTs ? { "messaging.message.id": messageTs } : {}
6671
- );
6672
- if (conversationId && !lifecycleTerminalized) {
6673
- await deps.services.turnLifecycle.fail({
6674
- conversationId,
6675
- createdAtMs: Date.now(),
6676
- ...persistenceEventId ? { eventId: persistenceEventId } : void 0,
6677
- failureCode: "persistence_failed",
6678
- turnId
6679
- });
6680
- lifecycleTerminalized = true;
6681
- }
6682
- }
6683
- preparedState.conversation = completedState.conversation;
6684
- persistedAtLeastOnce = true;
6685
- options.onTurnOutcome?.(turnResult);
6686
- if (!lifecycleTerminalized && conversationId) {
6687
- if (reply.diagnostics.outcome === "success") {
6688
- await deps.services.turnLifecycle.complete({
6689
- conversationId,
6690
- createdAtMs: Date.now(),
6691
- outcome: assistantMessageDelivered ? "success" : "no_reply",
6692
- turnId
6693
- });
6694
- } else {
6695
- await deps.services.turnLifecycle.fail({
6696
- conversationId,
6697
- createdAtMs: Date.now(),
6698
- ...finalizedFailureEventId ? { eventId: finalizedFailureEventId } : void 0,
6699
- failureCode: "model_execution_failed",
6700
- turnId
6701
- });
6702
- }
6703
- lifecycleTerminalized = true;
6708
+ if (!completedResult) {
6709
+ throw new Error("Completed Turn did not save a result");
6704
6710
  }
6705
6711
  if (shouldEmitDevAgentTrace()) {
6706
6712
  logInfo("agent.turn.completed", {
6707
- "app.ai.outcome": reply.diagnostics.outcome,
6708
- "app.ai.tool_call_count": reply.diagnostics.toolCalls.length,
6709
- "app.ai.tool_error_results": reply.diagnostics.toolErrorCount
6713
+ "app.ai.outcome": completedResult.diagnostics.outcome,
6714
+ "app.ai.tool_call_count": completedResult.diagnostics.toolCalls.length,
6715
+ "app.ai.tool_error_results": completedResult.diagnostics.toolErrorCount
6710
6716
  });
6711
6717
  }
6712
6718
  await notifyTurnCompleted();
6713
- if (reply.diagnostics.outcome === "success" && conversationId) {
6719
+ if (completedResult.diagnostics.outcome === "success" && conversationId) {
6714
6720
  try {
6715
- await deps.services.scheduleSessionCompletedPluginTasks({
6716
- conversationId,
6717
- sessionId: turnId
6718
- });
6721
+ await scheduleSessionCompletedPluginTasks(
6722
+ {
6723
+ conversationId,
6724
+ sessionId: turnId
6725
+ },
6726
+ deps.sendPluginTask ? { send: deps.sendPluginTask } : void 0
6727
+ );
6719
6728
  } catch (error) {
6720
6729
  logException(
6721
6730
  error,
@@ -6754,8 +6763,9 @@ function createSlackTurn(deps) {
6754
6763
  shouldPersistFailureState = true;
6755
6764
  }
6756
6765
  shouldPersistFailureState = true;
6757
- const classifiedFailure = getConversationTurnBoundaryError(error);
6758
- const failureCause = classifiedFailure?.cause ?? error;
6766
+ const runFailure = error instanceof AgentRunError ? error.cause : error;
6767
+ const classifiedFailure = getConversationTurnBoundaryError(runFailure);
6768
+ const failureCause = classifiedFailure?.cause ?? runFailure;
6759
6769
  if (failureCause instanceof AuthorizationFlowDisabledError || failureCause instanceof PluginCredentialFailureError) {
6760
6770
  terminalDispatchFailureOutcome = "blocked";
6761
6771
  }
@@ -7209,6 +7219,9 @@ function upsertSkippedConversationMessage(conversation, args) {
7209
7219
  }
7210
7220
  function createSlackRuntime(options) {
7211
7221
  const services = createJuniorRuntimeServices(options.services);
7222
+ const turnLifecycle = new ConversationTurnLifecycleService(
7223
+ getConversationEventStore()
7224
+ );
7212
7225
  const prepareTurnState = createPrepareTurnState({
7213
7226
  compactConversationIfNeeded: services.conversationMemory.compactConversationIfNeeded,
7214
7227
  hydrateConversationVisionContext: services.visionContext.hydrateConversationVisionContext,
@@ -7224,34 +7237,29 @@ function createSlackRuntime(options) {
7224
7237
  (message) => ensureSlackMessageActorIdentity(
7225
7238
  message,
7226
7239
  destination.teamId,
7227
- services.replyExecutor.lookupSlackUser
7240
+ lookupSlackUser
7228
7241
  )
7229
7242
  )
7230
7243
  );
7231
7244
  }
7232
7245
  });
7233
7246
  const executeSlackTurn = createSlackTurn({
7247
+ contextCompactor: services.contextCompactor,
7248
+ executeTurn: services.executeTurn,
7234
7249
  getSlackAdapter: options.getSlackAdapter,
7250
+ pausedTurns: options.pausedTurns ?? createPausedTurns(),
7235
7251
  prepareTurnState,
7236
7252
  resolveUserAttachments: services.visionContext.resolveUserAttachments,
7237
- services: services.replyExecutor
7253
+ sendPluginTask: options.sendPluginTask,
7254
+ turnLifecycle
7238
7255
  });
7239
7256
  const runtime = createSlackTurnRuntime({
7240
7257
  assistantUserName: botConfig.userName,
7241
7258
  cancelEventSubscriptions: cancelSubscriptions,
7259
+ getBotUserId: () => options.getSlackAdapter().botUserId,
7242
7260
  modelId: defaultModelId(botConfig),
7243
7261
  now: options.now ?? (() => Date.now()),
7244
- getThreadId,
7245
- getChannelId,
7246
- getRunId,
7247
- stripLeadingBotMention: (text, stripOptions) => stripLeadingBotMention(text, {
7248
- ...stripOptions,
7249
- botUserId: options.getSlackAdapter().botUserId
7250
- }),
7251
- withSpan,
7252
- logWarn,
7253
- logException,
7254
- failConversationTurn: (input) => services.replyExecutor.turnLifecycle.fail(input),
7262
+ failConversationTurn: (input) => turnLifecycle.fail(input),
7255
7263
  prepareTurnState,
7256
7264
  persistPreparedState: async ({ thread, preparedState }) => {
7257
7265
  await persistThreadState(thread, {
@@ -7552,8 +7560,7 @@ async function runPausedTurnInContext(payload, options, runOptions) {
7552
7560
  "Paused turn"
7553
7561
  );
7554
7562
  const wakePausedTurn2 = options.wakePausedTurn ?? wakePausedTurn;
7555
- const resumeTurn = options.resumeTurn ?? resumeSlackTurn;
7556
- return await resumeTurn({
7563
+ return await resumeSlackTurn({
7557
7564
  messageText: "",
7558
7565
  conversationId: payload.conversationId,
7559
7566
  turnId: payload.turnId,
@@ -7562,7 +7569,7 @@ async function runPausedTurnInContext(payload, options, runOptions) {
7562
7569
  lockKey: payload.conversationId,
7563
7570
  // Queue continue runs under the conversation work lease already.
7564
7571
  ownsConversationLease: true,
7565
- agentRunner: options.agentRunner,
7572
+ executeTurn: async (run, saveResult, timeoutMs) => await executeTurn(options.agentRunner, run, saveResult, timeoutMs),
7566
7573
  scheduleSessionCompletedPluginTasks: options.scheduleSessionCompletedPluginTasks,
7567
7574
  beforeStart: async () => {
7568
7575
  let turn;
@@ -7650,7 +7657,7 @@ async function runPausedTurnInContext(payload, options, runOptions) {
7650
7657
  messageTs: getTurnUserSlackMessageTs(userMessage),
7651
7658
  inputMessageIds: [userMessage.id],
7652
7659
  initialStatus: latestReportedProgress(turnMessages),
7653
- replyContext: {
7660
+ run: {
7654
7661
  instruction: {
7655
7662
  ...conversationContext ? { context: conversationContext } : void 0,
7656
7663
  // Attachment fields come from the turn user message context helper.
@@ -7888,24 +7895,18 @@ async function runNextPausedTurnInContext(conversationId, options, runOptions) {
7888
7895
  // src/chat/app/conversation-work.ts
7889
7896
  function createConversationWork(options) {
7890
7897
  const apiTurnCancellation = createApiTurnCancellation();
7891
- const services = {
7892
- ...options.services,
7893
- replyExecutor: {
7894
- ...options.services?.replyExecutor,
7895
- agentRunner: options.agentRunner,
7896
- getPausedTurnRequest: options.services?.replyExecutor?.getPausedTurnRequest ?? (async (request) => await getPausedTurnRequest({
7897
- ...request,
7898
- conversationStore: options.conversationStore
7899
- })),
7900
- wakePausedTurn: options.services?.replyExecutor?.wakePausedTurn ?? (async (request) => await wakePausedTurn(request, {
7901
- queue: options.queue,
7902
- state: options.state
7903
- }))
7904
- }
7905
- };
7898
+ const pausedTurns = createPausedTurns({
7899
+ conversationStore: options.conversationStore,
7900
+ queue: options.queue,
7901
+ ...options.state ? { state: options.state } : void 0
7902
+ });
7906
7903
  const runtime = createSlackRuntime({
7907
7904
  getSlackAdapter: options.getSlackAdapter,
7908
- services
7905
+ pausedTurns,
7906
+ services: {
7907
+ ...options.services,
7908
+ agentRunner: options.agentRunner
7909
+ }
7909
7910
  });
7910
7911
  const slackWorker = createSlackConversationWorker({
7911
7912
  getSlackAdapter: options.getSlackAdapter,
@@ -7914,8 +7915,7 @@ function createConversationWork(options) {
7914
7915
  conversationId,
7915
7916
  {
7916
7917
  agentRunner: options.agentRunner,
7917
- scheduleSessionCompletedPluginTasks: services.replyExecutor?.scheduleSessionCompletedPluginTasks,
7918
- wakePausedTurn: services.replyExecutor?.wakePausedTurn
7918
+ wakePausedTurn: pausedTurns.wake
7919
7919
  },
7920
7920
  runOptions
7921
7921
  ),
@@ -7930,8 +7930,7 @@ function createConversationWork(options) {
7930
7930
  agentRunner: options.agentRunner,
7931
7931
  inputMessageIds: [getDispatchInputMessageId(dispatch2.id)],
7932
7932
  routingContext: buildDispatchRoutingContext(dispatch2),
7933
- scheduleSessionCompletedPluginTasks: services.replyExecutor?.scheduleSessionCompletedPluginTasks,
7934
- wakePausedTurn: services.replyExecutor?.wakePausedTurn
7933
+ wakePausedTurn: pausedTurns.wake
7935
7934
  },
7936
7935
  { shouldYield: hooks.shouldYield }
7937
7936
  );
@@ -7947,11 +7946,10 @@ function createConversationWork(options) {
7947
7946
  conversationStore: options.conversationStore,
7948
7947
  queue: options.queue,
7949
7948
  run: routeApiTurnWork({
7950
- apiTurnWorker: createApiTurnWorker({
7951
- agentRunner: options.agentRunner,
7952
- cancellation: apiTurnCancellation,
7953
- turnLifecycle: services.replyExecutor?.turnLifecycle
7954
- }),
7949
+ apiTurnWorker: createApiTurnWorker(
7950
+ options.agentRunner,
7951
+ apiTurnCancellation
7952
+ ),
7955
7953
  fallbackWorker: routeAgentInvocationWork({
7956
7954
  invocationWorker: createAgentInvocationWorker(options.agentRunner),
7957
7955
  fallbackWorker: providerWorker
@@ -8477,9 +8475,25 @@ var textContentBlockSchema = z5.object({
8477
8475
  text: z5.string(),
8478
8476
  type: z5.literal("text")
8479
8477
  }).strict();
8478
+ var resourceLinkContentBlockSchema = z5.object({
8479
+ _meta: metaSchema.optional(),
8480
+ annotations: annotationsSchema.nullable().optional(),
8481
+ description: z5.string().nullable().optional(),
8482
+ mimeType: z5.string().nullable().optional(),
8483
+ name: z5.string(),
8484
+ size: z5.number().finite().nullable().optional(),
8485
+ title: z5.string().nullable().optional(),
8486
+ type: z5.literal("resource_link"),
8487
+ uri: z5.string()
8488
+ }).strict();
8480
8489
  var promptParamsSchema = z5.object({
8481
8490
  _meta: metaSchema.optional(),
8482
- prompt: z5.array(textContentBlockSchema),
8491
+ prompt: z5.array(
8492
+ z5.discriminatedUnion("type", [
8493
+ textContentBlockSchema,
8494
+ resourceLinkContentBlockSchema
8495
+ ])
8496
+ ),
8483
8497
  sessionId: acpSessionIdSchema
8484
8498
  }).strict();
8485
8499
  var cancelParamsSchema = z5.object({
@@ -9619,15 +9633,30 @@ function rejectUnsupportedMcpServers(mcpServers) {
9619
9633
  );
9620
9634
  }
9621
9635
  }
9636
+ function resourceLinkText(block) {
9637
+ return [
9638
+ "Resource link:",
9639
+ `Name: ${block.name}`,
9640
+ `URI: ${block.uri}`,
9641
+ ...block.title ? [`Title: ${block.title}`] : [],
9642
+ ...block.description ? [`Description: ${block.description}`] : [],
9643
+ ...block.mimeType ? [`MIME type: ${block.mimeType}`] : [],
9644
+ ...block.size !== void 0 && block.size !== null ? [`Size: ${block.size} bytes`] : []
9645
+ ].join("\n");
9646
+ }
9622
9647
  function promptText(prompt) {
9623
9648
  if (prompt.length === 0) {
9624
9649
  throw acp4.RequestError.invalidParams(
9625
9650
  { field: "prompt" },
9626
- "Junior accepts one or more text blocks only"
9651
+ "Junior accepts one or more text or resource link blocks"
9627
9652
  );
9628
9653
  }
9629
9654
  const blocks = [];
9630
9655
  for (const block of prompt) {
9656
+ if (block.type === "resource_link") {
9657
+ blocks.push(resourceLinkText(block));
9658
+ continue;
9659
+ }
9631
9660
  if (!block.text.trim()) {
9632
9661
  throw acp4.RequestError.invalidParams(
9633
9662
  { field: "prompt" },
@@ -10710,7 +10739,7 @@ async function createApp(options) {
10710
10739
  tracePropagation
10711
10740
  });
10712
10741
  const runtimeServiceOverrides = {
10713
- replyExecutor: { agentRunner },
10742
+ agentRunner,
10714
10743
  sandbox: { tracePropagation }
10715
10744
  };
10716
10745
  let conversationWorkOptions;