@sentry/junior 0.188.0 → 0.190.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 (115) hide show
  1. package/dist/{agent-hooks-5RQEVLQD.js → agent-hooks-3IG2FQW2.js} +11 -11
  2. package/dist/api/acp/conversations.d.ts +2 -2
  3. package/dist/api/conversations/list.d.ts +7 -0
  4. package/dist/api/people/shared.d.ts +54 -0
  5. package/dist/api.js +44 -55
  6. package/dist/app.d.ts +1 -1
  7. package/dist/app.js +1025 -349
  8. package/dist/{catalog-runtime-L4A6BJ3U.js → catalog-runtime-2OT7S3ZC.js} +4 -4
  9. package/dist/chat/actor.d.ts +7 -2
  10. package/dist/chat/agent/resume.d.ts +0 -2
  11. package/dist/chat/agent/types.d.ts +8 -9
  12. package/dist/chat/agent-dispatch/work.d.ts +1 -10
  13. package/dist/chat/agent-invocations/spawn.d.ts +1 -1
  14. package/dist/chat/agent-invocations/types.d.ts +44 -108
  15. package/dist/chat/app/conversation-work.d.ts +16 -8
  16. package/dist/chat/conversation-privacy.d.ts +7 -7
  17. package/dist/chat/conversations/destination.d.ts +12 -0
  18. package/dist/chat/conversations/projection.d.ts +2 -2
  19. package/dist/chat/conversations/sql/location.d.ts +13 -4
  20. package/dist/chat/{api-turns → conversations}/stop.d.ts +2 -2
  21. package/dist/chat/conversations/store.d.ts +4 -4
  22. package/dist/chat/conversations/structured-events.d.ts +1 -1
  23. package/dist/chat/{api-turns/authorization.d.ts → conversations/web-authorization.d.ts} +1 -0
  24. package/dist/chat/conversations/web-input.d.ts +98 -0
  25. package/dist/chat/conversations/web-mailbox.d.ts +12 -0
  26. package/dist/chat/event-tasks/tool-support.d.ts +1 -7
  27. package/dist/chat/providers/slack/runtime.d.ts +1 -0
  28. package/dist/chat/providers/slack/system-turn.d.ts +8 -0
  29. package/dist/chat/resource-events/actor.d.ts +13 -12
  30. package/dist/chat/resource-events/notification.d.ts +1 -1
  31. package/dist/chat/services/guardian-action-policy.d.ts +1 -1
  32. package/dist/chat/services/turn-session-routing.d.ts +2 -2
  33. package/dist/chat/source.d.ts +3 -3
  34. package/dist/chat/task-execution/assistant-message.d.ts +32 -0
  35. package/dist/chat/task-execution/conversation-turn.d.ts +8 -0
  36. package/dist/chat/{api-turns → task-execution}/mailbox-input.d.ts +1 -2
  37. package/dist/chat/task-execution/mailbox-turn.d.ts +52 -0
  38. package/dist/chat/task-execution/paused-turn.d.ts +1 -1
  39. package/dist/chat/task-execution/slack-work.d.ts +0 -2
  40. package/dist/chat/task-execution/state.d.ts +2 -2
  41. package/dist/chat/task-execution/store.d.ts +1 -1
  42. package/dist/chat/task-execution/turn-cursor.d.ts +10 -1
  43. package/dist/chat/tools/types.d.ts +9 -2
  44. package/dist/{chunk-XJIPMHKI.js → chunk-2MKHYSYL.js} +3 -3
  45. package/dist/{chunk-QCGNHSMA.js → chunk-2MRF22J4.js} +25 -10
  46. package/dist/{chunk-HCIVBCP5.js → chunk-3J3BCB4J.js} +1 -1
  47. package/dist/chunk-4BLFIYVK.js +703 -0
  48. package/dist/{chunk-NZLZ4KYZ.js → chunk-4PKEJK5B.js} +1 -1
  49. package/dist/{chunk-VFZAUQ5V.js → chunk-62DRKZQU.js} +5 -183
  50. package/dist/{chunk-QIOUTXTZ.js → chunk-663DQH5W.js} +1 -1
  51. package/dist/{chunk-Z5SKZE5B.js → chunk-67MMSYSE.js} +4 -12
  52. package/dist/{chunk-ZX7RSBQ6.js → chunk-6BXUSF7J.js} +1 -1
  53. package/dist/{chunk-W42ENMJW.js → chunk-6H7YU6XH.js} +1 -1
  54. package/dist/{chunk-WGZJ5SU4.js → chunk-7UJ6IJCK.js} +1 -1
  55. package/dist/{chunk-QDHJTKPE.js → chunk-7Y7XMI6P.js} +8 -6
  56. package/dist/{chunk-6YGFBU3A.js → chunk-BGOLRC36.js} +62 -336
  57. package/dist/{chunk-CVBDVIF4.js → chunk-BUJU6C2J.js} +1 -1
  58. package/dist/{chunk-XI4PVY2T.js → chunk-CZXZKTAI.js} +5 -5
  59. package/dist/chunk-DA2KGZZI.js +13 -0
  60. package/dist/{chunk-RMB7CERI.js → chunk-DJZGQ7OL.js} +311 -137
  61. package/dist/{chunk-FIUCHYT6.js → chunk-DVX6U6GI.js} +1 -1
  62. package/dist/{chunk-AW77HH54.js → chunk-ECOR3OXY.js} +19 -299
  63. package/dist/{chunk-WW2Y7JIA.js → chunk-F3K2267N.js} +51 -50
  64. package/dist/{chunk-W2DDJCPS.js → chunk-FVFJ57RK.js} +8 -8
  65. package/dist/{chunk-UVUXFRYN.js → chunk-GWCFXTB6.js} +211 -7
  66. package/dist/{chunk-X55FOVZO.js → chunk-HI5KXE3C.js} +3 -3
  67. package/dist/{chunk-ERZMACYA.js → chunk-IRQ3RSX3.js} +3 -3
  68. package/dist/{chunk-32XSSFZV.js → chunk-JV7U4665.js} +1 -1
  69. package/dist/chunk-MNHJ4WLE.js +285 -0
  70. package/dist/{chunk-SC67CH3C.js → chunk-OJFX2FP7.js} +14 -17
  71. package/dist/{chunk-IUUQWIG2.js → chunk-OKAHLUSU.js} +70 -19
  72. package/dist/{chunk-PSHMPRIU.js → chunk-OON4IQHH.js} +2 -2
  73. package/dist/{chunk-6JZGXLL2.js → chunk-OYCOLHCR.js} +5 -7
  74. package/dist/{chunk-3HEZWDS5.js → chunk-REVH4BZU.js} +2 -2
  75. package/dist/{chunk-CDSLOYOR.js → chunk-RLYJYEIY.js} +6 -6
  76. package/dist/{chunk-CZRWU4ZM.js → chunk-T66GV7A3.js} +2 -5
  77. package/dist/{chunk-Q7O74WOO.js → chunk-VWNIDTFR.js} +2 -2
  78. package/dist/{chunk-CIG6WI7Q.js → chunk-W2C4TPLB.js} +5 -5
  79. package/dist/{chunk-QIMN3FXL.js → chunk-Y4WL4OYD.js} +1 -1
  80. package/dist/{chunk-MQDIIFZM.js → chunk-YFU4DGZY.js} +12 -5
  81. package/dist/chunk-YKIAUKYH.js +311 -0
  82. package/dist/{chunk-QVH6FW3T.js → chunk-ZFCO2TMB.js} +7 -3
  83. package/dist/cli/chat.js +34 -33
  84. package/dist/cli/check.js +5 -5
  85. package/dist/cli/plugins.js +12 -12
  86. package/dist/cli/snapshot-create.js +9 -9
  87. package/dist/cli/upgrade.js +6 -6
  88. package/dist/db/schema/agent-invocations.d.ts +18 -42
  89. package/dist/db/schema/conversations.d.ts +62 -0
  90. package/dist/db/schema.d.ts +49 -42
  91. package/dist/{db-YPRZAA2T.js → db-2IFDMDDY.js} +6 -6
  92. package/dist/instrumentation.js +3 -3
  93. package/dist/nitro.js +6 -6
  94. package/dist/{oauth-callback-server-DBBIR3XG.js → oauth-callback-server-SZSS2KH6.js} +30 -28
  95. package/dist/{runner-FKVFFPLO.js → runner-2N4QU77X.js} +25 -21
  96. package/dist/{skills-4RBAZEMV.js → skills-VU2LZAKX.js} +5 -5
  97. package/dist/spawn-3K7RV4T5.js +42 -0
  98. package/dist/task-runner-52DYFHW3.js +36 -0
  99. package/dist/{validation-E6Z5LHZM.js → validation-IJGHK7NI.js} +5 -5
  100. package/dist/version.js +1 -1
  101. package/dist/{work-OFTXWOK4.js → work-DI45MLRL.js} +22 -21
  102. package/dist/{worker-OMWNOKTJ.js → worker-FY7KWG2M.js} +10 -10
  103. package/migrations/0037_conversation_location.sql +23 -0
  104. package/migrations/meta/0037_snapshot.json +3192 -0
  105. package/migrations/meta/_journal.json +7 -0
  106. package/package.json +4 -4
  107. package/dist/chat/api-turns/assistant-message.d.ts +0 -12
  108. package/dist/chat/api-turns/cancellation.d.ts +0 -24
  109. package/dist/chat/api-turns/routing.d.ts +0 -51
  110. package/dist/chat/api-turns/work.d.ts +0 -99
  111. package/dist/chat/task-execution/slack-resource-event.d.ts +0 -55
  112. package/dist/chunk-6FGN7ZEG.js +0 -221
  113. package/dist/chunk-LODJKINF.js +0 -1502
  114. package/dist/spawn-CO7QFCNJ.js +0 -41
  115. package/dist/task-runner-DUGZGI7V.js +0 -34
package/dist/app.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  processConversationWork
3
- } from "./chunk-CDSLOYOR.js";
3
+ } from "./chunk-RLYJYEIY.js";
4
4
  import {
5
5
  bindSpawnAgent
6
- } from "./chunk-CZRWU4ZM.js";
6
+ } from "./chunk-T66GV7A3.js";
7
7
  import {
8
8
  createAgentInvocationWorker,
9
9
  enqueueAgentInvocation,
10
10
  listPendingAgentInvocationMailboxAppends,
11
- routeAgentInvocationWork
12
- } from "./chunk-SC67CH3C.js";
11
+ resolveAgentInvocationId
12
+ } from "./chunk-OJFX2FP7.js";
13
13
  import {
14
14
  GET as GET2,
15
15
  GET2 as GET3,
@@ -37,30 +37,12 @@ import {
37
37
  startProcessingReaction,
38
38
  stripLeadingBotMention,
39
39
  wakePausedTurn
40
- } from "./chunk-WW2Y7JIA.js";
40
+ } from "./chunk-F3K2267N.js";
41
41
  import "./chunk-FA6POGLH.js";
42
- import {
43
- GET,
44
- apiTurnIdForMessage,
45
- appendAndEnqueueApiConversationMessage,
46
- conversationVisibilityFromSlackChannelType,
47
- createApiTurnCancellation,
48
- createApiTurnWorker,
49
- createVercelAttachmentStorage,
50
- getAuthPausedApiTurnId,
51
- lookupSlackUser,
52
- readConversationAccessFromSql,
53
- recordApiConversationActivity,
54
- resolveSlackChannelTypeFromMessage,
55
- resolveSlackConversationContext,
56
- routeApiTurnWork,
57
- webActorFromEmail
58
- } from "./chunk-LODJKINF.js";
59
- import "./chunk-PSHMPRIU.js";
60
42
  import {
61
43
  AgentRunError,
62
44
  executeTurn
63
- } from "./chunk-ERZMACYA.js";
45
+ } from "./chunk-IRQ3RSX3.js";
64
46
  import {
65
47
  buildDeliveredTurnStatePatch,
66
48
  completeAuthPauseTurn,
@@ -71,7 +53,7 @@ import {
71
53
  getTurnUserSlackMessageTs,
72
54
  persistAuthPauseTurnState,
73
55
  requireTurnFailureEventId
74
- } from "./chunk-QDHJTKPE.js";
56
+ } from "./chunk-7Y7XMI6P.js";
75
57
  import {
76
58
  claimDispatchMailboxAppend,
77
59
  confirmDispatchMailboxAppend,
@@ -88,14 +70,14 @@ import {
88
70
  markDispatchCompleted,
89
71
  markDispatchFailed,
90
72
  markDispatchRunning,
91
- recordTaskExecution,
92
- resolveConversationRouting,
73
+ processPluginTask,
93
74
  resolveTurnSessionRouting,
94
75
  scheduleSessionCompletedPluginTasks
95
- } from "./chunk-AW77HH54.js";
76
+ } from "./chunk-ECOR3OXY.js";
96
77
  import {
78
+ ConversationTurnLifecycleService,
97
79
  getTurnLifecycle
98
- } from "./chunk-W42ENMJW.js";
80
+ } from "./chunk-6H7YU6XH.js";
99
81
  import {
100
82
  coerceThreadConversationState,
101
83
  getLocationConfigurationService,
@@ -104,17 +86,39 @@ import {
104
86
  persistThreadRuntimeState,
105
87
  persistThreadState,
106
88
  persistThreadStateById
107
- } from "./chunk-CIG6WI7Q.js";
89
+ } from "./chunk-W2C4TPLB.js";
90
+ import {
91
+ GET,
92
+ appendAndEnqueueWebMessage,
93
+ conversationTurnIdForMessage,
94
+ conversationVisibilityFromSlackChannelType,
95
+ createVercelAttachmentStorage,
96
+ legacyWebMailboxMetadataSchema,
97
+ lookupSlackUser,
98
+ readConversationAccessFromSql,
99
+ recordWebConversationActivity,
100
+ resolveConversationDestination,
101
+ resolveSlackChannelTypeFromMessage,
102
+ resolveSlackConversationContext,
103
+ webActorFromEmail
104
+ } from "./chunk-4BLFIYVK.js";
105
+ import {
106
+ createWebAuthorization,
107
+ deleteWebAuthorization
108
+ } from "./chunk-OON4IQHH.js";
109
+ import {
110
+ recordTaskExecution
111
+ } from "./chunk-MNHJ4WLE.js";
108
112
  import "./chunk-UTL3MHPC.js";
