@sentry/junior 0.193.0 → 0.195.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 (99) hide show
  1. package/dist/{agent-hooks-DWY3MZZ7.js → agent-hooks-VIBTIP5F.js} +11 -11
  2. package/dist/api/activity.d.ts +9 -1
  3. package/dist/api/code/overview.d.ts +12 -0
  4. package/dist/api/conversations/aggregate.d.ts +2 -0
  5. package/dist/api/conversations/list.d.ts +1 -1
  6. package/dist/api/conversations/projection.d.ts +1 -1
  7. package/dist/api/locations/detail.d.ts +9 -1
  8. package/dist/api/locations/list.d.ts +5 -0
  9. package/dist/api/people/code.d.ts +6 -0
  10. package/dist/api/people/shared.d.ts +9 -1
  11. package/dist/api/reporting-window.d.ts +39 -1
  12. package/dist/api/schema/code.d.ts +12 -0
  13. package/dist/api/schema/conversation.d.ts +28 -3
  14. package/dist/api/schema/location.d.ts +14 -1
  15. package/dist/api/schema/person.d.ts +15 -1
  16. package/dist/api/schema/task.d.ts +83 -8
  17. package/dist/api/schema.d.ts +2 -2
  18. package/dist/api/schema.js +3 -1
  19. package/dist/api.js +320 -222
  20. package/dist/app.js +108 -39
  21. package/dist/{catalog-runtime-NAD44W5K.js → catalog-runtime-6E6SGRZK.js} +4 -4
  22. package/dist/chat/agent/resume.d.ts +2 -0
  23. package/dist/chat/config.d.ts +2 -0
  24. package/dist/chat/conversations/history.d.ts +4 -2
  25. package/dist/chat/event-tasks/store.d.ts +27 -17
  26. package/dist/chat/resource-events/notification.d.ts +2 -1
  27. package/dist/chat/services/automated-turn-limit.d.ts +110 -0
  28. package/dist/chat/services/turn-limit.d.ts +11 -1
  29. package/dist/chat/slack/automated-turn-limit-notice.d.ts +38 -0
  30. package/dist/chat/slack/{source-link.d.ts → location-url.d.ts} +1 -1
  31. package/dist/chat/task-execution/checkpoint.d.ts +2 -0
  32. package/dist/chat/task-execution/turn-cursor.d.ts +3 -0
  33. package/dist/chat/tasks/execution-stats.d.ts +15 -2
  34. package/dist/chat/tasks/read.d.ts +5 -2
  35. package/dist/chat/usage.d.ts +4 -0
  36. package/dist/{chunk-GUKGU6R7.js → chunk-3VWIZVK7.js} +1 -1
  37. package/dist/{chunk-THYNA2QN.js → chunk-5HNXLP4W.js} +1 -1
  38. package/dist/{chunk-GUMBIDDL.js → chunk-5NR7N567.js} +194 -43
  39. package/dist/{chunk-N6Q2PNSI.js → chunk-6GGDBXXP.js} +3 -3
  40. package/dist/{chunk-HMBTX5RK.js → chunk-6TRQLG3D.js} +1 -1
  41. package/dist/{chunk-IOUUS6H4.js → chunk-7MYXH5LA.js} +1 -1
  42. package/dist/{chunk-WH5VV2RW.js → chunk-7PQMTME5.js} +1 -1
  43. package/dist/{chunk-5E5SLAVD.js → chunk-7UED4D5T.js} +23 -25
  44. package/dist/{chunk-4UA5C7AM.js → chunk-BJZML4RT.js} +8 -8
  45. package/dist/{chunk-QDU5MW2R.js → chunk-C4NY6L7S.js} +1 -1
  46. package/dist/{chunk-DVU734PI.js → chunk-CE2P6TOV.js} +3 -3
  47. package/dist/{chunk-BFP3ZKG6.js → chunk-DTYOEHUP.js} +148 -19
  48. package/dist/{chunk-S5HS6WRH.js → chunk-FE3Y4KES.js} +5 -5
  49. package/dist/{chunk-PYBFVK6K.js → chunk-FEZIEEOP.js} +985 -569
  50. package/dist/{chunk-5S6AQFNG.js → chunk-FPQPYJEG.js} +23 -29
  51. package/dist/{chunk-42N6CDWF.js → chunk-HE5PZAPS.js} +4 -4
  52. package/dist/{chunk-QY2IU47O.js → chunk-HUQOXMDG.js} +1 -1
  53. package/dist/{chunk-IQCL5JGL.js → chunk-I4RH3KLJ.js} +1 -1
  54. package/dist/{chunk-LXRTHE43.js → chunk-JBSCMOLR.js} +5 -5
  55. package/dist/{chunk-OICYQPKP.js → chunk-KBPWC7NU.js} +1 -1
  56. package/dist/{chunk-2CYWEVOP.js → chunk-KQ3GZGBK.js} +88 -68
  57. package/dist/{chunk-GTXQHZ2O.js → chunk-KUQRWV53.js} +5 -5
  58. package/dist/{chunk-IBXXTO3J.js → chunk-L62JVQPL.js} +3 -3
  59. package/dist/{chunk-KWXZMHJS.js → chunk-LM7UE523.js} +3 -3
  60. package/dist/{chunk-WJJDQLVL.js → chunk-LMYRF6HX.js} +6 -2
  61. package/dist/{chunk-AZVDODSP.js → chunk-N67T4VY3.js} +9 -9
  62. package/dist/{chunk-D4XQZOHB.js → chunk-OQHO62VA.js} +8 -8
  63. package/dist/{chunk-FQ5HFSFR.js → chunk-PFQRZ4IB.js} +9 -6
  64. package/dist/{chunk-LG7Q4OW4.js → chunk-PYTRZZ4V.js} +8 -8
  65. package/dist/{chunk-THFNL3TL.js → chunk-QHJZSYKY.js} +2 -2
  66. package/dist/{chunk-5LEVZYXF.js → chunk-QKHZF2LH.js} +4 -4
  67. package/dist/{chunk-EYIMZY5O.js → chunk-QPZL2IYT.js} +100 -9
  68. package/dist/{chunk-D5YQPCEG.js → chunk-R5BGW4WR.js} +24 -2
  69. package/dist/{chunk-COCVPDWX.js → chunk-R5OHONYU.js} +6 -6
  70. package/dist/{chunk-DXFUYLHX.js → chunk-RKA22BQP.js} +1 -1
  71. package/dist/{chunk-3YZ2Q6AW.js → chunk-RQO67SAO.js} +2 -2
  72. package/dist/{chunk-ZFPEPWOO.js → chunk-RZ3PBNDV.js} +60 -29
  73. package/dist/{chunk-K47OVEO4.js → chunk-VYDIA2UL.js} +1 -1
  74. package/dist/{chunk-QWY4KI2V.js → chunk-X3PBQ4BK.js} +1 -1
  75. package/dist/cli/chat.js +33 -33
  76. package/dist/cli/check.js +5 -5
  77. package/dist/cli/plugins.js +12 -12
  78. package/dist/cli/snapshot-create.js +9 -9
  79. package/dist/cli/upgrade.js +6 -6
  80. package/dist/db/schema/event-tasks.d.ts +21 -0
  81. package/dist/db/schema.d.ts +19 -0
  82. package/dist/{db-H5MDRQEY.js → db-FVCSDROR.js} +6 -6
  83. package/dist/instrumentation.js +3 -3
  84. package/dist/nitro.js +6 -6
  85. package/dist/{oauth-callback-server-IOU3NUHT.js → oauth-callback-server-Z5PXTDOE.js} +29 -29
  86. package/dist/{runner-FZ5ZHLFG.js → runner-RHYU7OGV.js} +21 -21
  87. package/dist/{skills-AR3WD6BX.js → skills-QTN73DN5.js} +5 -5
  88. package/dist/spawn-R56OWLUH.js +42 -0
  89. package/dist/task-runner-LLJZTLRP.js +36 -0
  90. package/dist/{validation-VYE7TQY7.js → validation-2ZK7GA6N.js} +5 -5
  91. package/dist/version.js +1 -1
  92. package/dist/{work-CTQFWYKE.js → work-7IBKSZRU.js} +21 -21
  93. package/dist/{worker-6WQU3IT5.js → worker-RNVQVCO7.js} +10 -10
  94. package/migrations/0038_event_task_status.sql +5 -0
  95. package/migrations/meta/0038_snapshot.json +3323 -0
  96. package/migrations/meta/_journal.json +8 -1
  97. package/package.json +4 -4
  98. package/dist/spawn-ZU6JABR7.js +0 -42
  99. package/dist/task-runner-EEGGG2PM.js +0 -36
