@sentry/junior 0.200.0 → 0.201.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 (65) hide show
  1. package/dist/{agent-hooks-6LGY2MBH.js → agent-hooks-HMG23EIR.js} +11 -11
  2. package/dist/api.js +25 -25
  3. package/dist/app.js +207 -122
  4. package/dist/{catalog-runtime-CIO3ERVQ.js → catalog-runtime-7TIXWSYG.js} +4 -4
  5. package/dist/{chunk-PIHLVU7T.js → chunk-3XPQV262.js} +6 -6
  6. package/dist/{chunk-PMSENMWY.js → chunk-44W7JB5V.js} +1 -1
  7. package/dist/{chunk-LICM66W2.js → chunk-4DDQVL3Q.js} +2 -2
  8. package/dist/{chunk-22Y5SBDM.js → chunk-5LXHEN3P.js} +8 -8
  9. package/dist/{chunk-5JDNDQHL.js → chunk-6CYKW2J7.js} +1 -1
  10. package/dist/{chunk-JLUCKXGI.js → chunk-6QQYL2XW.js} +6 -6
  11. package/dist/{chunk-RDWWCDA4.js → chunk-73RVLY6A.js} +2 -2
  12. package/dist/{chunk-T6263C3N.js → chunk-7V4KWIXL.js} +2 -2
  13. package/dist/{chunk-ADNSL3MX.js → chunk-7YNSWPVU.js} +8 -8
  14. package/dist/{chunk-TF5TXGRD.js → chunk-APX6WBD7.js} +1 -1
  15. package/dist/{chunk-UR43NMUR.js → chunk-BQFWG7MB.js} +4 -4
  16. package/dist/{chunk-4Q5IR5GA.js → chunk-FNAEGMGB.js} +1 -1
  17. package/dist/{chunk-V2VL335Y.js → chunk-GHZ677GD.js} +21 -21
  18. package/dist/{chunk-5Q6KP6LH.js → chunk-H5SDC32F.js} +1 -1
  19. package/dist/{chunk-OIILBD56.js → chunk-I7F3JVYE.js} +3 -3
  20. package/dist/{chunk-ZPLAAHVP.js → chunk-IXGQ4NTO.js} +5 -5
  21. package/dist/{chunk-PSQ4SWI3.js → chunk-J4AWOSCT.js} +4 -4
  22. package/dist/{chunk-N5VHBUXF.js → chunk-JYJG6LAG.js} +19 -6
  23. package/dist/{chunk-OVHO76WN.js → chunk-KKI5K43Z.js} +3 -3
  24. package/dist/{chunk-YVP6QNBZ.js → chunk-KS5RPVQI.js} +3 -3
  25. package/dist/{chunk-RG74Q34N.js → chunk-LINEEYW6.js} +1 -1
  26. package/dist/{chunk-OTTKTTVI.js → chunk-NN5Y32TJ.js} +1 -1
  27. package/dist/{chunk-AV552V2K.js → chunk-OZ2QJWQF.js} +3 -3
  28. package/dist/{chunk-GFXDMDHR.js → chunk-PJIU4AGA.js} +2 -2
  29. package/dist/{chunk-IAZBUDVU.js → chunk-Q3BTNRDK.js} +36 -30
  30. package/dist/{chunk-SY2RQ77O.js → chunk-QHCI2E2A.js} +1 -1
  31. package/dist/{chunk-752M26LC.js → chunk-RAWQD5DS.js} +1 -1
  32. package/dist/{chunk-7DO36XLF.js → chunk-SIMN6AUL.js} +1 -1
  33. package/dist/{chunk-ODSGDVHT.js → chunk-T4WKGKAW.js} +5 -5
  34. package/dist/{chunk-3WUBDFFL.js → chunk-UEIDAG2O.js} +1 -1
  35. package/dist/{chunk-K2QYWZ7F.js → chunk-UJRD4NN4.js} +14 -3
  36. package/dist/{chunk-JMRHEW6B.js → chunk-VGNL3QUM.js} +3 -3
  37. package/dist/{chunk-LUITHZZL.js → chunk-VQ2XYXLB.js} +8 -8
  38. package/dist/{chunk-M7BHRB3G.js → chunk-VRD7FJZ2.js} +4 -4
  39. package/dist/{chunk-X2Q4H6JQ.js → chunk-X2PTNIN5.js} +311 -166
  40. package/dist/{chunk-5VRPXF4T.js → chunk-Y6EUAX5O.js} +1 -1
  41. package/dist/{chunk-VLBLCJXK.js → chunk-ZPGGVW34.js} +5 -5
  42. package/dist/{chunk-EOOWKTQC.js → chunk-ZXSPPXX3.js} +9 -9
  43. package/dist/cli/chat.js +33 -33
  44. package/dist/cli/check.js +5 -5
  45. package/dist/cli/plugins.js +12 -12
  46. package/dist/cli/snapshot-create.js +9 -9
  47. package/dist/cli/upgrade.js +6 -6
  48. package/dist/{db-SCTYCGQ5.js → db-S5DGFIFR.js} +6 -6
  49. package/dist/instrumentation.js +3 -3
  50. package/dist/nitro.js +6 -6
  51. package/dist/{oauth-callback-server-QXKBXP5M.js → oauth-callback-server-JDEUY5KP.js} +29 -29
  52. package/dist/{runner-Z3EQSZ23.js → runner-OQZRPML2.js} +21 -21
  53. package/dist/{skills-CGEPG74A.js → skills-4VE2VHGF.js} +5 -5
  54. package/dist/spawn-4WCYSTFY.js +42 -0
  55. package/dist/task-runner-7SDXKQ3L.js +36 -0
  56. package/dist/{validation-YLALMVMB.js → validation-CX2H5J6S.js} +5 -5
  57. package/dist/version.js +1 -1
  58. package/dist/{work-N6PUG4MY.js → work-GUHO34OE.js} +21 -21
  59. package/dist/{worker-M7464FAO.js → worker-F44XXKBH.js} +10 -10
  60. package/migrations/0039_attachment_provider.sql +7 -0
  61. package/migrations/meta/0039_snapshot.json +3368 -0
  62. package/migrations/meta/_journal.json +7 -0
  63. package/package.json +5 -5
  64. package/dist/spawn-WBEM46BW.js +0 -42
  65. package/dist/task-runner-2X5MUSHN.js +0 -36
