@sentry/junior 0.200.0 → 0.202.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-UXITLYOK.js} +11 -11
  2. package/dist/api.js +25 -25
  3. package/dist/app.js +228 -122
  4. package/dist/{catalog-runtime-CIO3ERVQ.js → catalog-runtime-BG3JLLK2.js} +4 -4
  5. package/dist/{chunk-PMSENMWY.js → chunk-2MK3QBGA.js} +1 -1
  6. package/dist/{chunk-EOOWKTQC.js → chunk-3PGQSKJV.js} +9 -9
  7. package/dist/{chunk-ZPLAAHVP.js → chunk-3UI3WFTX.js} +5 -5
  8. package/dist/{chunk-SY2RQ77O.js → chunk-5NOPO64K.js} +1 -1
  9. package/dist/{chunk-JLUCKXGI.js → chunk-5PKWYPFT.js} +6 -6
  10. package/dist/{chunk-GFXDMDHR.js → chunk-63NKKFJL.js} +2 -2
  11. package/dist/{chunk-M7BHRB3G.js → chunk-6AYH6252.js} +4 -4
  12. package/dist/{chunk-RDWWCDA4.js → chunk-7DHZP5KJ.js} +2 -2
  13. package/dist/{chunk-RG74Q34N.js → chunk-A76OIMYN.js} +1 -1
  14. package/dist/{chunk-YVP6QNBZ.js → chunk-AWMS3SPP.js} +3 -3
  15. package/dist/{chunk-ODSGDVHT.js → chunk-B3LY5RCL.js} +5 -5
  16. package/dist/{chunk-4Q5IR5GA.js → chunk-BD2KT3OB.js} +1 -1
  17. package/dist/{chunk-5Q6KP6LH.js → chunk-BXCX5QKA.js} +1 -1
  18. package/dist/{chunk-TF5TXGRD.js → chunk-C6VVF43U.js} +1 -1
  19. package/dist/{chunk-5JDNDQHL.js → chunk-DBVY6HLX.js} +1 -1
  20. package/dist/{chunk-PIHLVU7T.js → chunk-DL2KLKVH.js} +6 -6
  21. package/dist/{chunk-3WUBDFFL.js → chunk-ELWOYVOY.js} +1 -1
  22. package/dist/{chunk-PSQ4SWI3.js → chunk-EWT7H65X.js} +4 -4
  23. package/dist/{chunk-OTTKTTVI.js → chunk-HMREVIO2.js} +2 -2
  24. package/dist/{chunk-LUITHZZL.js → chunk-IIWUT4FO.js} +8 -8
  25. package/dist/{chunk-V2VL335Y.js → chunk-JSJQEWBJ.js} +21 -21
  26. package/dist/{chunk-T6263C3N.js → chunk-KHKKHDLD.js} +2 -2
  27. package/dist/{chunk-OIILBD56.js → chunk-LA6R4A7Q.js} +3 -3
  28. package/dist/{chunk-X2Q4H6JQ.js → chunk-LOOU2DUR.js} +315 -166
  29. package/dist/{chunk-ADNSL3MX.js → chunk-M6FHWXE3.js} +9 -9
  30. package/dist/{chunk-JMRHEW6B.js → chunk-M76HMB7M.js} +3 -3
  31. package/dist/{chunk-7DO36XLF.js → chunk-MAGNK5J4.js} +1 -1
  32. package/dist/{chunk-OVHO76WN.js → chunk-NSXKRGRT.js} +3 -3
  33. package/dist/{chunk-UR43NMUR.js → chunk-OWMPFXJA.js} +4 -4
  34. package/dist/{chunk-K2QYWZ7F.js → chunk-PW4P4JYF.js} +14 -3
  35. package/dist/{chunk-VLBLCJXK.js → chunk-QB54UQUS.js} +5 -5
  36. package/dist/{chunk-752M26LC.js → chunk-QP3OGJXF.js} +1 -1
  37. package/dist/{chunk-LICM66W2.js → chunk-REOIRYPR.js} +2 -2
  38. package/dist/{chunk-AV552V2K.js → chunk-SCOZRLZ4.js} +3 -3
  39. package/dist/{chunk-IAZBUDVU.js → chunk-TXJSXBV5.js} +36 -30
  40. package/dist/{chunk-N5VHBUXF.js → chunk-U2GPUYAL.js} +19 -6
  41. package/dist/{chunk-22Y5SBDM.js → chunk-WQSHDTTI.js} +8 -8
  42. package/dist/{chunk-5VRPXF4T.js → chunk-YDUR3ZYW.js} +1 -1
  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-3L2MCVRI.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-YVV6C6T2.js} +29 -29
  52. package/dist/{runner-Z3EQSZ23.js → runner-LQ7RETDP.js} +21 -21
  53. package/dist/{skills-CGEPG74A.js → skills-XRWYEDCD.js} +5 -5
  54. package/dist/spawn-RC6SJUAI.js +42 -0
  55. package/dist/task-runner-7DY7ARYH.js +36 -0
  56. package/dist/{validation-YLALMVMB.js → validation-7MNQGCJA.js} +5 -5
  57. package/dist/version.js +1 -1
  58. package/dist/{work-N6PUG4MY.js → work-COALHUCG.js} +21 -21
  59. package/dist/{worker-M7464FAO.js → worker-6MURZIPD.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 +6 -6
  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-6AYH6252.js";
4
4
  import {
5
5
  bindSpawnAgent
6
- } from "./chunk-LICM66W2.js";
6
+ } from "./chunk-REOIRYPR.js";
7
7
  import {
8
8
  createAgentInvocationWorker,
9
9
  enqueueAgentInvocation,
10
10
  listPendingAgentInvocationMailboxAppends,
11
11
  resolveAgentInvocationId
12
- } from "./chunk-EOOWKTQC.js";
12
+ } from "./chunk-3PGQSKJV.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-JSJQEWBJ.js";
41
41
  import "./chunk-FA6POGLH.js";