package/dist/app.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  processConversationWork
3
- } from "./chunk-42N6CDWF.js";
3
+ } from "./chunk-HE5PZAPS.js";
4
4
  import {
5
5
  bindSpawnAgent
6
- } from "./chunk-THFNL3TL.js";
6
+ } from "./chunk-QHJZSYKY.js";
7
7
  import {
8
8
  createAgentInvocationWorker,
9
9
  enqueueAgentInvocation,
10
10
  listPendingAgentInvocationMailboxAppends,
11
11
  resolveAgentInvocationId
12
- } from "./chunk-AZVDODSP.js";
12
+ } from "./chunk-N67T4VY3.js";
13
13
  import {
14
14
  GET as GET2,
15
15
  GET2 as GET3,
@@ -37,12 +37,12 @@ import {
37
37
  startProcessingReaction,
38
38
  stripLeadingBotMention,
39
39
  wakePausedTurn
40
- } from "./chunk-5E5SLAVD.js";
40
+ } from "./chunk-7UED4D5T.js";
41
41
  import "./chunk-FA6POGLH.js";
42
42
  import {
43
43
  AgentRunError,
44
44
  executeTurn
45
- } from "./chunk-DVU734PI.js";
45
+ } from "./chunk-CE2P6TOV.js";
46
46
  import {
47
47
  buildDeliveredTurnStatePatch,
48
48
  completeAuthPauseTurn,
@@ -53,7 +53,7 @@ import {
53
53
  getTurnUserSlackMessageTs,
54
54
  persistAuthPauseTurnState,
55
55
  requireTurnFailureEventId
56
- } from "./chunk-GTXQHZ2O.js";
56
+ } from "./chunk-KUQRWV53.js";
57
57
  import {
58
58
  claimDispatchMailboxAppend,
59
59
  confirmDispatchMailboxAppend,
@@ -73,11 +73,11 @@ import {
73
73
  processPluginTask,
74
74
  resolveTurnSessionRouting,
75
75
  scheduleSessionCompletedPluginTasks
76
- } from "./chunk-4UA5C7AM.js";
76
+ } from "./chunk-BJZML4RT.js";
77
77
  import {
78
78
  ConversationTurnLifecycleService,
79
79
  getTurnLifecycle
80
- } from "./chunk-WH5VV2RW.js";
80
+ } from "./chunk-7PQMTME5.js";
81
81
  import {
82
82
  coerceThreadConversationState,
83
83
  getLocationConfigurationService,
@@ -86,7 +86,7 @@ import {
86
86
  persistThreadRuntimeState,
87
87
  persistThreadState,
88
88
  persistThreadStateById
89
- } from "./chunk-S5HS6WRH.js";
89
+ } from "./chunk-FE3Y4KES.js";
90
90
  import {
91
91
  GET,
92
92
  appendAndEnqueueWebMessage,
@@ -101,24 +101,24 @@ import {
101
101
  resolveSlackChannelTypeFromMessage,
102
102
  resolveSlackConversationContext,
103
103
  webActorFromEmail
104
- } from "./chunk-LG7Q4OW4.js";
104
+ } from "./chunk-PYTRZZ4V.js";
105
105
  import {
106
106
  createWebAuthorization,
107
107
  deleteWebAuthorization
108
- } from "./chunk-THYNA2QN.js";
108
+ } from "./chunk-5HNXLP4W.js";
109
109
  import {
110
110
  recordTaskExecution
111
- } from "./chunk-GUMBIDDL.js";
111
+ } from "./chunk-5NR7N567.js";
112
112
  import "./chunk-RC745GGZ.js";
