@sentry/junior 0.184.0 → 0.185.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/{agent-hooks-XTZVALGQ.js → agent-hooks-NGZQLL5O.js} +13 -11
  2. package/dist/api/acp/schema.d.ts +20 -2
  3. package/dist/api/code/overview.d.ts +39 -0
  4. package/dist/api/locations/detail.d.ts +1 -1
  5. package/dist/api/people/code.d.ts +22 -0
  6. package/dist/api/schema/code.d.ts +46 -0
  7. package/dist/api/schema/conversation.d.ts +100 -20
  8. package/dist/api/schema/location.d.ts +1 -1
  9. package/dist/api/schema/person.d.ts +1 -1
  10. package/dist/api/schema.d.ts +4 -4
  11. package/dist/api/schema.js +12 -1
  12. package/dist/api.js +358 -76
  13. package/dist/app.js +406 -377
  14. package/dist/{catalog-runtime-5357XR4F.js → catalog-runtime-AAEAO2RL.js} +4 -4
  15. package/dist/chat/api-turns/accepted-reply.d.ts +11 -0
  16. package/dist/chat/api-turns/cancellation.d.ts +3 -5
  17. package/dist/chat/api-turns/work.d.ts +4 -9
  18. package/dist/chat/app/conversation-work.d.ts +1 -1
  19. package/dist/chat/app/factory.d.ts +4 -0
  20. package/dist/chat/app/services.d.ts +4 -3
  21. package/dist/chat/conversations/history.d.ts +83 -9
  22. package/dist/chat/conversations/turn-lifecycle.d.ts +4 -3
  23. package/dist/chat/providers/slack/input.d.ts +32 -0
  24. package/dist/chat/{runtime → providers/slack}/processing-reaction.d.ts +6 -8
  25. package/dist/chat/{runtime/slack-resume.d.ts → providers/slack/resume.d.ts} +16 -19
  26. package/dist/chat/providers/slack/runtime.d.ts +1 -10
  27. package/dist/chat/providers/slack/turn.d.ts +11 -24
  28. package/dist/chat/resource-events/store.d.ts +1 -1
  29. package/dist/chat/resource-events/tool-support.d.ts +0 -5
  30. package/dist/chat/runtime/turn-execution.d.ts +7 -2
  31. package/dist/chat/sandbox/egress/credentials.d.ts +3 -3
  32. package/dist/chat/sandbox/egress/session.d.ts +5 -6
  33. package/dist/chat/scheduled-tasks/tool-support.d.ts +5 -5
  34. package/dist/chat/scheduled-tasks/tools/create.d.ts +2 -2
  35. package/dist/chat/scheduled-tasks/tools/delete.d.ts +2 -2
  36. package/dist/chat/scheduled-tasks/tools/list.d.ts +2 -2
  37. package/dist/chat/scheduled-tasks/tools/run-now.d.ts +2 -2
  38. package/dist/chat/scheduled-tasks/tools/update.d.ts +2 -2
  39. package/dist/chat/scheduled-tasks/types.d.ts +1 -1
  40. package/dist/chat/services/provider-retry.d.ts +2 -0
  41. package/dist/chat/services/turn-failure-response.d.ts +4 -0
  42. package/dist/chat/task-execution/paused-turn.d.ts +0 -2
  43. package/dist/chat/task-execution/state.d.ts +2 -2
  44. package/dist/chat/task-execution/store.d.ts +1 -1
  45. package/dist/chat/task-execution/turn-wake.d.ts +12 -0
  46. package/dist/chat/tool-support/action-review.d.ts +1 -1
  47. package/dist/chat/tools/resource-events.d.ts +1 -1
  48. package/dist/chat/tools/search-conversation-events.d.ts +1 -1
  49. package/dist/chat/tools/types.d.ts +1 -1
  50. package/dist/chat/tools/watch-resource-events.d.ts +2 -2
  51. package/dist/{chunk-FKEZZMXS.js → chunk-4HA36IWS.js} +9 -94
  52. package/dist/{chunk-WVIA7V3M.js → chunk-4K25ODAO.js} +27 -1
  53. package/dist/{chunk-UF6BUA5W.js → chunk-4S47VHJR.js} +3 -3
  54. package/dist/{chunk-JNO2GUDS.js → chunk-6DOAUXLD.js} +231 -198
  55. package/dist/{chunk-M3QYTBQ6.js → chunk-6Q7YZLCL.js} +2 -1
  56. package/dist/{chunk-6VOYP4M6.js → chunk-7GAP2XG4.js} +1 -1
  57. package/dist/{chunk-LHXIZLFF.js → chunk-7MHNIGHP.js} +1 -1
  58. package/dist/{chunk-IZDYYYGP.js → chunk-ABAX75GG.js} +10 -384
  59. package/dist/{chunk-WQFEWULF.js → chunk-ATUWN6Z3.js} +2 -2
  60. package/dist/{chunk-4RONS3WR.js → chunk-C6TS47CQ.js} +4 -4
  61. package/dist/chunk-D4YV5TDV.js +45 -0
  62. package/dist/{chunk-Z3QAXJR7.js → chunk-D63IUQQE.js} +4 -4
  63. package/dist/{chunk-M5YWNMTE.js → chunk-DAPC2HTM.js} +24 -6
  64. package/dist/{chunk-BHYRYYLY.js → chunk-EIJCPJOY.js} +1 -1
  65. package/dist/{chunk-SHJK75Z2.js → chunk-EJYP3NQ4.js} +4 -4
  66. package/dist/{chunk-K7VDC2QW.js → chunk-EWEH2PJW.js} +6 -6
  67. package/dist/{chunk-6WGC3SO4.js → chunk-FFHXG2FX.js} +13 -11
  68. package/dist/{chunk-MLSQX2EX.js → chunk-FTVMXDNN.js} +1 -1
  69. package/dist/chunk-GFBR4S3Q.js +406 -0
  70. package/dist/{chunk-PJPRXO2T.js → chunk-GJTIZQGJ.js} +1 -1
  71. package/dist/{chunk-BT53RIGJ.js → chunk-HJPC32TQ.js} +12 -50
  72. package/dist/{chunk-RF6J3DIO.js → chunk-INQHUE72.js} +84 -1
  73. package/dist/{chunk-6UDPINOX.js → chunk-LRI5IRGY.js} +19 -44
  74. package/dist/{chunk-BCHYQS4B.js → chunk-LVK4WJKM.js} +1 -1
  75. package/dist/{chunk-UBOIHNTH.js → chunk-MWOH6CIK.js} +178 -148
  76. package/dist/{chunk-3S7ULUWW.js → chunk-OMQ2J6F6.js} +1 -1
  77. package/dist/{chunk-DUKIDPF6.js → chunk-PNYJOEVV.js} +1 -1
  78. package/dist/{chunk-MAPJFUMV.js → chunk-QCT4226Q.js} +3 -3
  79. package/dist/{chunk-HIPUIPJM.js → chunk-QZKHHG3B.js} +34 -8
  80. package/dist/{chunk-QABCY33S.js → chunk-TVVAMOLS.js} +2 -2
  81. package/dist/{chunk-JA43DV4Y.js → chunk-U4CTAVWN.js} +1 -1
  82. package/dist/{chunk-LCP4EDKR.js → chunk-UUULGCKK.js} +1 -1
  83. package/dist/{chunk-4CNDGK25.js → chunk-VH4IU3UC.js} +928 -984
  84. package/dist/chunk-W7GCLNIV.js +58 -0
  85. package/dist/{chunk-2ZQPVX7C.js → chunk-WLKWN4CD.js} +22 -12
  86. package/dist/{chunk-ACPDVEJO.js → chunk-X2SS6BF7.js} +198 -209
  87. package/dist/{chunk-YKX6MTLU.js → chunk-X7NCJQAA.js} +1 -1
  88. package/dist/{chunk-E57WPXWY.js → chunk-Y5G23T2D.js} +5 -5
  89. package/dist/{chunk-HUXFMDBZ.js → chunk-ZIF2S464.js} +1 -1
  90. package/dist/{chunk-JM2COLGC.js → chunk-ZKKGFUWM.js} +6 -6
  91. package/dist/cli/chat.js +35 -33
  92. package/dist/cli/check.js +5 -5
  93. package/dist/cli/plugins.js +14 -12
  94. package/dist/cli/snapshot-create.js +10 -9
  95. package/dist/cli/upgrade.js +7 -6
  96. package/dist/{db-MA52H62H.js → db-TRJ77FAU.js} +8 -6
  97. package/dist/instrumentation.js +3 -3
  98. package/dist/nitro.js +7 -6
  99. package/dist/{oauth-callback-server-DXGHKN6S.js → oauth-callback-server-XD5SV3MS.js} +30 -27
  100. package/dist/{runner-4IXUAQNK.js → runner-KFX7NG6D.js} +24 -19
  101. package/dist/{skills-X3DY7AXO.js → skills-J2AH26CW.js} +5 -5
  102. package/dist/spawn-VU3CSRI6.js +41 -0
  103. package/dist/task-runner-5JG3VIIY.js +34 -0
  104. package/dist/{validation-Z6JXSTJS.js → validation-O5J4VOPF.js} +5 -5
  105. package/dist/version.js +1 -1
  106. package/dist/{work-OKWRFBDW.js → work-ECPQTG3U.js} +24 -19
  107. package/dist/worker-RS3DXUDO.js +24 -0
  108. package/package.json +4 -4
  109. package/dist/spawn-43WGS6CH.js +0 -37
  110. package/dist/task-runner-VDRKITPV.js +0 -32
  111. package/dist/worker-B236AE72.js +0 -22
