@sentry/junior 0.226.0 → 0.228.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 (57) hide show
  1. package/dist/{agent-hooks-FUetyyLe.js → agent-hooks-DUQ3ASdp.js} +227 -12
  2. package/dist/{agent-runner-DEF7auSj.js → agent-runner-CIesujf5.js} +123 -77
  3. package/dist/api/schema.d.ts +203 -32
  4. package/dist/api/schema.js +3 -3
  5. package/dist/api.js +105 -67
  6. package/dist/{app-TVL42pGL.d.ts → app-BRZB3MuD.d.ts} +1 -1
  7. package/dist/app.d.ts +1 -1
  8. package/dist/app.js +275 -137
  9. package/dist/{briefs-Cb4T2BUI.js → briefs-BTrVMqUg.js} +4 -4
  10. package/dist/{catalog-runtime-BYGR3Dr4.js → catalog-runtime-NOBDOyJi.js} +1 -1
  11. package/dist/{checkpoint-CJe-dZFF.js → checkpoint-CzN3gXoB.js} +7 -7
  12. package/dist/cli/chat.js +13 -13
  13. package/dist/cli/check.js +3 -3
  14. package/dist/cli/main.js +1 -1
  15. package/dist/cli/plugins.js +3 -3
  16. package/dist/cli/snapshot-create.js +3 -3
  17. package/dist/cli/upgrade.js +3 -3
  18. package/dist/{client-C2WBBx7m.js → client-C6VUBzL_.js} +2 -2
  19. package/dist/{config-Bws6Rpsh.js → config-BLPaWN1Q.js} +2 -2
  20. package/dist/{context-Bplcgypl.js → context-0Et9iVSB.js} +1 -1
  21. package/dist/{conversation-DPbmIwjy.js → conversation-DOI6Y60M.js} +52 -24
  22. package/dist/{conversation-privacy-pCcW0a5Y.js → conversation-privacy-DJ88ECSq.js} +1 -1
  23. package/dist/{credential-sync-ibuNsMyl.js → credential-sync-OKs419AB.js} +14 -14
  24. package/dist/{executor-D36FWjcf.js → executor-DZVZBfmX.js} +1 -1
  25. package/dist/{history-DI9KJT3J.d.ts → history-H-SI5Dej.d.ts} +27 -1
  26. package/dist/images-D3x6EemU.js +82 -0
  27. package/dist/instrumentation.js +2 -2
  28. package/dist/{job-queue-2mFFDMHB.js → job-queue-BuSPM0cX.js} +1 -1
  29. package/dist/{logging-CvjMHRvg.js → logging-Blgn76r3.js} +1 -1
  30. package/dist/nitro.d.ts +1 -1
  31. package/dist/nitro.js +3 -3
  32. package/dist/{oauth-authorization-l4O1rXsL.js → oauth-authorization-t-NPqTNB.js} +1 -1
  33. package/dist/{oauth-callback-server-Ds8M5FFX.js → oauth-callback-server-BP7SgTcu.js} +2 -2
  34. package/dist/{pending-auth-DLNJbD8H.js → pending-auth-CXLwmDaG.js} +1 -1
  35. package/dist/{profile-dvV7PB7u.js → profile-a5xmeUHf.js} +4 -4
  36. package/dist/{prompt-DehgjkO5.js → prompt-9C-wUwwx.js} +1 -1
  37. package/dist/{registry-C6FHctIu.js → registry-BUbczT2k.js} +2 -2
  38. package/dist/{resolve-DqwGI9wq.js → resolve-3PhWSiEF.js} +2 -2
  39. package/dist/{runner-CzYEcB73.js → runner-CsnuKcsq.js} +10 -10
  40. package/dist/{sandbox-egress-signals-BZOv0fns.js → sandbox-egress-signals-D34sI4J6.js} +1 -1
  41. package/dist/{schema-BZg-xzfG.js → schema-CXmCvVLn.js} +1 -1
  42. package/dist/{skills-EhiVbjF4.js → skills-CLgyYrgF.js} +2 -2
  43. package/dist/{spawn-Ck3L0rEr.js → spawn-CS56i7Nm.js} +2 -2
  44. package/dist/{task-queue-TXhAWQwj.js → task-queue-C2sTDXqQ.js} +3 -3
  45. package/dist/{task-runner-axUJS1No.js → task-runner-uSodiP4v.js} +10 -10
  46. package/dist/{thread-state-CTuWhjru.js → thread-state-BurqeqMv.js} +5 -5
  47. package/dist/{turn-failure-response-csVoLOzx.js → turn-failure-response-Bshcqa0a.js} +9 -9
  48. package/dist/{turn-lifecycle-C1S6vELh.js → turn-lifecycle-foKlVl_T.js} +1 -1
  49. package/dist/{turn-session-routing-5RejBvit.js → turn-session-routing-DDUMJ2GY.js} +1 -1
  50. package/dist/{validation-q2PFxkTQ.js → validation-DZc56dXw.js} +1 -1
  51. package/dist/{version-ByLtIYyy.js → version-y4cRp5Y2.js} +1 -1
  52. package/dist/version.js +1 -1
  53. package/dist/{web-authorization-Biy8nsS7.js → web-authorization-BfVYx0t1.js} +6 -6
  54. package/dist/{web-input-DM9LaEdn.js → web-input-B6FZlrgg.js} +73 -41
  55. package/dist/{work-QrbHdXTc.js → work-Dy8sW9MZ.js} +7 -7
  56. package/dist/{worker-r17aopXW.js → worker-BH0RP7Hj.js} +5 -5
  57. package/package.json +5 -4
