@sentry/junior 0.221.0 → 0.222.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 (64) hide show
  1. package/dist/{agent-CFrfUdN5.js → agent-7kKtDe-6.js} +47 -27
  2. package/dist/{agent-hooks-kjLDY-Aa.js → agent-hooks-DkriF84n.js} +9 -8
  3. package/dist/{agent-runner-DMMa36Zl.js → agent-runner-D0ImXS7U.js} +6 -5
  4. package/dist/api/schema.d.ts +51 -2
  5. package/dist/api/schema.js +4 -4
  6. package/dist/api.js +18 -515
  7. package/dist/{app-BYD2Nyji.d.ts → app-C0zbsnr7.d.ts} +1 -1
  8. package/dist/app.d.ts +1 -1
  9. package/dist/app.js +153 -32
  10. package/dist/{auth-pause-state-TdhAyYM4.js → auth-pause-state-3OT67TA8.js} +52 -7
  11. package/dist/{briefs-CIN2DMSo.js → briefs-CNH1ztn5.js} +4 -4
  12. package/dist/{catalog-runtime-D1v0KsgY.js → catalog-runtime-XH_LFA_7.js} +1 -1
  13. package/dist/{checkpoint-B2-uc-1h.js → checkpoint-CRod8es5.js} +8 -7
  14. package/dist/cli/chat.js +13 -13
  15. package/dist/cli/check.js +3 -3
  16. package/dist/cli/main.js +1 -1
  17. package/dist/cli/plugins.js +3 -3
  18. package/dist/cli/snapshot-create.js +3 -3
  19. package/dist/cli/upgrade.js +3 -3
  20. package/dist/{client-DIe9JhwF.js → client-CcSboWx_.js} +2 -2
  21. package/dist/{config-0_JixokJ.js → config-CGYv-YPE.js} +2 -2
  22. package/dist/{conversation-BSRGzJmY.js → conversation-BBDt88di.js} +46 -3
  23. package/dist/{conversation-privacy-6NLCEkzx.js → conversation-privacy-BGjdDVWD.js} +1 -1
  24. package/dist/{credential-sync-Dqg2o90r.js → credential-sync-BfzGNruT.js} +125 -30
  25. package/dist/{execution-stats-vnXVMVeu.js → execution-stats-D97ePWuM.js} +3 -3
  26. package/dist/{executor-CmZKtNpH.js → executor-BLBZ-UB8.js} +1 -1
  27. package/dist/{history-ClE4toxe.d.ts → history-CaV8Ww7M.d.ts} +16 -1
  28. package/dist/instrumentation.js +2 -2
  29. package/dist/{job-queue-B1k3woMW.js → job-queue-_8gxwDzt.js} +1 -1
  30. package/dist/{logging-D2YJv_PA.js → logging-qmsMdU0y.js} +1 -1
  31. package/dist/nitro.d.ts +1 -1
  32. package/dist/nitro.js +3 -3
  33. package/dist/{oauth-callback-server-BQtO5l5M.js → oauth-callback-server-Mjfm46A5.js} +2 -2
  34. package/dist/{pending-auth-DuSNoTpn.js → pending-auth-_1Ry-_Bw.js} +2 -2
  35. package/dist/{profile-C3TEFAVI.js → profile-DbG8AlNd.js} +4 -4
  36. package/dist/{prompt-BkaHwBW0.js → prompt-B8rCQI7K.js} +1 -1
  37. package/dist/{registry-Bp0kd2xe.js → registry-DGyQCsiy.js} +1 -1
  38. package/dist/reporting-window-DbUqng0P.js +229 -0
  39. package/dist/{resolve-BABNNBLL.js → resolve-D5SqDbCA.js} +2 -2
  40. package/dist/{runner-Bvn90ijl.js → runner-BRAFjJhe.js} +21 -10
  41. package/dist/{sandbox-egress-signals-DLfYAOiO.js → sandbox-egress-signals-CdI1aVHT.js} +1 -1
  42. package/dist/{schema-YPJXVcOW.js → schema-CTOODa3L.js} +5 -128
  43. package/dist/{short-title-C2fM-ERl.js → short-title-CB2fxEyx.js} +2 -2
  44. package/dist/{skills-D1otDVYp.js → skills-BoS3b8cg.js} +2 -2
  45. package/dist/{spawn-C-fAS-Rk.js → spawn-BXCU1udr.js} +2 -2
  46. package/dist/{stats-BfUFTUrM.js → stats-qUXQZq-w.js} +52 -13
  47. package/dist/{task-queue-VdYCCwO0.js → task-queue-Di_q8922.js} +3 -3
  48. package/dist/{task-runner-6tzKHNbM.js → task-runner-4rCppQMo.js} +8 -8
  49. package/dist/{thread-state-CD_fsyrM.js → thread-state-2Paza8DV.js} +5 -5
  50. package/dist/{turn-execution-eVhqozjK.js → turn-execution--F7a9kEU.js} +3 -3
  51. package/dist/{turn-lifecycle-CxAtVANu.js → turn-lifecycle-f-y0Irpi.js} +1 -1
  52. package/dist/{validation-CMERqrCD.js → validation-Be9lSORU.js} +1 -1
  53. package/dist/{version-C8XFxpkQ.js → version-BydrOZMQ.js} +1 -1
  54. package/dist/version.js +1 -1
  55. package/dist/{web-authorization-Dq2NDhY0.js → web-authorization-BdfOkTuG.js} +1 -1
  56. package/dist/web-input-DegYUyKU.js +899 -0
  57. package/dist/{work-DCwaUeWu.js → work-Citqpnfc.js} +9 -9
  58. package/dist/{worker-grswNVoc.js → worker-Bn_HFyvM.js} +5 -5
  59. package/migrations/0044_event_automation_channel_destinations.sql +36 -0
  60. package/migrations/meta/0044_snapshot.json +3473 -0
  61. package/migrations/meta/_journal.json +7 -0
  62. package/package.json +5 -5
  63. package/dist/reporting-schema-DosTN__Q.js +0 -105
  64. package/dist/web-input-Bdh_rCZ7.js +0 -392