package/dist/app.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  processConversationWork
3
- } from "./chunk-M7BHRB3G.js";
3
+ } from "./chunk-VRD7FJZ2.js";
4
4
  import {
5
5
  bindSpawnAgent
6
- } from "./chunk-LICM66W2.js";
6
+ } from "./chunk-4DDQVL3Q.js";
7
7
  import {
8
8
  createAgentInvocationWorker,
9
9
  enqueueAgentInvocation,
10
10
  listPendingAgentInvocationMailboxAppends,
11
11
  resolveAgentInvocationId
12
- } from "./chunk-EOOWKTQC.js";
12
+ } from "./chunk-ZXSPPXX3.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-V2VL335Y.js";
40
+ } from "./chunk-GHZ677GD.js";
41
41
  import "./chunk-FA6POGLH.js";
42
42
  import {
43
43
  AgentRunError,
44
44
  executeTurn
45
- } from "./chunk-YVP6QNBZ.js";
45
+ } from "./chunk-KS5RPVQI.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-ODSGDVHT.js";
56
+ } from "./chunk-T4WKGKAW.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-LUITHZZL.js";
76
+ } from "./chunk-VQ2XYXLB.js";
77
77
  import {
78
78
  ConversationTurnLifecycleService,
79
79
  getTurnLifecycle
80
- } from "./chunk-5JDNDQHL.js";
80
+ } from "./chunk-6CYKW2J7.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-ZPLAAHVP.js";
89
+ } from "./chunk-IXGQ4NTO.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-ADNSL3MX.js";
104
+ } from "./chunk-7YNSWPVU.js";
105
105
  import {
106
106
  createWebAuthorization,
107
107
  deleteWebAuthorization
108
- } from "./chunk-752M26LC.js";
108
+ } from "./chunk-RAWQD5DS.js";
109
109
  import {
110
110
  recordTaskExecution
111
- } from "./chunk-PSQ4SWI3.js";
111
+ } from "./chunk-J4AWOSCT.js";
112
112
  import "./chunk-RC745GGZ.js";
