@sentry/junior 0.202.0 → 0.204.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 (174) hide show
  1. package/dist/agent-CMyTD4DD.js +17509 -0
  2. package/dist/agent-hooks-Bbcp9e33.js +4040 -0
  3. package/dist/agent-runner-DNb1A49M.js +678 -0
  4. package/dist/api/schema.d.ts +2728 -2639
  5. package/dist/api/schema.js +4 -169
  6. package/dist/api.d.ts +23 -17
  7. package/dist/api.js +3881 -5326
  8. package/dist/app-B1TOqBI8.d.ts +246 -0
  9. package/dist/app.d.ts +4 -520
  10. package/dist/app.js +9522 -11875
  11. package/dist/auth-pause-state-DosEalIG.js +168 -0
  12. package/dist/catalog-runtime-BReos-D4.js +7 -0
  13. package/dist/checkpoint-CNrPyRJN.js +2450 -0
  14. package/dist/cli/chat.d.ts +20 -0
  15. package/dist/cli/chat.js +229 -336
  16. package/dist/cli/check.d.ts +8 -0
  17. package/dist/cli/check.js +513 -806
  18. package/dist/cli/env.d.ts +13 -0
  19. package/dist/cli/env.js +63 -12
  20. package/dist/cli/init.d.ts +3 -0
  21. package/dist/cli/init.js +90 -159
  22. package/dist/cli/main.d.ts +6 -0
  23. package/dist/cli/main.js +43 -64
  24. package/dist/cli/plugins.d.ts +13 -0
  25. package/dist/cli/plugins.js +148 -227
  26. package/dist/cli/run.d.ts +16 -0
  27. package/dist/cli/run.js +52 -8
  28. package/dist/cli/snapshot-create.d.ts +4 -0
  29. package/dist/cli/snapshot-create.js +71 -125
  30. package/dist/cli/upgrade.d.ts +15 -0
  31. package/dist/cli/upgrade.js +232 -335
  32. package/dist/config-nGCW1OTG.js +941 -0
  33. package/dist/context-B45_WqVX.js +298 -0
  34. package/dist/conversation-privacy-B4voFRSm.js +182 -0
  35. package/dist/conversation-work-C6y3T5Hx.js +51 -0
  36. package/dist/credential-sync-kXr1hvO1.js +2660 -0
  37. package/dist/db-BeyXKJOI.d.ts +5 -0
  38. package/dist/destinations-BeBiJeEM.js +29 -0
  39. package/dist/execution-stats-DWfSihcH.js +373 -0
  40. package/dist/executor-DcMSlI5c.js +721 -0
  41. package/dist/experimental-CIXf7Uye.js +46 -0
  42. package/dist/history-ClE4toxe.d.ts +32 -0
  43. package/dist/history-CqTuSAdI.js +441 -0
  44. package/dist/instrumentation.d.ts +3 -3
  45. package/dist/instrumentation.js +130 -176
  46. package/dist/job-queue-Drn_LXlM.js +63 -0
  47. package/dist/logging-BzAk1S_s.js +1210 -0
  48. package/dist/model-profile-CZmVoGdX.js +49 -0
  49. package/dist/nitro.d.ts +31 -36
  50. package/dist/nitro.js +275 -456
  51. package/dist/oauth-callback-server-JiftokvA.js +130 -0
  52. package/dist/oauth-relay-CdCnu80W.js +62 -0
  53. package/dist/package-discovery-7a9YqLhE.js +455 -0
  54. package/dist/pending-auth-CWmSdZVg.js +185 -0
  55. package/dist/plugin-module-BKGOXca2.js +81 -0
  56. package/dist/plugins-BI9A1vKA.d.ts +95 -0
  57. package/dist/plugins-egKWjgue.js +99 -0
  58. package/dist/private-trace-result-BLvBjy_e.js +16 -0
  59. package/dist/profile-CrT5nXbw.js +861 -0
  60. package/dist/registry-DH1xUo2N.js +1419 -0
  61. package/dist/reporting-schema-DosTN__Q.js +105 -0
  62. package/dist/resolve-CZHnfxaS.js +546 -0
  63. package/dist/rolldown-runtime-B4FMCO8f.js +28 -0
  64. package/dist/runner-CZV2sC46.js +392 -0
  65. package/dist/sandbox-egress-signals-bHZfmhbd.js +46 -0
  66. package/dist/schema-Rn8-XEaN.js +1140 -0
  67. package/dist/sentry-CD3SdJl-.js +26 -0
  68. package/dist/skills-CIcDQSgM.js +316 -0
  69. package/dist/spawn-DdkUFRmq.js +29 -0
  70. package/dist/stats-DTUbAb88.js +2634 -0
  71. package/dist/store-C5qxF2ac.d.ts +208 -0
  72. package/dist/task-queue-CJIR4RF7.js +136 -0
  73. package/dist/task-runner-D-O3A-Cp.js +639 -0
  74. package/dist/thread-state-CRc9jTJS.js +431 -0
  75. package/dist/turn-execution-BkinIdJF.js +47 -0
  76. package/dist/turn-lifecycle-DQV19VTW.js +54 -0
  77. package/dist/usage-D3EbSO7w.js +296 -0
  78. package/dist/usage-schema-CKaDkH_j.js +20 -0
  79. package/dist/validation-C2CR-OX3.js +40 -0
  80. package/dist/vercel-queue-DIkVcfK4.js +167 -0
  81. package/dist/vercel.d.ts +6 -6
  82. package/dist/vercel.js +14 -6
  83. package/dist/version-CnXZ614E.d.ts +5 -0
  84. package/dist/version-DxcWdoKa.js +8 -0
  85. package/dist/version.d.ts +2 -4
  86. package/dist/version.js +2 -6
  87. package/dist/web-authorization-RMBxAR_t.js +76 -0
  88. package/dist/web-input-3EPfpf55.js +494 -0
  89. package/dist/work-fGofI7Op.js +509 -0
  90. package/dist/worker-CsOLq-mR.js +625 -0
  91. package/package.json +9 -9
  92. package/dist/agent-hooks-UXITLYOK.js +0 -51
  93. package/dist/catalog-runtime-BG3JLLK2.js +0 -14
  94. package/dist/chunk-2LYHWMR4.js +0 -46
  95. package/dist/chunk-2MK3QBGA.js +0 -321
  96. package/dist/chunk-3PGQSKJV.js +0 -692
  97. package/dist/chunk-3UI3WFTX.js +0 -519
  98. package/dist/chunk-3Y47VMHV.js +0 -6
  99. package/dist/chunk-4UO6FK4G.js +0 -64
  100. package/dist/chunk-5NOPO64K.js +0 -198
  101. package/dist/chunk-5PKWYPFT.js +0 -2943
  102. package/dist/chunk-63NKKFJL.js +0 -1228
  103. package/dist/chunk-6AYH6252.js +0 -787
  104. package/dist/chunk-6Y5B5PEX.js +0 -80
  105. package/dist/chunk-7DHZP5KJ.js +0 -333
  106. package/dist/chunk-7H2VZTWN.js +0 -103
  107. package/dist/chunk-7NL7T6VU.js +0 -406
  108. package/dist/chunk-A76OIMYN.js +0 -102
  109. package/dist/chunk-AWMS3SPP.js +0 -58
  110. package/dist/chunk-B3LY5RCL.js +0 -229
  111. package/dist/chunk-BD2KT3OB.js +0 -36
  112. package/dist/chunk-BXCX5QKA.js +0 -2086
  113. package/dist/chunk-C6VVF43U.js +0 -81
  114. package/dist/chunk-CEMMLV5L.js +0 -98
  115. package/dist/chunk-CM5HNV2W.js +0 -131
  116. package/dist/chunk-DA2KGZZI.js +0 -13
  117. package/dist/chunk-DBVY6HLX.js +0 -64
  118. package/dist/chunk-DIB4GX3G.js +0 -8
  119. package/dist/chunk-DKIJ2RP5.js +0 -68
  120. package/dist/chunk-DL2KLKVH.js +0 -931
  121. package/dist/chunk-DWPN6SCH.js +0 -172
  122. package/dist/chunk-ELWOYVOY.js +0 -206
  123. package/dist/chunk-EWT7H65X.js +0 -506
  124. package/dist/chunk-FA6POGLH.js +0 -70
  125. package/dist/chunk-HMREVIO2.js +0 -135
  126. package/dist/chunk-IIWUT4FO.js +0 -820
  127. package/dist/chunk-JAL3CH4G.js +0 -27
  128. package/dist/chunk-JSJQEWBJ.js +0 -3295
  129. package/dist/chunk-KHKKHDLD.js +0 -387
  130. package/dist/chunk-LA6R4A7Q.js +0 -706
  131. package/dist/chunk-LOOU2DUR.js +0 -20428
  132. package/dist/chunk-M6FHWXE3.js +0 -700
  133. package/dist/chunk-M76HMB7M.js +0 -1856
  134. package/dist/chunk-MAGNK5J4.js +0 -1520
  135. package/dist/chunk-MTM5IFCY.js +0 -1190
  136. package/dist/chunk-N7TMSOZH.js +0 -235
  137. package/dist/chunk-NHJU2ZAL.js +0 -56
  138. package/dist/chunk-NSXKRGRT.js +0 -717
  139. package/dist/chunk-OWMPFXJA.js +0 -1764
  140. package/dist/chunk-PDO5BLNM.js +0 -22
  141. package/dist/chunk-PEQXYSSE.js +0 -45
  142. package/dist/chunk-PW4P4JYF.js +0 -1135
  143. package/dist/chunk-QB54UQUS.js +0 -320
  144. package/dist/chunk-QP3OGJXF.js +0 -105
  145. package/dist/chunk-RC745GGZ.js +0 -122
  146. package/dist/chunk-REOIRYPR.js +0 -37
  147. package/dist/chunk-SCOZRLZ4.js +0 -164
  148. package/dist/chunk-TXJSXBV5.js +0 -1433
  149. package/dist/chunk-TXKUKMVO.js +0 -417
  150. package/dist/chunk-U2GPUYAL.js +0 -3656
  151. package/dist/chunk-UIE3R5XU.js +0 -17
  152. package/dist/chunk-UXPG6ZIN.js +0 -84
  153. package/dist/chunk-VFUK3X5B.js +0 -50
  154. package/dist/chunk-WQSHDTTI.js +0 -1163
  155. package/dist/chunk-X6GDDWQH.js +0 -60
  156. package/dist/chunk-Y2CM7HXH.js +0 -111
  157. package/dist/chunk-Y7X25LFY.js +0 -15
  158. package/dist/chunk-YDUR3ZYW.js +0 -10
  159. package/dist/conversation-work-VIOQ5ZF3.js +0 -54
  160. package/dist/db-3L2MCVRI.js +0 -26
  161. package/dist/discovery-DWVDM7UK.js +0 -44
  162. package/dist/experimental-P5FZM4CU.js +0 -12
  163. package/dist/oauth-callback-server-YVV6C6T2.js +0 -243
  164. package/dist/oauth-relay-5XPVRPYB.js +0 -8
  165. package/dist/plugins-YTYJMMJF.js +0 -14
  166. package/dist/runner-LQ7RETDP.js +0 -522
  167. package/dist/sandbox-egress-signals-FIL7EGPR.js +0 -73
  168. package/dist/sentry-MB3NL3IR.js +0 -42
  169. package/dist/skills-XRWYEDCD.js +0 -27
  170. package/dist/spawn-RC6SJUAI.js +0 -42
  171. package/dist/task-runner-7DY7ARYH.js +0 -36
  172. package/dist/validation-7MNQGCJA.js +0 -17
  173. package/dist/work-COALHUCG.js +0 -51
  174. package/dist/worker-6MURZIPD.js +0 -24