42
42
  import {
43
43
  AgentRunError,
44
44
  executeTurn
45
- } from "./chunk-YVP6QNBZ.js";
45
+ } from "./chunk-AWMS3SPP.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-B3LY5RCL.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-IIWUT4FO.js";
77
77
  import {
78
78
  ConversationTurnLifecycleService,
79
79
  getTurnLifecycle
80
- } from "./chunk-5JDNDQHL.js";
80
+ } from "./chunk-DBVY6HLX.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-3UI3WFTX.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-M6FHWXE3.js";
105
105
  import {
106
106
  createWebAuthorization,
107
107
  deleteWebAuthorization
108
- } from "./chunk-752M26LC.js";
108
+ } from "./chunk-QP3OGJXF.js";
109
109
  import {
110
110
  recordTaskExecution
111
- } from "./chunk-PSQ4SWI3.js";
111
+ } from "./chunk-EWT7H65X.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-SCOZRLZ4.js";
118
118
  import {
119
119
  validatePluginEgressCredentialHooks,
120
120
  validatePluginRegistrations
121
- } from "./chunk-TF5TXGRD.js";
121
+ } from "./chunk-C6VVF43U.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-LOOU2DUR.js";
164
167
  import {
165
168
  AuthorizationFlowDisabledError,
166
169
  PluginCredentialFailureError
167
- } from "./chunk-VLBLCJXK.js";
170
+ } from "./chunk-QB54UQUS.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-WQSHDTTI.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-DL2KLKVH.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-ELWOYVOY.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-5PKWYPFT.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-TXJSXBV5.js";
257
261
  import {
258
262
  parseSlackThreadId
259
- } from "./chunk-RG74Q34N.js";
263
+ } from "./chunk-A76OIMYN.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-OWMPFXJA.js";
275
279
  import {
276
280
  buildDeterministicAssistantMessageId,
277
281
  buildDeterministicTurnId
278
282
  } from "./chunk-DA2KGZZI.js";