113
113
  import {
114
114
  createVercelPluginTaskCallback,
115
115
  queueCallback,
116
116
  registerVercelPluginTaskDevConsumer
117
- } from "./chunk-AV552V2K.js";
117
+ } from "./chunk-OZ2QJWQF.js";
118
118
  import {
119
119
  validatePluginEgressCredentialHooks,
120
120
  validatePluginRegistrations
121
- } from "./chunk-TF5TXGRD.js";
121
+ } from "./chunk-APX6WBD7.js";
122
122
  import {
123
123
  defineJuniorPlugins,
124
124
  pluginCatalogConfigFromEnv,
@@ -141,6 +141,7 @@ import {
141
141
  ingestResourceEvent,
142
142
  isResourceEventConversationMessage,
143
143
  isResourceEventMailboxMetadata,
144
+ isVisionImageMediaType,
144
145
  latestReportedProgress,
145
146
  listThreadReplies,
146
147
  logScheduledTaskRunSkipped,
@@ -149,8 +150,10 @@ import {
149
150
  parseSandboxEgressCredentialToken,
150
151
  processWorkspaceSnapshotJob,
151
152
  publicArtifactHeaders,
153
+ readAttachmentVisionSummary,
152
154
  readPublicArtifact,
153
155
  recordFinishedTurnForAutomatedLimit,
156
+ recordSlackAttachment,
154
157
  renderAttachmentText,
155
158
  renderBlockText,
156
159
  renderTaskInput,
@@ -160,11 +163,11 @@ import {
160
163
  shouldEmitDevAgentTrace,
161
164
  shouldPropagateSandboxEgressTrace,
162
165
  unpublishedArtifactHeaders
163
- } from "./chunk-X2Q4H6JQ.js";
166
+ } from "./chunk-X2PTNIN5.js";
164
167
  import {
165
168
  AuthorizationFlowDisabledError,
166
169
  PluginCredentialFailureError
167
- } from "./chunk-VLBLCJXK.js";
170
+ } from "./chunk-ZPGGVW34.js";
168
171
  import "./chunk-6Y5B5PEX.js";
169
172
  import "./chunk-DIB4GX3G.js";
170
173
  import {
@@ -172,14 +175,14 @@ import {
172
175
  deleteMcpAuthSessionsForUserProvider,
173
176
  deleteMcpServerSessionId,
174
177
  deleteMcpStoredOAuthCredentials
175
- } from "./chunk-22Y5SBDM.js";
178
+ } from "./chunk-5LXHEN3P.js";
176
179
  import {
177
180
  RetryableDeliveryError,
178
181
  createAgentRunner,
179
182
  formatProviderLabel,
180
183
  postSlackMessage,
181
184
  startOAuthFlow
182
- } from "./chunk-PIHLVU7T.js";
185
+ } from "./chunk-3XPQV262.js";
183
186
  import {
184
187
  ConversationTurnBoundaryError,
185
188
  CooperativeTurnYieldError,
@@ -195,7 +198,7 @@ import {
195
198
  markTurnCompleted,
196
199
  markTurnFailed,
197
200
  startActiveTurn
198
- } from "./chunk-3WUBDFFL.js";
201
+ } from "./chunk-UEIDAG2O.js";
199
202
  import {
200
203
  abandonTurnRecord,
201
204
  appendConversationMessages,
@@ -233,7 +236,7 @@ import {
233
236
  trimTrailingAssistantMessages,
234
237
  turnHasReply,
235
238
  upsertConversationMessage
236
- } from "./chunk-JLUCKXGI.js";
239
+ } from "./chunk-6QQYL2XW.js";
237
240
  import {
238
241
  getExperimentalFeatures,
239
242
  isExperimentalFeatureEnabled,
@@ -252,11 +255,12 @@ import {
252
255
  saveScheduledTaskInLock,
253
256
  scheduledRunId,
254
257
  scheduledRunSchema,
258
+ storeAttachment,
255
259
  withScheduledTaskLock
256
- } from "./chunk-IAZBUDVU.js";
260
+ } from "./chunk-Q3BTNRDK.js";
257
261
  import {
258
262
  parseSlackThreadId
259
- } from "./chunk-RG74Q34N.js";
263
+ } from "./chunk-LINEEYW6.js";
260
264
  import {
261
265
  CONVERSATION_WORK_STALE_ENQUEUE_MS,
262
266
  appendAndEnqueueInboundMessage,
@@ -271,16 +275,16 @@ import {
271
275
  removeActiveConversation,
272
276
  requestConversationWork,
273
277
  stopConversationWork
274
- } from "./chunk-UR43NMUR.js";
278
+ } from "./chunk-BQFWG7MB.js";
275
279
  import {
276
280
  buildDeterministicAssistantMessageId,
277
281
  buildDeterministicTurnId
278
282
  } from "./chunk-DA2KGZZI.js";