@@ -0,0 +1,625 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
2
+ import { P as isProviderRetryError, i as getChatConfig } from "./config-nGCW1OTG.js";
3
+ import { S as withLogContext, d as logInfo, f as logWarn, u as logException } from "./logging-BzAk1S_s.js";
4
+ import { At as releaseConversationWork, Bt as isInvalidConversationRecordError, Ct as ensureConversationWake, Mt as requestAnotherSlice, Ot as recordAttemptFailure, Pt as startConversationWork, St as drainConversationMailbox, Tt as getConversationWorkState, bt as countPendingConversationMessages, gt as clearConsumedConversationWake, ht as checkInConversationWork, kt as recordConversationRetry, pt as beginConversationResume, ut as ackMessages, vt as completeConversationStop, xt as deadLetterAttempt, yt as completeConversationWork, zt as isFinalAttempt } from "./stats-DTUbAb88.js";
5
+ import { c as ConversationQueueMessageRejectedError } from "./vercel-queue-DIkVcfK4.js";
6
+ import { a as getTurnRequestDeadline } from "./job-queue-Drn_LXlM.js";
7
+ //#region src/chat/task-execution/worker.ts
8
+ var worker_exports = /* @__PURE__ */ __exportAll({
9
+ CONVERSATION_WORK_DEFER_DELAY_MS: () => CONVERSATION_WORK_DEFER_DELAY_MS,
10
+ processConversationWork: () => processConversationWork
11
+ });
12
+ const CONVERSATION_WORK_DEFER_DELAY_MS = 15e3;
13
+ const CONVERSATION_STOP_CHECK_INTERVAL_MS = 500;
14
+ function now(options) {
15
+ return options.nowMs?.() ?? Date.now();
16
+ }
17
+ function selectContiguousTurnBatch(messages) {
18
+ const first = messages[0];
19
+ if (!first) return [];
20
+ const nextTurnIndex = messages.findIndex((message) => message.input.authorId !== first.input.authorId || message.source !== first.source);
21
+ return messages.slice(0, nextTurnIndex === -1 ? messages.length : nextTurnIndex);
22
+ }
23
+ /** Prioritize interrupts while keeping each attempt to one Actor and Source. */
24
+ function selectAttemptMessages(work) {
25
+ const messages = work.messages;
26
+ const interrupts = messages.filter((message) => message.delivery === "interrupt");
27
+ if (interrupts.length > 0) return selectContiguousTurnBatch(interrupts);
28
+ return work.execution.status === "paused" ? [] : selectContiguousTurnBatch(messages);
29
+ }
30
+ function nudgeIdempotencyKey(reason, conversationId, nowMs) {
31
+ return `${reason}:${conversationId}:${nowMs}`;
32
+ }
33
+ async function requestLostLeaseRecovery(args) {
34
+ const before = await getConversationWorkState({
35
+ conversationId: args.conversationId,
36
+ state: args.options.state
37
+ });
38
+ const retry = await recordConversationRetry({
39
+ conversationId: args.conversationId,
40
+ leaseToken: args.leaseToken,
41
+ conversationStore: args.options.conversationStore,
42
+ nowMs: args.nowMs,
43
+ state: args.options.state
44
+ });
45
+ if (retry === "lost_lease") return;
46
+ if (retry === "stopped") {
47
+ logException(/* @__PURE__ */ new Error("Conversation work stopped after repeated failed attempts"), "conversation.work.retry.exhausted", {
48
+ "app.run.id": before?.execution.runId ?? "unknown",
49
+ "app.worker.last_progress_at_ms": before?.execution.lastProgressAtMs ?? before?.createdAtMs ?? 0,
50
+ "app.worker.retry_count": (before?.execution.retryCount ?? 0) + 1
51
+ });
52
+ return;
53
+ }
54
+ if (!await requestAnotherSlice({
55
+ conversationId: args.conversationId,
56
+ destination: args.destination,
57
+ leaseToken: args.leaseToken,
58
+ conversationStore: args.options.conversationStore,
59
+ nowMs: args.nowMs,
60
+ state: args.options.state
61
+ })) return;
62
+ if (!await releaseConversationWork({
63
+ conversationId: args.conversationId,
64
+ leaseToken: args.leaseToken,
65
+ conversationStore: args.options.conversationStore,
66
+ nowMs: args.nowMs,
67
+ state: args.options.state
68
+ })) return;
69
+ await ensureConversationWake({
70
+ conversationId: args.conversationId,
71
+ conversationStore: args.options.conversationStore,
72
+ idempotencyKey: nudgeIdempotencyKey("lost_lease", args.conversationId, args.nowMs),
73
+ nowMs: args.nowMs,
74
+ queue: args.options.queue,
75
+ replaceExistingWake: true,
76
+ state: args.options.state
77
+ });
78
+ }
79
+ /**
80
+ * Record one failed delivery attempt and surface dead-lettered messages.
81
+ *
82
+ * Consumption is logged here so every dead-lettered message leaves a
83
+ * `conversation.work.dead_lettered` trail with its terminal attempt count.
84
+ */
85
+ async function recordFailedDeliveryAttempt(args) {
86
+ const failure = await recordAttemptFailure({
87
+ conversationId: args.conversationId,
88
+ inboundMessageIds: args.messageIds,
89
+ leaseToken: args.leaseToken,
90
+ conversationStore: args.options.conversationStore,
91
+ nowMs: args.nowMs,
92
+ state: args.options.state
93
+ });
94
+ for (const message of failure.deadLetteredMessages) logWarn("conversation.work.dead_lettered", {
95
+ "app.conversation.source": message.source,
96
+ "app.inbound.attempt_count": message.attemptCount ?? 0,
97
+ "app.inbound.message_id": message.inboundMessageId,
98
+ "app.inbound.pending_count": failure.pendingCount
99
+ });
100
+ return failure;
101
+ }
102
+ /** True only when this attempt dead-lettered messages and left no further pending work. */
103
+ function isTerminalFailure(failure) {
104
+ return failure.status === "recorded" && failure.deadLetteredMessages.length > 0 && failure.pendingCount === 0;
105
+ }
106
+ function logRetryExhausted(args) {
107
+ logException(args.error, "conversation.work.retry.exhausted", {
108
+ "app.run.id": args.work.execution.runId ?? "unknown",
109
+ "app.worker.last_progress_at_ms": args.work.execution.lastProgressAtMs ?? args.work.createdAtMs,
110
+ "app.worker.retry_count": args.retryCount
111
+ });
112
+ }
113
+ function startLeaseCheckIn(args) {
114
+ const timer = setInterval(() => {
115
+ const nowMs = now(args.options);
116
+ checkInConversationWork({
117
+ conversationId: args.conversationId,
118
+ leaseToken: args.leaseToken,
119
+ conversationStore: args.options.conversationStore,
120
+ nowMs,
121
+ state: args.options.state
122
+ }).then((checkedIn) => {
123
+ if (!checkedIn) {
124
+ args.onLostLease();
125
+ logWarn("conversation.work.check_in.failed");
126
+ }
127
+ }, (error) => {
128
+ logException(error, "conversation.work.check_in.failed");
129
+ });
130
+ }, args.options.checkInIntervalMs ?? 15e3);
131
+ timer.unref?.();
132
+ return timer;
133
+ }
134
+ /** Poll shared state only when a worker adapter asks to observe remote stops. */
135
+ function createConversationStopSignal(args) {
136
+ const controller = new AbortController();
137
+ let checking = false;
138
+ let failureCaptured = false;
139
+ let listening = false;
140
+ let timer;
141
+ const requestStop = () => {
142
+ if (!controller.signal.aborted) controller.abort(/* @__PURE__ */ new Error("Conversation work stopped"));
143
+ };
144
+ if (args.initialStopRunId === args.runId) requestStop();
145
+ const check = async () => {
146
+ if (checking || controller.signal.aborted) return;
147
+ checking = true;
148
+ try {
149
+ if ((await getConversationWorkState({
150
+ conversationId: args.conversationId,
151
+ state: args.options.state
152
+ }))?.execution.stop?.runId === args.runId) requestStop();
153
+ } catch (error) {
154
+ if (!failureCaptured) {
155
+ failureCaptured = true;
156
+ logException(error, "conversation.work.stop_check.failed");
157
+ }
158
+ } finally {
159
+ checking = false;
160
+ }
161
+ };
162
+ return {
163
+ close() {
164
+ if (timer) clearInterval(timer);
165
+ },
166
+ isEnabled() {
167
+ return listening;
168
+ },
169
+ wasObserved() {
170
+ return listening && controller.signal.aborted;
171
+ },
172
+ signal() {
173
+ listening = true;
174
+ if (!timer && !controller.signal.aborted) {
175
+ timer = setInterval(() => void check(), CONVERSATION_STOP_CHECK_INTERVAL_MS);
176
+ timer.unref?.();
177
+ }
178
+ return controller.signal;
179
+ }
180
+ };
181
+ }
182
+ /** Process one queue wake-up for a conversation. */
183
+ async function processConversationWork(message, options) {
184
+ return withLogContext({ conversationId: message.conversationId }, () => processConversationWorkInContext(message, options));
185
+ }
186
+ async function processConversationWorkInContext(message, options) {
187
+ const conversationId = message.conversationId;
188
+ let initial;
189
+ try {
190
+ initial = await getConversationWorkState({
191
+ conversationId,
192
+ state: options.state
193
+ });
194
+ } catch (error) {
195
+ if (isInvalidConversationRecordError(error)) throw new ConversationQueueMessageRejectedError("invalid_record", `Conversation record failed validation for ${conversationId}`, { conversationId });
196
+ throw error;
197
+ }
198
+ if (!initial || countPendingConversationMessages(initial) === 0 && initial.execution.status === "idle" && !initial.execution.lease) {
199
+ if (initial) await clearConsumedConversationWake({
200
+ conversationId,
201
+ conversationStore: options.conversationStore,
202
+ nowMs: now(options),
203
+ state: options.state
204
+ });
205
+ return { status: "no_work" };
206
+ }
207
+ let destination = initial.destination;
208
+ if (!destination && options.conversationStore) {
209
+ const stored = await options.conversationStore.get({ conversationId });
210
+ if (stored && !stored.parentConversationId) destination = stored.destination;
211
+ }
212
+ const lease = await startConversationWork({
213
+ conversationId,
214
+ conversationStore: options.conversationStore,
215
+ nowMs: now(options),
216
+ state: options.state
217
+ });
218
+ if (lease.status === "no_work") {
219
+ await clearConsumedConversationWake({
220
+ conversationId,
221
+ conversationStore: options.conversationStore,
222
+ nowMs: now(options),
223
+ state: options.state
224
+ });
225
+ return { status: "no_work" };
226
+ }
227
+ if (lease.status === "active") {
228
+ const nudgeNowMs = now(options);
229
+ await ensureConversationWake({
230
+ conversationId,
231
+ conversationStore: options.conversationStore,
232
+ delayMs: CONVERSATION_WORK_DEFER_DELAY_MS,
233
+ idempotencyKey: nudgeIdempotencyKey("active", conversationId, nudgeNowMs),
234
+ nowMs: nudgeNowMs,
235
+ queue: options.queue,
236
+ replaceExistingWake: true,
237
+ state: options.state
238
+ });
239
+ logInfo("conversation.work.nudge.deferred", { "app.lease.expires_at_ms": lease.leaseExpiresAtMs });
240
+ return { status: "active" };
241
+ }
242
+ const startedAtMs = now(options);
243
+ const softYieldDeadlineMs = startedAtMs + (options.softYieldAfterMs ?? getChatConfig().conversationWorkSoftYieldAfterMs);
244
+ let attemptMessageIds = [];
245
+ let attemptSelectedMessageIds = /* @__PURE__ */ new Set();
246
+ let attemptStartMessageIds = /* @__PURE__ */ new Set();
247
+ let failedWithoutProgress = false;
248
+ let leaseLost = false;
249
+ const markLeaseLost = () => {
250
+ leaseLost = true;
251
+ };
252
+ const timer = startLeaseCheckIn({
253
+ conversationId,
254
+ leaseToken: lease.leaseToken,
255
+ onLostLease: markLeaseLost,
256
+ options
257
+ });
258
+ logInfo("conversation.work.lease.acquired", {
259
+ "app.lease.expires_at_ms": lease.leaseExpiresAtMs,
260
+ "app.worker.soft_yield_deadline_ms": softYieldDeadlineMs
261
+ });
262
+ const drain = (handle) => drainConversationMailbox({
263
+ conversationId,
264
+ leaseToken: lease.leaseToken,
265
+ conversationStore: options.conversationStore,
266
+ handle: async (messages) => {
267
+ const candidates = messages.filter((message) => message.delivery === "interrupt" && (attemptSelectedMessageIds.has(message.inboundMessageId) || !attemptStartMessageIds.has(message.inboundMessageId)));
268
+ if (candidates.length === 0) return [];
269
+ return await handle(candidates) ?? candidates.map((message) => message.inboundMessageId);
270
+ },
271
+ nowMs: now(options),
272
+ state: options.state
273
+ });
274
+ const requestDeadlineAtMs = getTurnRequestDeadline()?.deadlineAtMs;
275
+ const shouldYield = () => leaseLost || now(options) >= softYieldDeadlineMs || requestDeadlineAtMs !== void 0 && Date.now() >= requestDeadlineAtMs;
276
+ const checkIn = async () => {
277
+ const checkedIn = await checkInConversationWork({
278
+ conversationId,
279
+ leaseToken: lease.leaseToken,
280
+ conversationStore: options.conversationStore,
281
+ nowMs: now(options),
282
+ state: options.state
283
+ });
284
+ if (!checkedIn) markLeaseLost();
285
+ return checkedIn;
286
+ };
287
+ const yieldWork = async () => {
288
+ const yieldNowMs = now(options);
289
+ await ensureConversationWake({
290
+ conversationId,
291
+ conversationStore: options.conversationStore,
292
+ idempotencyKey: nudgeIdempotencyKey("yield", conversationId, yieldNowMs),
293
+ nowMs: yieldNowMs,
294
+ queue: options.queue,
295
+ replaceExistingWake: true,
296
+ state: options.state
297
+ });
298
+ if (!await releaseConversationWork({
299
+ conversationId,
300
+ leaseToken: lease.leaseToken,
301
+ conversationStore: options.conversationStore,
302
+ nowMs: yieldNowMs,
303
+ state: options.state
304
+ })) return { status: "lost_lease" };
305
+ logInfo("conversation.work.yielded", {
306
+ "app.worker.elapsed_ms": now(options) - startedAtMs,
307
+ "app.worker.soft_yield_deadline_ms": softYieldDeadlineMs
308
+ });
309
+ return { status: "yielded" };
310
+ };
311
+ try {
312
+ let hasRun = false;
313
+ let resumeIfStopped = false;
314
+ while (true) {
315
+ attemptMessageIds = [];
316
+ const leasedWork = await getConversationWorkState({
317
+ conversationId,
318
+ state: options.state
319
+ });
320
+ if (!leasedWork || leasedWork.lease?.leaseToken !== lease.leaseToken || leaseLost) {
321
+ markLeaseLost();
322
+ await requestLostLeaseRecovery({
323
+ conversationId,
324
+ destination,
325
+ leaseToken: lease.leaseToken,
326
+ nowMs: now(options),
327
+ options
328
+ });
329
+ return { status: "lost_lease" };
330
+ }
331
+ const resumePending = leasedWork.execution.status === "paused";
332
+ const attemptMessages = selectAttemptMessages(leasedWork);
333
+ const runId = leasedWork.execution.runId;
334
+ if (!runId) throw new Error(`Conversation run is missing for ${conversationId}`);
335
+ attemptStartMessageIds = new Set(leasedWork.messages.map((message) => message.inboundMessageId));
336
+ if (hasRun && shouldYield()) {
337
+ if (resumePending) return await yieldWork();
338
+ break;
339
+ }
340
+ if (resumePending && attemptMessages.length === 0) {
341
+ if (!await beginConversationResume({
342
+ conversationId,
343
+ leaseToken: lease.leaseToken,
344
+ conversationStore: options.conversationStore,
345
+ nowMs: now(options),
346
+ state: options.state
347
+ })) {
348
+ markLeaseLost();
349
+ await requestLostLeaseRecovery({
350
+ conversationId,
351
+ destination,
352
+ leaseToken: lease.leaseToken,
353
+ nowMs: now(options),
354
+ options
355
+ });
356
+ return { status: "lost_lease" };
357
+ }
358
+ }
359
+ attemptMessageIds = attemptMessages.map((message) => message.inboundMessageId);
360
+ attemptSelectedMessageIds = new Set(attemptMessageIds);
361
+ const ack = async () => {
362
+ if (!await ackMessages({
363
+ conversationId,
364
+ inboundMessageIds: attemptMessageIds,
365
+ leaseToken: lease.leaseToken,
366
+ conversationStore: options.conversationStore,
367
+ nowMs: now(options),
368
+ state: options.state
369
+ })) {
370
+ markLeaseLost();
371
+ throw new Error(`Conversation work lease lost before inbox ack for ${conversationId}`);
372
+ }
373
+ };
374
+ const stop = createConversationStopSignal({
375
+ conversationId,
376
+ initialStopRunId: leasedWork.execution.stop?.runId,
377
+ options,
378
+ runId
379
+ });
380
+ const workerContext = {
381
+ attempt: {
382
+ ack,
383
+ conversationId,
384
+ destination,
385
+ drain,
386
+ isFinalAttempt: attemptMessages.some((message) => isFinalAttempt(message)),
387
+ messages: attemptMessages
388
+ },
389
+ conversationId,
390
+ destination,
391
+ shouldYield,
392
+ stopSignal: stop.signal,
393
+ checkIn
394
+ };
395
+ let result;
396
+ try {
397
+ result = await options.run(workerContext);
398
+ } finally {
399
+ stop.close();
400
+ }
401
+ resumeIfStopped ||= stop.isEnabled();
402
+ hasRun = true;
403
+ if (result.status === "lost_lease") {
404
+ await requestLostLeaseRecovery({
405
+ conversationId,
406
+ destination,
407
+ leaseToken: lease.leaseToken,
408
+ nowMs: now(options),
409
+ options
410
+ });
411
+ return { status: "lost_lease" };
412
+ }
413
+ if (leaseLost) {
414
+ await requestLostLeaseRecovery({
415
+ conversationId,
416
+ destination,
417
+ leaseToken: lease.leaseToken,
418
+ nowMs: now(options),
419
+ options
420
+ });
421
+ return { status: "lost_lease" };
422
+ }
423
+ if (result.status === "completed" && stop.wasObserved()) {
424
+ if ((await completeConversationStop({
425
+ conversationId,
426
+ conversationStore: options.conversationStore,
427
+ leaseToken: lease.leaseToken,
428
+ nowMs: now(options),
429
+ runId,
430
+ state: options.state
431
+ })).status === "lost_lease") {
432
+ markLeaseLost();
433
+ await requestLostLeaseRecovery({
434
+ conversationId,
435
+ destination,
436
+ leaseToken: lease.leaseToken,
437
+ nowMs: now(options),
438
+ options
439
+ });
440
+ return { status: "lost_lease" };
441
+ }
442
+ }
443
+ if (result.status === "yielded") {
444
+ if (!await requestAnotherSlice({
445
+ conversationId,
446
+ destination,
447
+ leaseToken: lease.leaseToken,
448
+ conversationStore: options.conversationStore,
449
+ nowMs: now(options),
450
+ state: options.state
451
+ })) return { status: "lost_lease" };
452
+ return await yieldWork();
453
+ }
454
+ if (result.status === "deferred") {
455
+ const deferredNowMs = now(options);
456
+ if (!await releaseConversationWork({
457
+ conversationId,
458
+ leaseToken: lease.leaseToken,
459
+ conversationStore: options.conversationStore,
460
+ nowMs: deferredNowMs,
461
+ state: options.state
462
+ })) return { status: "lost_lease" };
463
+ return (await ensureConversationWake({
464
+ conversationId,
465
+ conversationStore: options.conversationStore,
466
+ idempotencyKey: nudgeIdempotencyKey("deferred", conversationId, deferredNowMs),
467
+ nowMs: deferredNowMs,
468
+ queue: options.queue,
469
+ state: options.state
470
+ })).status === "enqueued" ? { status: "pending_requeued" } : { status: "completed" };
471
+ }
472
+ if (attemptMessageIds.length > 0) {
473
+ const failure = await recordFailedDeliveryAttempt({
474
+ conversationId,
475
+ leaseToken: lease.leaseToken,
476
+ nowMs: now(options),
477
+ messageIds: attemptMessageIds,
478
+ options
479
+ });
480
+ if (isTerminalFailure(failure)) {
481
+ if (failure.retryCount >= 5) logRetryExhausted({
482
+ error: /* @__PURE__ */ new Error("Conversation work stopped after repeated failed attempts"),
483
+ retryCount: failure.retryCount,
484
+ work: leasedWork
485
+ });
486
+ await deadLetterAttempt({
487
+ conversationId,
488
+ leaseToken: lease.leaseToken,
489
+ conversationStore: options.conversationStore,
490
+ nowMs: now(options),
491
+ state: options.state
492
+ });
493
+ return { status: "failed" };
494
+ }
495
+ if (failure.status === "lost_lease") return { status: "lost_lease" };
496
+ if (failure.status === "recorded") {
497
+ failedWithoutProgress = true;
498
+ break;
499
+ }
500
+ }
501
+ if (result.status === "paused") break;
502
+ const next = await getConversationWorkState({
503
+ conversationId,
504
+ state: options.state
505
+ });
506
+ if (!next || next.lease?.leaseToken !== lease.leaseToken) return { status: "lost_lease" };
507
+ if (next.execution.status !== "paused" && countPendingConversationMessages(next) === 0) break;
508
+ }
509
+ const completion = await completeConversationWork({
510
+ conversationId,
511
+ leaseToken: lease.leaseToken,
512
+ madeProgress: !failedWithoutProgress,
513
+ resumeIfStopped,
514
+ conversationStore: options.conversationStore,
515
+ nowMs: now(options),
516
+ state: options.state
517
+ });
518
+ if (completion === "lost_lease") return { status: "lost_lease" };
519
+ if (completion === "pending") {
520
+ const nudgeNowMs = now(options);
521
+ return (await ensureConversationWake({
522
+ conversationId,
523
+ conversationStore: options.conversationStore,
524
+ idempotencyKey: nudgeIdempotencyKey("pending", conversationId, nudgeNowMs),
525
+ nowMs: nudgeNowMs,
526
+ queue: options.queue,
527
+ state: options.state
528
+ })).status === "enqueued" ? { status: "pending_requeued" } : { status: "completed" };
529
+ }
530
+ logInfo("conversation.work.completed", { "app.worker.elapsed_ms": now(options) - startedAtMs });
531
+ return { status: "completed" };
532
+ } catch (error) {
533
+ const errorNowMs = now(options);
534
+ let recoveryRecorded = false;
535
+ try {
536
+ const failure = attemptMessageIds.length > 0 ? await recordFailedDeliveryAttempt({
537
+ conversationId,
538
+ leaseToken: lease.leaseToken,
539
+ nowMs: errorNowMs,
540
+ messageIds: attemptMessageIds,
541
+ options
542
+ }) : void 0;
543
+ if (failure && isTerminalFailure(failure)) {
544
+ if (failure.retryCount >= 5) logRetryExhausted({
545
+ error,
546
+ retryCount: failure.retryCount,
547
+ work: initial
548
+ });
549
+ await deadLetterAttempt({
550
+ conversationId,
551
+ leaseToken: lease.leaseToken,
552
+ conversationStore: options.conversationStore,
553
+ nowMs: errorNowMs,
554
+ state: options.state
555
+ });
556
+ } else if (failure?.status === "recorded") {
557
+ await releaseConversationWork({
558
+ conversationId,
559
+ leaseToken: lease.leaseToken,
560
+ conversationStore: options.conversationStore,
561
+ nowMs: errorNowMs,
562
+ state: options.state
563
+ });
564
+ await ensureConversationWake({
565
+ conversationId,
566
+ conversationStore: options.conversationStore,
567
+ idempotencyKey: nudgeIdempotencyKey("error", conversationId, errorNowMs),
568
+ nowMs: errorNowMs,
569
+ queue: options.queue,
570
+ replaceExistingWake: true,
571
+ state: options.state
572
+ });
573
+ } else {
574
+ if ((failure ? failure.status : await recordConversationRetry({
575
+ conversationId,
576
+ leaseToken: lease.leaseToken,
577
+ conversationStore: options.conversationStore,
578
+ nowMs: errorNowMs,
579
+ state: options.state
580
+ })) === "stopped") {
581
+ logException(error, "conversation.work.retry.exhausted", {
582
+ "app.run.id": initial.execution.runId ?? "unknown",
583
+ "app.worker.last_progress_at_ms": initial.execution.lastProgressAtMs ?? initial.createdAtMs,
584
+ "app.worker.retry_count": failure?.retryCount ?? (initial.execution.retryCount ?? 0) + 1
585
+ });
586
+ recoveryRecorded = true;
587
+ return { status: "failed" };
588
+ }
589
+ if (await requestAnotherSlice({
590
+ conversationId,
591
+ destination,
592
+ leaseToken: lease.leaseToken,
593
+ conversationStore: options.conversationStore,
594
+ nowMs: errorNowMs,
595
+ state: options.state
596
+ })) await ensureConversationWake({
597
+ conversationId,
598
+ conversationStore: options.conversationStore,
599
+ idempotencyKey: nudgeIdempotencyKey("error", conversationId, errorNowMs),
600
+ nowMs: errorNowMs,
601
+ queue: options.queue,
602
+ replaceExistingWake: true,
603
+ state: options.state
604
+ });
605
+ await releaseConversationWork({
606
+ conversationId,
607
+ leaseToken: lease.leaseToken,
608
+ conversationStore: options.conversationStore,
609
+ nowMs: errorNowMs,
610
+ state: options.state
611
+ });
612
+ }
613
+ recoveryRecorded = true;
614
+ } catch (recoveryError) {
615
+ logException(recoveryError, "conversation.work.requeue.failed");
616
+ }
617
+ if (!isProviderRetryError(error)) logException(error, "conversation.work.failed", { "app.worker.elapsed_ms": now(options) - startedAtMs });
618
+ if (!recoveryRecorded) throw error;
619
+ return { status: "failed" };
620
+ } finally {
621
+ clearInterval(timer);
622
+ }
623
+ }
624
+ //#endregion
625
+ export { worker_exports as n, processConversationWork as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior",
3
- "version": "0.202.0",
3
+ "version": "0.204.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -85,7 +85,7 @@
85
85
  "pg": "^8.16.3",
86
86
  "yaml": "^2.9.0",
87
87
  "zod": "^4.5.4",
88
- "@sentry/junior-plugin-api": "0.202.0"
88
+ "@sentry/junior-plugin-api": "0.204.0"
89
89
  },