package/dist/api.js CHANGED
@@ -1,18 +1,19 @@
1
- import { Ft as getConversation, P as parseSlackThreadId, Tt as cancelHumanFacingPendingMessages, b as readStats, j as readLiveAttachment } from "./agent-runner-DEF7auSj.js";
2
- import { d as logException, p as logWarn } from "./logging-CvjMHRvg.js";
3
- import { _ as parseSlackMessageTs, h as parseSlackTeamId, p as parseSlackChannelId } from "./context-Bplcgypl.js";
4
- import { $ as resolveViewerUser, Ct as conversationArchivedForEmail, D as SANDBOX_RUNTIME, Dt as conversationNotArchivedForEmail, Et as conversationHasParticipantUser, J as withSlackRetries, Jt as getSqlExecutor, Kt as getConversationStore, Lt as listConversationAnnotations, Mt as readConversationEventPage, Nt as buildSentryConversationUrl, Ot as conversationNotArchivedForUser, Qt as locationFromRow, Rt as listConversationAnnotationsById, S as WorkspaceValidationError, St as conversationArchiveTimes, Tt as conversationHasParticipantEmail, U as getSlackClient, Z as findUserByEmail, _ as deleteWorkspace, an as hasAgentTurnUsage, b as listWorkspaces, bt as createPluginLogger, en as parseSessionSource, et as updateViewerDisplayName, g as createWorkspace, in as agentTurnUsageSchema, j as workspaceRepoCheckoutPath, jt as readLatestConversationBrief, kt as viewerConversationMembership, on as resolveRootConversationId, qt as getDb, u as getPlugins, v as getWorkspace, wt as conversationArchivedForUser, x as updateWorkspace, xt as readConversationAccessFromSql } from "./agent-hooks-FUetyyLe.js";
1
+ import { Ct as cancelHumanFacingPendingMessages, M as parseSlackThreadId, Nt as getConversation, b as readStats, k as readLiveAttachment } from "./agent-runner-CIesujf5.js";
2
+ import { d as logException, p as logWarn } from "./logging-Blgn76r3.js";
3
+ import { b as parseSlackMessageTs, h as parseSlackTeamId, p as parseSlackChannelId } from "./context-0Et9iVSB.js";
4
+ import { $ as resolveViewerUser, $t as getConversationStore, At as conversationNotArchivedForEmail, Ct as createPluginLogger, D as SANDBOX_RUNTIME, Dt as conversationArchivedForUser, Et as conversationArchivedForEmail, Ft as readConversationEventPage, Gt as listConversationAnnotationsById, It as buildSentryConversationUrl, J as withSlackRetries, Mt as viewerConversationMembership, Ot as conversationHasParticipantEmail, Pt as readLatestConversationBrief, S as WorkspaceValidationError, Tt as conversationArchiveTimes, U as getSlackClient, Wt as listConversationAnnotations, Z as findUserByEmail, _ as deleteWorkspace, an as locationFromRow, b as listWorkspaces, dn as agentTurnUsageSchema, en as getDb, et as updateViewerDisplayName, fn as hasAgentTurnUsage, g as createWorkspace, j as workspaceRepoCheckoutPath, jt as conversationNotArchivedForUser, kt as conversationHasParticipantUser, pn as resolveRootConversationId, sn as parseSessionSource, tn as getSqlExecutor, u as getPlugins, v as getWorkspace, wt as readConversationAccessFromSql, x as updateWorkspace } from "./agent-hooks-DUQ3ASdp.js";
5
5
  import { n as juniorDestinations } from "./destinations-BeBiJeEM.js";