@@ -574,6 +574,48 @@ function parseBriefInput(input) {
574
574
  };
575
575
  }
576
576
  //#endregion
577
+ //#region src/chat/automations/card.ts
578
+ /** Saved automation facts shown with a Message, not a live status view. */
579
+ const automationCardSchema = z.object({
580
+ kind: z.literal("automation"),
581
+ id: z.string().min(1),
582
+ title: z.string().min(1).max(160),
583
+ url: z.string().url().nullable(),
584
+ instruction: z.string().max(4e3),
585
+ trigger: z.string().min(1),
586
+ warning: z.string().nullable()
587
+ }).strict();
588
+ /** Render saved card facts for text-only delivery and accessible fallbacks. */
589
+ function automationCardText(card) {
590
+ return [
591
+ card.title,
592
+ card.warning,
593
+ card.trigger,
594
+ card.instruction,
595
+ card.url,
596
+ `Automation ID: ${card.id}`
597
+ ].filter(Boolean).join("\n");
598
+ }
599
+ //#endregion
600
+ //#region src/chat/conversations/cards.ts
601
+ /** Built-in response types accepted by Message storage and delivery. */
602
+ const messageCardSchema = z.discriminatedUnion("kind", [automationCardSchema]);
603
+ const storedCardSchema = automationCardSchema.extend({ operation: z.enum([
604
+ "created",
605
+ "updated",
606
+ "deleted"
607
+ ]).optional() });
608
+ /** Read saved cards without exposing obsolete operation receipts. */
609
+ function readMessageCards(value) {
610
+ return storedCardSchema.array().parse(value).flatMap(({ operation, ...card }) => operation === "deleted" ? [] : [card]);
611
+ }
612
+ /** Render each built-in card with its own text format. */
613
+ function messageCardText(card) {
614
+ switch (card.kind) {
615
+ case "automation": return automationCardText(card);
616
+ }
617
+ }
618
+ //#endregion
577
619
  //#region src/api/schema/conversation.ts