113
113
  import {
114
114
  createVercelPluginTaskCallback,
115
115
  queueCallback,
116
116
  registerVercelPluginTaskDevConsumer
117
- } from "./chunk-N6Q2PNSI.js";
117
+ } from "./chunk-6GGDBXXP.js";
118
118
  import {
119
119
  validatePluginEgressCredentialHooks,
120
120
  validatePluginRegistrations
121
- } from "./chunk-GUKGU6R7.js";
121
+ } from "./chunk-3VWIZVK7.js";
122
122
  import {
123
123
  defineJuniorPlugins,
124
124
  pluginCatalogConfigFromEnv,
@@ -129,6 +129,7 @@ import {
129
129
  RESOURCE_EVENT_MESSAGE_AUTHOR,
130
130
  RESOURCE_EVENT_SYSTEM_ACTOR,
131
131
  SANDBOX_EGRESS_PROXY_PATH,
132
+ admitAutomatedTurn,
132
133
  buildSteeringPiMessage,
133
134
  clearSandboxEgressSignals,
134
135
  consumeSandboxEgressAuthRequiredSignal,
@@ -144,11 +145,14 @@ import {
144
145
  latestReportedProgress,
145
146
  listThreadReplies,
146
147
  logScheduledTaskRunSkipped,
148
+ maybePostAutomatedTurnLimitNotice,
147
149
  normalizeSandboxEgressTracePropagationDomains,
148
150
  parseSandboxEgressCredentialToken,
151
+ postAutomatedTurnLimitNoticeForDestination,
149
152
  processWorkspaceSnapshotJob,
150
153
  publicArtifactHeaders,
151
154
  readPublicArtifact,
155
+ recordFinishedTurnForAutomatedLimit,
152
156
  renderAttachmentText,
153
157
  renderBlockText,
154
158
  renderTaskInput,
@@ -158,11 +162,11 @@ import {
158
162
  shouldEmitDevAgentTrace,
159
163
  shouldPropagateSandboxEgressTrace,
160
164
  unpublishedArtifactHeaders
161
- } from "./chunk-PYBFVK6K.js";
165
+ } from "./chunk-FEZIEEOP.js";
162
166
  import {
163
167
  AuthorizationFlowDisabledError,
164
168
  PluginCredentialFailureError
165
- } from "./chunk-LXRTHE43.js";
169
+ } from "./chunk-JBSCMOLR.js";
166
170
  import "./chunk-6Y5B5PEX.js";
167
171
  import "./chunk-DIB4GX3G.js";
168
172
  import {
@@ -170,14 +174,14 @@ import {
170
174
  deleteMcpAuthSessionsForUserProvider,
171
175
  deleteMcpServerSessionId,
172
176
  deleteMcpStoredOAuthCredentials
173
- } from "./chunk-D4XQZOHB.js";
177
+ } from "./chunk-OQHO62VA.js";
174
178
  import {
175
179
  RetryableDeliveryError,
176
180
  createAgentRunner,
177
181
  formatProviderLabel,
178
182
  postSlackMessage,
179
183
  startOAuthFlow
180
- } from "./chunk-COCVPDWX.js";
184
+ } from "./chunk-R5OHONYU.js";
181
185
  import {
182
186
  ConversationTurnBoundaryError,
183
187
  CooperativeTurnYieldError,
@@ -193,11 +197,12 @@ import {
193
197
  markTurnCompleted,
194
198
  markTurnFailed,
195
199
  startActiveTurn
196
- } from "./chunk-K47OVEO4.js";
200
+ } from "./chunk-VYDIA2UL.js";
197
201
  import {
198
202
  abandonTurnRecord,
199
203
  appendThreadContextMessages,
200
204
  buildConversationContext,
205
+ buildTurnErrorResponse,
201
206
  commitAcceptedReply,
202
207
  commitMessages,
203
208
  completeTurnRecord,
@@ -229,7 +234,7 @@ import {
229
234
  trimTrailingAssistantMessages,
230
235
  turnHasReply,
231
236
  upsertConversationMessage
232
- } from "./chunk-ZFPEPWOO.js";
237
+ } from "./chunk-RZ3PBNDV.js";
233
238
  import {
234
239
  getExperimentalFeatures,
235
240
  isExperimentalFeatureEnabled,
@@ -249,10 +254,10 @@ import {
249
254
  scheduledRunId,
250
255
  scheduledRunSchema,
251
256
  withScheduledTaskLock
252
- } from "./chunk-BFP3ZKG6.js";
257
+ } from "./chunk-DTYOEHUP.js";
253
258
  import {
254
259
  parseSlackThreadId
255
- } from "./chunk-HMBTX5RK.js";
260
+ } from "./chunk-6TRQLG3D.js";
256
261
  import {
257
262
  CONVERSATION_WORK_STALE_ENQUEUE_MS,
258
263
  appendAndEnqueueInboundMessage,
@@ -267,16 +272,16 @@ import {
267
272
  removeActiveConversation,
268
273
  requestConversationWork,
269
274
  stopConversationWork
270
- } from "./chunk-5LEVZYXF.js";
275
+ } from "./chunk-QKHZF2LH.js";
271
276
  import {
272
277
  buildDeterministicAssistantMessageId,
273
278
  buildDeterministicTurnId
274
279
  } from "./chunk-DA2KGZZI.js";