279
- import "./chunk-RDWWCDA4.js";
283
+ import "./chunk-7DHZP5KJ.js";
280
284
  import {
281
285
  getSandboxResourceConfig,
282
286
  setSandboxResourceConfig
283
- } from "./chunk-OIILBD56.js";
287
+ } from "./chunk-LA6R4A7Q.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-BD2KT3OB.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-U2GPUYAL.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-M76HMB7M.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-PW4P4JYF.js";
356
+ import "./chunk-NSXKRGRT.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-2MK3QBGA.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-63NKKFJL.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-5NOPO64K.js";
392
+ import "./chunk-KHKKHDLD.js";
388
393
  import {
389
394
  pluginCatalogRuntime
390
- } from "./chunk-5VRPXF4T.js";
391
- import "./chunk-5Q6KP6LH.js";
395
+ } from "./chunk-YDUR3ZYW.js";
396
+ import "./chunk-BXCX5QKA.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-MAGNK5J4.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-HMREVIO2.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,13 +5142,27 @@ 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");
5146
5154
  }
5155
+ function buildAttachmentResolutionFailurePromptText(args) {
5156
+ return [
5157
+ "<attachment>",
5158
+ `filename: ${args.filename ?? "unnamed"}`,
5159
+ `media_type: ${args.mediaType}`,
5160
+ "<resolution-error>",
5161
+ "The user attached this file, but Junior could not download its content from Slack. Tell the user the attachment could not be read; do not say no attachment was sent.",
5162
+ "</resolution-error>",
5163
+ "</attachment>"
5164
+ ].join("\n");
5165
+ }
5147
5166
  async function summarizeImageWithVision(args) {
5148
5167
  const visionModelId = botConfig.visionModelId;
5149
5168
  if (!visionModelId) {
@@ -5182,6 +5201,24 @@ async function summarizeImageWithVision(args) {
5182
5201
  function truncateVisionSummary(summary) {
5183
5202
  return summary.slice(0, MAX_VISION_SUMMARY_CHARS);
5184
5203
  }
5204
+ function buildStoredAttachmentPromptText(args) {
5205
+ return [
5206
+ "<attachment>",
5207
+ `filename: ${args.filename ?? "unnamed"}`,
5208
+ `media_type: ${args.mediaType}`,
5209
+ `attachment_id: ${args.attachmentId}`,
5210
+ "Use loadAttachment with this id to access the original file.",
5211
+ "</attachment>"
5212
+ ].join("\n");
5213
+ }
5214
+ function getSlackFileId(attachment) {
5215
+ const metadataId = attachment.fetchMetadata?.fileId;
5216
+ if (metadataId) return metadataId;
5217
+ const match = (attachment.url ?? attachment.fetchMetadata?.url ?? "").match(
5218
+ /(?:^|[-/])(F[A-Z0-9]+)(?:[-/]|$)/i
5219
+ );
5220
+ return match?.[1];
5221
+ }
5185
5222
  function getCachedImageSummaries(args) {
5186
5223
  if (!args.conversation || !args.messageTs) {
5187
5224
  return [];
@@ -5213,55 +5250,111 @@ async function resolveUserAttachmentsWithDeps(attachments, context, deps) {
5213
5250
  });
5214
5251
  let nextCachedImageSummaryIndex = 0;
5215
5252
  for (const attachment of attachments) {
5216
- if (results.length >= MAX_USER_ATTACHMENTS) break;
5217
- if (attachment.type !== "image" && attachment.type !== "file") continue;
5218
5253
  const mediaType = attachment.mimeType ?? "application/octet-stream";
5219
- const isImageAttachment = attachment.type === "image" || mediaType.startsWith("image/");
5220
- if (isImageAttachment && !isVisionEnabled()) {
5221
- continue;
5222
- }
5254
+ const isImageAttachment = isVisionImageMediaType(mediaType);
5255
+ let data;
5223
5256
  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({
5257
+ if (attachment.fetchData) {
5258
+ data = await attachment.fetchData();
5259
+ } else if (attachment.data instanceof Buffer) {
5260
+ data = attachment.data;
5261
+ } else {
5262
+ continue;
5263
+ }
5264
+ } catch (error) {
5265
+ logWarn("attachment.resolution.failed", {
5266
+ "exception.message": error instanceof Error ? error.message : String(error),
5267
+ "app.file.mime_type": mediaType
5268
+ });
5269
+ if (results.length < MAX_USER_ATTACHMENTS) {
5270
+ results.push({
5271
+ mediaType,
5272
+ filename: attachment.name,
5273
+ promptText: buildAttachmentResolutionFailurePromptText({
5233
5274
  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
- }
5275
+ mediaType
5276
+ })
5277
+ });
5278
+ }
5279
+ continue;
5280
+ }
5281
+ let attachmentId;
5282
+ const slackFileId = getSlackFileId(attachment);
5283
+ if (context.conversationId && deps.attachmentStorage) {
5284
+ try {
5285
+ const stored = await storeAttachment({
5286
+ conversationId: context.conversationId,
5287
+ db: getSqlExecutor(),
5288
+ file: {
5289
+ bytes: data.byteLength,
5290
+ data,
5291
+ filename: attachment.name ?? "attachment",
5292
+ mimeType: mediaType,
5293
+ path: attachment.name ?? "attachment"
5294
+ },
5295
+ ...slackFileId ? { source: { id: slackFileId, provider: "slack" } } : void 0,
5296
+ storage: deps.attachmentStorage
5297
+ });
5298
+ attachmentId = stored.id;
5299
+ } catch (error) {
5300
+ logWarn("attachment.storage.failed", {
5301
+ "exception.message": error instanceof Error ? error.message : String(error),
5302
+ "app.file.mime_type": mediaType,
5303
+ ...attachment.name ? { "file.name": attachment.name } : void 0
5304
+ });
5305
+ }
5306
+ }
5307
+ if (results.length >= MAX_USER_ATTACHMENTS || attachment.type !== "image" && attachment.type !== "file") {
5308
+ continue;
5309
+ }
5310
+ const resolvedAttachment = {
5311
+ attachmentId,
5312
+ mediaType,
5313
+ filename: attachment.name
5314
+ };
5315
+ if (data.byteLength > MAX_USER_ATTACHMENT_BYTES) {
5316
+ logWarn("attachment.size_limit.skipped", {
5317
+ "file.size": data.byteLength,
5318
+ "app.file.mime_type": mediaType
5319
+ });
5320
+ if (attachmentId) {
5321
+ resolvedAttachment.promptText = buildStoredAttachmentPromptText({
5322
+ attachmentId,
5323
+ filename: attachment.name,
5324
+ mediaType
5325
+ });
5326
+ results.push(resolvedAttachment);
5327
+ }
5328
+ continue;
5329
+ }
5330
+ if (isImageAttachment && isVisionEnabled()) {
5331
+ const storedVisionSummary = attachmentId ? await readAttachmentVisionSummary({
5332
+ attachmentId,
5333
+ conversationId: context.conversationId,
5334
+ db: getSqlExecutor()
5335
+ }) : void 0;
5336
+ const cachedSummary = storedVisionSummary ?? cachedImageSummaries[nextCachedImageSummaryIndex];
5337
+ nextCachedImageSummaryIndex += 1;
5338
+ if (cachedSummary) {
5339
+ resolvedAttachment.promptText = buildImageAttachmentPromptText({
5340
+ attachmentId,
5341
+ filename: attachment.name,
5342
+ mediaType,
5343
+ summary: cachedSummary
5344
+ });
5345
+ results.push(resolvedAttachment);
5346
+ continue;
5347
+ }
5348
+ try {
5256
5349
  const summary = await summarizeImageWithVision({
5257
5350
  completeText: deps.completeText,
5258
- imageData,
5351
+ imageData: data,
5259
5352
  mimeType: mediaType,
5260
5353
  maxTokens: 220,
5261
5354
  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.",
5355
+ "Describe this image with concise facts that help answer the user's request.",
5356
+ "Include visible text, UI state, charts, diagrams, errors, and names.",
5357
+ "Do not guess.",
5265
5358
  "Return plain text only."
5266
5359
  ].join(" "),
5267
5360
  metadata: {
@@ -5277,32 +5370,22 @@ async function resolveUserAttachmentsWithDeps(attachments, context, deps) {
5277
5370
  filename: attachment.name
5278
5371
  });
5279
5372
  }
5373
+ const truncatedSummary = truncateVisionSummary(summary);
5280
5374
  resolvedAttachment.promptText = buildImageAttachmentPromptText({
5375
+ attachmentId,
5281
5376
  filename: attachment.name,
5282
5377
  mediaType,
5283
- summary: truncateVisionSummary(summary)
5378
+ summary: truncatedSummary
5284
5379
  });
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) {
5380
+ if (attachmentId) {
5381
+ await recordSlackAttachment({
5382
+ attachmentId,
5383
+ conversationId: context.conversationId,
5384
+ db: getSqlExecutor(),
5385
+ visionSummary: truncatedSummary
5386
+ });
5387
+ }
5388
+ } catch (error) {
5306
5389
  const attachmentError = error instanceof ImageAttachmentProcessingError ? error : createImageAttachmentProcessingError({
5307
5390
  filename: attachment.name
5308
5391
  });
@@ -5311,22 +5394,26 @@ async function resolveUserAttachmentsWithDeps(attachments, context, deps) {
5311
5394
  "app.file.mime_type": mediaType,
5312
5395
  ...attachment.name ? { "file.name": attachment.name } : void 0
5313
5396
  });
5314
- results.push({
5315
- mediaType,
5397
+ resolvedAttachment.promptText = buildImageAttachmentFailurePromptText({
5398
+ attachmentId,
5316
5399
  filename: attachment.name,
5317
- promptText: buildImageAttachmentFailurePromptText({
5318
- filename: attachment.name,
5319
- mediaType,
5320
- message: attachmentError.message
5321
- })
5400
+ mediaType,
5401
+ message: attachmentError.message
5322
5402
  });
5323
- continue;
5324
5403
  }
5325
- logWarn("attachment.resolution.failed", {
5326
- "exception.message": error instanceof Error ? error.message : String(error),
5327
- "app.file.mime_type": mediaType
5404
+ results.push(resolvedAttachment);
5405
+ continue;
5406
+ }
5407
+ if (isImageAttachment && attachmentId) {
5408
+ resolvedAttachment.promptText = buildStoredAttachmentPromptText({
5409
+ attachmentId,
5410
+ filename: attachment.name,
5411
+ mediaType
5328
5412
  });
5413
+ } else {
5414
+ resolvedAttachment.data = data;
5329
5415
  }
5416
+ results.push(resolvedAttachment);
5330
5417
  }
5331
5418
  return results;
5332
5419
  }
@@ -5430,7 +5517,7 @@ async function hydrateConversationVisionContextWithDeps(conversation, context, d
5430
5517
  const imageFiles = (reply.files ?? []).filter((file) => {
5431
5518
  const mimeType = toOptionalString(file.mimetype);
5432
5519
  return Boolean(
5433
- toOptionalString(file.id) && mimeType?.startsWith("image/")
5520
+ toOptionalString(file.id) && mimeType && isVisionImageMediaType(mimeType)
5434
5521
  );
5435
5522
  }).slice(0, MAX_MESSAGE_IMAGE_ATTACHMENTS);
5436
5523
  if (imageFiles.length === 0) {
@@ -6622,6 +6709,7 @@ function createJuniorRuntimeServices(overrides = {}) {
6622
6709
  autoCompactionTriggerTokens: overrides.contextCompactor?.autoCompactionTriggerTokens
6623
6710
  });
6624
6711
  const visionContext = createVisionContextService({
6712
+ attachmentStorage: overrides.visionContext?.attachmentStorage,
6625
6713
  completeText: overrides.visionContext?.completeText ?? completeText,
6626
6714
  listThreadReplies: overrides.visionContext?.listThreadReplies ?? listThreadReplies,
6627
6715
  downloadFile: overrides.visionContext?.downloadFile ?? downloadPrivateSlackFile
@@ -7076,6 +7164,7 @@ function createSlackTurn(deps) {
7076
7164
  timestampMs: queued.message.metadata.dateSent.getTime(),
7077
7165
  omittedImageAttachmentCount: !isVisionEnabled() && hasPotentialImageAttachment(attachments) ? countPotentialImageAttachments(attachments) : 0,
7078
7166
  attachments: await deps.resolveUserAttachments(attachments, {
7167
+ conversationId,
7079
7168
  threadId,
7080
7169
  actorId: queued.message.author.userId,
7081
7170
  channelId,
@@ -7301,6 +7390,7 @@ function createSlackTurn(deps) {
7301
7390
  const userAttachments = await deps.resolveUserAttachments(
7302
7391
  turnAttachments,
7303
7392
  {
7393
+ conversationId,
7304
7394
  threadId,
7305
7395
  actorId: slackActorId,
7306
7396
  channelId,
@@ -9897,6 +9987,21 @@ function createResourceEventTeamIdResolver() {
9897
9987
  function createResourceEventAppPublisher(args) {
9898
9988
  const resolveEventTaskTeamId = createResourceEventTeamIdResolver();
9899
9989
  return {
9990
+ async hasMatch(event) {
9991
+ const work = args.conversationWork();
9992
+ const eventTaskTeamId = await resolveEventTaskTeamId();
9993
+ const [subscriptions, tasks] = await Promise.all([
9994
+ findMatchingResourceEventSubscriptions({
9995
+ data: event.data,
9996
+ eventType: event.eventType,
9997
+ namespace: event.namespace,
9998
+ identifier: event.identifier,
9999
+ state: work.state
10000
+ }),
10001
+ eventTaskTeamId ? findMatchingEventTasks(getDb(), event, eventTaskTeamId) : Promise.resolve([])
10002
+ ]);
10003
+ return subscriptions.length > 0 || tasks.length > 0;
10004
+ },
9900
10005
  async neededMatchKeys(input) {
9901
10006
  const work = args.conversationWork();
9902
10007
  const eventTaskTeamId = await resolveEventTaskTeamId();
@@ -12444,7 +12549,8 @@ async function createApp(options) {
12444
12549
  });
12445
12550
  const runtimeServiceOverrides = {
12446
12551
  agentRunner,
12447
- sandbox: { tracePropagation }
12552
+ sandbox: { tracePropagation },
12553
+ visionContext: { attachmentStorage }
12448
12554
  };
12449
12555
  let conversationWorkOptions;
12450
12556
  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-YDUR3ZYW.js";
4
+ import "./chunk-BXCX5QKA.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-MAGNK5J4.js";
10
10
  import "./chunk-PEQXYSSE.js";
11
- import "./chunk-OTTKTTVI.js";
11
+ import "./chunk-HMREVIO2.js";
12
12
  export {
13
13
  pluginCatalogRuntime
14
14
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getChatConfig
3
- } from "./chunk-GFXDMDHR.js";
3
+ } from "./chunk-63NKKFJL.js";
4
4
 
5
5
  // src/chat/state/adapter.ts
6
6
  import { createMemoryState } from "@chat-adapter/state-memory";