6
- import { C as juniorCodeRepositories, D as juniorIdentities, E as juniorConversations, O as juniorUsers, S as juniorCodeChanges, T as conversationReadColumns, b as juniorApiTokens, g as juniorConversationBriefs, m as juniorConversationParticipants, v as juniorConversationMetrics, y as juniorConversationEvents } from "./executor-D36FWjcf.js";
7
- import { D as createConversationBodySchema, O as createConversationMessageBodySchema, T as conversationStatsReportSchema, _ as conversationParamsSchema, a as cancelConversationPendingMessagesBodySchema, c as conversationAttachmentParamsSchema, d as conversationDetailReportSchema, g as conversationFeedSchema, h as conversationFeedQuerySchema, i as archiveConversationResponseSchema, m as conversationEventsQuerySchema, o as cancelConversationPendingMessagesResponseSchema, p as conversationEventPageSchema, r as archiveConversationBodySchema, t as acceptedConversationMessageSchema, u as conversationDetailQuerySchema, x as conversationPendingMessagesReportSchema } from "./conversation-DPbmIwjy.js";
8
- import { n as hash, t as create } from "./profile-dvV7PB7u.js";
9
- import { t as getCachedSnapshot } from "./resolve-DqwGI9wq.js";
10
- import { a as getVercelConversationWorkQueue } from "./job-queue-2mFFDMHB.js";
6
+ import { C as juniorCodeRepositories, D as juniorIdentities, E as juniorConversations, O as juniorUsers, S as juniorCodeChanges, T as conversationReadColumns, b as juniorApiTokens, g as juniorConversationBriefs, m as juniorConversationParticipants, v as juniorConversationMetrics, y as juniorConversationEvents } from "./executor-DZVZBfmX.js";
7
+ import { D as createConversationBodySchema, I as readMessageAttachments, L as INPUT_IMAGE_TYPES, O as createConversationMessageBodySchema, T as conversationStatsReportSchema, _ as conversationParamsSchema, a as cancelConversationPendingMessagesBodySchema, c as conversationAttachmentParamsSchema, d as conversationDetailReportSchema, g as conversationFeedSchema, h as conversationFeedQuerySchema, i as archiveConversationResponseSchema, m as conversationEventsQuerySchema, o as cancelConversationPendingMessagesResponseSchema, p as conversationEventPageSchema, r as archiveConversationBodySchema, t as acceptedConversationMessageSchema, u as conversationDetailQuerySchema, x as conversationPendingMessagesReportSchema } from "./conversation-DOI6Y60M.js";
8
+ import { n as hash, t as create } from "./profile-a5xmeUHf.js";
9
+ import { t as getCachedSnapshot } from "./resolve-3PhWSiEF.js";
10
+ import { a as getVercelConversationWorkQueue } from "./job-queue-BuSPM0cX.js";
11
11
  import { C as skillReportsSchema, a as fillUtcHours, b as pluginsSchema, c as sumUtcHoursIntoSixHours, d as trailingUtcSixHourWindow, f as utcDayKey, h as pluginOperationalReportFeedSchema, i as fillUtcDays, l as trailingUtcDayWindow, m as healthReportSchema, n as DAY_MS$1, o as fillUtcSixHours, p as utcHourKey, r as HOUR_MS$1, s as startOfUtcHour, u as trailingUtcHourWindow, x as runtimeInfoReportSchema } from "./web-message-id-xPI_EFSC.js";