109
113
  import {
110
114
  createVercelPluginTaskCallback,
111
115
  queueCallback,
112
116
  registerVercelPluginTaskDevConsumer
113
- } from "./chunk-XI4PVY2T.js";
117
+ } from "./chunk-CZXZKTAI.js";
114
118
  import {
115
119
  validatePluginEgressCredentialHooks,
116
120
  validatePluginRegistrations
117
- } from "./chunk-HCIVBCP5.js";
121
+ } from "./chunk-3J3BCB4J.js";
118
122
  import {
119
123
  defineJuniorPlugins,
120
124
  pluginCatalogConfigFromEnv,
@@ -122,6 +126,8 @@ import {
122
126
  pluginRuntimeRegistrationsFromPluginSet
123
127
  } from "./chunk-CM5HNV2W.js";
124
128
  import {
129
+ RESOURCE_EVENT_MESSAGE_AUTHOR,
130
+ RESOURCE_EVENT_SYSTEM_ACTOR,
125
131
  SANDBOX_EGRESS_PROXY_PATH,
126
132
  buildSteeringPiMessage,
127
133
  clearSandboxEgressSignals,
@@ -133,6 +139,8 @@ import {
133
139
  getConfigDefaults,
134
140
  getNextRunAtMs,
135
141
  ingestResourceEvent,
142
+ isResourceEventConversationMessage,
143
+ isResourceEventMailboxMetadata,
136
144
  latestReportedProgress,
137
145
  listThreadReplies,
138
146
  logScheduledTaskRunSkipped,
@@ -143,18 +151,18 @@ import {
143
151
  readPublicArtifact,
144
152
  renderAttachmentText,
145
153
  renderBlockText,
146
- resolveDestinationVisibility,
154
+ renderTaskInput,
147
155
  resolveSandboxEgressProviderForHost,
148
156
  scheduledTaskRunAttributes,
149
157
  setConfigDefaults,
150
158
  shouldEmitDevAgentTrace,
151
159
  shouldPropagateSandboxEgressTrace,
152
160
  unpublishedArtifactHeaders
153
- } from "./chunk-RMB7CERI.js";
161
+ } from "./chunk-DJZGQ7OL.js";
154
162
  import {
155
163
  AuthorizationFlowDisabledError,
156
164
  PluginCredentialFailureError
157
- } from "./chunk-6JZGXLL2.js";
165
+ } from "./chunk-OYCOLHCR.js";
158
166
  import "./chunk-6Y5B5PEX.js";
159
167
  import "./chunk-DIB4GX3G.js";
160
168
  import {
@@ -162,63 +170,19 @@ import {
162
170
  deleteMcpAuthSessionsForUserProvider,
163
171
  deleteMcpServerSessionId,
164
172
  deleteMcpStoredOAuthCredentials
165
- } from "./chunk-W2DDJCPS.js";
173
+ } from "./chunk-FVFJ57RK.js";
166
174
  import {
175
+ RetryableDeliveryError,
176
+ createAgentRunner,
167
177
  formatProviderLabel,
168
178
  postSlackMessage,
169
179
  startOAuthFlow
170
- } from "./chunk-UVUXFRYN.js";
171
- import {
172
- RESOURCE_EVENT_AUTHOR_ID,
173
- RESOURCE_EVENT_MESSAGE_AUTHOR,
174
- RESOURCE_EVENT_SYSTEM_ACTOR,
175
- collectAttachmentGarbage,
176
- collectEventTaskMatchKeys,
177
- findMatchingEventTasks,
178
- getResourceEventCatalog,
179
- isResourceEventConversationMessage,
180
- isResourceEventMailboxMetadata,
181
- isResourceEventSlackMessage,
182
- listScheduledTasks,
183
- listScheduledTasksForTeam,
184
- readScheduledTask,
185
- renderTaskInput,
186
- requestAttachmentDeletion,
187
- resourceEventGuidance,
188
- saveScheduledTaskInLock,
189
- scheduledRunId,
190
- scheduledRunSchema,
191
- withScheduledTaskLock
192
- } from "./chunk-VFZAUQ5V.js";
193
- import {
194
- parseSlackThreadId
195
- } from "./chunk-CVBDVIF4.js";
196
- import {
197
- RetryableDeliveryError,
198
- createAgentRunner
199
- } from "./chunk-6FGN7ZEG.js";
200
- import {
201
- CONVERSATION_WORK_STALE_ENQUEUE_MS,
202
- appendAndEnqueueInboundMessage,
203
- clearExpiredConversationLease,
204
- ensureConversationWake,
205
- getConversation,
206
- getConversationWorkState,
207
- hasRunnableConversationWork,
208
- hasRunnableConversationWork2,
209
- isInvalidConversationRecordError,
210
- listActiveConversationIds,
211
- removeActiveConversation,
212
- requestConversationWork,
213
- stopConversationWork
214
- } from "./chunk-MQDIIFZM.js";
180
+ } from "./chunk-GWCFXTB6.js";
215
181
  import {
216
182
  ConversationTurnBoundaryError,
217
183
  CooperativeTurnYieldError,
218
184
  TurnInputCommitLostError,
219
185
  TurnInputDeferredError,
220
- buildDeterministicAssistantMessageId,
221
- buildDeterministicTurnId,
222
186
  clearPendingAuth,
223
187
  getAssistantReplyText,
224
188
  getConversationTurnBoundaryError,
@@ -229,7 +193,7 @@ import {
229
193
  markTurnCompleted,
230
194
  markTurnFailed,
231
195
  startActiveTurn
232
- } from "./chunk-Z5SKZE5B.js";
196
+ } from "./chunk-67MMSYSE.js";
233
197
  import {
234
198
  abandonTurnRecord,
235
199
  appendThreadContextMessages,
@@ -265,22 +229,63 @@ import {
265
229
  trimTrailingAssistantMessages,
266
230
  turnHasReply,
267
231
  upsertConversationMessage
268
- } from "./chunk-6YGFBU3A.js";
232
+ } from "./chunk-BGOLRC36.js";
269
233
  import {
270
234
  getExperimentalFeatures,
271
235
  isExperimentalFeatureEnabled,
272
236
  setExperimentalFeatures
273
237
  } from "./chunk-2LYHWMR4.js";
238
+ import {
239
+ collectAttachmentGarbage,
240
+ collectEventTaskMatchKeys,
241
+ findMatchingEventTasks,
242
+ getResourceEventCatalog,
243
+ listScheduledTasks,
244
+ listScheduledTasksForTeam,
245
+ readScheduledTask,
246
+ requestAttachmentDeletion,
247
+ resourceEventGuidance,
248
+ saveScheduledTaskInLock,
249
+ scheduledRunId,
250
+ scheduledRunSchema,
251
+ withScheduledTaskLock
252
+ } from "./chunk-62DRKZQU.js";
253
+ import {
254
+ parseSlackThreadId
255
+ } from "./chunk-BUJU6C2J.js";
256
+ import {
257
+ CONVERSATION_WORK_STALE_ENQUEUE_MS,
258
+ appendAndEnqueueInboundMessage,
259
+ clearExpiredConversationLease,
260
+ ensureConversationWake,
261
+ getConversation,
262
+ getConversationWorkState,
263
+ hasRunnableConversationWork,
264
+ hasRunnableConversationWork2,
265
+ isInvalidConversationRecordError,
266
+ listActiveConversationIds,
267
+ removeActiveConversation,
268
+ requestConversationWork,
269
+ stopConversationWork
270
+ } from "./chunk-YFU4DGZY.js";
271
+ import {
272
+ buildDeterministicAssistantMessageId,
273
+ buildDeterministicTurnId
274
+ } from "./chunk-DA2KGZZI.js";
275
+ import "./chunk-YKIAUKYH.js";
274
276
  import {
275
277
  getSandboxResourceConfig,
276
278
  setSandboxResourceConfig
277
- } from "./chunk-XJIPMHKI.js";
279
+ } from "./chunk-2MKHYSYL.js";
278
280
  import "./chunk-PDO5BLNM.js";
279
281
  import "./chunk-UIE3R5XU.js";
280
282
  import {
281
283
  WORKSPACE_SNAPSHOT_JOB_QUEUE_TOPIC,
282
284
  verifyWorkspaceSnapshotJobMessage
283
285
  } from "./chunk-X6GDDWQH.js";
286
+ import {
287
+ getTurnRequestDeadline
288
+ } from "./chunk-7UJ6IJCK.js";
284
289
  import {
285
290
  getVercelConversationWorkQueue,
286
291
  resolveConversationWorkQueueTopic,
@@ -291,9 +296,6 @@ import {
291
296
  isConversationQueueMessageRejectedError
292
297
  } from "./chunk-JAL3CH4G.js";
293
298
  import "./chunk-7H2VZTWN.js";
294
- import {
295
- getTurnRequestDeadline
296
- } from "./chunk-WGZJ5SU4.js";
297
299
  import {
298
300
  SlackActionError,
299
301
  bindEventTaskCredentialSubject,
@@ -319,7 +321,7 @@ import {
319
321
  verifyEventTaskCredentialSubject,
320
322
  verifyScheduledTaskCredentialSubject,
321
323
  verifySlackDirectCredentialSubject
322
- } from "./chunk-QCGNHSMA.js";
324
+ } from "./chunk-2MRF22J4.js";
323
325
  import "./chunk-3Y47VMHV.js";
324
326
  import {
325
327
  createSlackDestination,
@@ -331,7 +333,7 @@ import {
331
333
  requireSlackDestination,
332
334
  withConversationEventLock,
333
335
  withConversationMutationLock
334
- } from "./chunk-IUUQWIG2.js";
336
+ } from "./chunk-OKAHLUSU.js";
335
337
  import {
336
338
  juniorAgentBindings,
337
339
  juniorAgentInvocations,
@@ -339,15 +341,14 @@ import {
339
341
  juniorConversations,
340
342
  juniorSchedulerRuns,
341
343
  juniorSchedulerTasks
342
- } from "./chunk-QVH6FW3T.js";
343
- import "./chunk-X55FOVZO.js";
344
+ } from "./chunk-ZFCO2TMB.js";
345
+ import "./chunk-HI5KXE3C.js";
344
346
  import {
345
347
  acquireActiveLock,
346
348
  getStateAdapter,
347
349
  withActiveLock
348
- } from "./chunk-ZX7RSBQ6.js";
350
+ } from "./chunk-6BXUSF7J.js";
349
351
  import {
350
- contextProvenance,
351
352
  instructionProvenanceFor
352
353
  } from "./chunk-GFBR4S3Q.js";
353
354
  import {
@@ -368,17 +369,17 @@ import {
368
369
  isProviderRetryError,
369
370
  setProfiles,
370
371
  setSlackReactionConfig
371
- } from "./chunk-Q7O74WOO.js";
372
+ } from "./chunk-VWNIDTFR.js";
372
373
  import {
373
374
  defaultModelId,
374
375
  modelIdForProfile
375
376
  } from "./chunk-D4YV5TDV.js";
376
- import "./chunk-FIUCHYT6.js";
377
- import "./chunk-3HEZWDS5.js";
377
+ import "./chunk-DVX6U6GI.js";
378
+ import "./chunk-REVH4BZU.js";
378
379
  import {
379
380
  pluginCatalogRuntime
380
- } from "./chunk-NZLZ4KYZ.js";
381
- import "./chunk-QIOUTXTZ.js";
381
+ } from "./chunk-4PKEJK5B.js";
382
+ import "./chunk-663DQH5W.js";
382
383
  import {
383
384
  credentialContextForActor
384
385
  } from "./chunk-CEMMLV5L.js";
@@ -414,13 +415,13 @@ import {
414
415
  withContext,
415
416
  withLogContext,
416
417
  withSpan
417
- } from "./chunk-QIMN3FXL.js";
418
+ } from "./chunk-Y4WL4OYD.js";
418
419
  import {
419
420
  continueTrace
420
421
  } from "./chunk-PEQXYSSE.js";
421
422
  import {
422
423
  JUNIOR_VERSION
423
- } from "./chunk-32XSSFZV.js";
424
+ } from "./chunk-JV7U4665.js";
424
425
 
425
426
  // src/app.ts
426
427
  import { createRequire } from "module";
@@ -569,7 +570,6 @@ function buildDispatchRoutingContext(dispatch2) {
569
570
  dispatch2.actor,
570
571
  dispatch2.credentialSubject
571
572
  ),