@@ -7,7 +7,7 @@ import {
7
7
  PluginCredentialFailureError,
8
8
  agentNameSchema,
9
9
  createPluginAuthOrchestration
10
- } from "./chunk-K7VDC2QW.js";
10
+ } from "./chunk-EWEH2PJW.js";
11
11
  import {
12
12
  parseSandboxEgressAuthRequiredSignal,
13
13
  parseSandboxEgressPermissionDeniedSignal,
@@ -38,15 +38,7 @@ import {
38
38
  searchSlackUsers,
39
39
  selectPluginGrant,
40
40
  toMcpProviderError
41
- } from "./chunk-FKEZZMXS.js";
42
- import {
43
- RetryableDeliveryError,
44
- actorFromRun,
45
- assertRunConsistency,
46
- isAgentRunFeatureDisabled,
47
- surfaceFromRun,
48
- toolInvocationDestination
49
- } from "./chunk-RF6J3DIO.js";
41
+ } from "./chunk-4HA36IWS.js";
50
42
  import {
51
43
  addReactionToMessage,
52
44
  deliverOAuthAuthorization,
@@ -54,11 +46,13 @@ import {
54
46
  getSlackMessagePermalink,
55
47
  resolveBaseUrl,
56
48
  uploadFilesToConversation
57
- } from "./chunk-JM2COLGC.js";
49
+ } from "./chunk-ZKKGFUWM.js";
58
50
  import {
59
51
  SCHEDULED_TASK_SYSTEM_ACTOR,
52
+ canRouteResourceEvents,
60
53
  compactEventTask,
61
54
  createEventTask,
55
+ createResourceEventTeamIdResolver,
62
56
  createScheduledTask,
63
57
  deleteEventTask,
64
58
  eventNamespaceSchema,
@@ -90,13 +84,21 @@ import {
90
84
  saveScheduledTask,
91
85
  storeAttachments,
92
86
  writableEventTask
93
- } from "./chunk-HIPUIPJM.js";
87
+ } from "./chunk-QZKHHG3B.js";
94
88
  import {
95
89
  parseSlackThreadId
96
- } from "./chunk-YKX6MTLU.js";
90
+ } from "./chunk-X7NCJQAA.js";
91
+ import {
92
+ RetryableDeliveryError,
93
+ actorFromRun,
94
+ assertRunConsistency,
95
+ isAgentRunFeatureDisabled,
96
+ surfaceFromRun,
97
+ toolInvocationDestination
98
+ } from "./chunk-INQHUE72.js";
97
99
  import {
98
100
  appendAndEnqueueInboundMessage
99
- } from "./chunk-Z3QAXJR7.js";
101
+ } from "./chunk-D63IUQQE.js";
100
102
  import {
101
103
  CooperativeTurnYieldError,
102
104
  NO_REPLY_MARKER,
@@ -111,7 +113,7 @@ import {
111
113
  isTurnInputCommitLostError,
112
114
  isTurnInputDeferredError,
113
115
  sanitizeAssistantText
114
- } from "./chunk-JA43DV4Y.js";
116
+ } from "./chunk-U4CTAVWN.js";
115
117
  import {
116
118
  AGENTS_REMOVAL_NOTICE,
117
119
  AGENTS_REPLACEMENT_NOTICE,
@@ -120,6 +122,7 @@ import {
120
122
  RIPGREP_EXCLUDED_GLOBS,
121
123
  SHORT_TITLE_MAX_LENGTH,
122
124
  TURN_CONTEXT_TAG,
125
+ ToolInputError,
123
126
  TurnSliceLimitExceededError,
124
127
  addAgentTurnUsage,
125
128
  buildAgentsInstructionsMessage,
@@ -170,7 +173,7 @@ import {
170
173
  stripRuntimeTurnContext,
171
174
  trimTrailingAssistantMessages,
172
175
  truncateText
173
- } from "./chunk-2ZQPVX7C.js";
176
+ } from "./chunk-WLKWN4CD.js";
174
177
  import {
175
178
  bindSandboxFileSystem,
176
179
  createSandboxSession,
@@ -181,7 +184,7 @@ import {
181
184
  resolve,
182
185
  setSnapshotSpanAttributes,
183
186
  stopSession
184
- } from "./chunk-MAPJFUMV.js";
187
+ } from "./chunk-QCT4226Q.js";
185
188
  import {
186
189
  privateTraceResultAttributes
187
190
  } from "./chunk-UIE3R5XU.js";
@@ -194,7 +197,7 @@ import {
194
197
  } from "./chunk-DKIJ2RP5.js";
195
198
  import {
196
199
  getTurnRequestDeadline
197
- } from "./chunk-MLSQX2EX.js";
200
+ } from "./chunk-FTVMXDNN.js";
198
201
  import {
199
202
  RESOURCE_SUBSCRIPTION_DEFAULT_TTL_MS,
200
203
  RESOURCE_SUBSCRIPTION_MAX_TTL_MS,
@@ -202,15 +205,11 @@ import {
202
205
  SANDBOX_RUNTIME,
203
206
  STOP_WATCHING_TOOL_NAME,
204
207
  SlackActionError,
205
- ToolInputError,
206
208
  WorkspaceValidationError,
207
- canRouteResourceEvents,
208
- canUseResourceEventSubscriptionTools,
209
209
  cancelResourceEventSubscription,
210
210
  cancelSubscriptions,
211
211
  createPluginHookRunner,
212
212
  createResourceEventSubscription,
213
- createResourceEventTeamIdResolver,
214
213
  createWorkspace,
215
214
  deleteWorkspace,
216
215
  deleteWorkspaceSnapshotBuilders,
@@ -235,7 +234,6 @@ import {
235
234
  loadSnapshotsForProfile,
236
235
  normalizeSlackConversationId,
237
236
  readActorIdentity,
238
- requireResourceWatchConversation,
239
237
  resolveChannelCapabilities,
240
238
  runWithSlackInstallationToken,
241
239
  setWorkspaceSnapshot,
@@ -244,26 +242,21 @@ import {
244
242
  updateWorkspace,
245
243
  withSlackRetries,
246
244
  workspaceRepoCheckoutPath
247
- } from "./chunk-4CNDGK25.js";
245
+ } from "./chunk-VH4IU3UC.js";
248
246
  import {
249
- KNOWN_CONVERSATION_EVENT_TYPES,
250
- contextProvenance,
251
247
  createSlackDestination,
252
248
  getConversationEventStore,
253
249
  getConversationMessageSearchStore,
254
250
  getConversationStore,
255
251
  getDb,
256
252
  getSqlExecutor,
257
- instructionActors,
258
- instructionProvenanceFor,
259
- requireSlackDestination,
260
- sameActorIdentity
261
- } from "./chunk-IZDYYYGP.js";
253
+ requireSlackDestination
254
+ } from "./chunk-ABAX75GG.js";
262
255
  import {
263
256
  juniorArtifacts,
264
257
  juniorIdentities,
265
258
  juniorSchedulerRuns
266
- } from "./chunk-BCHYQS4B.js";
259
+ } from "./chunk-LVK4WJKM.js";
267
260
  import {
268
261
  SANDBOX_DATA_ROOT,
269
262
  SANDBOX_REPOS_ROOT,
@@ -290,12 +283,19 @@ import {
290
283
  sleep,
291
284
  throwSandboxOperationError,
292
285
  wrapSandboxSetupError
293
- } from "./chunk-SHJK75Z2.js";
286
+ } from "./chunk-EJYP3NQ4.js";
294
287
  import {
295
288
  fenceLock,
296
289
  getStateAdapter,
297
290
  withLock
298
- } from "./chunk-DUKIDPF6.js";
291
+ } from "./chunk-PNYJOEVV.js";
292
+ import {
293
+ KNOWN_CONVERSATION_EVENT_TYPES,
294
+ contextProvenance,
295
+ instructionActors,
296
+ instructionProvenanceFor,
297
+ sameActorIdentity
298
+ } from "./chunk-GFBR4S3Q.js";
299
299
  import {
300
300
  ACTIVE_TURN_COMPACTION_SUMMARY_PREFIX,
301
301
  COMPACTION_SUMMARY_PREFIX,
@@ -304,9 +304,7 @@ import {
304
304
  GEN_AI_SERVER_PORT,
305
305
  MISSING_GATEWAY_CREDENTIALS_ERROR,
306
306
  MODEL_HANDOFF_SUMMARY_PREFIX,
307
- ModelProfileNotConfiguredError,
308
307
  ProviderError,
309
- TURN_REASONING_LEVELS,
310
308
  botConfig,
311
309
  completeObject,
312
310
  completeText,
@@ -318,15 +316,19 @@ import {
318
316
  hasCompactedConversationContext,
319
317
  isCompactionSummaryText,
320
318
  isProviderRetryError,
321
- modelIdForProfile,
322
- modelProfileSchema,
323
319
  normalizeSlackEmojiName,
324
- profileConfig,
325
320
  renderCurrentInstruction,
326
321
  resolveGatewayCredential,
327
322
  resolveGatewayModel,
328
323
  unwrapCurrentInstruction
329
- } from "./chunk-6UDPINOX.js";
324
+ } from "./chunk-LRI5IRGY.js";
325
+ import {
326
+ ModelProfileNotConfiguredError,
327
+ TURN_REASONING_LEVELS,
328
+ modelIdForProfile,
329
+ modelProfileSchema,
330
+ profileConfig
331
+ } from "./chunk-D4YV5TDV.js";
330
332
  import {
331
333
  canExposeConversationPayload,
332
334
  resolveConversationPrivacy,
@@ -336,16 +338,16 @@ import {
336
338
  toGenAiMessagesTraceAttributes,
337
339
  toGenAiPayloadMetadata,
338
340
  toGenAiPayloadTraceAttributes
339
- } from "./chunk-BHYRYYLY.js";
341
+ } from "./chunk-EIJCPJOY.js";
340
342
  import {
341
343
  discoverSkills,
342
344
  findSkillByName,
343
345
  loadSkillsByName,
344
346
  parseSkillInvocation
345
- } from "./chunk-WQFEWULF.js";
347
+ } from "./chunk-ATUWN6Z3.js";
346
348
  import {
347
349
  pluginCatalogRuntime
348
- } from "./chunk-PJPRXO2T.js";
350
+ } from "./chunk-GJTIZQGJ.js";
349
351
  import {
350
352
  CredentialUnavailableError,
351
353
  OAuthProviderError,
@@ -353,7 +355,7 @@ import {
353
355
  getOAuthProviderErrorAttributes,
354
356
  resolveAuthTokenPlaceholder,
355
357
  resolvePluginCommandEnv
356
- } from "./chunk-LHXIZLFF.js";
358
+ } from "./chunk-7MHNIGHP.js";
357
359
  import {
358
360
  credentialContextForActor,
359
361
  credentialUserSubjectId
@@ -393,7 +395,7 @@ import {
393
395
  summarizeMessageText,
394
396
  withLogContext,
395
397
  withSpan
396
- } from "./chunk-3S7ULUWW.js";
398
+ } from "./chunk-OMQ2J6F6.js";
397
399
  import {
398
400
  startInactiveSpan,
399
401
  withActiveSpan
@@ -1738,6 +1740,11 @@ function buildChatEndAttributes(message, mode) {
1738
1740
  if (message.model) {
1739
1741
  attributes["gen_ai.response.model"] = message.model;
1740
1742
  }
1743
+ if (message.stopReason === "error") {
1744
+ const providerError = createProviderError(message.errorMessage ?? "");
1745
+ Object.assign(attributes, getProviderErrorAttributes(providerError));
1746
+ attributes["error.type"] = providerError.kind;
1747
+ }
1741
1748
  return attributes;
1742
1749
  }
1743
1750
  function createTracedStreamFn(baseOrOptions = streamSimple) {
@@ -1770,14 +1777,16 @@ function createTracedStreamFn(baseOrOptions = streamSimple) {
1770
1777
  stream.result().then(
1771
1778
  (finalMessage) => {
1772
1779
  try {
1773
- for (const [key, value] of Object.entries(
1774
- buildChatEndAttributes(finalMessage, mode)
1775
- )) {
1780
+ const endAttributes = buildChatEndAttributes(finalMessage, mode);
1781
+ for (const [key, value] of Object.entries(endAttributes)) {
1776
1782
  span.setAttribute(key, value);
1777
1783
  }
1778
1784
  if (finalMessage.stopReason === "error") {
1779
- span.setAttribute("error.type", "provider_error");
1780
- span.setStatus({ code: 2, message: "LLM stream failed" });
1785
+ const summary = endAttributes["app.ai.provider_error.summary"];
1786
+ span.setStatus({
1787
+ code: 2,
1788
+ message: typeof summary === "string" ? summary : "LLM stream failed"
1789
+ });
1781
1790
  }
1782
1791
  } finally {
1783
1792
  span.end();
@@ -1948,7 +1957,7 @@ function nextProviderRetry(args) {
1948
1957
  if (tailRole !== "user" && tailRole !== "toolResult") {
1949
1958
  return void 0;
1950
1959
  }
1951
- return { delayMs, messages };
1960
+ return { delayMs, messages, providerError };
1952
1961
  }
1953
1962
 
1954
1963
  // src/chat/services/empty-output-continuation.ts
@@ -3675,11 +3684,15 @@ var SANDBOX_EGRESS_AUTH_SIGNAL_PREFIX = "sandbox-egress-auth-required";
3675
3684
  var SANDBOX_EGRESS_PERMISSION_SIGNAL_PREFIX = "sandbox-egress-permission-denied";
3676
3685
  var SANDBOX_EGRESS_LEASE_PREFIX = "sandbox-egress-lease";
3677
3686
  var DEFAULT_SESSION_TTL_MS = 30 * 60 * 1e3;
3687
+ var LEASE_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
3678
3688
  function leaseKey(provider, grant, context) {
3689
+ if (grant.name.startsWith("installation-")) {
3690
+ return `${SANDBOX_EGRESS_LEASE_PREFIX}:${provider}:${grant.name}:shared`;
3691
+ }
3679
3692
  const actor = context.credentials.actor;
3680
- const actorKey = "type" in actor ? `user:${actor.userId}` : `system:${actor.name}`;
3681
- const grantKey = grant.leaseScope ? `${grant.name}:${grant.leaseScope}` : grant.name;
3682
- return `${SANDBOX_EGRESS_LEASE_PREFIX}:${provider}:${grantKey}:${actorKey}:${context.egressId}:${context.contextId}`;
3693
+ const subject = "subject" in context.credentials ? context.credentials.subject : void 0;
3694
+ const ownerKey = subject ? `subject:${subject.userId}` : "type" in actor ? `user:${actor.userId}` : `system:${actor.name}`;
3695
+ return `${SANDBOX_EGRESS_LEASE_PREFIX}:${provider}:${grant.name}:${ownerKey}`;
3683
3696
  }
3684
3697
  function authSignalKey(egressId, access) {
3685
3698
  return `${SANDBOX_EGRESS_AUTH_SIGNAL_PREFIX}:${egressId}:${access}`;
@@ -3720,7 +3733,7 @@ function parseLease(value) {
3720
3733
  return void 0;
3721
3734
  }
3722
3735
  const expiresAtMs = Date.parse(result.data.expiresAt);
3723
- if (!Number.isFinite(expiresAtMs) || expiresAtMs <= Date.now()) {
3736
+ if (!Number.isFinite(expiresAtMs) || expiresAtMs <= Date.now() + LEASE_REFRESH_BUFFER_MS) {
3724
3737
  return void 0;
3725
3738
  }
3726
3739
  return result.data;
@@ -3774,10 +3787,7 @@ async function setSandboxEgressCredentialLease(context, lease) {
3774
3787
  if (!Number.isFinite(leaseExpiresAtMs) || leaseExpiresAtMs <= Date.now()) {
3775
3788
  return;
3776
3789
  }
3777
- const ttlMs2 = Math.max(
3778
- 1,
3779
- Math.min(leaseExpiresAtMs, context.expiresAtMs) - Date.now()
3780
- );
3790
+ const ttlMs2 = Math.max(1, leaseExpiresAtMs - Date.now());
3781
3791
  const state = getStateAdapter();
3782
3792
  await state.connect();
3783
3793
  await state.set(leaseKey(lease.provider, lease.grant, context), lease, ttlMs2);
@@ -9349,9 +9359,8 @@ function createListResourceEventSubscriptionsTool(context) {
9349
9359
  inputSchema: z19.object({}).strict(),
9350
9360
  outputSchema,
9351
9361
  async execute() {
9352
- const conversationId = requireResourceWatchConversation(context);
9353
9362
  const subscriptions = await listResourceEventSubscriptions({
9354
- conversationId
9363
+ conversationId: context.conversationId
9355
9364
  });
9356
9365
  const details = {
9357
9366
  subscriptions: subscriptions.map((subscription) => ({
@@ -9486,11 +9495,10 @@ function createStopWatchingResourcesTool(context) {
9486
9495
  inputSchema: z21.object({ id: z21.string().min(1).nullable().optional() }).strict(),
9487
9496
  outputSchema: outputSchema3,
9488
9497
  async execute({ id }) {
9489
- const conversationId = requireResourceWatchConversation(context);
9490
9498
  let stoppedIds;
9491
9499
  if (id) {
9492
9500
  const stopped = await cancelResourceEventSubscription({
9493
- conversationId,
9501
+ conversationId: context.conversationId,
9494
9502
  id
9495
9503
  });
9496
9504
  if (!stopped) {
@@ -9501,9 +9509,9 @@ function createStopWatchingResourcesTool(context) {
9501
9509
  stoppedIds = [stopped.id];
9502
9510
  } else {
9503
9511
  const subscriptions = await listResourceEventSubscriptions({
9504
- conversationId
9512
+ conversationId: context.conversationId
9505
9513
  });
9506
- await cancelSubscriptions({ conversationId });
9514
+ await cancelSubscriptions({ conversationId: context.conversationId });
9507
9515
  stoppedIds = subscriptions.map((subscription) => subscription.id);
9508
9516
  }
9509
9517
  const details = {
@@ -9598,7 +9606,6 @@ function createWatchResourceEventsTool(context, catalog) {
9598
9606
  inputSchema: inputSchema(catalog),
9599
9607
  outputSchema: outputSchema4,
9600
9608
  async execute(input) {
9601
- const conversationId = requireResourceWatchConversation(context);
9602
9609
  const events = cleanStrings(input.events);
9603
9610
  for (const eventType of events) {
9604
9611
  if (!pluginSupportsEvent(
@@ -9621,7 +9628,7 @@ function createWatchResourceEventsTool(context, catalog) {
9621
9628
  });
9622
9629
  const nowMs = Date.now();
9623
9630
  const subscription = await createResourceEventSubscription({
9624
- conversationId,
9631
+ conversationId: context.conversationId,
9625
9632
  destination: context.destination,
9626
9633
  events,
9627
9634
  expiresAtMs: nowMs + ttlMs(input),
@@ -9661,15 +9668,9 @@ function createWatchResourceEventsTool(context, catalog) {
9661
9668
  // src/chat/tools/resource-events.ts
9662
9669
  function createResourceEventTools(context, catalog) {
9663
9670
  const enabled = Object.keys(catalog).length > 0;
9664
- const discoveryTools = context.destination.platform === "slack" && enabled ? {
9665
- searchResourceEventTypes: createSearchResourceEventTypesTool(catalog)
9666
- } : {};
9667
- if (!canUseResourceEventSubscriptionTools(context)) {
9668
- return discoveryTools;
9669
- }
9670
9671
  return {
9671
- ...discoveryTools,
9672
9672
  ...enabled ? {
9673
+ searchResourceEventTypes: createSearchResourceEventTypesTool(catalog),
9673
9674
  watchResourceEvents: createWatchResourceEventsTool(context, catalog)
9674
9675
  } : void 0,
9675
9676
  listResourceEventSubscriptions: createListResourceEventSubscriptionsTool(context),
@@ -14424,12 +14425,7 @@ function createSearchConversationEventsTool(context) {
14424
14425
  }).strict(),
14425
14426
  outputSchema: searchConversationEventsOutputSchema,
14426
14427
  execute: async (input) => {
14427
- const currentConversationId = context.conversationId?.trim();
14428
- if (!currentConversationId) {
14429
- throw new ToolInputError(
14430
- "searchConversationEvents requires an active conversation"
14431
- );
14432
- }
14428
+ const currentConversationId = context.conversationId;
14433
14429
  const conversationId = input.conversation_id?.trim() || currentConversationId;
14434
14430
  const afterSeq = input.after_seq ?? void 0;
14435
14431
  const beforeSeq = input.before_seq ?? void 0;
@@ -15572,7 +15568,7 @@ function createWorkspaceTools(context) {
15572
15568
  workspaceId: workspace.id,
15573
15569
  workspaceName: workspace.name
15574
15570
  });
15575
- const conversationId = canRouteResourceEvents() && canUseResourceEventSubscriptionTools(context) ? requireResourceWatchConversation(context) : void 0;
15571
+ const conversationId = canRouteResourceEvents() && context.destination.platform === "slack" ? context.conversationId.trim() : void 0;
15576
15572
  const subscription = conversationId ? await createResourceEventSubscription({
15577
15573
  conversationId,
15578
15574
  destination: context.destination,
@@ -15671,9 +15667,7 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
15671
15667
  ...createScheduledTaskTools(context),
15672
15668
  ...createWorkspaceTools(context)
15673
15669
  };
15674
- if (context.conversationId) {
15675
- tools.searchConversationEvents = createSearchConversationEventsTool(context);
15676
- }
15670
+ tools.searchConversationEvents = createSearchConversationEventsTool(context);
15677
15671
  if (context.supportsImageInput) {
15678
15672
  tools.viewImage = createViewImageTool(
15679
15673
  context.workspace,
@@ -15693,7 +15687,7 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
15693
15687
  hooks.toolOverrides?.imageGenerate
15694
15688
  );
15695
15689
  }
15696
- if (context.attachmentStorage && context.conversationId) {
15690
+ if (context.attachmentStorage) {
15697
15691
  tools.publishImage = createPublishImageTool({
15698
15692
  conversationId: context.conversationId,
15699
15693
  db: getSqlExecutor(),
@@ -15721,7 +15715,7 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
15721
15715
  tools.slackCanvasWrite = createSlackCanvasWriteTool(state);
15722
15716
  tools.slackThreadRead = createSlackThreadReadTool(slackContext);
15723
15717
  tools.slackChannelJoin = createSlackChannelJoinTool(slackContext);
15724
- if (context.conversationId && slackContext.source.visibility === "public") {
15718
+ if (slackContext.source.visibility === "public") {
15725
15719
  tools.searchConversationMessages = createSlackConversationMessageSearchTool(
15726
15720
  {
15727
15721
  kind: "public_provider_tenant",
@@ -15764,7 +15758,7 @@ function createTools(availableSkills, hooks = {}, context, options = {}) {
15764
15758
  slackContext,
15765
15759
  state,
15766
15760
  (input) => readSandboxFileUpload(context.workspace, input),
15767
- context.conversationId && context.attachmentStorage ? {
15761
+ context.attachmentStorage ? {
15768
15762
  conversationId: context.conversationId,
15769
15763
  db: getSqlExecutor(),
15770
15764
  storage: context.attachmentStorage
@@ -16074,9 +16068,6 @@ function actionCredential(credentialContext) {
16074
16068
  };
16075
16069
  }
16076
16070
  function assertAuthoritativeContext(context) {
16077
- if (!context.conversationId?.trim()) {
16078
- throw new ToolActionReviewUnavailableError();
16079
- }
16080
16071
  if (!context.actor) {
16081
16072
  throw new ToolActionReviewUnavailableError();
16082
16073
  }
@@ -17432,7 +17423,7 @@ function githubPermissionHeaders(upstream) {
17432
17423
  };
17433
17424
  }
17434
17425
  function permissionDeniedMessage(provider, grant) {
17435
- return `${provider} returned HTTP 403 after Junior injected the ${grant.name} grant. Junior forwarded the request; this is not a local runtime block.`;
17426
+ return `${provider} returned HTTP 403 after the runtime injected the ${grant.name} grant. The request was forwarded; this is not a local runtime block.`;
17436
17427
  }
17437
17428
  function isEgressAuthRequired(error) {
17438
17429
  return error instanceof EgressAuthRequired || error instanceof Error && error.name === "EgressAuthRequired";
@@ -17692,15 +17683,17 @@ async function executeCredentialedEgressRequest(input) {
17692
17683
  const clearCredentialLease = deps.clearCredentialLease ?? clearSandboxEgressCredentialLease;
17693
17684
  const recordAuthRequired = deps.recordAuthRequired ?? recordSandboxAuthRequired;
17694
17685
  const recordPermissionDenied = deps.recordPermissionDenied ?? recordSandboxPermissionDenied;
17695
- let lease;
17696
- try {
17697
- lease = await issueCredentialLease(
17698
- provider,
17699
- grantSelection,
17700
- credentialContext
17701
- );
17702
- } catch (error) {
17703
- if (error instanceof SandboxEgressCredentialError) {
17686
+ async function resolveLease() {
17687
+ try {
17688
+ return await issueCredentialLease(
17689
+ provider,
17690
+ grantSelection,
17691
+ credentialContext
17692
+ );
17693
+ } catch (error) {
17694
+ if (!(error instanceof SandboxEgressCredentialError)) {
17695
+ throw error;
17696
+ }
17704
17697
  await recordAuthRequired({
17705
17698
  credentialContext,
17706
17699
  provider: error.provider,
@@ -17733,20 +17726,24 @@ async function executeCredentialedEgressRequest(input) {
17733
17726
  message: error.message
17734
17727
  });
17735
17728
  }
17736
- throw error;
17737
17729
  }
17738
- const attributes = (status, upstream2) => leaseLogAttributes({
17730
+ let leaseOrResponse = await resolveLease();
17731
+ if (leaseOrResponse instanceof Response) {
17732
+ return leaseOrResponse;
17733
+ }
17734
+ let lease = leaseOrResponse;
17735
+ const attributes = (activeLease, status, upstream) => leaseLogAttributes({
17739
17736
  egressId: activeEgressId,
17740
- lease,
17737
+ lease: activeLease,
17741
17738
  provider,
17742
17739
  request,
17743
17740
  status,
17744
- ...upstream2 ? { upstream: upstream2 } : void 0,
17741
+ ...upstream ? { upstream } : void 0,
17745
17742
  upstreamUrl
17746
17743
  });
17747
17744
  if (!hasSandboxEgressLeaseTransformForHost(lease, upstreamUrl.hostname)) {
17748
17745
  logWarn("sandbox.egress.transform.missing", {
17749
- ...attributes(403),
17746
+ ...attributes(lease, 403),
17750
17747
  "app.sandbox.egress.transform_domains": lease.headerTransforms.map(
17751
17748
  (transform) => transform.domain
17752
17749
  )
@@ -17757,103 +17754,92 @@ async function executeCredentialedEgressRequest(input) {
17757
17754
  );
17758
17755
  }
17759
17756
  const fetchImpl = deps.fetch ?? fetch;
17760
- const headers = requestHeaders(
17761
- request,
17762
- lease,
17763
- upstreamUrl.hostname,
17764
- deps.tracePropagation ?? {}
17765
- );
17766
17757
  const body = bodyForGrantSelection ?? await requestBodyBytes(request);
17767
- const intercepted = await deps.interceptHttp?.({
17768
- provider,
17769
- request: new Request(upstreamUrl, {
17770
- method: request.method,
17771
- headers,
17772
- ...body !== void 0 ? { body } : void 0
17773
- }),
17774
- upstreamUrl
17775
- });
17776
- if (intercepted) {
17777
- return intercepted;
17778
- }
17779
- const upstream = await fetchImpl(upstreamUrl, {
17780
- method: request.method,
17781
- headers,
17782
- ...body !== void 0 ? { body } : void 0,
17783
- redirect: "manual"
17784
- });
17785
- try {
17786
- const effects = await onPluginEgressResponse({
17758
+ let retriedAfter403 = false;
17759
+ while (true) {
17760
+ const headers = requestHeaders(
17761
+ request,
17762
+ lease,
17763
+ upstreamUrl.hostname,
17764
+ deps.tracePropagation ?? {}
17765
+ );
17766
+ const intercepted = await deps.interceptHttp?.({
17787
17767
  provider,
17788
- grant: lease.grant,
17768
+ request: new Request(upstreamUrl, {
17769
+ method: request.method,
17770
+ headers,
17771
+ ...body !== void 0 ? { body } : void 0
17772
+ }),
17773
+ upstreamUrl
17774
+ });
17775
+ if (intercepted) {
17776
+ return intercepted;
17777
+ }
17778
+ const requestBody = body instanceof ArrayBuffer ? body.slice(0) : body;
17779
+ const upstream = await fetchImpl(upstreamUrl, {
17789
17780
  method: request.method,
17790
- ...operation ? { operation } : void 0,
17791
- upstreamUrl,
17792
- response: {
17793
- headers: new Headers(upstream.headers),
17794
- readText: async (maxBytes) => await responseTextWithinLimit(upstream, maxBytes),
17795
- status: upstream.status
17796
- }
17781
+ headers,
17782
+ ...requestBody !== void 0 ? { body: requestBody } : void 0,
17783
+ redirect: "manual"
17797
17784
  });
17798
- if (effects.permissionDenied) {
17799
- await recordPermissionDenied({
17785
+ let pluginPermissionDenied;
17786
+ try {
17787
+ const effects = await onPluginEgressResponse({
17788
+ provider,
17789
+ grant: lease.grant,
17790
+ method: request.method,
17791
+ ...operation ? { operation } : void 0,
17792
+ upstreamUrl,
17793
+ response: {
17794
+ headers: new Headers(upstream.headers),
17795
+ readText: async (maxBytes) => await responseTextWithinLimit(upstream, maxBytes),
17796
+ status: upstream.status
17797
+ }
17798
+ });
17799
+ pluginPermissionDenied = effects.permissionDenied;
17800
+ } catch (error) {
17801
+ if (!isEgressAuthRequired(error)) {
17802
+ throw error;
17803
+ }
17804
+ await clearCredentialLease(provider, lease.grant, credentialContext);
17805
+ await recordAuthRequired({
17800
17806
  credentialContext,
17801
17807
  provider,
17802
- lease,
17803
- message: effects.permissionDenied.message,
17804
- upstream,
17805
- upstreamUrl
17808
+ grant: lease.grant,
17809
+ authorization: error.authorization ?? lease.authorization,
17810
+ message: error.message
17806
17811
  });
17807
- logWarn("sandbox.egress.upstream_permission.classified", {
17808
- ...attributes(upstream.status, upstream)
17812
+ logWarn("sandbox.egress.upstream_auth_requirement.classified", {
17813
+ ...attributes(lease, upstream.status, upstream)
17814
+ });
17815
+ await upstream.body?.cancel().catch(() => void 0);
17816
+ return authRequiredResponse({
17817
+ provider,
17818
+ grant: lease.grant,
17819
+ message: error.message
17809
17820
  });
17810
17821
  }
17811
- } catch (error) {
17812
- if (!isEgressAuthRequired(error)) {
17813
- throw error;
17814
- }
17815
- await clearCredentialLease(provider, lease.grant, credentialContext);
17816
- await recordAuthRequired({
17817
- credentialContext,
17818
- provider,
17819
- grant: lease.grant,
17820
- authorization: error.authorization ?? lease.authorization,
17821
- message: error.message
17822
- });
17823
- logWarn("sandbox.egress.upstream_auth_requirement.classified", {
17824
- ...attributes(upstream.status, upstream)
17825
- });
17826
- await upstream.body?.cancel().catch(() => void 0);
17827
- return authRequiredResponse({
17822
+ logSandboxEgressUpstreamRequest({
17823
+ egressId: activeEgressId,
17824
+ grantAccess: lease.grant.access,
17825
+ grantName: lease.grant.name,
17826
+ grantReason: lease.grant.reason,
17828
17827
  provider,
17829
- grant: lease.grant,
17830
- message: error.message
17831
- });
17832
- }
17833
- logSandboxEgressUpstreamRequest({
17834
- egressId: activeEgressId,
17835
- grantAccess: lease.grant.access,
17836
- grantName: lease.grant.name,
17837
- grantReason: lease.grant.reason,
17838
- provider,
17839
- request,
17840
- upstream,
17841
- upstreamUrl
17842
- });
17843
- if (upstream.status >= 400) {
17844
- logWarn("sandbox.egress.upstream_response.failed", {
17845
- ...attributes(upstream.status, upstream),
17846
- "error.type": `http_${upstream.status}`
17847
- });
17848
- }
17849
- if (upstream.status === UPSTREAM_TOKEN_REJECTION_STATUS || upstream.status === UPSTREAM_PERMISSION_REJECTION_STATUS) {
17850
- logWarn("sandbox.egress.upstream_auth.rejected", {
17851
- ...attributes(upstream.status, upstream),
17852
- ...upstream.status === UPSTREAM_TOKEN_REJECTION_STATUS ? {
17853
- "app.sandbox.egress.www_authenticate": upstream.headers.get("www-authenticate") ?? void 0
17854
- } : void 0
17828
+ request,
17829
+ upstream,
17830
+ upstreamUrl
17855
17831
  });
17832
+ if (upstream.status >= 400) {
17833
+ logWarn("sandbox.egress.upstream_response.failed", {
17834
+ ...attributes(lease, upstream.status, upstream),
17835
+ "error.type": `http_${upstream.status}`
17836
+ });
17837
+ }
17856
17838
  if (upstream.status === UPSTREAM_TOKEN_REJECTION_STATUS) {
17839
+ logWarn("sandbox.egress.upstream_auth.rejected", {
17840
+ ...attributes(lease, upstream.status, upstream),
17841
+ "app.sandbox.egress.www_authenticate": upstream.headers.get("www-authenticate") ?? void 0
17842
+ });
17857
17843
  await clearCredentialLease(provider, lease.grant, credentialContext);
17858
17844
  await recordAuthRequired({
17859
17845
  credentialContext,
@@ -17869,23 +17855,67 @@ async function executeCredentialedEgressRequest(input) {
17869
17855
  message: `Provider rejected the injected ${provider} credential.
17870
17856
  `
17871
17857
  });
17872
- } else {
17858
+ }
17859
+ if (upstream.status === UPSTREAM_PERMISSION_REJECTION_STATUS && !retriedAfter403) {
17860
+ logWarn("sandbox.egress.upstream_auth.rejected", {
17861
+ ...attributes(lease, upstream.status, upstream)
17862
+ });
17863
+ await clearCredentialLease(provider, lease.grant, credentialContext);
17864
+ await upstream.body?.cancel().catch(() => void 0);
17865
+ logWarn("sandbox.egress.upstream_auth.retrying", {
17866
+ ...attributes(lease, upstream.status, upstream)
17867
+ });
17868
+ leaseOrResponse = await resolveLease();
17869
+ if (leaseOrResponse instanceof Response) {
17870
+ return leaseOrResponse;
17871
+ }
17872
+ lease = leaseOrResponse;
17873
+ retriedAfter403 = true;
17874
+ continue;
17875
+ }
17876
+ if (upstream.status === UPSTREAM_PERMISSION_REJECTION_STATUS) {
17877
+ logWarn("sandbox.egress.upstream_auth.rejected", {
17878
+ ...attributes(lease, upstream.status, upstream)
17879
+ });
17873
17880
  await clearCredentialLease(provider, lease.grant, credentialContext);
17874
17881
  await recordPermissionDenied({
17875
17882
  credentialContext,
17876
17883
  provider,
17877
17884
  lease,
17878
- message: permissionDeniedMessage(provider, lease.grant),
17885
+ message: pluginPermissionDenied?.message ?? permissionDeniedMessage(provider, lease.grant),
17879
17886
  upstream,
17880
17887
  upstreamUrl
17881
17888
  });
17889
+ if (pluginPermissionDenied) {
17890
+ logWarn("sandbox.egress.upstream_permission.classified", {
17891
+ ...attributes(lease, upstream.status, upstream)
17892
+ });
17893
+ }
17894
+ return new Response(upstream.body, {
17895
+ status: upstream.status,
17896
+ statusText: upstream.statusText,
17897
+ headers: responseHeaders(upstream)
17898
+ });
17882
17899
  }
17900
+ if (pluginPermissionDenied) {
17901
+ await recordPermissionDenied({
17902
+ credentialContext,
17903
+ provider,
17904
+ lease,
17905
+ message: pluginPermissionDenied.message,
17906
+ upstream,
17907
+ upstreamUrl
17908
+ });
17909
+ logWarn("sandbox.egress.upstream_permission.classified", {
17910
+ ...attributes(lease, upstream.status, upstream)
17911
+ });
17912
+ }
17913
+ return new Response(upstream.body, {
17914
+ status: upstream.status,
17915
+ statusText: upstream.statusText,
17916
+ headers: responseHeaders(upstream)
17917
+ });
17883
17918
  }
17884
- return new Response(upstream.body, {
17885
- status: upstream.status,
17886
- statusText: upstream.statusText,
17887
- headers: responseHeaders(upstream)
17888
- });
17889
17919
  }
17890
17920
 
17891
17921
  // src/chat/egress/plugin.ts
@@ -20472,7 +20502,10 @@ async function executeAgentRunInPrivacyContext(run, conversationPrivacy, runLogC
20472
20502
  }
20473
20503
  providerRetryAttempt += 1;
20474
20504
  await prepareRetry(providerRetry.messages);
20475
- logWarn("agent.turn.provider.retrying");
20505
+ logWarn("agent.turn.provider.retrying", {
20506
+ ...getProviderErrorAttributes(providerRetry.providerError),
20507
+ "app.ai.provider_error.retry_attempt": providerRetryAttempt
20508
+ });
20476
20509
  await sleep(providerRetry.delayMs, signal);
20477
20510
  run2 = agent.continue();
20478
20511
  }