90
90
  "devDependencies": {
91
91
  "@emnapi/core": "^1.10.0",
@@ -100,20 +100,20 @@
100
100
  "msw": "^2.14.6",
101
101
  "nitro": "3.0.260522-beta",
102
102
  "oxlint": "^1.79.0",
103
- "tsup": "^8.5.1",
103
+ "tsdown": "0.23.0",
104
104
  "typescript": "^6.0.3",
105
105
  "vercel": "^54.4.0",
106
106
  "vitest": "^4.1.7",
107
- "@sentry/junior-testing": "0.0.0",
108
- "@sentry/junior-github": "0.202.0",
109
- "@sentry/junior-memory": "0.202.0"
107
+ "@sentry/junior-github": "0.204.0",
108
+ "@sentry/junior-memory": "0.204.0",
109
+ "@sentry/junior-testing": "0.0.0"
110
110
  },
111
111
  "scripts": {
112
- "build": "tsup",
112
+ "build": "tsdown",
113
113
  "acp:smoke": "pnpm exec tsx scripts/acp-smoke.ts",
114
114
  "db:generate": "pnpm exec drizzle-kit generate --config drizzle.config.ts",
115
- "lint": "oxlint --config .oxlintrc.json --deny-warnings src tests scripts bin tsup.config.ts && depcruise --config .dependency-cruiser.mjs src/chat",
116
- "lint:fix": "oxlint --config .oxlintrc.json --deny-warnings --fix src tests scripts bin tsup.config.ts",
115
+ "lint": "oxlint --config .oxlintrc.json --deny-warnings src tests scripts bin tsdown.config.ts && depcruise --config .dependency-cruiser.mjs src/chat",
116
+ "lint:fix": "oxlint --config .oxlintrc.json --deny-warnings --fix src tests scripts bin tsdown.config.ts",
117
117
  "test": "vitest run --maxWorkers=4",
118
118
  "test:watch": "vitest",
119
119
  "typecheck": "tsc --noEmit",