275
- import "./chunk-D5YQPCEG.js";
280
+ import "./chunk-R5BGW4WR.js";
276
281
  import {
277
282
  getSandboxResourceConfig,
278
283
  setSandboxResourceConfig
279
- } from "./chunk-IBXXTO3J.js";
284
+ } from "./chunk-L62JVQPL.js";
280
285
  import "./chunk-PDO5BLNM.js";
281
286
  import "./chunk-UIE3R5XU.js";
282
287
  import {
@@ -285,7 +290,7 @@ import {
285
290
  } from "./chunk-X6GDDWQH.js";
286
291
  import {
287
292
  getTurnRequestDeadline
288
- } from "./chunk-IQCL5JGL.js";
293
+ } from "./chunk-I4RH3KLJ.js";
289
294
  import {
290
295
  getVercelConversationWorkQueue,
291
296
  resolveConversationWorkQueueTopic,
@@ -321,7 +326,7 @@ import {
321
326
  verifyEventTaskCredentialSubject,
322
327
  verifyScheduledTaskCredentialSubject,
323
328
  verifySlackDirectCredentialSubject
324
- } from "./chunk-FQ5HFSFR.js";
329
+ } from "./chunk-PFQRZ4IB.js";
325
330
  import "./chunk-3Y47VMHV.js";
326
331
  import {
327
332
  createSlackDestination,
@@ -333,7 +338,7 @@ import {
333
338
  requireSlackDestination,
334
339
  withConversationEventLock,
335
340
  withConversationMutationLock
336
- } from "./chunk-2CYWEVOP.js";
341
+ } from "./chunk-KQ3GZGBK.js";
337
342
  import {
338
343
  juniorAgentBindings,
339
344
  juniorAgentInvocations,
@@ -341,13 +346,13 @@ import {
341
346
  juniorConversations,
342
347
  juniorSchedulerRuns,
343
348
  juniorSchedulerTasks
344
- } from "./chunk-5S6AQFNG.js";
345
- import "./chunk-KWXZMHJS.js";
349
+ } from "./chunk-FPQPYJEG.js";
350
+ import "./chunk-LM7UE523.js";
346
351
  import {
347
352
  acquireActiveLock,
348
353
  getStateAdapter,
349
354
  withActiveLock
350
- } from "./chunk-IOUUS6H4.js";
355
+ } from "./chunk-7MYXH5LA.js";
351
356
  import {
352
357
  instructionProvenanceFor
353
358
  } from "./chunk-GFBR4S3Q.js";
@@ -369,17 +374,17 @@ import {
369
374
  isProviderRetryError,
370
375
  setProfiles,
371
376
  setSlackReactionConfig
372
- } from "./chunk-WJJDQLVL.js";
377
+ } from "./chunk-LMYRF6HX.js";
373
378
  import {
374
379
  defaultModelId,
375
380
  modelIdForProfile
376
381
  } from "./chunk-D4YV5TDV.js";
377
- import "./chunk-OICYQPKP.js";
378
- import "./chunk-3YZ2Q6AW.js";
382
+ import "./chunk-KBPWC7NU.js";
383
+ import "./chunk-RQO67SAO.js";
379
384
  import {
380
385
  pluginCatalogRuntime
381
- } from "./chunk-DXFUYLHX.js";
382
- import "./chunk-QWY4KI2V.js";
386
+ } from "./chunk-RKA22BQP.js";
387
+ import "./chunk-X3PBQ4BK.js";
383
388
  import {
384
389
  credentialContextForActor
385
390
  } from "./chunk-CEMMLV5L.js";