12
- import { F as createVercelAttachmentStorage, _ as readViewerAutomations, a as webActorFromEmail, b as clearSlackPendingReactions, c as getProductionSlackAdapter, d as ViewerTaskNotFoundError, f as deleteViewerTask, h as readViewerAutomationRuns, k as legacyWebMailboxMetadataSchema, l as formatSlackConversationRedactedLabel, m as readViewerAutomationExecutions, p as readConversationSourceTask, r as createAndEnqueueConversation, t as appendAndEnqueueWebMessage, u as resolveSlackConversationContextFromThreadId, x as lookupSlackUser, z as readHealthReport } from "./web-input-DM9LaEdn.js";
13
- import { A as conversationAggregateColumns, j as conversationRangeColumns, k as conversationActiveDaysColumn } from "./task-runner-axUJS1No.js";
14
- import { r as getWebAuthorization } from "./web-authorization-Biy8nsS7.js";
15
- import { A as actorProfileReportSchema, C as createPersonalTokenBodySchema, D as personalTokenParamsSchema, F as locationDirectoryReportSchema, G as codePersonReportSchema, I as locationParamsSchema, L as activityDays$1, M as personalSpendReportSchema, O as revokePersonalTokenResponseSchema, P as locationDetailReportSchema, R as activityHours$1, T as personalTokenListSchema, W as codeOverviewReportSchema, _ as automationRunListSchema, a as workspaceBodySchema, g as automationParamsSchema, h as automationListSchema, i as deleteWorkspaceResponseSchema, j as personParamsSchema, k as actorDirectoryReportSchema, l as workspaceSchema, m as automationListQuerySchema, n as statsReportSchema, o as workspaceListSchema, q as apiErrorSchema, s as workspaceParamsSchema, u as automationExecutionListSchema, w as createdPersonalTokenSchema, z as activitySixHours$1 } from "./schema-BZg-xzfG.js";
12
+ import { F as createVercelAttachmentStorage, _ as readViewerAutomations, a as webActorFromEmail, b as clearSlackPendingReactions, c as getProductionSlackAdapter, d as ViewerTaskNotFoundError, f as deleteViewerTask, h as readViewerAutomationRuns, k as legacyWebMailboxMetadataSchema, l as formatSlackConversationRedactedLabel, m as readViewerAutomationExecutions, p as readConversationSourceTask, r as createAndEnqueueConversation, t as appendAndEnqueueWebMessage, u as resolveSlackConversationContextFromThreadId, x as lookupSlackUser, z as readHealthReport } from "./web-input-B6FZlrgg.js";
13
+ import { A as conversationAggregateColumns, j as conversationRangeColumns, k as conversationActiveDaysColumn } from "./task-runner-uSodiP4v.js";
14
+ import { r as getWebAuthorization } from "./web-authorization-BfVYx0t1.js";
15
+ import { t as decodeInputImages } from "./images-D3x6EemU.js";
16
+ import { A as actorProfileReportSchema, C as createPersonalTokenBodySchema, D as personalTokenParamsSchema, F as locationDirectoryReportSchema, G as codePersonReportSchema, I as locationParamsSchema, L as activityDays$1, M as personalSpendReportSchema, O as revokePersonalTokenResponseSchema, P as locationDetailReportSchema, R as activityHours$1, T as personalTokenListSchema, W as codeOverviewReportSchema, _ as automationRunListSchema, a as workspaceBodySchema, g as automationParamsSchema, h as automationListSchema, i as deleteWorkspaceResponseSchema, j as personParamsSchema, k as actorDirectoryReportSchema, l as workspaceSchema, m as automationListQuerySchema, n as statsReportSchema, o as workspaceListSchema, q as apiErrorSchema, s as workspaceParamsSchema, u as automationExecutionListSchema, w as createdPersonalTokenSchema, z as activitySixHours$1 } from "./schema-CXmCvVLn.js";
16
17
  import { Hono } from "hono";
17
18
  import path from "node:path";
18
19
  import { z } from "zod";