279
- import "./chunk-RDWWCDA4.js";
283
+ import "./chunk-73RVLY6A.js";
280
284
  import {
281
285
  getSandboxResourceConfig,
282
286
  setSandboxResourceConfig
283
- } from "./chunk-OIILBD56.js";
287
+ } from "./chunk-I7F3JVYE.js";
284
288
  import "./chunk-PDO5BLNM.js";
285
289
  import "./chunk-UIE3R5XU.js";
286
290
  import {
@@ -289,7 +293,7 @@ import {
289
293
  } from "./chunk-X6GDDWQH.js";
290
294
  import {
291
295
  getTurnRequestDeadline
292
- } from "./chunk-4Q5IR5GA.js";
296
+ } from "./chunk-FNAEGMGB.js";
293
297
  import {
294
298
  getVercelConversationWorkQueue,
295
299
  resolveConversationWorkQueueTopic,
@@ -310,6 +314,7 @@ import {
310
314
  createPluginLogger,
311
315
  createPluginState,
312
316
  downloadPrivateSlackFile,
317
+ findMatchingResourceEventSubscriptions,
313
318
  getPluginApiRoutes,
314
319
  getPluginRoutes,
315
320
  getPlugins,
@@ -325,7 +330,7 @@ import {
325
330
  verifyEventTaskCredentialSubject,
326
331
  verifyScheduledTaskCredentialSubject,
327
332
  verifySlackDirectCredentialSubject
328
- } from "./chunk-N5VHBUXF.js";
333
+ } from "./chunk-JYJG6LAG.js";
329
334
  import {
330
335
  JUNIOR_THREAD_STATE_TTL_MS
331
336
  } from "./chunk-3Y47VMHV.js";
@@ -339,7 +344,7 @@ import {
339
344
  requireSlackDestination,
340
345
  withConversationEventLock,
341
346
  withConversationMutationLock
342
- } from "./chunk-JMRHEW6B.js";
347
+ } from "./chunk-VGNL3QUM.js";
343
348
  import {
344
349
  juniorAgentBindings,
345
350
  juniorAgentInvocations,
@@ -347,15 +352,15 @@ import {
347
352
  juniorConversations,
348
353
  juniorSchedulerRuns,
349
354
  juniorSchedulerTasks
350
- } from "./chunk-K2QYWZ7F.js";
351
- import "./chunk-OVHO76WN.js";
355
+ } from "./chunk-UJRD4NN4.js";
356
+ import "./chunk-KKI5K43Z.js";
352
357
  import {
353
358
  MUTATION_LOCK_TTL_MS,
354
359
  acquireActiveLock,
355
360
  getStateAdapter,
356
361
  withActiveLock,
357
362
  withLock
358
- } from "./chunk-PMSENMWY.js";
363
+ } from "./chunk-44W7JB5V.js";
359
364
  import {
360
365
  instructionProvenanceFor
361
366
  } from "./chunk-7NL7T6VU.js";
@@ -378,17 +383,17 @@ import {
378
383
  setBotModelConfig,
379
384
  setProfiles,
380
385
  setSlackReactionConfig
381
- } from "./chunk-GFXDMDHR.js";
386
+ } from "./chunk-PJIU4AGA.js";
382
387
  import {
383
388
  defaultModelId,
384
389
  modelIdForProfile
385
390
  } from "./chunk-NHJU2ZAL.js";
386
- import "./chunk-SY2RQ77O.js";
387
- import "./chunk-T6263C3N.js";
391
+ import "./chunk-QHCI2E2A.js";
392
+ import "./chunk-7V4KWIXL.js";
388
393
  import {
389
394
  pluginCatalogRuntime
390
- } from "./chunk-5VRPXF4T.js";
391
- import "./chunk-5Q6KP6LH.js";
395
+ } from "./chunk-Y6EUAX5O.js";
396
+ import "./chunk-H5SDC32F.js";
392
397
  import {
393
398
  credentialContextForActor
394
399
  } from "./chunk-CEMMLV5L.js";
@@ -424,13 +429,13 @@ import {
424
429
  withContext,
425
430
  withLogContext,
426
431
  withSpan
427
- } from "./chunk-7DO36XLF.js";
432
+ } from "./chunk-SIMN6AUL.js";
428
433
  import {
429
434
  continueTrace
430
435
  } from "./chunk-PEQXYSSE.js";
431
436
  import {
432
437
  JUNIOR_VERSION
433
- } from "./chunk-OTTKTTVI.js";
438
+ } from "./chunk-NN5Y32TJ.js";
434
439
 