572
- destinationVisibility: dispatch2.destinationVisibility,
573
573
  dispatch: {
574
574
  actor: dispatch2.actor,
575
575
  id: dispatch2.id,
@@ -689,12 +689,6 @@ async function resolveAgentDispatchId(context) {
689
689
  const dispatch2 = await getDispatchRecord(durableDispatchId);
690
690
  return dispatch2 && !isTerminalDispatchStatus(dispatch2.status) ? durableDispatchId : void 0;
691
691
  }
692
- function createAgentDispatchWorkRouter(options) {
693
- return async (context) => {
694
- const dispatchId = await resolveAgentDispatchId(context);
695
- return dispatchId ? await options.dispatchWorker(context, dispatchId) : await options.fallbackWorker(context);
696
- };
697
- }
698
692
  async function readDispatchTurnResult(dispatch2) {
699
693
  const conversationId = getDispatchConversationId(dispatch2);
700
694
  const turnId = getDispatchTurnId(dispatch2.id);
@@ -948,7 +942,7 @@ function dispatchOptionsErrorMessage(issues) {
948
942
  return "Dispatch source must not include unknown fields";
949
943
  }
950
944
  if (hasIssueAtPath(issues, ["source"])) {
951
- return "Dispatch source platform is required";
945
+ return "Dispatch Source kind is required";
952
946
  }
953
947
  if (hasIssueUnderPath(issues, ["source", "teamId"])) {
954
948
  return "Dispatch source teamId must be a Slack team id";
@@ -2742,13 +2736,13 @@ async function GET6(request) {
2742
2736
  // src/chat/ingress/slack-webhook.ts
2743
2737
  import {
2744
2738
  ChannelImpl,
2745
- ThreadImpl as ThreadImpl3
2739
+ ThreadImpl as ThreadImpl2
2746
2740
  } from "chat";
2747
2741
 
2748
2742
  // src/chat/task-execution/slack-work.ts
2749
2743
  import {
2750
- Message as Message3,
2751
- ThreadImpl as ThreadImpl2
2744
+ Message as Message2,
2745
+ ThreadImpl
2752
2746
  } from "chat";
2753
2747
  import { z as z3 } from "zod";
2754
2748
 
@@ -2938,85 +2932,6 @@ async function ensureSlackMessageActorIdentity(message, teamId, lookupSlackUser2
2938
2932
  return actor;
2939
2933
  }
2940
2934
 
2941
- // src/chat/task-execution/slack-resource-event.ts
2942
- import { Message as Message2, ThreadImpl } from "chat";
2943
- async function resolveSlackResourceEventThread(args) {
2944
- const routing = await resolveConversationRouting({
2945
- conversationId: args.conversationId,
2946
- conversationStore: args.conversationStore
2947
- });
2948
- const destination = requireSlackDestination(
2949
- routing?.destination ?? args.destination,
2950
- "Slack resource-event turn"
2951
- );
2952
- const threadTs = routing?.source?.platform === "slack" ? routing.source.threadTs?.trim() : void 0;
2953
- if (!threadTs) {
2954
- return void 0;
2955
- }
2956
- return { destination, threadTs };
2957
- }
2958
- function isPlainResourceEventRecord(record) {
2959
- return record.source === "resource_event" && isResourceEventMailboxMetadata(record.input.metadata) && !hasSlackConversationMetadata(record.input.metadata);
2960
- }
2961
- function hasSlackConversationMetadata(value) {
2962
- if (!value || typeof value !== "object" || Array.isArray(value)) {
2963
- return false;
2964
- }
2965
- const record = value;
2966
- return record.platform === "slack" && typeof record.thread === "object" && record.thread !== null && typeof record.message === "object" && record.message !== null;
2967
- }
2968
- function buildResourceEventSlackMessage(args) {
2969
- if (!isResourceEventMailboxMetadata(args.record.input.metadata)) {
2970
- throw new Error(
2971
- "Resource-event Slack turn requires resource-event metadata"
2972
- );
2973
- }
2974
- const event = args.record.input.metadata.resourceEvent;
2975
- const messageId = `resource-event-${event.subscriptionId}-${event.eventKey}`;
2976
- const threadId = `slack:${args.channelId}:${args.threadTs}`;
2977
- return new Message2({
2978
- id: messageId,
2979
- threadId,
2980
- text: args.record.input.text,
2981
- author: {
2982
- ...RESOURCE_EVENT_MESSAGE_AUTHOR,
2983
- isMe: false
2984
- },
2985
- isMention: false,
2986
- attachments: [],
2987
- metadata: {
2988
- dateSent: new Date(args.record.createdAtMs),
2989
- edited: false
2990
- },
2991
- formatted: { type: "root", children: [] },
2992
- raw: {
2993
- channel: args.channelId,
2994
- event_type: "resource_event",
2995
- resource_event_type: event.eventType,
2996
- thread_ts: args.threadTs,
2997
- type: "message",
2998
- user: RESOURCE_EVENT_AUTHOR_ID
2999
- }
3000
- });
3001
- }
3002
- function buildResourceEventSlackThread(args) {
3003
- const threadId = normalizeIncomingSlackThreadId(
3004
- `slack:${args.channelId}:${args.threadTs}`,
3005
- args.message
3006
- );
3007
- const message = withNormalizedThreadId(args.message, threadId);
3008
- return new ThreadImpl({
3009
- adapter: args.adapter,
3010
- stateAdapter: args.state,
3011
- id: threadId,
3012
- channelId: args.channelId,
3013
- currentMessage: message,
3014
- initialMessage: message,
3015
- isDM: args.channelId.startsWith("D"),
3016
- isSubscribedContext: true
3017
- });
3018
- }
3019
-
3020
2935
  // src/chat/slack/message-control.ts
3021
2936
  var LEADING_MENTION_BEFORE_STEERING_RE = /^(\s*(?:<@[^>]+>|@[A-Za-z0-9._-]+\b)[\s,:-]*)!!\s*/;
3022
2937
  function stripLeadingSteeringOverride(text) {
@@ -3251,9 +3166,6 @@ function compareInboundMessages(left, right) {
3251
3166
  }
3252
3167
  function routeForRecords(records) {
3253
3168
  return records.some((record) => {
3254
- if (isPlainResourceEventRecord(record)) {
3255
- return false;
3256
- }
3257
3169
  const metadata = parseSlackMetadata(record.input.metadata);
3258
3170
  if (!metadata) {
3259
3171
  throw new Error("Conversation mailbox record is not Slack metadata");
@@ -3262,23 +3174,11 @@ function routeForRecords(records) {
3262
3174
  }) ? "mention" : "subscribed";
3263
3175
  }
3264
3176
  function restoreMessage(args) {
3265
- if (isPlainResourceEventRecord(args.record)) {
3266
- if (!args.threadTs) {
3267
- throw new Error(
3268
- "Resource-event Slack turn requires a thread timestamp"
3269
- );
3270
- }
3271
- return buildResourceEventSlackMessage({
3272
- channelId: args.channelId,
3273
- record: args.record,
3274
- threadTs: args.threadTs
3275
- });
3276
- }
3277
3177
  const metadata = parseSlackMetadata(args.record.input.metadata);
3278
3178
  if (!metadata) {
3279
3179
  throw new Error("Conversation mailbox record is not a Slack message");
3280
3180
  }
3281
- const message = Message3.fromJSON(metadata.message);
3181
+ const message = Message2.fromJSON(metadata.message);
3282
3182
  message.attachments = message.attachments.map(
3283
3183
  (attachment) => args.adapter.rehydrateAttachment(attachment)
3284
3184
  );
@@ -3288,9 +3188,6 @@ function restoreMessage(args) {
3288
3188
  async function bindSlackActorIdentities(args) {
3289
3189
  const byAuthorId = /* @__PURE__ */ new Map();
3290
3190
  for (const message of args.messages) {
3291
- if (isResourceEventSlackMessage(message)) {
3292
- continue;
3293
- }
3294
3191
  const authorId = requireSlackAuthorId(message);
3295
3192
  byAuthorId.set(authorId, [...byAuthorId.get(authorId) ?? [], message]);
3296
3193
  }
@@ -3315,7 +3212,7 @@ function restoreThread(args) {
3315
3212
  args.message
3316
3213
  );
3317
3214
  const message = withNormalizedThreadId(args.message, threadId);
3318
- return new ThreadImpl2({
3215
+ return new ThreadImpl({
3319
3216
  adapter: args.adapter,
3320
3217
  stateAdapter: args.state,
3321
3218
  id: threadId,
@@ -3380,10 +3277,9 @@ function createSlackConversationWorker(options) {
3380
3277
  if (!latestRecord) {
3381
3278
  return { status: "completed" };
3382
3279
  }
3383
- const hasPlainResourceEvent = records.some(isPlainResourceEventRecord);
3384
- const publishExternally = hasPlainResourceEvent ? true : latestRecord.publishExternally ?? context.publishExternally;
3385
- const latestMetadata = isPlainResourceEventRecord(latestRecord) ? void 0 : parseSlackMetadata(latestRecord.input.metadata);
3386
- if (!isPlainResourceEventRecord(latestRecord) && !latestMetadata) {
3280
+ const publishExternally = latestRecord.publishExternally ?? context.publishExternally;
3281
+ const latestMetadata = parseSlackMetadata(latestRecord.input.metadata);
3282
+ if (!latestMetadata) {
3387
3283
  throw new Error(
3388
3284
  "Latest conversation mailbox record is not Slack metadata"
3389
3285
  );
@@ -3391,34 +3287,19 @@ function createSlackConversationWorker(options) {
3391
3287
  if (!await context.checkIn()) {
3392
3288
  return { status: "lost_lease" };
3393
3289
  }
3394
- const resourceEventThread = hasPlainResourceEvent ? await resolveSlackResourceEventThread({
3395
- conversationId: context.conversationId,
3396
- conversationStore: options.conversationStore,
3397
- destination: context.destination
3398
- }) : void 0;
3399
- if (hasPlainResourceEvent && !resourceEventThread) {
3400
- logWarn("conversation.work.resource_event.missing_thread", {
3401
- "app.inbound.message_count": records.length
3402
- });
3403
- await context.attempt.ack();
3404
- return { status: "completed" };
3405
- }
3406
3290
  const turnResult = await runWithSlackInstallation({
3407
3291
  adapter,
3408
- installation: resourceEventThread ? { teamId: resourceEventThread.destination.teamId } : getInstallation(records),
3292
+ installation: getInstallation(records),
3409
3293
  state,
3410
3294
  task: async () => {
3411
- const destination = resourceEventThread?.destination ?? requireSlackDestination(
3295
+ const destination = requireSlackDestination(
3412
3296
  context.destination,
3413
3297
  "Slack conversation work"
3414
3298
  );
3415
- const threadTs = resourceEventThread?.threadTs;
3416
3299
  const messages = records.map(
3417
3300
  (record) => restoreMessage({
3418
3301
  adapter,
3419
- channelId: destination.channelId,
3420
- record,
3421
- ...threadTs ? { threadTs } : void 0
3302
+ record
3422
3303
  })
3423
3304
  );
3424
3305
  await bindSlackActorIdentities({
@@ -3431,13 +3312,7 @@ function createSlackConversationWorker(options) {
3431
3312
  return;
3432
3313
  }
3433
3314
  const route = routeForRecords(records);
3434
- const thread = isPlainResourceEventRecord(latestRecord) && threadTs ? buildResourceEventSlackThread({
3435
- adapter,
3436
- channelId: destination.channelId,
3437
- message: latestMessage,
3438
- state,
3439
- threadTs
3440
- }) : restoreThread({
3315
+ const thread = restoreThread({
3441
3316
  adapter,
3442
3317
  isSubscribedContext: route === "subscribed",
3443
3318
  message: latestMessage,
@@ -3449,7 +3324,7 @@ function createSlackConversationWorker(options) {
3449
3324
  skipped,
3450
3325
  totalSinceLastHandler: messages.length
3451
3326
  };
3452
- const activeAuthorId = isResourceEventSlackMessage(latestMessage) ? RESOURCE_EVENT_AUTHOR_ID : requireSlackAuthorId(latestMessage);
3327
+ const activeAuthorId = requireSlackAuthorId(latestMessage);
3453
3328
  let initialMessagesAcked = false;
3454
3329
  const ack = async () => {
3455
3330
  if (initialMessagesAcked) {
@@ -3467,17 +3342,15 @@ function createSlackConversationWorker(options) {
3467
3342
  const drainSteeringMessages = async (accept) => {
3468
3343
  await context.attempt.drain(async (pendingRecords) => {
3469
3344
  const candidates = pendingRecords.filter(
3470
- (record) => isPlainResourceEventRecord(record) ? publishExternally : record.publishExternally === publishExternally
3345
+ (record) => record.publishExternally === publishExternally
3471
3346
  ).map((record) => ({
3472
3347
  inboundMessageId: record.inboundMessageId,
3473
3348
  message: restoreMessage({
3474
3349
  adapter,
3475
- channelId: destination.channelId,
3476
- record,
3477
- ...threadTs ? { threadTs } : void 0
3350
+ record
3478
3351
  })
3479
3352
  })).filter(
3480
- (candidate) => crossActorMidRunMode === "steer" || isResourceEventSlackMessage(candidate.message) || requireSlackAuthorId(candidate.message) === activeAuthorId || hasSteeringOverride(candidate.message.text)
3353
+ (candidate) => crossActorMidRunMode === "steer" || requireSlackAuthorId(candidate.message) === activeAuthorId || hasSteeringOverride(candidate.message.text)
3481
3354
  );
3482
3355
  return candidates.length > 0 ? await accept(candidates) : [];
3483
3356
  });
@@ -3635,7 +3508,7 @@ function textMentionsBot(text, botUserId) {
3635
3508
  }
3636
3509
 
3637
3510
  // src/chat/ingress/message-changed.ts
3638
- import { Message as Message4 } from "chat";
3511
+ import { Message as Message3 } from "chat";
3639
3512
  function getEditedMentionMessageId(messageTs) {
3640
3513
  return `${messageTs}:message_changed_mention`;
3641
3514
  }
@@ -3702,7 +3575,7 @@ function extractMessageChangedMention(body, botUserId, adapter) {
3702
3575
  ...sourceTeam ? { source_team: sourceTeam } : void 0,
3703
3576
  ...botId ? { bot_id: botId } : void 0
3704
3577
  };
3705
- const message = new Message4({
3578
+ const message = new Message3({
3706
3579
  id: getEditedMentionMessageId(messageTs),
3707
3580
  threadId,
3708
3581
  text: newText,
@@ -3941,7 +3814,7 @@ function normalizeMessageThreadId(message) {
3941
3814
  }
3942
3815
  async function buildThread(args) {
3943
3816
  const normalized = normalizeMessageThreadId(args.message);
3944
- return new ThreadImpl3({
3817
+ return new ThreadImpl2({
3945
3818
  adapter: args.adapter,
3946
3819
  stateAdapter: args.state,
3947
3820
  id: normalized.threadId,
@@ -5531,8 +5404,7 @@ function createSlackTurnRuntime(deps) {
5531
5404
  const threadId = getThreadId(thread, message);
5532
5405
  const channelId = getChannelId(thread, message);
5533
5406
  const runId = getRunId(thread, message);
5534
- const isResourceEventNotification = isResourceEventSlackMessage(message);
5535
- const actorId = isResourceEventNotification ? void 0 : message.author.userId;
5407
+ const actorId = message.author.userId;
5536
5408
  const turnContext = logContext({
5537
5409
  threadId,
5538
5410
  actorId,
@@ -5565,7 +5437,7 @@ function createSlackTurnRuntime(deps) {
5565
5437
  });
5566
5438
  const combinedText = combineTurnText(queuedMessages, currentText);
5567
5439
  const turnIsExplicitMention = Boolean(message.isMention) || queuedMessages.some((queued) => queued.explicitMention);
5568
- const preflightDecision = isResourceEventNotification ? void 0 : getSubscribedReplyPreflightDecision({
5440
+ const preflightDecision = getSubscribedReplyPreflightDecision({
5569
5441
  botUserName: deps.assistantUserName,
5570
5442
  rawText: combinedText.rawText,
5571
5443
  text: combinedText.userText,
@@ -5583,7 +5455,7 @@ function createSlackTurnRuntime(deps) {
5583
5455
  });
5584
5456
  return;
5585
5457
  }
5586
- if (!isResourceEventNotification && !turnIsExplicitMention && !isExperimentalFeatureEnabled("passive-routing")) {
5458
+ if (!turnIsExplicitMention && !isExperimentalFeatureEnabled("passive-routing")) {
5587
5459
  const decision2 = await deps.decideSubscribedReply({
5588
5460
  rawText: combinedText.rawText,
5589
5461
  text: combinedText.userText,
@@ -5621,7 +5493,7 @@ function createSlackTurnRuntime(deps) {
5621
5493
  thread,
5622
5494
  preparedState
5623
5495
  });
5624
- const decision = isResourceEventNotification ? { shouldReply: true, reason: "resource_event" } : await deps.decideSubscribedReply({
5496
+ const decision = await deps.decideSubscribedReply({
5625
5497
  rawText: combinedText.rawText,
5626
5498
  text: combinedText.userText,
5627
5499
  conversationContext: deps.getPreparedConversationContext(preparedState),
@@ -6431,6 +6303,21 @@ async function maybeApplyProviderDefaultConfigRequest(args) {
6431
6303
  };
6432
6304
  }
6433
6305
 
6306
+ // src/chat/conversations/destination-visibility.ts
6307
+ async function resolveDestinationVisibility(args) {
6308
+ if (args.visibility) {
6309
+ return args.visibility;
6310
+ }
6311
+ if (args.destination.platform === "local") {
6312
+ return "private";
6313
+ }
6314
+ return await getConversationStore().getDestinationVisibility({
6315
+ provider: "slack",
6316
+ providerDestinationId: args.destination.channelId,
6317
+ providerTenantId: args.destination.teamId
6318
+ });
6319
+ }
6320
+
6434
6321
  // src/chat/providers/slack/input.ts
6435
6322
  function steeringMessageKey(message) {
6436
6323
  if (message.role !== "user") {
@@ -6488,9 +6375,6 @@ function inboundMessageActor(queued) {
6488
6375
  };
6489
6376
  }
6490
6377
  function inboundMessageProvenance(queued, teamId) {
6491
- if (isResourceEventSlackMessage(queued.message)) {
6492
- return contextProvenance;
6493
- }
6494
6378
  const identity = getMessageActorIdentity(queued.message);
6495
6379
  const author = identity && "platform" in identity ? identity : createActor(
6496
6380
  { userId: parseActorUserId(queued.message.author.userId) },
@@ -6650,6 +6534,15 @@ function createSlackTurn(deps) {
6650
6534
  modelId: defaultModelId(botConfig)
6651
6535
  },
6652
6536
  async () => {
6537
+ await getConversationStore().recordActivity({
6538
+ activityAtMs: message.metadata.dateSent.getTime(),
6539
+ channelName,
6540
+ conversationId,
6541
+ destination,
6542
+ sessionSource: source,
6543
+ source: "slack",
6544
+ visibility: destinationVisibility
6545
+ });
6653
6546
  const content = parseContent(message);
6654
6547
  const strippedUserText = stripLeadingBotMention(
6655
6548
  stripLeadingSteeringOverride(content.topLevelText),
@@ -6663,7 +6556,7 @@ function createSlackTurn(deps) {
6663
6556
  userText: replaceTopLevelText(content, strippedUserText)
6664
6557
  };
6665
6558
  await Promise.all(
6666
- (options.queuedMessages ?? []).filter((queued) => !isResourceEventSlackMessage(queued.message)).map(
6559
+ (options.queuedMessages ?? []).map(
6667
6560
  (queued) => ensureSlackMessageActorIdentity(
6668
6561
  queued.message,
6669
6562
  teamId,
@@ -6677,9 +6570,6 @@ function createSlackTurn(deps) {
6677
6570
  if (options.execution) {
6678
6571
  executionActor = options.execution.dispatch.actor;
6679
6572
  credentialContext = options.execution.credentialContext;
6680
- } else if (isResourceEventSlackMessage(message)) {
6681
- executionActor = RESOURCE_EVENT_SYSTEM_ACTOR;
6682
- credentialContext = credentialContextForActor(executionActor);
6683
6573
  } else {
6684
6574
  executionActor = await ensureSlackMessageActorIdentity(
6685
6575
  message,
@@ -6769,7 +6659,7 @@ function createSlackTurn(deps) {
6769
6659
  omittedImageAttachmentCount: !isVisionEnabled() && hasPotentialImageAttachment(attachments) ? countPotentialImageAttachments(attachments) : 0,
6770
6660
  attachments: await deps.resolveUserAttachments(attachments, {
6771
6661
  threadId,
6772
- actorId: isResourceEventSlackMessage(queued.message) ? void 0 : queued.message.author.userId,
6662
+ actorId: queued.message.author.userId,
6773
6663
  channelId,
6774
6664
  runId,
6775
6665
  conversation: preparedState.conversation,
@@ -6859,8 +6749,7 @@ function createSlackTurn(deps) {
6859
6749
  await abandonTurnRecord({
6860
6750
  conversationId,
6861
6751
  turnId: activeTurnId,
6862
- // TODO(dcramer): Rename this legacy text in Slack and Conversation API Turn records together.
6863
- errorMessage: "Auth-parked session superseded by a new user message"
6752
+ errorMessage: "Auth-paused Turn superseded by new input"
6864
6753
  });
6865
6754
  markTurnClosed({
6866
6755
  conversation: preparedState.conversation,
@@ -7277,16 +7166,15 @@ function createSlackTurn(deps) {
7277
7166
  },
7278
7167
  history: piMessages,
7279
7168
  credentialContext,
7280
- // Always set the execution actor when known. Resource-event turns
7281
- // carry the system principal; interactive turns carry the Slack user.
7169
+ // Always set the execution Actor when known.
7282
7170
  actor: executionActor,
7283
7171
  slackConversation,
7284
- source: location ? { ...source, location } : source,
7172
+ source,
7173
+ ...location ? { location } : void 0,
7285
7174
  destination,
7286
7175
  publishExternally: shouldPublishExternally2(
7287
7176
  options.publishExternally
7288
7177
  ),
7289
- ...destinationVisibility ? { destinationVisibility } : void 0,
7290
7178
  surface: options.execution?.surface ?? "slack",
7291
7179
  dispatch: options.execution?.dispatch,
7292
7180
  toolChannelId,
@@ -7313,10 +7201,7 @@ function createSlackTurn(deps) {
7313
7201
  });
7314
7202
  }
7315
7203
  },
7316
- delivery: {
7317
- ...location && shouldPublishExternally2(options.publishExternally) ? { location } : void 0,
7318
- send: deliverAssistantMessage
7319
- },
7204
+ delivery: deliverAssistantMessage,
7320
7205
  durability: {
7321
7206
  onInputCommitted: options.ack,
7322
7207
  drainSteeringMessages,
@@ -7738,11 +7623,6 @@ async function persistConversationVisionCache(conversationId, vision) {
7738
7623
 
7739
7624
  // src/chat/runtime/conversation-message.ts
7740
7625
  var NON_TEXT_MESSAGE_TEXT = "[non-text message]";
7741
- function resourceEventType(entry) {
7742
- if (!entry.raw || typeof entry.raw !== "object") return void 0;
7743
- const raw = entry.raw;
7744
- return raw.event_type === "resource_event" && typeof raw.resource_event_type === "string" ? raw.resource_event_type : void 0;
7745
- }
7746
7626
  function resolveMessageText(args) {
7747
7627
  const text = normalizeConversationText(args.text);
7748
7628
  return text || NON_TEXT_MESSAGE_TEXT;
@@ -7767,7 +7647,6 @@ function toConversationMessage(args) {
7767
7647
  },
7768
7648
  meta: {
7769
7649
  attachmentCount: args.entry.attachments.length,
7770
- eventType: resourceEventType(args.entry),
7771
7650
  explicitMention: args.explicitMention,
7772
7651
  imageAttachmentCount: imageAttachmentCount > 0 ? imageAttachmentCount : void 0,
7773
7652
  imagesHydrated: !messageHasPotentialImageAttachment,
@@ -7937,14 +7816,14 @@ function createPrepareTurnState(deps) {
7937
7816
  }
7938
7817
 
7939
7818
  // src/chat/slack/dispatch-turn.ts
7940
- import { Message as Message5, ThreadImpl as ThreadImpl4 } from "chat";
7819
+ import { Message as Message4, ThreadImpl as ThreadImpl3 } from "chat";
7941
7820
  function createSlackDispatchTurnRunner(options) {
7942
7821
  return async function runSlackDispatchTurn(dispatch2, hooks) {
7943
7822
  const state = getStateAdapter();
7944
7823
  await state.connect();
7945
7824
  const conversationId = getDispatchConversationId(dispatch2);
7946
7825
  const adapter = options.getSlackAdapter();
7947
- const message = new Message5({
7826
+ const message = new Message4({
7948
7827
  id: getDispatchInputMessageId(dispatch2.id),
7949
7828
  threadId: conversationId,
7950
7829
  text: dispatch2.input,
@@ -7967,7 +7846,7 @@ function createSlackDispatchTurnRunner(options) {
7967
7846
  }
7968
7847
  });
7969
7848
  message.isMention = true;
7970
- const thread = new ThreadImpl4({
7849
+ const thread = new ThreadImpl3({
7971
7850
  adapter,
7972
7851
  stateAdapter: state,
7973
7852
  id: conversationId,
@@ -8307,10 +8186,10 @@ async function resolveSlackResumeUserActor(args) {
8307
8186
  async function resolveResumeExecutionIdentity(args) {
8308
8187
  const routing = args.routingContext;
8309
8188
  if (routing?.credentialContext) {
8310
- const actor2 = routing.dispatch?.actor ?? routing.actor ?? (!("type" in routing.credentialContext.actor) ? routing.credentialContext.actor : void 0);
8189
+ const actor2 = args.actor ?? routing.dispatch?.actor ?? routing.actor ?? (!("type" in routing.credentialContext.actor) ? routing.credentialContext.actor : void 0);
8311
8190
  return actor2 ? { actor: actor2, credentialContext: routing.credentialContext } : void 0;
8312
8191
  }
8313
- let actor = routing?.actor;
8192
+ let actor = args.actor ?? routing?.actor;
8314
8193
  if (!actor && isResourceEventConversationMessage(args.userMessage)) {
8315
8194
  actor = RESOURCE_EVENT_SYSTEM_ACTOR;
8316
8195
  }
@@ -8400,6 +8279,7 @@ async function runPausedTurnInContext(payload, options, runOptions) {
8400
8279
  return false;
8401
8280
  }
8402
8281
  const activeTurn = turn;
8282
+ const { dispatch: dispatch2, surface } = options.routingContext ?? {};
8403
8283
  const currentState = await getPersistedThreadState(
8404
8284
  payload.conversationId
8405
8285
  );
@@ -8408,7 +8288,7 @@ async function runPausedTurnInContext(payload, options, runOptions) {
8408
8288
  conversation,
8409
8289
  conversationId: payload.conversationId
8410
8290
  });
8411
- const dispatchId = activeTurn.dispatchId ?? options.routingContext?.dispatch?.id;
8291
+ const dispatchId = activeTurn.dispatchId ?? dispatch2?.id;
8412
8292
  const dispatchUserMessage = dispatchId ? conversation.messages.find(
8413
8293
  (message) => message.role === "user" && options.inputMessageIds?.includes(message.id)
8414
8294
  ) : void 0;
@@ -8425,6 +8305,7 @@ async function runPausedTurnInContext(payload, options, runOptions) {
8425
8305
  return false;
8426
8306
  }
8427
8307
  const identity = await resolveResumeExecutionIdentity({
8308
+ actor: activeTurn.actor,
8428
8309
  conversationId: payload.conversationId,
8429
8310
  routingContext: options.routingContext,
8430
8311
  teamId: destination.teamId,
@@ -8451,21 +8332,19 @@ async function runPausedTurnInContext(payload, options, runOptions) {
8451
8332
  const routingDestination = routing.destination;
8452
8333
  const turnMessages = activeTurn.turnStartMessageIndex === void 0 ? [] : activeTurn.piMessages.slice(activeTurn.turnStartMessageIndex);
8453
8334
  const recordDispatchOutcome = async (dispatchOutcome) => {
8454
- const dispatchId2 = options.routingContext?.dispatch?.id;
8455
- if (!dispatchId2) {
8335
+ if (!dispatch2) {
8456
8336
  return;
8457
8337
  }
8458
8338
  await recordTurnSummary({
8459
8339
  conversationId: payload.conversationId,
8460
8340
  destination: routingDestination,
8461
- destinationVisibility: options.routingContext?.destinationVisibility,
8462
- dispatchId: dispatchId2,
8341
+ dispatchId: dispatch2.id,
8463
8342
  dispatchOutcome,
8464
8343
  turnId: payload.turnId,
8465
8344
  sliceId: activeTurn.sliceId,
8466
8345
  source,
8467
8346
  state: "failed",
8468
- surface: options.routingContext?.surface ?? "slack"
8347
+ surface: surface ?? "slack"
8469
8348
  });
8470
8349
  };
8471
8350
  return {
@@ -8481,21 +8360,24 @@ async function runPausedTurnInContext(payload, options, runOptions) {
8481
8360
  ...getTurnUserReplyAttachmentContext(userMessage),
8482
8361
  text: userMessage.text
8483
8362
  },
8484
- // Pi history is SQL-authoritative: the resumed run reads its
8485
- // exact dispatch session so unrelated conversation input cannot
8486
- // gain system authority. Interactive turns retain their merged
8487
- // projection so queued steering remains visible.
8363
+ // A dispatch reads only history saved for this Turn. Other input
8364
+ // must not become part of a system Turn. Other Turns read
8365
+ // Conversation history. This keeps queued steering visible.
8488
8366
  history: dispatchId ? activeTurn.piMessages : await loadProjection({
8489
8367
  conversationId: payload.conversationId
8490
8368
  }),
8491
- ...options.routingContext,
8492
- credentialContext,
8493
8369
  actor,
8370
+ credentialContext,
8494
8371
  destination: routingDestination,
8372
+ ...dispatch2 ? { dispatch: dispatch2 } : void 0,
8373
+ ...routing.location ? { location: routing.location } : void 0,
8495
8374
  // Slack resume publishes unless the checkpoint opted out.
8496
8375
  // Missing means legacy/in-flight Slack turns still post.
8376
+ // TODO(dcramer): Remove this missing-as-publish fallback after no
8377
+ // stored Turn checkpoint can omit publishExternally.
8497
8378
  publishExternally: activeTurn.publishExternally !== false,
8498
8379
  source,
8380
+ ...surface ? { surface } : void 0,
8499
8381
  toolChannelId: destination.channelId,
8500
8382
  environment: {
8501
8383
  locationConfiguration
@@ -8709,30 +8591,812 @@ async function runNextPausedTurnInContext(conversationId, options, runOptions) {
8709
8591
  return false;
8710
8592
  }
8711
8593
 
8594
+ // src/chat/task-execution/conversation-turn.ts
8595
+ import { createHash } from "crypto";
8596
+
8597
+ // src/chat/task-execution/assistant-message.ts
8598
+ async function commitAssistantMessage(args) {
8599
+ const conversationMessageId = recordDeliveredAssistantMessage({
8600
+ conversation: args.conversation,
8601
+ sessionId: args.sessionId,
8602
+ source: args.source,
8603
+ text: args.text,
8604
+ userMessageId: args.userMessageId
8605
+ });
8606
+ if (args.publishedMessage?.providerMessageId) {
8607
+ markConversationMessage(args.conversation, conversationMessageId, {
8608
+ slackTs: args.publishedMessage.providerMessageId
8609
+ });
8610
+ }
8611
+ try {
8612
+ await persistWithRetry(
8613
+ () => commitAcceptedReply({
8614
+ ...args.agentMessage ? { agentMessage: args.agentMessage } : void 0,
8615
+ conversation: args.conversation,
8616
+ conversationMessageId,
8617
+ conversationId: args.conversationId,
8618
+ providerConversationBindings: args.publishedMessage?.providerConversationBindings
8619
+ })
8620
+ );
8621
+ } catch (error) {
8622
+ logException(
8623
+ new Error("Assistant message persistence failed"),
8624
+ "conversation.assistant.message_persist.failed",
8625
+ {
8626
+ "error.type": error instanceof Error ? error.name : typeof error
8627
+ }
8628
+ );
8629
+ }
8630
+ }
8631
+
8632
+ // src/chat/task-execution/mailbox-turn.ts
8633
+ import {
8634
+ createResourceEventSource,
8635
+ createLocalSource,
8636
+ createWebSource
8637
+ } from "@sentry/junior-plugin-api";
8638
+ function turnInputFactsFromConversationMessage(message, args) {
8639
+ if (isResourceEventConversationMessage(message)) {
8640
+ return {
8641
+ actor: args.savedActor ?? RESOURCE_EVENT_SYSTEM_ACTOR,
8642
+ author: message.author ?? RESOURCE_EVENT_MESSAGE_AUTHOR,
8643
+ // Stored Turns written before Source was saved can only restore the old
8644
+ // provider stand-in from the Conversation.
8645
+ source: args.savedSource ?? (args.location ? createWebSource(
8646
+ args.conversationId,
8647
+ args.visibility === "private" ? "private" : "public"
8648
+ ) : createLocalSource(args.conversationId))
8649
+ };
8650
+ }
8651
+ const actor = args.savedActor ?? createActor(message.author, {
8652
+ platform: "web",
8653
+ userId: message.author?.userId
8654
+ });
8655
+ if (actor?.platform !== "web") {
8656
+ return void 0;
8657
+ }
8658
+ return {
8659
+ actor,
8660
+ author: message.author ?? { userId: actor.userId },
8661
+ source: args.savedSource?.kind === "web" ? args.savedSource : createWebSource(
8662
+ args.conversationId,
8663
+ args.visibility === "private" ? "private" : "public"
8664
+ )
8665
+ };
8666
+ }
8667
+ function sourceFromTurnInput(args) {
8668
+ if (args.source.kind === "web") {
8669
+ return createWebSource(
8670
+ args.conversationId,
8671
+ args.visibility === "private" ? "private" : "public"
8672
+ );
8673
+ }
8674
+ return args.source;
8675
+ }
8676
+ function hasResourceEventActor(actors) {
8677
+ return Boolean(
8678
+ actors?.some(
8679
+ (actor) => actor.platform === "system" && actor.name === RESOURCE_EVENT_SYSTEM_ACTOR.name
8680
+ )
8681
+ );
8682
+ }
8683
+ async function getActiveConversationTurnId(conversationId) {
8684
+ const summaries = await listTurnSummaries(conversationId);
8685
+ const active = summaries.filter(
8686
+ (summary) => summary.surface === "api" && !summary.dispatchId && (summary.state === "paused" || summary.state === "running")
8687
+ );
8688
+ if (active.length > 1) {
8689
+ throw new Error(
8690
+ `Conversation ${conversationId} has multiple active web turns`
8691
+ );
8692
+ }
8693
+ const turnId = active[0]?.turnId;
8694
+ if (!turnId) return void 0;
8695
+ const record = await getTurnRecord(conversationId, turnId);
8696
+ return record && (record.source?.kind === "web" || !record.source && record.surface === "api") && !record.dispatchId && (record.state === "paused" || record.state === "running") ? turnId : void 0;
8697
+ }
8698
+ async function getActiveMailboxTurnId(conversationId) {
8699
+ const summaries = await listTurnSummaries(conversationId);
8700
+ const active = (await Promise.all(
8701
+ summaries.filter(
8702
+ (summary) => !summary.dispatchId && (summary.state === "paused" || summary.state === "running")
8703
+ ).map((summary) => getTurnRecord(conversationId, summary.turnId))
8704
+ )).filter(
8705
+ (record) => record && !record.dispatchId && (record.source?.kind === "web" || record.source?.kind === "resource_event" || !record.source && (record.surface === "api" || hasResourceEventActor(record.actors))) && (record.state === "paused" || record.state === "running")
8706
+ );
8707
+ if (active.length > 1) {
8708
+ throw new Error(
8709
+ `Conversation ${conversationId} has multiple active mailbox Turns`
8710
+ );
8711
+ }
8712
+ return active[0]?.turnId;
8713
+ }
8714
+ async function getAuthPausedConversationTurnId(conversationId) {
8715
+ const turnId = await getActiveConversationTurnId(conversationId);
8716
+ if (!turnId) return void 0;
8717
+ const record = await getTurnRecord(conversationId, turnId);
8718
+ return record?.state === "paused" && record.resumeReason === "auth" ? turnId : void 0;
8719
+ }
8720
+ function parseWebMessages(messages) {
8721
+ if (messages.length === 0) {
8722
+ return [];
8723
+ }
8724
+ const parsed = messages.map((message) => ({
8725
+ message,
8726
+ metadata: legacyWebMailboxMetadataSchema.safeParse(message.input.metadata)
8727
+ }));
8728
+ if (parsed.every((entry) => !entry.metadata.success)) {
8729
+ return [];
8730
+ }
8731
+ if (parsed.some((entry) => !entry.metadata.success)) {
8732
+ throw new Error("A Turn cannot combine different kinds of input");
8733
+ }
8734
+ return parsed.map((entry) => {
8735
+ if (!entry.metadata.success) {
8736
+ throw new Error("User message has invalid metadata");
8737
+ }
8738
+ const metadata = entry.metadata.data;
8739
+ const actor = {
8740
+ platform: "web",
8741
+ userId: metadata.authorUserId,
8742
+ email: metadata.authorEmail.trim().toLowerCase(),
8743
+ ...metadata.authorFullName ? { fullName: metadata.authorFullName } : void 0,
8744
+ ...metadata.authorUserName ? { userName: metadata.authorUserName } : void 0
8745
+ };
8746
+ return {
8747
+ actor,
8748
+ author: {
8749
+ email: actor.email,
8750
+ ...actor.fullName ? { fullName: actor.fullName } : void 0,
8751
+ userId: actor.userId,
8752
+ ...actor.userName ? { userName: actor.userName } : void 0
8753
+ },
8754
+ message: entry.message,
8755
+ source: createWebSource(entry.message.conversationId)
8756
+ };
8757
+ });
8758
+ }
8759
+ function parseResourceEventMessages(messages) {
8760
+ if (messages.length === 0) {
8761
+ return [];
8762
+ }
8763
+ if (!messages.every(
8764
+ (message) => message.source === "resource_event" && isResourceEventMailboxMetadata(message.input.metadata)
8765
+ )) {
8766
+ return [];
8767
+ }
8768
+ return messages.map((message) => {
8769
+ if (!isResourceEventMailboxMetadata(message.input.metadata)) {
8770
+ throw new Error("Resource event has invalid metadata");
8771
+ }
8772
+ return {
8773
+ actor: RESOURCE_EVENT_SYSTEM_ACTOR,
8774
+ author: RESOURCE_EVENT_MESSAGE_AUTHOR,
8775
+ message,
8776
+ source: createResourceEventSource({
8777
+ eventKey: message.input.metadata.resourceEvent.eventKey,
8778
+ eventType: message.input.metadata.resourceEvent.eventType,
8779
+ identifier: message.input.metadata.resourceEvent.identifier,
8780
+ namespace: message.input.metadata.resourceEvent.namespace
8781
+ })
8782
+ };
8783
+ });
8784
+ }
8785
+ async function resolveMailboxTurnWork(context) {
8786
+ const batch = parseWebMessages(context.attempt.messages);
8787
+ if (batch.length > 0) {
8788
+ return { kind: "mailbox", batch };
8789
+ }
8790
+ const resourceBatch = parseResourceEventMessages(context.attempt.messages);
8791
+ if (resourceBatch.length > 0) {
8792
+ return { kind: "mailbox", batch: resourceBatch };
8793
+ }
8794
+ if (context.attempt.messages.length > 0) {
8795
+ return void 0;
8796
+ }
8797
+ const turnId = await getActiveMailboxTurnId(context.conversationId);
8798
+ return turnId ? { kind: "resume", turnId } : void 0;
8799
+ }
8800
+
8801
+ // src/chat/task-execution/mailbox-input.ts
8802
+ function joinMailboxText(messages) {
8803
+ return messages.map((message) => message.input.text.trim()).filter(Boolean).join("\n\n");
8804
+ }
8805
+
8806
+ // src/chat/task-execution/conversation-turn.ts
8807
+ function stableHex(...parts) {
8808
+ return createHash("sha256").update(parts.join("\0")).digest("hex").slice(0, 24);
8809
+ }
8810
+ function captureConversationTurnFailure(args) {
8811
+ const eventId = logException(
8812
+ args.error,
8813
+ `conversation.turn.${args.failureCode}`,
8814
+ {
8815
+ conversationId: args.conversationId,
8816
+ ...args.runId ? { runId: args.runId } : void 0,
8817
+ turnId: args.turnId
8818
+ }
8819
+ );
8820
+ return typeof eventId === "string" ? eventId : void 0;
8821
+ }
8822
+ function hasLostTurnInputCommit(error) {
8823
+ const cause = getConversationTurnBoundaryError(error)?.cause ?? error;
8824
+ return isTurnInputCommitLostError(error) || isTurnInputCommitLostError(cause);
8825
+ }
8826
+ async function completeCancelledConversationTurn(args) {
8827
+ const pendingAuthorization = args.conversation.processing.pendingAuth?.sessionId === args.turnId ? args.conversation.processing.pendingAuth : void 0;
8828
+ await abandonTurnRecord({
8829
+ conversationId: args.conversationId,
8830
+ turnId: args.turnId,
8831
+ errorMessage: "Turn cancelled"
8832
+ });
8833
+ clearPendingAuth(args.conversation, args.turnId);
8834
+ markConversationMessage(args.conversation, args.userMessageId, {
8835
+ replied: false,
8836
+ skippedReason: "turn cancelled"
8837
+ });
8838
+ markTurnClosed({
8839
+ conversation: args.conversation,
8840
+ nowMs: Date.now(),
8841
+ sessionId: args.turnId
8842
+ });
8843
+ if (pendingAuthorization) {
8844
+ await deleteWebAuthorization({
8845
+ actorId: pendingAuthorization.actorId,
8846
+ conversationId: args.conversationId
8847
+ });
8848
+ }
8849
+ await persistThreadStateById(args.conversationId, {
8850
+ conversation: args.conversation,
8851
+ sandboxRef: args.sandboxRef
8852
+ });
8853
+ await new ConversationTurnLifecycleService(
8854
+ getConversationEventStore()
8855
+ ).complete({
8856
+ conversationId: args.conversationId,
8857
+ createdAtMs: Date.now(),
8858
+ outcome: "cancelled",
8859
+ turnId: args.turnId
8860
+ });
8861
+ await args.acknowledge();
8862
+ }
8863
+ function createConversationTurnWorker(agentRunner, publishMessage) {
8864
+ return async (context, resolved) => {
8865
+ const lifecycle = new ConversationTurnLifecycleService(
8866
+ getConversationEventStore()
8867
+ );
8868
+ const isResume = resolved.kind === "resume";
8869
+ let turnInputFacts;
8870
+ let text = "";
8871
+ let turnId = "";
8872
+ let userMessageId = "";
8873
+ let startedAtMs = Date.now();
8874
+ let inputMessageIds = [];
8875
+ const storedConversation = await getConversationStore().get({
8876
+ conversationId: context.conversationId
8877
+ });
8878
+ const mailboxDestination = resolved.kind === "mailbox" ? resolved.batch[0]?.message.destination : void 0;
8879
+ const destination = resolveConversationDestination({
8880
+ conversationId: context.conversationId,
8881
+ existing: context.destination ?? mailboxDestination ?? storedConversation?.destination
8882
+ });
8883
+ if (resolved.kind === "mailbox") {
8884
+ const first = resolved.batch[0];
8885
+ text = joinMailboxText(resolved.batch.map((entry) => entry.message));
8886
+ startedAtMs = first.message.createdAtMs;
8887
+ userMessageId = first.message.inboundMessageId;
8888
+ turnId = buildDeterministicTurnId(userMessageId);
8889
+ inputMessageIds = resolved.batch.map(
8890
+ (entry) => entry.message.inboundMessageId
8891
+ );
8892
+ turnInputFacts = first;
8893
+ } else {
8894
+ turnId = resolved.turnId;
8895
+ }
8896
+ const persisted = await getPersistedThreadState(context.conversationId);
8897
+ const conversation = coerceThreadConversationState(persisted);
8898
+ await hydrateConversationMessages({
8899
+ conversation,
8900
+ conversationId: context.conversationId
8901
+ });
8902
+ const savedTurn = isResume ? await getTurnRecord(context.conversationId, turnId) : void 0;
8903
+ let resumedResourceEvent = false;
8904
+ if (isResume) {
8905
+ const userMessage = getTurnUserMessage(conversation, turnId);
8906
+ if (!userMessage) {
8907
+ throw new Error(
8908
+ `Unable to locate the persisted user message for Turn "${turnId}"`
8909
+ );
8910
+ }
8911
+ resumedResourceEvent = isResourceEventConversationMessage(userMessage);
8912
+ turnInputFacts = turnInputFactsFromConversationMessage(userMessage, {
8913
+ conversationId: context.conversationId,
8914
+ location: storedConversation?.location,
8915
+ savedActor: savedTurn?.actor,
8916
+ savedSource: savedTurn?.source,
8917
+ visibility: storedConversation?.visibility
8918
+ });
8919
+ userMessageId = userMessage.id;
8920
+ text = userMessage.text;
8921
+ startedAtMs = userMessage.createdAtMs;
8922
+ inputMessageIds = [userMessageId];
8923
+ }
8924
+ if (!turnInputFacts) {
8925
+ throw new Error(
8926
+ `Resumed Turn is missing an Actor for Conversation ${context.conversationId}`
8927
+ );
8928
+ }
8929
+ const { actor, author } = turnInputFacts;
8930
+ const source = sourceFromTurnInput({
8931
+ conversationId: context.conversationId,
8932
+ source: turnInputFacts.source,
8933
+ visibility: storedConversation?.visibility
8934
+ });
8935
+ const webActor = actor.platform === "web" ? actor : void 0;
8936
+ const publish = savedTurn?.publishExternally ?? Boolean(
8937
+ storedConversation?.location && (source.kind === "resource_event" || resumedResourceEvent)
8938
+ );
8939
+ const surface = publish ? "slack" : "api";
8940
+ return await withLogContext(
8941
+ {
8942
+ conversationId: context.conversationId,
8943
+ platform: actor.platform,
8944
+ ...webActor ? {
8945
+ userId: webActor.userId,
8946
+ ...webActor.userName ? { userName: webActor.userName } : void 0
8947
+ } : void 0
8948
+ },
8949
+ async () => {
8950
+ let acknowledged = isResume || context.attempt.messages.length === 0;
8951
+ const acknowledge = async () => {
8952
+ if (acknowledged) {
8953
+ return;
8954
+ }
8955
+ try {
8956
+ await context.attempt.ack();
8957
+ } catch {
8958
+ throw new TurnInputCommitLostError(
8959
+ `Conversation work lease lost before mailbox Message acknowledgement for ${context.conversationId}`
8960
+ );
8961
+ }
8962
+ acknowledged = true;
8963
+ };
8964
+ let sandboxRef = getPersistedSandboxState(persisted);
8965
+ const initialSandboxRef = sandboxRef;
8966
+ const stopSignal = context.stopSignal?.();
8967
+ const completeCancelledTurn = async () => {
8968
+ try {
8969
+ await completeCancelledConversationTurn({
8970
+ acknowledge,
8971
+ conversation,
8972
+ conversationId: context.conversationId,
8973
+ sandboxRef,
8974
+ turnId,
8975
+ userMessageId
8976
+ });
8977
+ } catch (error) {
8978
+ if (hasLostTurnInputCommit(error)) {
8979
+ return { status: "lost_lease" };
8980
+ }
8981
+ throw error;
8982
+ }
8983
+ return { status: "completed" };
8984
+ };
8985
+ if (isResume) {
8986
+ if (stopSignal?.aborted) {
8987
+ return await completeCancelledTurn();
8988
+ }
8989
+ } else {
8990
+ upsertConversationMessage(conversation, {
8991
+ id: userMessageId,
8992
+ role: "user",
8993
+ text: normalizeConversationText(text),
8994
+ createdAtMs: startedAtMs,
8995
+ author,
8996
+ meta: {
8997
+ explicitMention: true,
8998
+ replied: false,
8999
+ ...source.kind === "web" ? { source: "web" } : void 0
9000
+ }
9001
+ });
9002
+ await persistConversationMessages({
9003
+ conversation,
9004
+ conversationId: context.conversationId
9005
+ });
9006
+ await lifecycle.start({
9007
+ conversationId: context.conversationId,
9008
+ createdAtMs: Date.now(),
9009
+ inputMessageIds,
9010
+ surface,
9011
+ turnId
9012
+ });
9013
+ if (stopSignal?.aborted) {
9014
+ return await completeCancelledTurn();
9015
+ }
9016
+ startActiveTurn({
9017
+ conversation,
9018
+ nextTurnId: turnId
9019
+ });
9020
+ }
9021
+ let currentRunId;
9022
+ let assistantMessageDelivered = false;
9023
+ let failureCode = "persistence_failed";
9024
+ let modelFailureEventId;
9025
+ let modelFailureCaptureAttempted = false;
9026
+ let completedSuccessfully = false;
9027
+ const deliverAssistantMessage = async (value) => {
9028
+ const agentMessage = typeof value === "string" ? void 0 : value;
9029
+ const replyText = typeof value === "string" ? value : getAssistantReplyText(value);
9030
+ if (!replyText?.trim()) {
9031
+ return;
9032
+ }
9033
+ failureCode = "delivery_failed";
9034
+ const location = storedConversation?.location;
9035
+ if (publish && (!location || !publishMessage)) {
9036
+ throw new Error(
9037
+ `Conversation ${context.conversationId} cannot publish its system Turn`
9038
+ );
9039
+ }
9040
+ const publishedMessage = publish && location && publishMessage ? await publishMessage({
9041
+ conversationId: context.conversationId,
9042
+ location,
9043
+ text: replyText
9044
+ }) : void 0;
9045
+ await commitAssistantMessage({
9046
+ ...agentMessage ? { agentMessage } : void 0,
9047
+ conversation,
9048
+ conversationId: context.conversationId,
9049
+ ...publishedMessage ? { publishedMessage } : void 0,
9050
+ sessionId: turnId,
9051
+ ...publishedMessage ? { source: "slack" } : source.kind === "web" ? { source: "web" } : void 0,
9052
+ text: replyText,
9053
+ userMessageId
9054
+ });
9055
+ assistantMessageDelivered = true;
9056
+ failureCode = "agent_run_failed";
9057
+ };
9058
+ try {
9059
+ if (stopSignal?.aborted) {
9060
+ return await completeCancelledTurn();
9061
+ }
9062
+ if (!isResume) {
9063
+ const pendingAuthorizationActorId = conversation.processing.pendingAuth?.actorId;
9064
+ const authParked = (await listTurnSummaries(context.conversationId)).filter(
9065
+ (summary) => summary.surface === "api" && !summary.dispatchId && summary.state === "paused" && summary.resumeReason === "auth"
9066
+ );
9067
+ for (const parked of authParked) {
9068
+ if (stopSignal?.aborted) {
9069
+ return await completeCancelledTurn();
9070
+ }
9071
+ await abandonTurnRecord({
9072
+ conversationId: context.conversationId,
9073
+ turnId: parked.turnId,
9074
+ errorMessage: "Auth-paused Turn superseded by new input"
9075
+ });
9076
+ markTurnClosed({
9077
+ conversation,
9078
+ nowMs: Date.now(),
9079
+ sessionId: parked.turnId
9080
+ });
9081
+ }
9082
+ if (authParked.length > 0 && pendingAuthorizationActorId) {
9083
+ await deleteWebAuthorization({
9084
+ actorId: pendingAuthorizationActorId,
9085
+ conversationId: context.conversationId
9086
+ });
9087
+ }
9088
+ }
9089
+ await persistThreadStateById(context.conversationId, {
9090
+ conversation
9091
+ });
9092
+ if (stopSignal?.aborted) {
9093
+ return await completeCancelledTurn();
9094
+ }
9095
+ const piMessages = await loadProjection({
9096
+ conversationId: context.conversationId
9097
+ });
9098
+ failureCode = "agent_run_failed";
9099
+ currentRunId = `conversation-run:${stableHex(turnId, String(startedAtMs))}`;
9100
+ setTags({ runId: currentRunId });
9101
+ const outcome = await executeTurn(
9102
+ agentRunner,
9103
+ {
9104
+ conversationId: context.conversationId,
9105
+ turnId,
9106
+ runId: currentRunId,
9107
+ instruction: {
9108
+ text,
9109
+ context: buildConversationContext(conversation, {
9110
+ excludeMessageId: userMessageId
9111
+ })
9112
+ },
9113
+ history: piMessages,
9114
+ actor,
9115
+ credentialContext: credentialContextForActor(actor),
9116
+ // TODO(dcramer): Remove AgentRun.destination after agent and tool
9117
+ // code reads AgentRun.location and no Run consumer needs it.
9118
+ destination,
9119
+ // TODO(dcramer): Remove AgentRun.publishExternally after the
9120
+ // saved Turn publish choice controls optional Delivery.
9121
+ publishExternally: publish,
9122
+ source,
9123
+ ...storedConversation?.location ? { location: storedConversation.location } : void 0,
9124
+ surface,
9125
+ ...stopSignal ? { signal: stopSignal } : void 0,
9126
+ ...webActor ? {
9127
+ authorization: createWebAuthorization({
9128
+ actorId: webActor.userId,
9129
+ conversationId: context.conversationId
9130
+ })
9131
+ } : { disabledFeatures: ["interactive-auth"] },
9132
+ state: {
9133
+ pendingAuth: conversation.processing.pendingAuth,
9134
+ sandboxRef
9135
+ },
9136
+ delivery: deliverAssistantMessage,
9137
+ durability: {
9138
+ onInputCommitted: acknowledge,
9139
+ shouldYield: context.shouldYield,
9140
+ onSandboxRefChanged: async (nextSandboxRef) => {
9141
+ sandboxRef = nextSandboxRef;
9142
+ await persistThreadStateById(context.conversationId, {
9143
+ conversation,
9144
+ sandboxRef
9145
+ });
9146
+ },
9147
+ recordPendingAuth: async (pendingAuth) => {
9148
+ conversation.processing.pendingAuth = pendingAuth;
9149
+ await persistThreadStateById(context.conversationId, {
9150
+ conversation,
9151
+ sandboxRef
9152
+ });
9153
+ }
9154
+ }
9155
+ },
9156
+ async (result) => {
9157
+ if (stopSignal?.aborted) {
9158
+ throw stopSignal.reason ?? new DOMException("Turn cancelled", "AbortError");
9159
+ }
9160
+ modelFailureCaptureAttempted = result.diagnostics.outcome !== "success";
9161
+ const finalized = finalizeFailedTurnReplyWithEvent({
9162
+ reply: result,
9163
+ logException
9164
+ });
9165
+ const modelFailureReason = finalized.failureReason;
9166
+ const reply = finalized.reply;
9167
+ modelFailureEventId = finalized.eventId;
9168
+ if (reply.diagnostics.outcome !== "success") {
9169
+ await deliverAssistantMessage(reply.text);
9170
+ }
9171
+ const completedState = buildDeliveredTurnStatePatch({
9172
+ conversation,
9173
+ reply,
9174
+ sessionId: turnId,
9175
+ userMessageId
9176
+ });
9177
+ await persistThreadStateById(context.conversationId, {
9178
+ conversation: completedState.conversation,
9179
+ sandboxRef: reply.sandboxRef ?? sandboxRef
9180
+ });
9181
+ if (reply.piMessages?.length) {
9182
+ const latest = await getTurnRecord(
9183
+ context.conversationId,
9184
+ turnId
9185
+ );
9186
+ await saveTurnCheckpoint({
9187
+ mode: "completed",
9188
+ conversationId: context.conversationId,
9189
+ turnId,
9190
+ sliceId: latest?.sliceId ?? 1,
9191
+ messages: reply.piMessages,
9192
+ durationMs: reply.diagnostics.durationMs,
9193
+ usage: reply.diagnostics.usage,
9194
+ // TODO(dcramer): Remove checkpoint Destination after resume
9195
+ // reads the Conversation Location.
9196
+ destination,
9197
+ publishExternally: publish,
9198
+ source,
9199
+ actor,
9200
+ surface
9201
+ });
9202
+ }
9203
+ completedSuccessfully = reply.diagnostics.outcome === "success";
9204
+ return completedSuccessfully ? {
9205
+ outcome: assistantMessageDelivered ? "success" : "no_reply"
9206
+ } : {
9207
+ ...modelFailureEventId ? { eventId: modelFailureEventId } : void 0,
9208
+ failureCode: "model_execution_failed",
9209
+ ...modelFailureReason ? { failureReason: modelFailureReason } : void 0,
9210
+ outcome: "failed"
9211
+ };
9212
+ }
9213
+ );
9214
+ if (outcome.status !== "completed" && stopSignal?.aborted) {
9215
+ return await completeCancelledTurn();
9216
+ }
9217
+ if (outcome.status === "suspended") {
9218
+ return { status: "yielded" };
9219
+ }
9220
+ if (outcome.status === "awaiting_auth") {
9221
+ completeAuthPauseTurn({
9222
+ conversation,
9223
+ sessionId: turnId
9224
+ });
9225
+ await persistThreadStateById(context.conversationId, {
9226
+ conversation,
9227
+ sandboxRef
9228
+ });
9229
+ await acknowledge();
9230
+ return { status: "paused" };
9231
+ }
9232
+ if (completedSuccessfully) {
9233
+ try {
9234
+ await scheduleSessionCompletedPluginTasks(
9235
+ {
9236
+ conversationId: context.conversationId,
9237
+ sessionId: turnId
9238
+ },
9239
+ {
9240
+ send: async (message) => {
9241
+ try {
9242
+ await processPluginTask(message);
9243
+ } catch (error) {
9244
+ logException(
9245
+ error,
9246
+ "conversation.plugin.session_completion_task.failed",
9247
+ {
9248
+ conversationId: context.conversationId,
9249
+ pluginName: message.plugin,
9250
+ taskName: message.name,
9251
+ turnId
9252
+ }
9253
+ );
9254
+ }
9255
+ }
9256
+ }
9257
+ );
9258
+ } catch (error) {
9259
+ logException(
9260
+ error,
9261
+ "conversation.plugin.session_completion_task.failed",
9262
+ {
9263
+ conversationId: context.conversationId,
9264
+ turnId
9265
+ }
9266
+ );
9267
+ }
9268
+ }
9269
+ await acknowledge();
9270
+ return { status: "completed" };
9271
+ } catch (error) {
9272
+ const failure = error instanceof AgentRunError ? error.cause : error;
9273
+ if (hasLostTurnInputCommit(failure)) {
9274
+ return { status: "lost_lease" };
9275
+ }
9276
+ if (stopSignal?.aborted) {
9277
+ return await completeCancelledTurn();
9278
+ }
9279
+ if (!context.attempt.isFinalAttempt) {
9280
+ throw failure;
9281
+ }
9282
+ const failureEventId = modelFailureCaptureAttempted && failureCode === "agent_run_failed" ? modelFailureEventId : captureConversationTurnFailure({
9283
+ conversationId: context.conversationId,
9284
+ error: failure,
9285
+ failureCode,
9286
+ runId: currentRunId,
9287
+ turnId
9288
+ });
9289
+ try {
9290
+ markTurnFailed({
9291
+ conversation,
9292
+ nowMs: Date.now(),
9293
+ sessionId: turnId,
9294
+ userMessageId,
9295
+ markConversationMessage
9296
+ });
9297
+ await persistThreadStateById(context.conversationId, {
9298
+ conversation,
9299
+ sandboxRef: initialSandboxRef ?? null
9300
+ });
9301
+ } catch (persistenceError) {
9302
+ captureConversationTurnFailure({
9303
+ conversationId: context.conversationId,
9304
+ error: persistenceError,
9305
+ failureCode: "persistence_failed",
9306
+ runId: currentRunId,
9307
+ turnId
9308
+ });
9309
+ }
9310
+ await lifecycle.fail({
9311
+ conversationId: context.conversationId,
9312
+ createdAtMs: Date.now(),
9313
+ ...failureEventId ? { eventId: failureEventId } : void 0,
9314
+ failureCode,
9315
+ turnId
9316
+ });
9317
+ await acknowledge();
9318
+ return { status: "completed" };
9319
+ }
9320
+ }
9321
+ );
9322
+ };
9323
+ }
9324
+
9325
+ // src/chat/providers/slack/system-turn.ts
9326
+ function createSlackSystemTurnPublisher(args) {
9327
+ return async ({ conversationId, location, text }) => {
9328
+ if (location.provider !== "slack") {
9329
+ throw new Error(
9330
+ `Slack system Turn cannot publish to ${location.provider} Location`
9331
+ );
9332
+ }
9333
+ let messageIds;
9334
+ try {
9335
+ messageIds = await runWithSlackInstallation({
9336
+ adapter: args.getSlackAdapter(),
9337
+ installation: { teamId: location.teamId },
9338
+ state: args.state,
9339
+ task: async () => await sendSlackReply({
9340
+ channelId: location.channelId,
9341
+ conversationId,
9342
+ text,
9343
+ ...location.threadTs ? { threadTs: location.threadTs } : void 0
9344
+ })
9345
+ });
9346
+ } catch (error) {
9347
+ if (isRetryableSlackPostError(error)) {
9348
+ throw new RetryableDeliveryError(error);
9349
+ }
9350
+ throw error;
9351
+ }
9352
+ const providerMessageId = messageIds.at(-1);
9353
+ const providerConversationId = location.threadTs ?? messageIds[0];
9354
+ return {
9355
+ ...providerMessageId ? { providerMessageId } : void 0,
9356
+ ...providerConversationId ? {
9357
+ providerConversationBindings: [
9358
+ {
9359
+ provider: "slack",
9360
+ providerDestinationId: location.channelId,
9361
+ providerTenantId: location.teamId,
9362
+ providerConversationId
9363
+ }
9364
+ ]
9365
+ } : void 0
9366
+ };
9367
+ };
9368
+ }
9369
+
8712
9370
  // src/chat/app/conversation-work.ts
8713
9371
  function createConversationWork(options) {
8714
- const apiTurnCancellation = createApiTurnCancellation();
8715
9372
  const pausedTurns = createPausedTurns({
8716
9373
  conversationStore: options.conversationStore,
8717
9374
  queue: options.queue,
8718
9375
  ...options.state ? { state: options.state } : void 0
8719
9376
  });
8720
- const runtime = createSlackRuntime({
9377
+ const baseRuntime = createSlackRuntime({
8721
9378
  getSlackAdapter: options.getSlackAdapter,
8722
9379
  pausedTurns,
9380
+ ...options.sendPluginTask ? { sendPluginTask: options.sendPluginTask } : void 0,
8723
9381
  services: {
8724
9382
  ...options.services,
8725
9383
  agentRunner: options.agentRunner
8726
9384
  }
8727
9385
  });
9386
+ const runtime = options.wrapRuntime?.(baseRuntime) ?? baseRuntime;
9387
+ const scheduleCompletedPluginTasks = options.sendPluginTask ? async (params) => await scheduleSessionCompletedPluginTasks(params, {
9388
+ send: options.sendPluginTask
9389
+ }) : void 0;
8728
9390
  const slackWorker = createSlackConversationWorker({
8729
9391
  getSlackAdapter: options.getSlackAdapter,
8730
- conversationStore: options.conversationStore,
8731
9392
  runNextPausedTurn: async (conversationId, runOptions) => await runNextPausedTurn(
8732
9393
  conversationId,
8733
9394
  {
8734
9395
  agentRunner: options.agentRunner,
8735
- wakePausedTurn: pausedTurns.wake
9396
+ wakePausedTurn: pausedTurns.wake,
9397
+ ...scheduleCompletedPluginTasks ? {
9398
+ scheduleSessionCompletedPluginTasks: scheduleCompletedPluginTasks
9399
+ } : void 0
8736
9400
  },
8737
9401
  runOptions
8738
9402
  ),
@@ -8747,13 +9411,24 @@ function createConversationWork(options) {
8747
9411
  agentRunner: options.agentRunner,
8748
9412
  inputMessageIds: [getDispatchInputMessageId(dispatch2.id)],
8749
9413
  routingContext: buildDispatchRoutingContext(dispatch2),
8750
- wakePausedTurn: pausedTurns.wake
9414
+ wakePausedTurn: pausedTurns.wake,
9415
+ ...scheduleCompletedPluginTasks ? {
9416
+ scheduleSessionCompletedPluginTasks: scheduleCompletedPluginTasks
9417
+ } : void 0
8751
9418
  },
8752
9419
  { shouldYield: hooks.shouldYield }
8753
9420
  );
8754
9421
  },
8755
9422
  runTurn: runtime.runDispatchTurn
8756
9423
  });
9424
+ const invocationWorker = createAgentInvocationWorker(options.agentRunner);
9425
+ const conversationTurnWorker = createConversationTurnWorker(
9426
+ options.agentRunner,
9427
+ createSlackSystemTurnPublisher({
9428
+ getSlackAdapter: options.getSlackAdapter,
9429
+ state: options.state
9430
+ })
9431
+ );
8757
9432
  const destinationWorker = async (context) => {
8758
9433
  const destination = context.destination;
8759
9434
  if (!destination) {
@@ -8768,24 +9443,25 @@ function createConversationWork(options) {
8768
9443
  `Conversation ${context.conversationId} has a ${destination.platform} destination but no matching conversation worker`
8769
9444
  );
8770
9445
  };
8771
- const providerWorker = createAgentDispatchWorkRouter({
8772
- dispatchWorker,
8773
- fallbackWorker: destinationWorker
8774
- });
9446
+ const run = async (context) => {
9447
+ const mailboxTurn = await resolveMailboxTurnWork(context);
9448
+ if (mailboxTurn) {
9449
+ return await conversationTurnWorker(context, mailboxTurn);
9450
+ }
9451
+ const invocationId = await resolveAgentInvocationId(context);
9452
+ if (invocationId) {
9453
+ return await invocationWorker(context, invocationId);
9454
+ }
9455
+ const dispatchId = await resolveAgentDispatchId(context);
9456
+ if (dispatchId) {
9457
+ return await dispatchWorker(context, dispatchId);
9458
+ }
9459
+ return await destinationWorker(context);
9460
+ };
8775
9461
  return {
8776
- apiTurnCancellation,
8777
9462
  conversationStore: options.conversationStore,
8778
9463
  queue: options.queue,
8779
- run: routeApiTurnWork({
8780
- apiTurnWorker: createApiTurnWorker(
8781
- options.agentRunner,
8782
- apiTurnCancellation
8783
- ),
8784
- fallbackWorker: routeAgentInvocationWork({
8785
- invocationWorker: createAgentInvocationWorker(options.agentRunner),
8786
- fallbackWorker: providerWorker
8787
- })
8788
- }),
9464
+ run,
8789
9465
  runtime,
8790
9466
  state: options.state
8791
9467
  };
@@ -8865,7 +9541,7 @@ async function publicArtifactGET(args) {
8865
9541
  }
8866
9542
 
8867
9543
  // src/chat/event-tasks/ingest.ts
8868
- import { createHash } from "crypto";
9544
+ import { createHash as createHash2 } from "crypto";
8869
9545
  import {
8870
9546
  createSlackSource as createSlackSource3,
8871
9547
  RESOURCE_EVENT_SUMMARY_MAX_LENGTH,
@@ -8873,7 +9549,7 @@ import {
8873
9549
  resourceEventSchema
8874
9550
  } from "@sentry/junior-plugin-api";
8875
9551
  function eventTaskDispatchKey(taskId, namespace, eventKey) {
8876
- return `event-task:${createHash("sha256").update(`${taskId}\0${namespace}\0${eventKey}`).digest("hex").slice(0, 32)}`;
9552
+ return `event-task:${createHash2("sha256").update(`${taskId}\0${namespace}\0${eventKey}`).digest("hex").slice(0, 32)}`;
8877
9553
  }
8878
9554
  function oneLine(value) {
8879
9555
  return value.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim().slice(0, 512);
@@ -9014,8 +9690,8 @@ function createResourceEventAppPublisher(args) {
9014
9690
  };
9015
9691
  }
9016
9692
 
9017
- // src/chat/api-turns/stop.ts
9018
- async function stopApiConversationTurn(args) {
9693
+ // src/chat/conversations/stop.ts
9694
+ async function stopConversationTurn(args) {
9019
9695
  const nowMs = args.nowMs ?? Date.now();
9020
9696
  const stop = async () => await stopConversationWork({
9021
9697
  conversationId: args.conversationId,
@@ -9024,7 +9700,7 @@ async function stopApiConversationTurn(args) {
9024
9700
  state: args.state
9025
9701
  });
9026
9702
  let result = await stop();
9027
- if (result.status === "no_work" && await getAuthPausedApiTurnId(args.conversationId)) {
9703
+ if (result.status === "no_work" && await getAuthPausedConversationTurnId(args.conversationId)) {
9028
9704
  const conversation = await getConversation({
9029
9705
  conversationId: args.conversationId,
9030
9706
  state: args.state
@@ -9042,7 +9718,7 @@ async function stopApiConversationTurn(args) {
9042
9718
  await ensureConversationWake({
9043
9719
  conversationId: args.conversationId,
9044
9720
  conversationStore: args.conversationStore,
9045
- idempotencyKey: `api-stop:${args.conversationId}:${result.runId}`,
9721
+ idempotencyKey: `conversation-stop:${args.conversationId}:${result.runId}`,
9046
9722
  nowMs,
9047
9723
  queue: args.queue,
9048
9724
  replaceExistingWake: true,
@@ -9096,7 +9772,7 @@ function createAcpConversations(options) {
9096
9772
  if (!await hasConversationAccess(conversationId, user)) {
9097
9773
  return "not_found";
9098
9774
  }
9099
- await stopApiConversationTurn({
9775
+ await stopConversationTurn({
9100
9776
  conversationId,
9101
9777
  conversationStore: options.conversationStore,
9102
9778
  queue: options.queue,
@@ -9105,7 +9781,7 @@ function createAcpConversations(options) {
9105
9781
  return "cancelled";
9106
9782
  },
9107
9783
  async create({ conversationId, user }) {
9108
- await recordApiConversationActivity({
9784
+ await recordWebConversationActivity({
9109
9785
  actor: actorFromUser(user),
9110
9786
  conversationId,
9111
9787
  conversationStore: options.conversationStore,
@@ -9124,10 +9800,10 @@ function createAcpConversations(options) {
9124
9800
  options.eventStore,
9125
9801
  conversationId
9126
9802
  );
9127
- if (await getAuthPausedApiTurnId(conversationId)) {
9803
+ if (await getAuthPausedConversationTurnId(conversationId)) {
9128
9804
  return { status: "active" };
9129
9805
  }
9130
- const admission = await appendAndEnqueueApiConversationMessage(
9806
+ const result = await appendAndEnqueueWebMessage(
9131
9807
  {
9132
9808
  actor: actorFromUser(user),
9133
9809
  conversationId,
@@ -9141,12 +9817,12 @@ function createAcpConversations(options) {
9141
9817
  state: options.state
9142
9818
  }
9143
9819
  );
9144
- if (admission.status === "active") return { status: "active" };
9820
+ if (result.status === "active") return { status: "active" };
9145
9821
  return {
9146
- afterCursor: admission.status === "duplicate" ? 0 : currentCursor,
9147
- messageId: admission.messageId,
9822
+ afterCursor: result.status === "duplicate" ? 0 : currentCursor,
9823
+ messageId: result.messageId,
9148
9824
  status: "accepted",
9149
- turnId: apiTurnIdForMessage(admission.messageId)
9825
+ turnId: conversationTurnIdForMessage(result.messageId)
9150
9826
  };
9151
9827
  },
9152
9828
  async readMessages(conversationId) {
@@ -9204,12 +9880,12 @@ function createAcpConversations(options) {
9204
9880
  }
9205
9881
 
9206
9882
  // src/api/acp/route.ts
9207
- import { createHash as createHash4 } from "crypto";
9883
+ import { createHash as createHash5 } from "crypto";
9208
9884
  import * as acp4 from "@agentclientprotocol/sdk";
9209
9885
 
9210
9886
  // src/api/acp/auth.ts
9211
9887
  import {
9212
- createHash as createHash3,
9888
+ createHash as createHash4,
9213
9889
  randomBytes,
9214
9890
  randomUUID as randomUUID2,
9215
9891
  timingSafeEqual as timingSafeEqual3
@@ -9254,7 +9930,7 @@ async function fenceLock(state, lock, ttlMs = MUTATION_LOCK_TTL_MS) {
9254
9930
  }
9255
9931
 
9256
9932
  // src/api/acp/transport.ts
9257
- import { createHash as createHash2, randomUUID } from "crypto";
9933
+ import { createHash as createHash3, randomUUID } from "crypto";
9258
9934
  import * as acp2 from "@agentclientprotocol/sdk";
9259
9935
  import { userSchema } from "@sentry/junior-plugin-api";
9260
9936
  import { z as z7 } from "zod";
@@ -9434,8 +10110,8 @@ var acpRequestReceiptSchema = z7.object({
9434
10110
  sessionId: z7.string().min(1).optional()
9435
10111
  }).strict();
9436
10112
  var acpStreamCursorSchema = z7.object({ itemId: z7.string().min(1) }).strict();
9437
- function stableHex(value) {
9438
- return createHash2("sha256").update(value).digest("hex").slice(0, 32);
10113
+ function stableHex2(value) {
10114
+ return createHash3("sha256").update(value).digest("hex").slice(0, 32);
9439
10115
  }
9440
10116
  function connectionKey(connectionId) {
9441
10117
  return `junior:acp:v1:connection:${connectionId}`;
@@ -9450,7 +10126,7 @@ function connectionLockKey(connectionId) {
9450
10126
  return `${connectionKey(connectionId)}:lock`;
9451
10127
  }
9452
10128
  function streamKey(route) {
9453
- const suffix = route.sessionId ? `session:${stableHex(route.sessionId)}` : "connection";
10129
+ const suffix = route.sessionId ? `session:${stableHex2(route.sessionId)}` : "connection";
9454
10130
  return `${connectionKey(route.connectionId)}:stream:${suffix}`;
9455
10131
  }
9456
10132
  function streamListKey(route) {
@@ -9466,7 +10142,7 @@ function streamAppendLockKey(route) {
9466
10142
  return `${streamKey(route)}:append`;
9467
10143
  }
9468
10144
  function requestStreamItemId(requestKey2, index) {
9469
- return `acp-item:${stableHex(`${requestKey2}:${index}`)}`;
10145
+ return `acp-item:${stableHex2(`${requestKey2}:${index}`)}`;
9470
10146
  }
9471
10147
  function parseStreamItem(value) {
9472
10148
  return storedAcpStreamItemSchema.parse(value);
@@ -10075,7 +10751,7 @@ function authorizationPointerLockKey(connectionId) {
10075
10751
  return `${authorizationPointerKey(connectionId)}:lock`;
10076
10752
  }
10077
10753
  function credentialHash(value) {
10078
- return createHash3("sha256").update(value).digest("hex");
10754
+ return createHash4("sha256").update(value).digest("hex");
10079
10755
  }
10080
10756
  function createUserCode() {
10081
10757
  const value = randomBytes(6).toString("hex").toUpperCase();
@@ -10539,8 +11215,8 @@ function promptText(prompt) {
10539
11215
  }
10540
11216
  return text;
10541
11217
  }
10542
- function stableHex2(value, length = 32) {
10543
- return createHash4("sha256").update(value).digest("hex").slice(0, length);
11218
+ function stableHex3(value, length = 32) {
11219
+ return createHash5("sha256").update(value).digest("hex").slice(0, length);
10544
11220
  }
10545
11221
  function canonicalJson(value) {
10546
11222
  if (Array.isArray(value)) return value.map(canonicalJson);
@@ -10550,11 +11226,11 @@ function canonicalJson(value) {
10550
11226
  );
10551
11227
  }
10552
11228
  function requestKey(call) {
10553
- const id = call.id === null ? "null" : `${typeof call.id}:${stableHex2(String(call.id))}`;
11229
+ const id = call.id === null ? "null" : `${typeof call.id}:${stableHex3(String(call.id))}`;
10554
11230
  const payload = JSON.stringify(
10555
11231
  canonicalJson({ method: call.method, params: call.params ?? null })
10556
11232
  );
10557
- return `${id}:${stableHex2(payload)}`;
11233
+ return `${id}:${stableHex3(payload)}`;
10558
11234
  }
10559
11235
  function sessionIdFromCall(call) {
10560
11236
  if (!call) return void 0;
@@ -10607,7 +11283,7 @@ async function createSession(args) {
10607
11283
  args.call.params
10608
11284
  );
10609
11285
  rejectUnsupportedMcpServers(params.mcpServers);
10610
- const sessionId = `${ACP_CONVERSATION_PREFIX}${stableHex2(
11286
+ const sessionId = `${ACP_CONVERSATION_PREFIX}${stableHex3(
10611
11287
  `${args.connection.nonce}:${args.requestKey}`
10612
11288
  )}`;
10613
11289
  await args.conversations.create({
@@ -10621,16 +11297,16 @@ async function acceptPrompt(args) {
10621
11297
  promptParamsSchema,
10622
11298
  args.call.params
10623
11299
  );
10624
- const admission = await args.conversations.prompt({
11300
+ const result = await args.conversations.prompt({
10625
11301
  conversationId: params.sessionId,
10626
11302
  idempotencyKey: `${args.connection.nonce}:${args.requestKey}`,
10627
11303
  text: promptText(params.prompt),
10628
11304
  user: args.user
10629
11305
  });
10630
- if (admission.status === "not_found") {
11306
+ if (result.status === "not_found") {
10631
11307
  throw acp4.RequestError.resourceNotFound(params.sessionId);
10632
11308
  }
10633
- if (admission.status === "active") {
11309
+ if (result.status === "active") {
10634
11310
  throw acp4.RequestError.invalidParams(
10635
11311
  { field: "sessionId" },
10636
11312
  "This ACP session already has an active prompt"
@@ -10638,11 +11314,11 @@ async function acceptPrompt(args) {
10638
11314
  }
10639
11315
  return {
10640
11316
  output: {
10641
- afterSeq: admission.afterCursor,
11317
+ afterSeq: result.afterCursor,
10642
11318
  kind: "prompt",
10643
- messageId: admission.messageId,
11319
+ messageId: result.messageId,
10644
11320
  requestId: args.requestId,
10645
- turnId: admission.turnId
11321
+ turnId: result.turnId
10646
11322
  },
10647
11323
  sessionId: params.sessionId
10648
11324
  };