@@ -415,13 +420,13 @@ import {
415
420
  withContext,
416
421
  withLogContext,
417
422
  withSpan
418
- } from "./chunk-QY2IU47O.js";
423
+ } from "./chunk-HUQOXMDG.js";
419
424
  import {
420
425
  continueTrace
421
426
  } from "./chunk-PEQXYSSE.js";
422
427
  import {
423
428
  JUNIOR_VERSION
424
- } from "./chunk-QDU5MW2R.js";
429
+ } from "./chunk-C4NY6L7S.js";
425
430
 
426
431
  // src/app.ts
427
432
  import { createRequire } from "module";
@@ -5017,7 +5022,9 @@ function createSlackTurnRuntime(deps) {
5017
5022
  };
5018
5023
  const postFallbackErrorReplyWithLogging = async (args) => {
5019
5024
  try {
5020
- await args.thread.post(buildTurnFailureResponse(args.eventId));
5025
+ await args.thread.post(
5026
+ buildTurnErrorResponse(args.error, args.eventId)
5027
+ );
5021
5028
  } catch (postError) {
5022
5029
  logException(postError, args.postFailureEventName, {
5023
5030
  "app.slack.reply_stage": "error_fallback_post",
@@ -5319,6 +5326,7 @@ function createSlackTurnRuntime(deps) {
5319
5326
  await postFallbackErrorReplyWithLogging({
5320
5327
  thread,
5321
5328
  eventId,
5329
+ error: failureCause,
5322
5330
  postFailureEventName: "mention.handler.failure_reply_post.failed"
5323
5331
  });
5324
5332
  if (lifecycleError) throw lifecycleError;
@@ -5607,6 +5615,7 @@ function createSlackTurnRuntime(deps) {
5607
5615
  await postFallbackErrorReplyWithLogging({
5608
5616
  thread,
5609
5617
  eventId,
5618
+ error: failureCause,
5610
5619
  postFailureEventName: "subscribed_message.handler.failure_reply_post.failed"
5611
5620
  });
5612
5621
  if (lifecycleError) throw lifecycleError;
@@ -7246,6 +7255,21 @@ function createSlackTurn(deps) {
7246
7255
  })
7247
7256
  );
7248
7257
  await persistThreadRuntimeStateWithRetry(thread, completedState);
7258
+ const automatedTurnLimit = await recordFinishedTurnForAutomatedLimit(
7259
+ {
7260
+ conversationId,
7261
+ destination,
7262
+ maxTurns: botConfig.maxConsecutiveAutomatedTurns,
7263
+ source
7264
+ }
7265
+ );
7266
+ await maybePostAutomatedTurnLimitNotice({
7267
+ conversationId,
7268
+ destination,
7269
+ maxTurns: botConfig.maxConsecutiveAutomatedTurns,
7270
+ threadTs,
7271
+ update: automatedTurnLimit
7272
+ });
7249
7273
  } catch (saveError) {
7250
7274
  saveFailed = true;
7251
7275
  saveFailureEventId = logException(
@@ -9136,6 +9160,19 @@ function createConversationTurnWorker(agentRunner, deliverMessage) {
9136
9160
  surface
9137
9161
  });
9138
9162
  }
9163
+ const automatedTurnLimit = await recordFinishedTurnForAutomatedLimit({
9164
+ conversationId: context.conversationId,
9165
+ destination,
9166
+ maxTurns: botConfig.maxConsecutiveAutomatedTurns,
9167
+ source
9168
+ });
9169
+ await maybePostAutomatedTurnLimitNotice({
9170
+ conversationId: context.conversationId,
9171
+ destination,
9172
+ maxTurns: botConfig.maxConsecutiveAutomatedTurns,
9173
+ threadTs: conversationLocation?.provider === "slack" ? conversationLocation.threadTs : void 0,
9174
+ update: automatedTurnLimit
9175
+ });
9139
9176
  completedSuccessfully = reply.diagnostics.outcome === "success";
9140
9177
  return completedSuccessfully ? {
9141
9178
  outcome: assistantMessageDelivered ? "success" : "no_reply"
@@ -9518,8 +9555,40 @@ async function ingestEventTasks(input, options) {
9518
9555
  const tasks = await findMatchingEventTasks(db, event, options.teamId);
9519
9556
  let dispatched = 0;
9520
9557
  const errors = [];
9558
+ const maxTurns = botConfig.maxConsecutiveAutomatedTurns;
9559
+ const noticedDestinations = /* @__PURE__ */ new Set();
9521
9560
  for (const task of tasks) {
9522
9561
  try {
9562
+ const decision = await admitAutomatedTurn({
9563
+ maxTurns,
9564
+ nowMs,
9565
+ scope: { kind: "destination", destination: task.destination }
9566
+ });
9567
+ if (decision.status === "paused") {
9568
+ const destinationId = `${task.destination.teamId}:${task.destination.channelId}`;
9569
+ logInfo("event_tasks.automated_turn_limit.paused", {
9570
+ "app.automated_turn_limit.consecutive": decision.consecutiveAutomatedTurns,
9571
+ "app.automated_turn_limit.max": maxTurns,
9572
+ "app.event_task.id": task.id,
9573
+ "app.resource_event.event_type": event.eventType,
9574
+ "app.resource_event.namespace": event.namespace,
9575
+ "app.slack.channel_id": task.destination.channelId,
9576
+ "app.slack.team_id": task.destination.teamId
9577
+ });
9578
+ if (decision.shouldPostNotice && !noticedDestinations.has(destinationId)) {
9579
+ const posted = await postAutomatedTurnLimitNoticeForDestination({
9580
+ destination: task.destination,
9581
+ maxTurns,
9582
+ nowMs,
9583
+ resumeIn: "channel",
9584
+ scope: { kind: "destination", destination: task.destination }
9585
+ });
9586
+ if (posted) {
9587
+ noticedDestinations.add(destinationId);
9588
+ }
9589
+ }
9590
+ continue;
9591
+ }
9523
9592
  const idempotencyKey = eventTaskDispatchKey(
9524
9593
  task.id,
9525
9594
  event.namespace,
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-DXFUYLHX.js";
4
- import "./chunk-QWY4KI2V.js";
3
+ } from "./chunk-RKA22BQP.js";
4
+ import "./chunk-X3PBQ4BK.js";
5
5
  import "./chunk-CEMMLV5L.js";
6
6
  import "./chunk-N7TMSOZH.js";
7
7
  import "./chunk-DWPN6SCH.js";
8
8
  import "./chunk-TXKUKMVO.js";
9
- import "./chunk-QY2IU47O.js";
9
+ import "./chunk-HUQOXMDG.js";
10
10
  import "./chunk-PEQXYSSE.js";
11
- import "./chunk-QDU5MW2R.js";
11
+ import "./chunk-C4NY6L7S.js";
12
12
  export {
13
13
  pluginCatalogRuntime
14
14
  };
@@ -38,6 +38,8 @@ export declare function createResumeState(args: ResumeStateArgs): {
38
38
  readonly timedOut: boolean;
39
39
  setTurnStartMessageIndex(index: number | undefined): void;
40
40
  setBeforeMessageCount(count: number): void;
41
+ /** Admit one tool call against the durable turn total, or throw the limit. */
42
+ admitToolCall(): void;
41
43
  setTurnContexts(contexts: PluginTurnContext[]): void;
42
44
  /** Use an already committed boundary as the resume baseline. */
43
45
  adoptCommittedBoundary(messages: PiMessage[]): void;
@@ -21,6 +21,8 @@ export interface BotConfig {
21
21
  reasoningLevel?: TurnReasoningLevel;
22
22
  visionModelId?: string;
23
23
  maxSlicesPerTurn: number;
24
+ maxToolCallsPerTurn: number;
25
+ maxConsecutiveAutomatedTurns: number;
24
26
  turnTimeoutMs: number;
25
27
  userName: string;
26
28
  webSearchModelId: string;
@@ -1124,12 +1124,12 @@ export interface ConversationEventPage {
1124
1124
  /** Persist and read the canonical per-conversation event log. */
1125
1125
  export interface ConversationEventStore {
1126
1126
  /**
1127
- * Append events atomically, optionally preserving conversation activity.
1127
+ * Append events atomically and return each event's sequence and history version.
1128
1128
  * Archive clears only for human user activity, not every non-preserve write.
1129
1129
  */
1130
1130
  append(conversationId: string, events: NewConversationEvent[], options?: {
1131
1131
  activity?: "preserve";
1132
- }): Promise<void>;
1132
+ }): Promise<Array<Pick<ConversationEvent, "seq" | "historyVersion">>>;
1133
1133
  /** Replace active model history with a compaction or handoff event. */
1134
1134
  replaceHistory(conversationId: string, replacement: HistoryReplacement): Promise<void>;
1135
1135
  /** One event selected by its retry-stable key across history versions. */
@@ -1138,6 +1138,8 @@ export interface ConversationEventStore {
1138
1138
  loadLatestStructuredEvent(conversationId: string, namespace: string, name: string): Promise<ConversationEvent | undefined>;
1139
1139
  /** Latest durable instruction across history versions. */
1140
1140
  loadLatestInstruction(conversationId: string): Promise<ConversationEvent | undefined>;
1141
+ /** Current model-history version, or zero when no event exists. */
1142
+ loadCurrentHistoryVersion(conversationId: string): Promise<number>;
1141
1143
  /** Events of the current history version in `seq` order. */
1142
1144
  loadCurrentHistory(conversationId: string): Promise<ConversationEvent[]>;
1143
1145
  /** Events in the history version containing `seq`, when it exists. */
@@ -1,24 +1,34 @@
1
1
  import { type ResourceEvent, type User } from "@sentry/junior-plugin-api";
2
2
  import type { JuniorDatabase } from "@/db/db";
3
+ import { type EventTaskStatus } from "@/db/schema/event-tasks";
3
4
  import { type EventTask } from "./types";
4
- /** Read one event task by id. */
5
- export declare function getEventTask(db: JuniorDatabase, id: string): Promise<EventTask | undefined>;
6
- /** Create one retry-stable event task or return its existing record. */
7
- export declare function createEventTask(db: JuniorDatabase, task: EventTask): Promise<EventTask>;
8
- /** Replace an existing event task. */
9
- export declare function saveEventTask(db: JuniorDatabase, task: EventTask): Promise<EventTask | undefined>;
10
- /** Delete one existing event task. */
11
- export declare function deleteEventTask(db: JuniorDatabase, id: string): Promise<EventTask | undefined>;
12
- /** List event tasks in one Slack workspace. */
13
- export declare function listEventTasksForTeam(db: JuniorDatabase, teamId: string): Promise<EventTask[]>;
5
+ /** Live event task plus retained SQL status for history after delete. */
6
+ export type StoredEventTask = EventTask & {
7
+ status: EventTaskStatus;
8
+ };
9
+ /** Read one event task by id, including deleted rows when present. */
10
+ export declare function getEventTask(db: JuniorDatabase, id: string): Promise<StoredEventTask | undefined>;
11
+ /** Create one retry-stable event task, or revive a deleted row with the new payload. */
12
+ export declare function createEventTask(db: JuniorDatabase, task: EventTask): Promise<StoredEventTask>;
13
+ /** Replace an existing non-deleted event task. */
14
+ export declare function saveEventTask(db: JuniorDatabase, task: EventTask): Promise<StoredEventTask | undefined>;
15
+ /** Mark one existing event task deleted while retaining the row for history. */
16
+ export declare function deleteEventTask(db: JuniorDatabase, id: string): Promise<StoredEventTask | undefined>;
17
+ /** List live event tasks in one Slack workspace. */
18
+ export declare function listEventTasksForTeam(db: JuniorDatabase, teamId: string): Promise<StoredEventTask[]>;
14
19
  /** Return whether one event task was created by a viewer-linked Slack identity. */
15
20
  export declare function eventTaskBelongsToUser(task: EventTask, user: User): boolean;
16
- /** List a bounded newest-first page of event tasks created by one user. */
17
- export declare function listEventTasksCreatedBy(db: JuniorDatabase, user: User, limit: number): Promise<EventTask[]>;
18
- /** List event tasks whose current Slack destination is public. */
19
- export declare function listPublicEventTasksForTeams(db: JuniorDatabase, teamIds: string[], limit: number): Promise<EventTask[]>;
21
+ /** List a bounded newest-first page of live event tasks created by one user. */
22
+ export declare function listEventTasksCreatedBy(db: JuniorDatabase, user: User, limit: number): Promise<StoredEventTask[]>;
20
23
  /**
21
- * Collect match keys from event tasks for these identifiers and event types.
24
+ * List deleted event tasks created by one user, newest first.
25
+ * Used only to keep historical runs after the live task list drops the row.
26
+ */
27
+ export declare function listDeletedEventTasksCreatedBy(db: JuniorDatabase, user: User, limit: number): Promise<StoredEventTask[]>;
28
+ /** List live event tasks whose current Slack destination is public. */
29
+ export declare function listPublicEventTasksForTeams(db: JuniorDatabase, teamIds: string[], limit: number): Promise<StoredEventTask[]>;
30
+ /**
31
+ * Collect match keys from live event tasks for these identifiers and event types.
22
32
  * Does not evaluate match values — only reports keys that filters use.
23
33
  */
24
34
  export declare function collectEventTaskMatchKeys(db: JuniorDatabase, input: {
@@ -27,5 +37,5 @@ export declare function collectEventTaskMatchKeys(db: JuniorDatabase, input: {
27
37
  namespace: string;
28
38
  teamId: string;
29
39
  }): Promise<string[]>;
30
- /** Find every task matching one normalized resource event. */
31
- export declare function findMatchingEventTasks(db: JuniorDatabase, event: ResourceEvent, teamId: string): Promise<EventTask[]>;
40
+ /** Find every live task matching one normalized resource event. */
41
+ export declare function findMatchingEventTasks(db: JuniorDatabase, event: ResourceEvent, teamId: string): Promise<StoredEventTask[]>;
@@ -43,7 +43,8 @@ export declare function createResourceEventInboundMessage(input: {
43
43
  * Enqueue a resource event as normal conversation mailbox input.
44
44
  *
45
45
  * The watch only names the conversation. Destination stays on the conversation
46
- * and is applied when the worker runs.
46
+ * and is applied when the worker runs. After too many automated Turns with no
47
+ * user Turn, later wakes stay quiet until a user message clears the pause.
47
48
  */
48
49
  export declare function enqueueResourceEventNotification(args: {
49
50
  event: ResourceEventNotification;
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Stops event wakes after too many automated Turns with no user Turn.
3
+ *
4
+ * Resource-event watches count on the Conversation. Event tasks and other
5
+ * agent dispatches count on the Slack Destination. A finished user Turn clears
6
+ * every scope that Turn can name.
7
+ */
8
+ import type { Destination, Source } from "@sentry/junior-plugin-api";
9
+ import type { StateAdapter } from "chat";
10
+ import { z } from "zod";
11
+ /** Stored consecutive-turn limit for one Conversation or Destination. */
12
+ declare const automatedTurnLimitStateSchema: z.ZodObject<{
13
+ consecutiveAutomatedTurns: z.ZodNumber;
14
+ noticePostedAtMs: z.ZodOptional<z.ZodNumber>;
15
+ paused: z.ZodBoolean;
16
+ updatedAtMs: z.ZodNumber;
17
+ }, z.core.$strict>;
18
+ export type AutomatedTurnLimitState = z.output<typeof automatedTurnLimitStateSchema>;
19
+ export type AutomatedTurnLimitScope = {
20
+ kind: "conversation";
21
+ conversationId: string;
22
+ } | {
23
+ kind: "destination";
24
+ destination: Destination;
25
+ };
26
+ export type AutomatedTurnLimitDecision = {
27
+ status: "allow";
28
+ consecutiveAutomatedTurns: number;
29
+ } | {
30
+ status: "paused";
31
+ consecutiveAutomatedTurns: number;
32
+ shouldPostNotice: boolean;
33
+ };
34
+ export type AutomatedTurnLimitUpdate = {
35
+ consecutiveAutomatedTurns: number;
36
+ paused: boolean;
37
+ shouldPostNotice: boolean;
38
+ /** Where the pause notice should tell the user to reply. */
39
+ resumeIn: "thread" | "channel";
40
+ };
41
+ /** True when this Source starts an automated Turn rather than a user Turn. */
42
+ export declare function isAutomatedTurnSource(source: Source | undefined): boolean;
43
+ /**
44
+ * Scope that counts automated Turns for this Source.
45
+ * Resource-event watches stay on the Conversation. Dispatches use Destination.
46
+ */
47
+ export declare function automatedTurnLimitScopeForSource(args: {
48
+ conversationId: string;
49
+ destination?: Destination;
50
+ source?: Source;
51
+ }): AutomatedTurnLimitScope | undefined;
52
+ /** Plain notice when automatic updates stop until the user replies. */
53
+ export declare function buildAutomatedTurnLimitResponse(args: {
54
+ maxTurns: number;
55
+ resumeIn?: "thread" | "channel";
56
+ }): string;
57
+ /** Read the current consecutive-turn limit for one scope. */
58
+ export declare function getAutomatedTurnLimitState(args: {
59
+ nowMs?: number;
60
+ scope: AutomatedTurnLimitScope;
61
+ state?: StateAdapter;
62
+ }): Promise<AutomatedTurnLimitState>;
63
+ /**
64
+ * Allow one automated wake, or refuse once the consecutive-turn limit is full.
65
+ * If a prior pause never posted its notice, claim the notice slot so one caller
66
+ * posts it. Clear the claim if that post fails or is skipped.
67
+ */
68
+ export declare function admitAutomatedTurn(args: {
69
+ maxTurns: number;
70
+ nowMs?: number;
71
+ scope: AutomatedTurnLimitScope;
72
+ state?: StateAdapter;
73
+ }): Promise<AutomatedTurnLimitDecision>;
74
+ /** Count one finished automated Turn toward the consecutive-turn limit. */
75
+ export declare function countAutomatedTurn(args: {
76
+ maxTurns: number;
77
+ nowMs?: number;
78
+ scope: AutomatedTurnLimitScope;
79
+ state?: StateAdapter;
80
+ }): Promise<AutomatedTurnLimitUpdate>;
81
+ /**
82
+ * Drop a failed notice claim so a later paused wake can post the notice.
83
+ * Keeps the pause and consecutive count.
84
+ */
85
+ export declare function clearAutomatedTurnLimitNoticeClaim(args: {
86
+ nowMs?: number;
87
+ scope: AutomatedTurnLimitScope;
88
+ state?: StateAdapter;
89
+ }): Promise<void>;
90
+ /** Clear the consecutive automated-turn count after a user-owned Turn. */
91
+ export declare function resetAutomatedTurnLimit(args: {
92
+ nowMs?: number;
93
+ scope: AutomatedTurnLimitScope;
94
+ state?: StateAdapter;
95
+ }): Promise<void>;
96
+ /**
97
+ * Update consecutive automated-turn limits after one finished Turn.
98
+ *
99
+ * Automated Turns count one matching scope. User Turns clear Conversation and
100
+ * Destination scopes so later event wakes can run again.
101
+ */
102
+ export declare function recordFinishedTurnForAutomatedLimit(args: {
103
+ conversationId: string;
104
+ destination?: Destination;
105
+ maxTurns: number;
106
+ nowMs?: number;
107
+ source?: Source;
108
+ state?: StateAdapter;
109
+ }): Promise<AutomatedTurnLimitUpdate | undefined>;
110
+ export {};
@@ -1,6 +1,16 @@
1
- /** Terminal failure raised when one agent turn exhausts its slice budget. */
1
+ /** Terminal failure when one turn uses too many execution slices. */
2
2
  export declare class TurnSliceLimitExceededError extends Error {
3
3
  constructor(maxSlices: number);
4
4
  }
5
+ /** Terminal failure when one turn uses too many tool calls. */
6
+ export declare class TurnToolCallLimitExceededError extends Error {
7
+ constructor(maxToolCalls: number);
8
+ }
9
+ /** True when a turn hit a hard execution limit, including one Error.cause wrap. */
10
+ export declare function isTurnExecutionLimitExceededError(error: unknown): boolean;
11
+ /** Stop the turn when its tool-call count is past the limit. */
12
+ export declare function assertTurnToolCallLimit(toolCallCount: number, maxToolCalls: number): void;
5
13
  /** Explain a terminal turn execution limit with actionable recovery guidance. */
6
14
  export declare function buildTurnLimitResponse(eventId: string): string;
15
+ /** User-facing reply for a thrown turn error. */
16
+ export declare function buildTurnErrorResponse(error: unknown, eventId: string): string;