435
440
  // src/app.ts
436
441
  import { createRequire } from "module";
@@ -5104,13 +5109,9 @@ function hasPotentialImageAttachment(attachments) {
5104
5109
  return countPotentialImageAttachments(attachments) > 0;
5105
5110
  }
5106
5111
  function countPotentialImageAttachments(attachments) {
5107
- return attachments?.filter((attachment) => {
5108
- if (attachment.type === "image") {
5109
- return true;
5110
- }
5111
- const mimeType = attachment.mimeType ?? "";
5112
- return attachment.type === "file" && mimeType.startsWith("image/");
5113
- }).length ?? 0;
5112
+ return attachments?.filter(
5113
+ (attachment) => isVisionImageMediaType(attachment.mimeType ?? "")
5114
+ ).length ?? 0;
5114
5115
  }
5115
5116
  function isVisionEnabled() {
5116
5117
  return Boolean(botConfig.visionModelId);
@@ -5126,6 +5127,10 @@ function buildImageAttachmentPromptText(args) {
5126
5127
  "<image-attachment>",
5127
5128
  `filename: ${args.filename ?? "unnamed"}`,
5128
5129
  `media_type: ${args.mediaType}`,
5130
+ ...args.attachmentId ? [
5131
+ `attachment_id: ${args.attachmentId}`,
5132
+ "Use loadAttachment with this id when the task needs the original file."
5133
+ ] : [],
5129
5134
  "<summary>",
5130
5135
  args.summary,
5131
5136
  "</summary>",
@@ -5137,9 +5142,12 @@ function buildImageAttachmentFailurePromptText(args) {
5137
5142
  "<image-attachment>",
5138
5143
  `filename: ${args.filename ?? "unnamed"}`,
5139
5144
  `media_type: ${args.mediaType}`,
5145
+ ...args.attachmentId ? [
5146
+ `attachment_id: ${args.attachmentId}`,
5147
+ "Use loadAttachment with this id to access the original file."
5148
+ ] : [],
5140
5149
  "<analysis-error>",
5141
5150
  args.message,
5142
- "The image contents are unavailable.",
5143
5151
  "</analysis-error>",
5144
5152
  "</image-attachment>"
5145
5153
  ].join("\n");
@@ -5182,6 +5190,24 @@ async function summarizeImageWithVision(args) {
5182
5190
  function truncateVisionSummary(summary) {
5183
5191
  return summary.slice(0, MAX_VISION_SUMMARY_CHARS);
5184
5192
  }
5193
+ function buildStoredAttachmentPromptText(args) {
5194
+ return [
5195
+ "<attachment>",
5196
+ `filename: ${args.filename ?? "unnamed"}`,
5197
+ `media_type: ${args.mediaType}`,
5198
+ `attachment_id: ${args.attachmentId}`,
5199
+ "Use loadAttachment with this id to access the original file.",
5200
+ "</attachment>"
5201
+ ].join("\n");
5202
+ }
5203
+ function getSlackFileId(attachment) {
5204
+ const metadataId = attachment.fetchMetadata?.fileId;
5205
+ if (metadataId) return metadataId;
5206
+ const match = (attachment.url ?? attachment.fetchMetadata?.url ?? "").match(
5207
+ /(?:^|[-/])(F[A-Z0-9]+)(?:[-/]|$)/i
5208
+ );
5209
+ return match?.[1];
5210
+ }
5185
5211
  function getCachedImageSummaries(args) {
5186
5212
  if (!args.conversation || !args.messageTs) {
5187
5213
  return [];
@@ -5213,55 +5239,101 @@ async function resolveUserAttachmentsWithDeps(attachments, context, deps) {
5213
5239
  });
5214
5240
  let nextCachedImageSummaryIndex = 0;
5215
5241
  for (const attachment of attachments) {
5216
- if (results.length >= MAX_USER_ATTACHMENTS) break;
5217
- if (attachment.type !== "image" && attachment.type !== "file") continue;
5218
5242
  const mediaType = attachment.mimeType ?? "application/octet-stream";
5219
- const isImageAttachment = attachment.type === "image" || mediaType.startsWith("image/");
5220
- if (isImageAttachment && !isVisionEnabled()) {
5243
+ const isImageAttachment = isVisionImageMediaType(mediaType);
5244
+ let data;
5245
+ try {
5246
+ if (attachment.fetchData) {
5247
+ data = await attachment.fetchData();
5248
+ } else if (attachment.data instanceof Buffer) {
5249
+ data = attachment.data;
5250
+ } else {
5251
+ continue;
5252
+ }
5253
+ } catch (error) {
5254
+ logWarn("attachment.resolution.failed", {
5255
+ "exception.message": error instanceof Error ? error.message : String(error),
5256
+ "app.file.mime_type": mediaType
5257
+ });
5221
5258
  continue;
5222
5259
  }
5223
- try {
5224
- const resolvedAttachment = {
5225
- mediaType,
5226
- filename: attachment.name
5227
- };
5228
- if (isImageAttachment) {
5229
- const cachedSummary = cachedImageSummaries[nextCachedImageSummaryIndex];
5230
- nextCachedImageSummaryIndex += 1;
5231
- if (cachedSummary) {
5232
- resolvedAttachment.promptText = buildImageAttachmentPromptText({
5233
- filename: attachment.name,
5234
- mediaType,
5235
- summary: cachedSummary
5236
- });
5237
- results.push(resolvedAttachment);
5238
- continue;
5239
- }
5240
- let imageData = null;
5241
- if (attachment.fetchData) {
5242
- imageData = await attachment.fetchData();
5243
- } else if (attachment.data instanceof Buffer) {
5244
- imageData = attachment.data;
5245
- }
5246
- if (!imageData) {
5247
- throw createImageAttachmentProcessingError({
5248
- filename: attachment.name
5249
- });
5250
- }
5251
- if (imageData.byteLength > MAX_USER_ATTACHMENT_BYTES) {
5252
- throw createImageAttachmentProcessingError({
5253
- filename: attachment.name
5254
- });
5255
- }
5260
+ let attachmentId;
5261
+ const slackFileId = getSlackFileId(attachment);
5262
+ if (context.conversationId && deps.attachmentStorage) {
5263
+ try {
5264
+ const stored = await storeAttachment({
5265
+ conversationId: context.conversationId,
5266
+ db: getSqlExecutor(),
5267
+ file: {
5268
+ bytes: data.byteLength,
5269
+ data,
5270
+ filename: attachment.name ?? "attachment",
5271
+ mimeType: mediaType,
5272
+ path: attachment.name ?? "attachment"
5273
+ },
5274
+ ...slackFileId ? { source: { id: slackFileId, provider: "slack" } } : void 0,
5275
+ storage: deps.attachmentStorage
5276
+ });
5277
+ attachmentId = stored.id;
5278
+ } catch (error) {
5279
+ logWarn("attachment.storage.failed", {
5280
+ "exception.message": error instanceof Error ? error.message : String(error),
5281
+ "app.file.mime_type": mediaType,
5282
+ ...attachment.name ? { "file.name": attachment.name } : void 0
5283
+ });
5284
+ }
5285
+ }
5286
+ if (results.length >= MAX_USER_ATTACHMENTS || attachment.type !== "image" && attachment.type !== "file") {
5287
+ continue;
5288
+ }
5289
+ const resolvedAttachment = {
5290
+ attachmentId,
5291
+ mediaType,
5292
+ filename: attachment.name
5293
+ };
5294
+ if (data.byteLength > MAX_USER_ATTACHMENT_BYTES) {
5295
+ logWarn("attachment.size_limit.skipped", {
5296
+ "file.size": data.byteLength,
5297
+ "app.file.mime_type": mediaType
5298
+ });
5299
+ if (attachmentId) {
5300
+ resolvedAttachment.promptText = buildStoredAttachmentPromptText({
5301
+ attachmentId,
5302
+ filename: attachment.name,
5303
+ mediaType
5304
+ });
5305
+ results.push(resolvedAttachment);
5306
+ }
5307
+ continue;
5308
+ }
5309
+ if (isImageAttachment && isVisionEnabled()) {
5310
+ const storedVisionSummary = attachmentId ? await readAttachmentVisionSummary({
5311
+ attachmentId,
5312
+ conversationId: context.conversationId,
5313
+ db: getSqlExecutor()
5314
+ }) : void 0;
5315
+ const cachedSummary = storedVisionSummary ?? cachedImageSummaries[nextCachedImageSummaryIndex];
5316
+ nextCachedImageSummaryIndex += 1;
5317
+ if (cachedSummary) {
5318
+ resolvedAttachment.promptText = buildImageAttachmentPromptText({
5319
+ attachmentId,
5320
+ filename: attachment.name,
5321
+ mediaType,
5322
+ summary: cachedSummary
5323
+ });
5324
+ results.push(resolvedAttachment);
5325
+ continue;
5326
+ }
5327
+ try {
5256
5328
  const summary = await summarizeImageWithVision({
5257
5329
  completeText: deps.completeText,
5258
- imageData,
5330
+ imageData: data,
5259
5331
  mimeType: mediaType,
5260
5332
  maxTokens: 220,
5261
5333
  prompt: [
5262
- "Extract concise, factual context from this user-provided image.",
5263
- "Focus on visible text, UI state, charts, diagrams, errors, names, and other concrete details useful for answering the user's current request.",
5264
- "Do not speculate.",
5334
+ "Describe this image with concise facts that help answer the user's request.",
5335
+ "Include visible text, UI state, charts, diagrams, errors, and names.",
5336
+ "Do not guess.",
5265
5337
  "Return plain text only."
5266
5338
  ].join(" "),
5267
5339
  metadata: {
@@ -5277,32 +5349,22 @@ async function resolveUserAttachmentsWithDeps(attachments, context, deps) {
5277
5349
  filename: attachment.name
5278
5350
  });
5279
5351
  }
5352
+ const truncatedSummary = truncateVisionSummary(summary);
5280
5353
  resolvedAttachment.promptText = buildImageAttachmentPromptText({
5354
+ attachmentId,
5281
5355
  filename: attachment.name,
5282
5356
  mediaType,
5283
- summary: truncateVisionSummary(summary)
5357
+ summary: truncatedSummary
5284
5358
  });
5285
- results.push(resolvedAttachment);
5286
- continue;
5287
- }
5288
- let data = null;
5289
- if (attachment.fetchData) {
5290
- data = await attachment.fetchData();
5291
- } else if (attachment.data instanceof Buffer) {
5292
- data = attachment.data;
5293
- }
5294
- if (!data) continue;
5295
- if (data.byteLength > MAX_USER_ATTACHMENT_BYTES) {
5296
- logWarn("attachment.size_limit.skipped", {
5297
- "file.size": data.byteLength,
5298
- "app.file.mime_type": mediaType
5299
- });
5300
- continue;
5301
- }
5302
- resolvedAttachment.data = data;
5303
- results.push(resolvedAttachment);
5304
- } catch (error) {
5305
- if (isImageAttachment) {
5359
+ if (attachmentId) {
5360
+ await recordSlackAttachment({
5361
+ attachmentId,
5362
+ conversationId: context.conversationId,
5363
+ db: getSqlExecutor(),
5364
+ visionSummary: truncatedSummary
5365
+ });
5366
+ }
5367
+ } catch (error) {
5306
5368
  const attachmentError = error instanceof ImageAttachmentProcessingError ? error : createImageAttachmentProcessingError({
5307
5369
  filename: attachment.name
5308
5370
  });
@@ -5311,22 +5373,26 @@ async function resolveUserAttachmentsWithDeps(attachments, context, deps) {
5311
5373
  "app.file.mime_type": mediaType,
5312
5374
  ...attachment.name ? { "file.name": attachment.name } : void 0
5313
5375
  });
5314
- results.push({
5315
- mediaType,
5376
+ resolvedAttachment.promptText = buildImageAttachmentFailurePromptText({
5377
+ attachmentId,
5316
5378
  filename: attachment.name,
5317
- promptText: buildImageAttachmentFailurePromptText({
5318
- filename: attachment.name,
5319
- mediaType,
5320
- message: attachmentError.message
5321
- })
5379
+ mediaType,
5380
+ message: attachmentError.message
5322
5381
  });
5323
- continue;
5324
5382
  }
5325
- logWarn("attachment.resolution.failed", {
5326
- "exception.message": error instanceof Error ? error.message : String(error),
5327
- "app.file.mime_type": mediaType
5383
+ results.push(resolvedAttachment);
5384
+ continue;
5385
+ }
5386
+ if (isImageAttachment && attachmentId) {
5387
+ resolvedAttachment.promptText = buildStoredAttachmentPromptText({
5388
+ attachmentId,
5389
+ filename: attachment.name,
5390
+ mediaType
5328
5391
  });
5392
+ } else {
5393
+ resolvedAttachment.data = data;
5329
5394
  }
5395
+ results.push(resolvedAttachment);
5330
5396
  }
5331
5397
  return results;
5332
5398
  }
@@ -5430,7 +5496,7 @@ async function hydrateConversationVisionContextWithDeps(conversation, context, d
5430
5496
  const imageFiles = (reply.files ?? []).filter((file) => {
5431
5497
  const mimeType = toOptionalString(file.mimetype);
5432
5498
  return Boolean(
5433
- toOptionalString(file.id) && mimeType?.startsWith("image/")
5499
+ toOptionalString(file.id) && mimeType && isVisionImageMediaType(mimeType)
5434
5500
  );
5435
5501
  }).slice(0, MAX_MESSAGE_IMAGE_ATTACHMENTS);
5436
5502
  if (imageFiles.length === 0) {
@@ -6622,6 +6688,7 @@ function createJuniorRuntimeServices(overrides = {}) {
6622
6688
  autoCompactionTriggerTokens: overrides.contextCompactor?.autoCompactionTriggerTokens
6623
6689
  });
6624
6690
  const visionContext = createVisionContextService({
6691
+ attachmentStorage: overrides.visionContext?.attachmentStorage,
6625
6692
  completeText: overrides.visionContext?.completeText ?? completeText,
6626
6693
  listThreadReplies: overrides.visionContext?.listThreadReplies ?? listThreadReplies,
6627
6694
  downloadFile: overrides.visionContext?.downloadFile ?? downloadPrivateSlackFile
@@ -7076,6 +7143,7 @@ function createSlackTurn(deps) {
7076
7143
  timestampMs: queued.message.metadata.dateSent.getTime(),
7077
7144
  omittedImageAttachmentCount: !isVisionEnabled() && hasPotentialImageAttachment(attachments) ? countPotentialImageAttachments(attachments) : 0,
7078
7145
  attachments: await deps.resolveUserAttachments(attachments, {
7146
+ conversationId,
7079
7147
  threadId,
7080
7148
  actorId: queued.message.author.userId,
7081
7149
  channelId,
@@ -7301,6 +7369,7 @@ function createSlackTurn(deps) {
7301
7369
  const userAttachments = await deps.resolveUserAttachments(
7302
7370
  turnAttachments,
7303
7371
  {
7372
+ conversationId,
7304
7373
  threadId,
7305
7374
  actorId: slackActorId,
7306
7375
  channelId,
@@ -9897,6 +9966,21 @@ function createResourceEventTeamIdResolver() {
9897
9966
  function createResourceEventAppPublisher(args) {
9898
9967
  const resolveEventTaskTeamId = createResourceEventTeamIdResolver();
9899
9968
  return {
9969
+ async hasMatch(event) {
9970
+ const work = args.conversationWork();
9971
+ const eventTaskTeamId = await resolveEventTaskTeamId();
9972
+ const [subscriptions, tasks] = await Promise.all([
9973
+ findMatchingResourceEventSubscriptions({
9974
+ data: event.data,
9975
+ eventType: event.eventType,
9976
+ namespace: event.namespace,
9977
+ identifier: event.identifier,
9978
+ state: work.state
9979
+ }),
9980
+ eventTaskTeamId ? findMatchingEventTasks(getDb(), event, eventTaskTeamId) : Promise.resolve([])
9981
+ ]);
9982
+ return subscriptions.length > 0 || tasks.length > 0;
9983
+ },
9900
9984
  async neededMatchKeys(input) {
9901
9985
  const work = args.conversationWork();
9902
9986
  const eventTaskTeamId = await resolveEventTaskTeamId();
@@ -12444,7 +12528,8 @@ async function createApp(options) {
12444
12528
  });
12445
12529
  const runtimeServiceOverrides = {
12446
12530
  agentRunner,
12447
- sandbox: { tracePropagation }
12531
+ sandbox: { tracePropagation },
12532
+ visionContext: { attachmentStorage }
12448
12533
  };
12449
12534
  let conversationWorkOptions;
12450
12535
  const getConversationWorkOptions = () => {
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-5VRPXF4T.js";
4
- import "./chunk-5Q6KP6LH.js";
3
+ } from "./chunk-Y6EUAX5O.js";
4
+ import "./chunk-H5SDC32F.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-7DO36XLF.js";
9
+ import "./chunk-SIMN6AUL.js";
10
10
  import "./chunk-PEQXYSSE.js";
11
- import "./chunk-OTTKTTVI.js";
11
+ import "./chunk-NN5Y32TJ.js";
12
12
  export {
13
13
  pluginCatalogRuntime
14
14
  };