@@ -22,6 +23,7 @@ import { conversationSidebarAnnotationSchema, pluginUserPageContentSchema, plugi
22
23
  import { alias } from "drizzle-orm/pg-core";
23
24
  import { readFileSync } from "node:fs";
24
25
  import { HTTPException } from "hono/http-exception";
26
+ import { bodyLimit } from "hono/body-limit";
25
27
  import { zValidator } from "@hono/zod-validator";
26
28
  import { createMiddleware } from "hono/factory";
27
29
  //#region src/api/http.ts
@@ -125,11 +127,8 @@ async function archiveConversation(viewer, conversationId, body) {
125
127
  }
126
128
  //#endregion
127
129
  //#region src/api/conversations/attachments.ts
128
- function mayDisplayInline(contentType) {
129
- return contentType === "image/gif" || contentType === "image/jpeg" || contentType === "image/png" || contentType === "image/webp";
130
- }
131
130
  function contentDisposition(filename, contentType) {
132
- return `${mayDisplayInline(contentType) ? "inline" : "attachment"}; filename="${filename.replace(/[^\x20-\x7e]|["\\]/g, "_")}"; filename*=UTF-8''${encodeURIComponent(filename)}`;
131
+ return `${INPUT_IMAGE_TYPES.some((type) => type === contentType) ? "inline" : "attachment"}; filename="${filename.replace(/[^\x20-\x7e]|["\\]/g, "_")}"; filename*=UTF-8''${encodeURIComponent(filename)}`;
133
132
  }
134
133
  /** Build response headers for one conversation attachment body. */
135
134
  function conversationAttachmentHeaders(args) {
@@ -170,6 +169,14 @@ async function requireConversationAttachment(args) {
170
169
  }
171
170
  //#endregion
172
171
  //#region src/api/conversations/create.ts
172
+ /** Turn image validation failures into request errors before accepting work. */
173
+ function parseImages(images) {
174
+ try {
175
+ return decodeInputImages(images ?? []);
176
+ } catch (error) {
177
+ throwApiError(400, error instanceof Error ? error.message : "Unable to read images.");
178
+ }
179
+ }
173
180
  function actorFromViewer(viewer) {
174
181
  const normalized = viewer.email.trim().toLowerCase();
175
182
  return webActorFromEmail(normalized, {
@@ -178,15 +185,18 @@ function actorFromViewer(viewer) {
178
185
  });
179
186
  }
180
187
  /** Create a dashboard root conversation and enqueue its first message. */
181
- async function createConversationForViewer(viewer, body) {
188
+ async function createConversationForViewer(viewer, body, attachmentStorage) {
189
+ const images = parseImages(body.images);
182
190
  try {
183
191
  return await createAndEnqueueConversation({
184
192
  actor: actorFromViewer(viewer),
185
193
  idempotencyKey: body.idempotencyKey,
186
194
  message: body.message,
195
+ images,
187
196
  ...body.visibility ? { visibility: body.visibility } : void 0
188
197
  }, {
189
198
  conversationStore: getConversationStore(),
199
+ attachmentStorage,
190
200
  queue: getVercelConversationWorkQueue()
191
201
  });
192
202
  } catch (error) {
@@ -194,20 +204,23 @@ async function createConversationForViewer(viewer, body) {
194
204
  }
195
205
  }
196
206
  /** Append one dashboard message to an existing conversation. */
197
- async function appendConversationMessageForViewer(viewer, conversationId, body) {
207
+ async function appendConversationMessageForViewer(viewer, conversationId, body, attachmentStorage) {
198
208
  const conversation = await getConversationStore().get({ conversationId });
199
209
  if (!conversation) throwApiError(404, "Conversation not found.");
200
210
  const destinationPlatform = conversation.destination?.platform;
201
211
  if (!(destinationPlatform === "local" && conversationId.startsWith("local:web:") || destinationPlatform === "slack")) throwApiError(409, "Conversation does not accept web messages.");
202
212
  if (!(await readConversationAccessFromSql(getDb(), [conversationId], viewer)).get(conversationId)?.isParticipant) throwApiError(403, "Only conversation participants can add messages.");
213
+ const images = parseImages(body.images);
203
214
  try {
204
215
  return await appendAndEnqueueWebMessage({
205
216
  actor: actorFromViewer(viewer),
206
217
  conversationId,
207
218
  idempotencyKey: body.idempotencyKey,
208
- message: body.message
219
+ message: body.message,
220
+ images
209
221
  }, {
210
222
  conversationStore: getConversationStore(),
223
+ attachmentStorage,
211
224
  queue: getVercelConversationWorkQueue()
212
225
  });
213
226
  } catch (error) {
@@ -215,6 +228,56 @@ async function appendConversationMessageForViewer(viewer, conversationId, body)
215
228
  }
216
229
  }
217
230
  //#endregion
231
+ //#region src/chat/plugins/conversation-sidebar.ts
232
+ /** Show native objects by default and let plugins select compact sidebar labels. */
233
+ async function listConversationSidebarAnnotations(conversationIds, annotationsByConversation) {
234
+ const candidates = new Set(conversationIds);
235
+ const selected = {};
236
+ const plugins = getPlugins();
237
+ const customOwners = new Set(plugins.filter((plugin) => plugin.hooks?.conversationSidebar).map((plugin) => plugin.manifest.name));
238
+ for (const conversationId of conversationIds) {
239
+ const objects = (annotationsByConversation.get(conversationId) ?? []).flatMap((annotation) => {
240
+ if (customOwners.has(annotation.plugin) || !annotation.objectType) return [];
241
+ return [{
242
+ key: annotation.key,
243
+ label: annotation.label,
244
+ objectType: annotation.objectType === "item" && annotation.kind === "object" && annotation.facts?.type === "deployment" ? "deployment" : annotation.objectType,
245
+ status: annotation.status
246
+ }];
247
+ });
248
+ if (objects.length) selected[conversationId] = objects;
249
+ }
250
+ for (const plugin of plugins) {
251
+ const hook = plugin.hooks?.conversationSidebar;
252
+ if (!hook) continue;
253
+ const annotationsByConversationId = Object.fromEntries(conversationIds.flatMap((conversationId) => {
254
+ const annotations = (annotationsByConversation.get(conversationId) ?? []).filter((annotation) => annotation.plugin === plugin.manifest.name);
255
+ return annotations.length > 0 ? [[conversationId, annotations]] : [];
256
+ }));
257
+ try {
258
+ const result = await hook({
259
+ annotationsByConversationId,
260
+ conversationIds,
261
+ db: getDb(),
262
+ log: createPluginLogger(plugin.manifest.name),
263
+ plugin: { name: plugin.manifest.name }
264
+ });
265
+ for (const [conversationId, annotations] of Object.entries(result.annotationsByConversationId)) {
266
+ if (!candidates.has(conversationId)) continue;
267
+ const parsed = conversationSidebarAnnotationSchema.array().safeParse(annotations);
268
+ if (!parsed.success || parsed.data.length === 0) continue;
269
+ selected[conversationId] = [...selected[conversationId] ?? [], ...parsed.data];
270
+ }
271
+ } catch (error) {
272
+ logWarn("plugin.conversation_sidebar.hook.failed", {
273
+ "app.plugin.name": plugin.manifest.name,
274
+ "exception.message": error instanceof Error ? error.message : String(error)
275
+ });
276
+ }
277
+ }
278
+ return selected;
279
+ }
280
+ //#endregion
218
281
  //#region src/chat/slack/location-url.ts
219
282
  /** Parse a Slack workspace subdomain used in `https://{domain}.slack.com` URLs. */
220
283
  function parseSlackTeamDomain(value) {
@@ -749,42 +812,6 @@ async function readConversationAuxiliaryCostsFromSql(db, conversationIds, option
749
812
  return result;
750
813
  }
751
814
  //#endregion
752
- //#region src/chat/plugins/conversation-sidebar.ts
753
- /** Return plugin-selected sidebar annotations for candidate conversations. */
754
- async function listConversationSidebarAnnotations(conversationIds, annotationsByConversation) {
755
- const candidates = new Set(conversationIds);
756
- const selected = {};
757
- for (const plugin of getPlugins()) {
758
- const hook = plugin.hooks?.conversationSidebar;
759
- if (!hook) continue;
760
- const annotationsByConversationId = Object.fromEntries(conversationIds.flatMap((conversationId) => {
761
- const annotations = (annotationsByConversation.get(conversationId) ?? []).filter((annotation) => annotation.plugin === plugin.manifest.name);
762
- return annotations.length > 0 ? [[conversationId, annotations]] : [];
763
- }));
764
- try {
765
- const result = await hook({
766
- annotationsByConversationId,
767
- conversationIds,
768
- db: getDb(),
769
- log: createPluginLogger(plugin.manifest.name),
770
- plugin: { name: plugin.manifest.name }
771
- });
772
- for (const [conversationId, annotations] of Object.entries(result.annotationsByConversationId)) {
773
- if (!candidates.has(conversationId)) continue;
774
- const parsed = conversationSidebarAnnotationSchema.array().safeParse(annotations);
775
- if (!parsed.success || parsed.data.length === 0) continue;
776
- selected[conversationId] = [...selected[conversationId] ?? [], ...parsed.data];
777
- }
778
- } catch (error) {
779
- logWarn("plugin.conversation_sidebar.hook.failed", {
780
- "app.plugin.name": plugin.manifest.name,
781
- "exception.message": error instanceof Error ? error.message : String(error)
782
- });
783
- }
784
- }
785
- return selected;
786
- }
787
- //#endregion
788
815
  //#region src/chat/plugins/unfinished-work.ts
789
816
  /**
790
817
  * Return assigned and unfinished plugin work for the candidate conversations.
@@ -1159,6 +1186,7 @@ function projectConversationDetail(args) {
1159
1186
  usage: args.usage
1160
1187
  }),
1161
1188
  annotations: canExposePayload ? args.annotations : [],
1189
+ sidebarAnnotations: canExposePayload ? args.sidebarAnnotations : void 0,
1162
1190
  ...canExposePayload && args.brief ? { brief: args.brief } : void 0,
1163
1191
  events: args.events,
1164
1192
  ...canExposePayload && args.participants.length > 0 ? { participants: args.participants } : void 0,
@@ -1200,6 +1228,7 @@ async function readConversationDetailFromSql(conversationId, options) {
1200
1228
  resolveSlackTeamDomains(record.conversation.location?.provider === "slack" ? [record.conversation.location.teamId] : [])
1201
1229
  ]);
1202
1230
  const access = accessByConversation.get(conversationId);
1231
+ const sidebarAnnotations = access?.canViewPrivateContent ? (await listConversationSidebarAnnotations([conversationId], /* @__PURE__ */ new Map([[conversationId, annotations]])))[conversationId] : void 0;
1203
1232
  const page = record.conversation.transcriptPurgedAtMs === void 0 ? await readConversationEventPage(executor, {
1204
1233
  canExposePayload: access?.canViewPrivateContent ?? false,
1205
1234
  conversationId,
@@ -1211,6 +1240,7 @@ async function readConversationDetailFromSql(conversationId, options) {
1211
1240
  access,
1212
1241
  ...archivedAtMs === void 0 ? void 0 : { archivedAtMs },
1213
1242
  annotations,
1243
+ sidebarAnnotations,
1214
1244
  auxiliaryCosts: auxiliaryCostsByConversation.get(conversationId),
1215
1245
  ...briefVersion ? { brief: {
1216
1246
  content: briefVersion.content,
@@ -1338,7 +1368,8 @@ async function projectPendingMessage(message, canExposePayload) {
1338
1368
  const metadata = legacyWebMailboxMetadataSchema.safeParse(message.input.metadata);
1339
1369
  if (!metadata.success) return void 0;
1340
1370
  const text = message.input.text.trim();
1341
- if (!text) return void 0;
1371
+ const attachments = readMessageAttachments(message.input.attachments);
1372
+ if (!text && !attachments.length) return void 0;
1342
1373
  return {
1343
1374
  createdAt: isoFromMs(message.createdAtMs),
1344
1375
  delivery: message.delivery,
@@ -1349,7 +1380,8 @@ async function projectPendingMessage(message, canExposePayload) {
1349
1380
  source: "web",
1350
1381
  ...canExposePayload ? {
1351
1382
  actorIdentity: actorIdentityFromWebMetadata(metadata.data),
1352
- text
1383
+ text,
1384
+ ...attachments.length ? { attachments } : void 0
1353
1385
  } : { redacted: true }
1354
1386
  };
1355
1387
  }
@@ -1780,6 +1812,12 @@ async function readConversationStats() {
1780
1812
  /** Create the HTTP routes owned by the conversations API. */
1781
1813
  function createConversationRoutes(options) {
1782
1814
  const app = new Hono();
1815
+ const messageBodyLimit = bodyLimit({
1816
+ maxSize: 445e4,
1817
+ onError: () => {
1818
+ throwApiError(413, "Images must total 3 MB or less.");
1819
+ }
1820
+ });
1783
1821
  app.get("/", validateRequest("query", conversationFeedQuerySchema, "Invalid query parameters."), async (context) => {
1784
1822
  const { actorEmail, q, status } = context.req.valid("query");
1785
1823
  const viewer = context.get("viewer");
@@ -1791,16 +1829,16 @@ function createConversationRoutes(options) {
1791
1829
  }));
1792
1830
  });
1793
1831
  app.get("/stats", async () => jsonResponse(conversationStatsReportSchema, await readConversationStats()));
1794
- app.post("/", requireViewer, validateRequest("json", createConversationBodySchema, "Invalid request body."), async (context) => {
1832
+ app.post("/", requireViewer, messageBodyLimit, validateRequest("json", createConversationBodySchema, "Invalid request body."), async (context) => {
1795
1833
  const viewer = context.get("viewer");
1796
1834
  const body = context.req.valid("json");
1797
- return jsonResponse(acceptedConversationMessageSchema, await createConversationForViewer(viewer, body));
1835
+ return jsonResponse(acceptedConversationMessageSchema, await createConversationForViewer(viewer, body, options.attachmentStorage));
1798
1836
  });
1799
- app.post("/:conversationId/messages", requireViewer, validateRequest("param", conversationParamsSchema, "Invalid route parameters."), validateRequest("json", createConversationMessageBodySchema, "Invalid request body."), async (context) => {
1837
+ app.post("/:conversationId/messages", requireViewer, messageBodyLimit, validateRequest("param", conversationParamsSchema, "Invalid route parameters."), validateRequest("json", createConversationMessageBodySchema, "Invalid request body."), async (context) => {
1800
1838
  const viewer = context.get("viewer");
1801
1839
  const { conversationId } = context.req.valid("param");
1802
1840
  const body = context.req.valid("json");
1803
- return jsonResponse(acceptedConversationMessageSchema, await appendConversationMessageForViewer(viewer, conversationId, body));
1841
+ return jsonResponse(acceptedConversationMessageSchema, await appendConversationMessageForViewer(viewer, conversationId, body, options.attachmentStorage));
1804
1842
  });
1805
1843
  app.patch("/:conversationId/archive", requireViewer, validateRequest("param", conversationParamsSchema, "Invalid route parameters."), validateRequest("json", archiveConversationBodySchema, "Invalid request body."), async (context) => {
1806
1844
  const viewer = context.get("viewer");
@@ -3021,7 +3059,7 @@ async function readPeoplePluginReports(args) {
3021
3059
  reports: [],
3022
3060
  source: "plugins"
3023
3061
  });
3024
- const { getPluginProfileReports } = await import("./agent-hooks-FUetyyLe.js").then((n) => n.t);
3062
+ const { getPluginProfileReports } = await import("./agent-hooks-DUQ3ASdp.js").then((n) => n.t);
3025
3063
  return pluginOperationalReportFeedSchema.parse({
3026
3064
  generatedAt: new Date(nowMs).toISOString(),
3027
3065
  reports: await getPluginProfileReports({
@@ -3630,7 +3668,7 @@ function readDescriptionText(home) {
3630
3668
  }
3631
3669
  /** Read discovered skill names for authenticated runtime diagnostics. */
3632
3670
  async function readSkillReports() {
3633
- const { discoverSkills } = await import("./skills-EhiVbjF4.js").then((n) => n.o);
3671
+ const { discoverSkills } = await import("./skills-CLgyYrgF.js").then((n) => n.o);
3634
3672
  const skills = await discoverSkills();
3635
3673
  return skillReportsSchema.parse(skills.map((skill) => ({
3636
3674
  name: skill.name,
@@ -3639,7 +3677,7 @@ async function readSkillReports() {
3639
3677
  }
3640
3678
  /** Read safe configured plugin metadata for authenticated runtime diagnostics. */
3641
3679
  async function readPlugins() {
3642
- const { pluginCatalogRuntime } = await import("./catalog-runtime-BYGR3Dr4.js").then((n) => n.t);
3680
+ const { pluginCatalogRuntime } = await import("./catalog-runtime-NOBDOyJi.js").then((n) => n.t);
3643
3681
  return pluginsSchema.parse(pluginCatalogRuntime.getProviders().map((plugin) => ({
3644
3682
  configKeys: plugin.manifest.configKeys ?? [],
3645
3683
  description: plugin.manifest.description,
@@ -3651,7 +3689,7 @@ async function readPlugins() {
3651
3689
  async function readRuntimeInfoReport() {
3652
3690
  const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
3653
3691
  import("./package-discovery-7a9YqLhE.js").then((n) => n.r),
3654
- import("./catalog-runtime-BYGR3Dr4.js").then((n) => n.t),
3692
+ import("./catalog-runtime-NOBDOyJi.js").then((n) => n.t),
3655
3693
  readPlugins(),
3656
3694
  readSkillReports()
3657
3695
  ]);
@@ -3668,7 +3706,7 @@ async function readRuntimeInfoReport() {
3668
3706
  /** Read sanitized operational summaries contributed by plugins. */
3669
3707
  async function readPluginOperationalReportFeed() {
3670
3708
  const nowMs = Date.now();
3671
- const { getPluginOperationalReports } = await import("./agent-hooks-FUetyyLe.js").then((n) => n.t);
3709
+ const { getPluginOperationalReports } = await import("./agent-hooks-DUQ3ASdp.js").then((n) => n.t);
3672
3710
  return pluginOperationalReportFeedSchema.parse({
3673
3711
  source: "plugins",
3674
3712
  generatedAt: new Date(nowMs).toISOString(),
@@ -1,5 +1,5 @@
1
1
  import { t as ConversationStore } from "./store-DoewL5mG.js";
2
- import "./history-DI9KJT3J.js";
2
+ import "./history-H-SI5Dej.js";
3
3
  import { n as JuniorPluginSet } from "./plugins-BT2l4We3.js";
4
4
  import { Hono } from "hono";
5
5
  import "@earendil-works/pi-ai/compat";
package/dist/app.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { i as ModelProfileInput, n as JuniorDashboardOptions, r as createApp, t as JuniorAppOptions } from "./app-TVL42pGL.js";
1
+ import { i as ModelProfileInput, n as JuniorDashboardOptions, r as createApp, t as JuniorAppOptions } from "./app-BRZB3MuD.js";
2
2
  import { i as defineJuniorPlugins, n as JuniorPluginSet, r as JuniorPluginSetOptions, t as JuniorPluginInput } from "./plugins-BT2l4We3.js";
3
3
  import { t as JUNIOR_VERSION } from "./version-CnXZ614E.js";
4
4
  export { JUNIOR_VERSION, JuniorAppOptions, JuniorDashboardOptions, type JuniorPluginInput, type JuniorPluginSet, type JuniorPluginSetOptions, type ModelProfileInput, createApp, defineJuniorPlugins };