578
620
  const conversationReportStatusSchema = z.enum([
579
621
  "active",
@@ -766,6 +808,7 @@ const conversationReportMessageEventDataSchema = z.object({
766
808
  eventType: z.string().min(1).optional(),
767
809
  explicitMention: z.boolean().optional(),
768
810
  trustedSummary: z.string().min(1).optional(),
811
+ cards: z.array(messageCardSchema).optional(),
769
812
  text: z.string().optional(),
770
813
  redacted: z.literal(true).optional()
771
814
  }).strict().superRefine((data, context) => {
@@ -773,9 +816,9 @@ const conversationReportMessageEventDataSchema = z.object({
773
816
  code: "custom",
774
817
  message: "message content must be text or explicitly redacted"
775
818
  });
776
- if (data.redacted && data.actorIdentity) context.addIssue({
819
+ if (data.redacted && (data.actorIdentity || data.cards)) context.addIssue({
777
820
  code: "custom",
778
- message: "redacted messages must not expose actor identity"
821
+ message: "redacted messages must not expose actor identity or cards"
779
822
  });
780
823
  });
781
824
  const conversationReportMessageHandledEventDataSchema = z.object({
@@ -1162,4 +1205,4 @@ const conversationStatsReportSchema = z.object({
1162
1205
  windowStart: z.string()
1163
1206
  }).strict();
1164
1207
  //#endregion
1165
- export { briefLinkSchema as A, historyReplacementSchema as B, conversationReportEventSchema as C, createConversationBodySchema as D, conversationSummaryReportSchema as E, agentHistoryItemSchema as F, sameActorIdentity as G, contextProvenance as H, conversationEventDataSchema as I, usageSchema as K, conversationTurnFailureCodeSchema as L, conversationBriefSchema as M, parseBriefInput as N, createConversationMessageBodySchema as O, KNOWN_CONVERSATION_EVENT_TYPES as P, conversationTurnFailureReasonSchema as R, conversationReportEventDataSchema as S, conversationStatsReportSchema as T, instructionActors as U, newConversationEventSchema as V, instructionProvenanceFor as W, conversationParamsSchema as _, cancelConversationPendingMessagesBodySchema as a, conversationPendingMessageSchema as b, conversationAttachmentParamsSchema as c, conversationDetailReportSchema as d, conversationEventHistorySchema as f, conversationFeedSchema as g, conversationFeedQuerySchema as h, archiveConversationResponseSchema as i, briefOutcomeStatusSchema as j, briefCodeChangeSchema as k, conversationAuxiliaryCostsSchema as l, conversationEventsQuerySchema as m, actorIdentitySchema as n, cancelConversationPendingMessagesResponseSchema as o, conversationEventPageSchema as p, archiveConversationBodySchema as r, conversationActivityPreviewSchema as s, acceptedConversationMessageSchema as t, conversationDetailQuerySchema as u, conversationPendingAuthorizationSchema as v, conversationStatsItemSchema as w, conversationPendingMessagesReportSchema as x, conversationPendingMessageDeliverySchema as y, decodeStoredConversationEvent as z };
1208
+ export { readMessageCards as A, conversationTurnFailureCodeSchema as B, conversationReportEventSchema as C, createConversationBodySchema as D, conversationSummaryReportSchema as E, conversationBriefSchema as F, contextProvenance as G, decodeStoredConversationEvent as H, parseBriefInput as I, sameActorIdentity as J, instructionActors as K, KNOWN_CONVERSATION_EVENT_TYPES as L, briefCodeChangeSchema as M, briefLinkSchema as N, createConversationMessageBodySchema as O, briefOutcomeStatusSchema as P, agentHistoryItemSchema as R, conversationReportEventDataSchema as S, conversationStatsReportSchema as T, historyReplacementSchema as U, conversationTurnFailureReasonSchema as V, newConversationEventSchema as W, usageSchema as Y, conversationParamsSchema as _, cancelConversationPendingMessagesBodySchema as a, conversationPendingMessageSchema as b, conversationAttachmentParamsSchema as c, conversationDetailReportSchema as d, conversationEventHistorySchema as f, conversationFeedSchema as g, conversationFeedQuerySchema as h, archiveConversationResponseSchema as i, automationCardSchema as j, messageCardText as k, conversationAuxiliaryCostsSchema as l, conversationEventsQuerySchema as m, actorIdentitySchema as n, cancelConversationPendingMessagesResponseSchema as o, conversationEventPageSchema as p, instructionProvenanceFor as q, archiveConversationBodySchema as r, conversationActivityPreviewSchema as s, acceptedConversationMessageSchema as t, conversationDetailQuerySchema as u, conversationPendingAuthorizationSchema as v, conversationStatsItemSchema as w, conversationPendingMessagesReportSchema as x, conversationPendingMessageDeliverySchema as y, conversationEventDataSchema as z };
@@ -1,4 +1,4 @@
1
- import { f as logWarn } from "./logging-D2YJv_PA.js";
1
+ import { f as logWarn } from "./logging-qmsMdU0y.js";
2
2
  import { AsyncLocalStorage } from "node:async_hooks";
3
3
  //#region src/chat/conversation-privacy.ts
4
4
  const SAFE_METADATA_KEY_LIMIT = 20;
@@ -1,28 +1,28 @@
1
- import { N as getMcpProviderErrorAttributes, X as createUserTokenStore, a as deleteMcpAuthSession, d as putMcpStoredOAuthCredentials, h as resolvePluginOAuthAccount, i as finalizeMcpAuthorization, l as getMcpAuthSession, u as getMcpStoredOAuthCredentials, y as lookupSlackUserProfile } from "./agent-CFrfUdN5.js";
2
- import { m as escapeXml } from "./client-DIe9JhwF.js";
3
- import { L as toOptionalString, S as withLogContext, d as logInfo, f as logWarn, m as runBestEffort, u as logException, y as setTags } from "./logging-D2YJv_PA.js";
4
- import { a as getChatConfig, h as normalizeSlackEmojiName, n as botConfig, o as getRuntimeMetadata } from "./config-0_JixokJ.js";
1
+ import { N as getMcpProviderErrorAttributes, X as createUserTokenStore, a as deleteMcpAuthSession, d as putMcpStoredOAuthCredentials, h as resolvePluginOAuthAccount, i as finalizeMcpAuthorization, l as getMcpAuthSession, u as getMcpStoredOAuthCredentials, y as lookupSlackUserProfile } from "./agent-7kKtDe-6.js";
2
+ import { m as escapeXml } from "./client-CcSboWx_.js";
3
+ import { L as toOptionalString, S as withLogContext, d as logInfo, f as logWarn, m as runBestEffort, u as logException, y as setTags } from "./logging-qmsMdU0y.js";
4
+ import { a as getChatConfig, h as normalizeSlackEmojiName, n as botConfig, o as getRuntimeMetadata } from "./config-CGYv-YPE.js";
5
5
  import { n as defaultModelId } from "./model-profile-CZmVoGdX.js";
6
6
  import { _ as parseSlackMessageTs, g as parseSlackUserId, l as isUserActor, s as createSlackResumeActor } from "./context-Bplcgypl.js";
7
- import { G as isDmChannel, H as getHeaderString, K as normalizeSlackConversationId, Kt as getSqlExecutor, Nt as buildSentryConversationUrl, U as getSlackClient, Wt as getConversationStore, cn as upsertLinkedIdentity, dn as requireSlackDestination, mt as getDashboardConversationLink, o as getPluginSlackConversationLink, sn as upsertIdentity, z as SlackActionError } from "./agent-hooks-kjLDY-Aa.js";
7
+ import { G as isDmChannel, H as getHeaderString, K as normalizeSlackConversationId, Kt as getSqlExecutor, Nt as buildSentryConversationUrl, U as getSlackClient, Wt as getConversationStore, cn as upsertLinkedIdentity, dn as requireSlackDestination, mt as getDashboardConversationLink, o as getPluginSlackConversationLink, sn as upsertIdentity, z as SlackActionError } from "./agent-hooks-DkriF84n.js";
8
8
  import { i as homeDir } from "./package-discovery-7a9YqLhE.js";
9
- import { n as buildOAuthTokenRequest, r as parseOAuthTokenResponse, u as hasRequiredOAuthScope } from "./registry-Bp0kd2xe.js";
10
- import { n as pluginCatalogRuntime } from "./catalog-runtime-D1v0KsgY.js";
11
- import { t as discoverSkills } from "./skills-D1otDVYp.js";
12
- import { B as recordAuthenticationLinked, F as loadProjection, V as recordAuthorizationCompleted, Y as hydrateConversationMessages, ct as recordDeliveredAssistantMessage, d as persistWithRetry, i as abandonTurnRecord, j as commitAcceptedReply, lt as turnHasReply, m as buildTurnErrorResponse, n as loadTurnCheckpoint, o as failTurnRecord, ot as markConversationMessage, r as saveTurnCheckpoint, s as getTurnRecord, tt as buildConversationContext, u as recordTurnSummary } from "./checkpoint-B2-uc-1h.js";
13
- import { E as acquireActiveLock, w as getStateAdapter } from "./profile-C3TEFAVI.js";
14
- import { Pt as requestConversationWork, c as parseSlackThreadId, d as resolveSlackChannelIdFromThreadId, l as readSlackRawMessageContext, u as resolveSlackChannelIdFromMessage, wt as ensureConversationWake } from "./stats-BfUFTUrM.js";
15
- import { a as isPendingAuthLatestRequest, f as CooperativeTurnYieldError, g as isCooperativeTurnYieldError, i as getConversationPendingAuth, r as clearPendingAuth, s as getAssistantReplyText, x as markTurnFailed } from "./pending-auth-DuSNoTpn.js";
16
- import { a as parseOAuthStatePayload, c as escapeSlackMrkdwnText, d as normalizeSlackStatusText, f as truncateStatusText, g as removeReactionFromMessage, h as postSlackMessage, i as formatProviderLabel, l as formatSlackLink, o as resolveBaseUrl, p as addReactionToMessage, u as normalizeSlackReplyMarkdown, v as RetryableDeliveryError } from "./agent-runner-DMMa36Zl.js";
9
+ import { n as buildOAuthTokenRequest, r as parseOAuthTokenResponse, u as hasRequiredOAuthScope } from "./registry-DGyQCsiy.js";
10
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-XH_LFA_7.js";
11
+ import { t as discoverSkills } from "./skills-BoS3b8cg.js";
12
+ import { B as recordAuthenticationLinked, F as loadProjection, V as recordAuthorizationCompleted, Y as hydrateConversationMessages, ct as recordDeliveredAssistantMessage, d as persistWithRetry, i as abandonTurnRecord, j as commitAcceptedReply, lt as turnHasReply, m as buildTurnErrorResponse, n as loadTurnCheckpoint, o as failTurnRecord, ot as markConversationMessage, r as saveTurnCheckpoint, s as getTurnRecord, tt as buildConversationContext, u as recordTurnSummary } from "./checkpoint-CRod8es5.js";
13
+ import { E as acquireActiveLock, w as getStateAdapter } from "./profile-DbG8AlNd.js";
14
+ import { Pt as requestConversationWork, c as parseSlackThreadId, d as resolveSlackChannelIdFromThreadId, l as readSlackRawMessageContext, u as resolveSlackChannelIdFromMessage, wt as ensureConversationWake } from "./stats-qUXQZq-w.js";
15
+ import { a as isPendingAuthLatestRequest, f as CooperativeTurnYieldError, g as isCooperativeTurnYieldError, i as getConversationPendingAuth, r as clearPendingAuth, s as getAssistantReplyText, x as markTurnFailed } from "./pending-auth-_1Ry-_Bw.js";
16
+ import { a as parseOAuthStatePayload, c as escapeSlackMrkdwnText, d as normalizeSlackStatusText, f as truncateStatusText, g as removeReactionFromMessage, h as postSlackMessage, i as formatProviderLabel, l as formatSlackLink, o as resolveBaseUrl, p as addReactionToMessage, u as normalizeSlackReplyMarkdown, v as RetryableDeliveryError } from "./agent-runner-D0ImXS7U.js";
17
17
  import { t as getVercelConversationWorkQueue } from "./vercel-queue-DIkVcfK4.js";
18
- import { a as getTurnRequestDeadline } from "./job-queue-B1k3woMW.js";
19
- import { i as resolveTurnSessionRouting, n as scheduleSessionCompletedPluginTasks } from "./task-runner-6tzKHNbM.js";
20
- import { n as getTurnLifecycle } from "./turn-lifecycle-CxAtVANu.js";
21
- import { n as executeTurn, t as AgentRunError } from "./turn-execution-eVhqozjK.js";
22
- import { c as configValueSchema, n as getPersistedSandboxState, o as persistThreadStateById, r as getPersistedThreadState, s as coerceThreadConversationState, t as getLocationConfigurationService } from "./thread-state-CD_fsyrM.js";
23
- import { a as requireTurnFailureEventId, c as getTurnUserMessageId, d as buildDeliveredTurnStatePatch, l as getTurnUserReplyAttachmentContext, n as persistAuthPauseTurnState, o as getInterruptionMarker, r as finalizeFailedTurnReplyWithEvent, s as getTurnUserMessage, u as getTurnUserSlackMessageTs } from "./auth-pause-state-TdhAyYM4.js";
18
+ import { a as getTurnRequestDeadline } from "./job-queue-_8gxwDzt.js";
19
+ import { i as resolveTurnSessionRouting, n as scheduleSessionCompletedPluginTasks } from "./task-runner-4rCppQMo.js";
20
+ import { n as getTurnLifecycle } from "./turn-lifecycle-f-y0Irpi.js";
21
+ import { n as executeTurn, t as AgentRunError } from "./turn-execution--F7a9kEU.js";
22
+ import { c as configValueSchema, n as getPersistedSandboxState, o as persistThreadStateById, r as getPersistedThreadState, s as coerceThreadConversationState, t as getLocationConfigurationService } from "./thread-state-2Paza8DV.js";
23
+ import { a as requireTurnFailureEventId, c as getTurnUserMessage, d as getTurnUserSlackMessageTs, f as buildDeliveredTurnStatePatch, l as getTurnUserMessageId, n as persistAuthPauseTurnState, o as getInterruptionMarker, r as finalizeFailedTurnReplyWithEvent, s as loadPendingMessageCards, u as getTurnUserReplyAttachmentContext } from "./auth-pause-state-3OT67TA8.js";
24
24
  import { n as relayLocalOAuthCallback } from "./oauth-relay-CdCnu80W.js";
25
- import { n as deleteWebAuthorization } from "./web-authorization-Dq2NDhY0.js";
25
+ import { n as deleteWebAuthorization } from "./web-authorization-BdfOkTuG.js";
26
26
  import path from "node:path";
27
27
  import { z } from "zod";
28
28
  import { createHmac, createSecretKey, timingSafeEqual } from "node:crypto";
@@ -348,6 +348,65 @@ function createSlackWebApiAssistantStatusSession(args) {
348
348
  });
349
349
  }
350
350
  //#endregion
351
+ //#region src/chat/slack/automation-card.ts
352
+ function preview(text, length) {
353
+ const compact = text.replace(/\s+/g, " ").trim();
354
+ return compact.length > length ? `${compact.slice(0, length - 1)}…` : compact;
355
+ }
356
+ /** Show an Automation as a native Work Object, not an operation receipt. */
357
+ function renderSlackAutomationCard(card) {
358
+ const title = preview(card.title, 160);
359
+ const trigger = preview(card.trigger, 500);
360
+ const warning = card.warning ? preview(card.warning, 500) : null;
361
+ const text = [
362
+ card.url ? formatSlackLink(card.url, title) : escapeSlackMrkdwnText(title),
363
+ escapeSlackMrkdwnText(trigger),
364
+ warning ? escapeSlackMrkdwnText(warning) : null
365
+ ].filter(Boolean).join("\n");
366
+ if (!card.url) return {
367
+ entity: null,
368
+ text
369
+ };
370
+ return {
371
+ text,
372
+ entity: {
373
+ entity_type: "slack#/entities/item",
374
+ external_ref: {
375
+ id: card.id,
376
+ type: "automation"
377
+ },
378
+ url: card.url,
379
+ entity_payload: {
380
+ attributes: {
381
+ title: { text: title },
382
+ display_type: "Automation"
383
+ },
384
+ custom_fields: [{
385
+ key: "trigger",
386
+ label: "When",
387
+ type: "string",
388
+ value: trigger,
389
+ long: true
390
+ }, ...warning ? [{
391
+ key: "warning",
392
+ label: "Needs attention",
393
+ type: "string",
394
+ value: warning,
395
+ long: true
396
+ }] : []]
397
+ }
398
+ }
399
+ };
400
+ }
401
+ //#endregion
402
+ //#region src/chat/slack/cards.ts
403
+ /** Select the Slack object renderer for a built-in card. */
404
+ function renderSlackCard(card) {
405
+ switch (card.kind) {
406
+ case "automation": return renderSlackAutomationCard(card);
407
+ }
408
+ }
409
+ //#endregion
351
410
  //#region src/chat/slack/footer.ts
352
411
  /** Render compact reply attribution for the Slack footer. */
353
412
  function formatReplyAttribution(attribution) {
@@ -377,11 +436,10 @@ function buildSlackReplyFooter(args) {
377
436
  }
378
437
  /** Build Slack blocks for a reply chunk using the Slack-flavored markdown block for the body. */
379
438
  function buildSlackReplyBlocks(text, footer) {
380
- if (!text.trim()) return;
381
- const blocks = [{
439
+ const blocks = text.trim() ? [{
382
440
  type: "markdown",
383
441
  text
384
- }];
442
+ }] : [];
385
443
  if (footer && (footer.attribution || footer.items.length > 0)) {
386
444
  const attributionElements = footer.attribution ? [{
387
445
  type: "plain_text",
@@ -395,7 +453,7 @@ function buildSlackReplyBlocks(text, footer) {
395
453
  }))]
396
454
  });
397
455
  }
398
- return blocks;
456
+ return blocks.length ? blocks : void 0;
399
457
  }
400
458
  //#endregion
401
459
  //#region src/chat/slack/output.ts
@@ -580,22 +638,47 @@ function buildSlackOutputMessage(text) {
580
638
  * context, and posts through the shared Slack outbound boundary.
581
639
  */
582
640
  async function sendSlackReply(args) {
583
- const chunks = splitSlackReplyText(args.text);
641
+ const posts = splitSlackReplyText(args.text).map((text) => ({
642
+ text,
643
+ cards: []
644
+ }));
645
+ const cards = (args.cards ?? []).map(renderSlackCard);
646
+ for (let index = 0; index < cards.length; index += 5) {
647
+ const group = cards.slice(index, index + 5);
648
+ const lastPost = posts.at(-1);
649
+ if (index === 0 && lastPost) lastPost.cards = group;
650
+ else posts.push({
651
+ text: "",
652
+ cards: group
653
+ });
654
+ }
584
655
  const footer = buildSlackReplyFooter({
585
656
  conversationId: args.conversationId,
586
657
  replyAttribution: args.replyAttribution
587
658
  });
588
659
  const messageTs = [];
589
660
  let threadTs = args.threadTs;
590
- for (const [index, text] of chunks.entries()) {
591
- const isFinalChunk = index === chunks.length - 1;
592
- const blocks = buildSlackReplyBlocks(text, isFinalChunk ? footer : void 0);
593
- const fallbackText = isFinalChunk && args.replyAttribution ? `${text}\n\n${escapeSlackMrkdwnText(formatReplyAttribution(args.replyAttribution))}` : text;
661
+ for (const [index, post] of posts.entries()) {
662
+ const { text, cards } = post;
663
+ const isFinalChunk = index === posts.length - 1;
664
+ const blocks = buildSlackReplyBlocks(text, void 0) ?? [];
665
+ for (const card of cards) if (!card.entity) blocks.push({
666
+ type: "section",
667
+ text: {
668
+ type: "mrkdwn",
669
+ text: card.text
670
+ }
671
+ });
672
+ if (isFinalChunk || !text.trim()) blocks.push(...buildSlackReplyBlocks("", footer) ?? []);
673
+ const entities = cards.flatMap((card) => card.entity ? [card.entity] : []);
674
+ const accessibleText = [text, ...cards.map((card) => card.text)].filter(Boolean).join("\n\n");
675
+ const fallbackText = isFinalChunk && args.replyAttribution ? `${accessibleText}\n\n${escapeSlackMrkdwnText(formatReplyAttribution(args.replyAttribution))}` : accessibleText;
594
676
  const response = await postSlackMessage({
595
677
  channelId: args.channelId,
596
678
  threadTs,
597
679
  text: fallbackText,
598
- ...blocks ? { blocks } : void 0
680
+ ...blocks.length ? { blocks } : void 0,
681
+ ...entities.length ? { entities } : void 0
599
682
  });
600
683
  if (response.ts) {
601
684
  messageTs.push(response.ts);
@@ -828,6 +911,14 @@ function buildAuthPauseResponse(slackUserId, providerDisplayName, requestText) {
828
911
  }
829
912
  //#endregion
830
913
  //#region src/chat/providers/slack/resume.ts
914
+ /**
915
+ * Resume a Slack Turn from saved Run state.
916
+ *
917
+ * Resumed Turns load their saved Run while holding the Slack thread lock.
918
+ * Status notices are best effort. Completed assistant replies and
919
+ * authorization pause notices use `sendSlackReply` so the footer stays
920
+ * consistent.
921
+ */
831
922
  function resolveReplyTimeoutMs() {
832
923
  const raw = process.env.EVAL_AGENT_REPLY_TIMEOUT_MS?.trim();
833
924
  if (!raw) return;
@@ -1103,11 +1194,13 @@ async function resumeSlackTurnInContext(args) {
1103
1194
  const text = typeof reply === "string" ? reply : getAssistantReplyText(reply);
1104
1195
  if (!text?.trim()) return;
1105
1196
  failureCode = "delivery_failed";
1197
+ const cards = await loadPendingMessageCards(conversationId);
1106
1198
  const deliveryState = await getDeliveryConversation();
1107
1199
  let slackMessageTs = [];
1108
1200
  try {
1109
1201
  const outcomes = runArgs.run?.dispatch?.outcomes;
1110
1202
  if (outcomes) for (const outcome of outcomes) slackMessageTs.push(...await sendSlackReply({
1203
+ cards,
1111
1204
  channelId: outcome.destination.channelId,
1112
1205
  conversationId: runArgs.conversationId,
1113
1206
  replyAttribution: runArgs.run?.dispatch?.replyAttribution,
@@ -1115,6 +1208,7 @@ async function resumeSlackTurnInContext(args) {
1115
1208
  threadTs: outcome.destination.threadTs
1116
1209
  }));
1117
1210
  else slackMessageTs = await sendSlackReply({
1211
+ cards,
1118
1212
  channelId: runArgs.channelId,
1119
1213
  conversationId: runArgs.conversationId,
1120
1214
  replyAttribution: runArgs.run?.dispatch?.replyAttribution,
@@ -1129,6 +1223,7 @@ async function resumeSlackTurnInContext(args) {
1129
1223
  assistantMessageDelivered = true;
1130
1224
  acceptedDeliveryId = messageTs;
1131
1225
  const recordedMessageId = recordDeliveredAssistantMessage({
1226
+ cards,
1132
1227
  conversation: deliveryState.conversation,
1133
1228
  sessionId: deliveryState.sessionId,
1134
1229
  source: "slack",
@@ -1,6 +1,6 @@
1
- import { f as logWarn } from "./logging-D2YJv_PA.js";
2
- import { Gt as getDb, nn as agentTurnTotalTokens, tn as agentTurnCostUsd } from "./agent-hooks-kjLDY-Aa.js";
3
- import { E as juniorConversations, s as juniorAutomationExecutions } from "./executor-CmZKtNpH.js";
1
+ import { f as logWarn } from "./logging-qmsMdU0y.js";
2
+ import { Gt as getDb, nn as agentTurnTotalTokens, tn as agentTurnCostUsd } from "./agent-hooks-DkriF84n.js";
3
+ import { E as juniorConversations, s as juniorAutomationExecutions } from "./executor-BLBZ-UB8.js";
4
4
  import { and, asc, count, desc, eq, gte, inArray, lte, max, or, sql } from "drizzle-orm";
5
5
  //#region src/api/conversations/aggregate.ts
6
6
  function usageTokenValue(source, field) {
@@ -1,5 +1,5 @@
1
1
  import { g as startSpanManual } from "./sentry-CgWZM_kV.js";
2
- import "./config-0_JixokJ.js";
2
+ import "./config-CGYv-YPE.js";
3
3
  import { n as juniorDestinations, r as timestamptz } from "./destinations-BeBiJeEM.js";
4
4
  import { AsyncLocalStorage } from "node:async_hooks";
5
5
  import { getTableColumns, sql } from "drizzle-orm";
@@ -1,4 +1,19 @@
1
1
  import { z } from "zod";
2
+ //#region src/chat/conversations/cards.d.ts
3
+ /** Built-in response types accepted by Message storage and delivery. */
4
+ declare const messageCardSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
5
+ kind: z.ZodLiteral<"automation">;
6
+ id: z.ZodString;
7
+ title: z.ZodString;
8
+ url: z.ZodNullable<z.ZodString>;
9
+ instruction: z.ZodString;
10
+ trigger: z.ZodString;
11
+ warning: z.ZodNullable<z.ZodString>;
12
+ }, z.core.$strict>], "kind">;
13
+ type MessageCard = z.output<typeof messageCardSchema>;
14
+ /** Render each built-in card with its own text format. */
15
+ declare function messageCardText(card: MessageCard): string;
16
+ //#endregion
2
17
  //#region src/chat/conversations/history.d.ts
3
18
  /** Where a failed turn stopped. */
4
19
  declare const conversationTurnFailureCodeSchema: z.ZodEnum<{
@@ -29,4 +44,4 @@ declare const conversationTurnFailureReasonSchema: z.ZodEnum<{
29
44
  suppressed_output: "suppressed_output";
30
45
  }>;
31
46
  //#endregion
32
- export { conversationTurnFailureReasonSchema as n, conversationTurnFailureCodeSchema as t };
47
+ export { messageCardText as i, conversationTurnFailureReasonSchema as n, MessageCard as r, conversationTurnFailureCodeSchema as t };
@@ -1,6 +1,6 @@
1
- import { M as getDeploymentServiceVersion, N as getDeploymentTelemetryAttributes } from "./logging-D2YJv_PA.js";
1
+ import { M as getDeploymentServiceVersion, N as getDeploymentTelemetryAttributes } from "./logging-qmsMdU0y.js";
2
2
  import { _ as vercelAIIntegration, a as getClient, b as withStreamedSpan, c as init, o as getGlobalScope } from "./sentry-CgWZM_kV.js";
3
- import { n as getCurrentConversationPrivacy } from "./conversation-privacy-6NLCEkzx.js";
3
+ import { n as getCurrentConversationPrivacy } from "./conversation-privacy-BGjdDVWD.js";
4
4
  import { t as consumePrivateTraceResultMarker } from "./private-trace-result-BLvBjy_e.js";
5
5
  //#region src/chat/sentry-payload-filter.ts
6
6
  const PAYLOAD_ATTRIBUTE_KEYS = /* @__PURE__ */ new Set([
@@ -1,4 +1,4 @@
1
- import { a as getChatConfig } from "./config-0_JixokJ.js";
1
+ import { a as getChatConfig } from "./config-CGYv-YPE.js";
2
2
  import { a as signQueueMessage, i as QUEUE_SIGNATURE_MAX_AGE_MS, o as verifyQueueMessage, s as createVercelQueueClient } from "./vercel-queue-DIkVcfK4.js";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
4
  import { z } from "zod";
@@ -1,5 +1,5 @@
1
1
  import { d as setTag, f as setUser, h as startSpan, i as getActiveSpan, l as logger, n as captureMessage, p as spanToJSON, s as getTraceData, t as captureException, y as withScope } from "./sentry-CgWZM_kV.js";
2
- import { t as JUNIOR_VERSION } from "./version-C8XFxpkQ.js";
2
+ import { t as JUNIOR_VERSION } from "./version-BydrOZMQ.js";
3
3
  import path from "node:path";
4
4
  import { styleText } from "node:util";
5
5
  import { ConfigError, configureSync, getConfig, getLogger } from "@logtape/logtape";
package/dist/nitro.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as JuniorDashboardOptions } from "./app-BYD2Nyji.js";
1
+ import { n as JuniorDashboardOptions } from "./app-C0zbsnr7.js";
2
2
  import { n as JuniorPluginSet } from "./plugins-BT2l4We3.js";
3
3
  //#region src/nitro.d.ts
4
4
  export type JuniorNitroDashboardOptions = JuniorDashboardOptions;
package/dist/nitro.js CHANGED
@@ -1,9 +1,9 @@
1
- import { A as JUNIOR_WORKSPACE_SNAPSHOT_JOB_CALLBACK_ROUTE, D as JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE, E as JUNIOR_HEARTBEAT_ROUTE, O as JUNIOR_RETENTION_CRON_SCHEDULE, T as JUNIOR_HEARTBEAT_CRON_SCHEDULE, k as JUNIOR_RETENTION_ROUTE, w as JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE } from "./logging-D2YJv_PA.js";
1
+ import { A as JUNIOR_WORKSPACE_SNAPSHOT_JOB_CALLBACK_ROUTE, D as JUNIOR_PLUGIN_TASK_CALLBACK_ROUTE, E as JUNIOR_HEARTBEAT_ROUTE, O as JUNIOR_RETENTION_CRON_SCHEDULE, T as JUNIOR_HEARTBEAT_CRON_SCHEDULE, k as JUNIOR_RETENTION_ROUTE, w as JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE } from "./logging-qmsMdU0y.js";
2
2
  import { d as resolvePackageDir, t as discoverInstalledPluginPackageContent, u as isValidPackageName } from "./package-discovery-7a9YqLhE.js";
3
3
  import { n as resolveConversationWorkQueueTopic } from "./vercel-queue-DIkVcfK4.js";
4
- import { t as WORKSPACE_SNAPSHOT_JOB_QUEUE_TOPIC } from "./job-queue-B1k3woMW.js";
4
+ import { t as WORKSPACE_SNAPSHOT_JOB_QUEUE_TOPIC } from "./job-queue-_8gxwDzt.js";
5
5
  import { a as pluginRuntimeRegistrationsFromPluginSet, r as pluginCatalogConfigFromPluginSet } from "./plugins-egKWjgue.js";
6
- import { t as PLUGIN_TASK_QUEUE_TOPIC } from "./task-queue-VdYCCwO0.js";
6
+ import { t as PLUGIN_TASK_QUEUE_TOPIC } from "./task-queue-Di_q8922.js";
7
7
  import { n as loadPluginSetFromModule, r as resolvePluginModule } from "./plugin-module-BKGOXca2.js";
8
8
  import path from "node:path";
9
9
  import { cpSync, existsSync, mkdirSync, readdirSync, statSync } from "node:fs";
@@ -1,5 +1,5 @@
1
- import { X as createUserTokenStore } from "./agent-CFrfUdN5.js";
2
- import { a as GET, n as syncLocalOAuthCredential, r as GET$1 } from "./credential-sync-Dqg2o90r.js";
1
+ import { X as createUserTokenStore } from "./agent-7kKtDe-6.js";
2
+ import { a as GET, n as syncLocalOAuthCredential, r as GET$1 } from "./credential-sync-BfzGNruT.js";
3
3
  import { createServer } from "node:http";
4
4
  //#region src/chat/local/oauth-callback-server.ts
5
5
  const LOCAL_OAUTH_TIMEOUT_MS = 6e5;
@@ -1,5 +1,5 @@
1
- import { g as extractAssistantText, i as abandonTurnRecord } from "./checkpoint-B2-uc-1h.js";
2
- import { qt as buildDeterministicTurnId } from "./stats-BfUFTUrM.js";
1
+ import { g as extractAssistantText, i as abandonTurnRecord } from "./checkpoint-CRod8es5.js";
2
+ import { qt as buildDeterministicTurnId } from "./stats-qUXQZq-w.js";
3
3
  //#region src/chat/runtime/turn.ts
4
4
  /** Classified Slack turn failure carrying the owning Sentry capture outward. */
5
5
  var ConversationTurnBoundaryError = class extends Error {
@@ -1,7 +1,7 @@
1
- import { w as toOptionalTrimmed } from "./client-DIe9JhwF.js";
2
- import { _ as setSpanAttributes, v as setSpanStatus } from "./logging-D2YJv_PA.js";
3
- import { a as getChatConfig } from "./config-0_JixokJ.js";
4
- import { n as pluginCatalogRuntime } from "./catalog-runtime-D1v0KsgY.js";
1
+ import { w as toOptionalTrimmed } from "./client-CcSboWx_.js";
2
+ import { _ as setSpanAttributes, v as setSpanStatus } from "./logging-qmsMdU0y.js";
3
+ import { a as getChatConfig } from "./config-CGYv-YPE.js";
4
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-XH_LFA_7.js";
5
5
  import { createHash } from "node:crypto";
6
6
  import { createMemoryState } from "@chat-adapter/state-memory";
7
7
  import { createRedisState } from "@chat-adapter/state-redis";
@@ -1,4 +1,4 @@
1
- import { M as conversationBriefSchema, N as parseBriefInput, j as briefOutcomeStatusSchema } from "./conversation-BSRGzJmY.js";
1
+ import { F as conversationBriefSchema, I as parseBriefInput, P as briefOutcomeStatusSchema } from "./conversation-BBDt88di.js";
2
2
  import { z } from "zod";
3
3
  //#region src/chat/briefs/generate.ts
4
4
  const MAX_INPUT_CHARS = 6e4;
@@ -1,4 +1,4 @@
1
- import { _ as setSpanAttributes, d as logInfo, f as logWarn } from "./logging-D2YJv_PA.js";
1
+ import { _ as setSpanAttributes, d as logInfo, f as logWarn } from "./logging-qmsMdU0y.js";
2
2
  import { i as credentialUserSubjectId } from "./context-Bplcgypl.js";
3
3
  import { n as normalizePluginPackageNames, o as pluginRoots, t as discoverInstalledPluginPackageContent } from "./package-discovery-7a9YqLhE.js";
4
4
  import path from "node:path";