@sentry/junior 0.221.1 → 0.223.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-CY49A4pN.js → agent-Bzbf92vv.js} +97 -42
  2. package/dist/{agent-hooks-BnZBgDPe.js → agent-hooks-DZU5nsd1.js} +60 -15
  3. package/dist/{agent-runner-BC8iSAfE.js → agent-runner-2VQ9WhkG.js} +6 -5
  4. package/dist/api/schema.d.ts +209 -11
  5. package/dist/api/schema.js +4 -4
  6. package/dist/api.js +18 -515
  7. package/dist/{app-BYD2Nyji.d.ts → app-BbSD6EtD.d.ts} +1 -1
  8. package/dist/app.d.ts +1 -1
  9. package/dist/app.js +241 -39
  10. package/dist/{auth-pause-state-CJwPs1cT.js → auth-pause-state-Bn2vX4PA.js} +41 -7
  11. package/dist/{briefs-BSOhy23c.js → briefs-BJPfCrlT.js} +6 -6
  12. package/dist/{catalog-runtime-0oMD2jas.js → catalog-runtime-BthunUDD.js} +1 -1
  13. package/dist/{checkpoint-Bl47qAIY.js → checkpoint-Deu-OVb3.js} +11 -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-BrThxuRI.js → client-DjC6-6iU.js} +56 -6
  21. package/dist/{config-CEuC6CFj.js → config-CtoUVs72.js} +6 -7
  22. package/dist/{conversation-BSRGzJmY.js → conversation-1HUoZr2l.js} +75 -4
  23. package/dist/{conversation-privacy-aHn1OwXL.js → conversation-privacy-xS1t92xa.js} +1 -1
  24. package/dist/{credential-sync-Dht95TJQ.js → credential-sync-CKdXEUDO.js} +180 -31
  25. package/dist/{execution-stats-D9m2kmmg.js → execution-stats-CrXs9vSH.js} +3 -3
  26. package/dist/{executor-3IasVOqK.js → executor-AOhG9X1t.js} +1 -1
  27. package/dist/history-yaSjGMD_.d.ts +65 -0
  28. package/dist/instrumentation.js +2 -2
  29. package/dist/{job-queue-36liupTq.js → job-queue-CNd9cpIy.js} +1 -1
  30. package/dist/{logging-gR24QCo_.js → logging-DiN3o3nB.js} +1 -1
  31. package/dist/nitro.d.ts +1 -1
  32. package/dist/nitro.js +3 -3
  33. package/dist/{oauth-callback-server-BvNIWVA3.js → oauth-callback-server-Ca0VLUEw.js} +2 -2
  34. package/dist/{pending-auth-Cl4BsopG.js → pending-auth-D7vmttn_.js} +2 -2
  35. package/dist/{profile-VmUpQuOm.js → profile-BsNrw8lj.js} +4 -4
  36. package/dist/{prompt-BkaHwBW0.js → prompt-90miy8VV.js} +1 -1
  37. package/dist/{registry-BATk1X_v.js → registry-Dankt-Pl.js} +1 -1
  38. package/dist/reporting-window-DbUqng0P.js +229 -0
  39. package/dist/{resolve-Cf79l1H8.js → resolve-B38CpJe2.js} +2 -2
  40. package/dist/{runner-DNN4EPj_.js → runner-Ck5rEjCm.js} +21 -10
  41. package/dist/{sandbox-egress-signals-C-HUJW1G.js → sandbox-egress-signals-BOfFkvly.js} +1 -1
  42. package/dist/{schema-YPJXVcOW.js → schema-RpbW5Od2.js} +5 -128
  43. package/dist/{short-title-Cy3D8vg1.js → short-title-BHd_jUFX.js} +2 -2
  44. package/dist/{skills-DMQkR1Yu.js → skills-DbP4TDft.js} +2 -2
  45. package/dist/{spawn-BHk7RpYw.js → spawn-DzXc_PKO.js} +2 -2
  46. package/dist/{stats-8Bzht8zO.js → stats-pNGp3G5q.js} +56 -15
  47. package/dist/{task-queue-Cm4FhC0n.js → task-queue-Cy9y1foT.js} +3 -3
  48. package/dist/{task-runner-dQwOhCYs.js → task-runner-DI1FBJFJ.js} +8 -8
  49. package/dist/{thread-state-D0Ktlch_.js → thread-state-DXgxOYpZ.js} +5 -5
  50. package/dist/{turn-execution-BfLZfabf.js → turn-execution-BNOXrZ-M.js} +3 -3
  51. package/dist/{turn-lifecycle-D75pWL8e.js → turn-lifecycle-Bjf6y2GO.js} +1 -1
  52. package/dist/{validation-D5fdtuzG.js → validation-D5CIslEu.js} +1 -1
  53. package/dist/{version-DErORHQC.js → version-_ZQFlslB.js} +1 -1
  54. package/dist/version.js +1 -1
  55. package/dist/{web-authorization-IHMPbDay.js → web-authorization-6mmfS_o-.js} +1 -1
  56. package/dist/web-input-BJpWm6go.js +899 -0
  57. package/dist/{work-CaaSjlNk.js → work-DvIlJR3C.js} +9 -9
  58. package/dist/{worker-Eom9CfBl.js → worker-D1qidg-Y.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 +4 -4
  63. package/dist/history-ClE4toxe.d.ts +0 -32
  64. package/dist/reporting-schema-DosTN__Q.js +0 -105
  65. package/dist/web-input-DskRJhrK.js +0 -392
package/dist/cli/main.js CHANGED
@@ -25,7 +25,7 @@ async function runChat(argv, pluginSet) {
25
25
  return await (await import("./chat.js")).runChat(argv, void 0, { pluginSet });
26
26
  }
27
27
  async function runBriefs(argv) {
28
- return await (await import("../briefs-BSOhy23c.js")).runBriefs(argv);
28
+ return await (await import("../briefs-BJPfCrlT.js")).runBriefs(argv);
29
29
  }
30
30
  function topLevelCommand(argv) {
31
31
  return (argv[0] === "--" ? argv.slice(1) : argv)[0];
@@ -1,6 +1,6 @@
1
- import { Gt as getDb, bt as createPluginLogger, d as setPlugins, f as validatePlugins } from "../agent-hooks-BnZBgDPe.js";
2
- import { n as pluginCatalogRuntime } from "../catalog-runtime-0oMD2jas.js";
3
- import { n as validatePluginRegistrations, t as validatePluginEgressCredentialHooks } from "../validation-D5fdtuzG.js";
1
+ import { bt as createPluginLogger, d as setPlugins, f as validatePlugins, qt as getDb } from "../agent-hooks-DZU5nsd1.js";
2
+ import { n as pluginCatalogRuntime } from "../catalog-runtime-BthunUDD.js";
3
+ import { n as validatePluginRegistrations, t as validatePluginEgressCredentialHooks } from "../validation-D5CIslEu.js";
4
4
  import { a as pluginRuntimeRegistrationsFromPluginSet, i as pluginCliRegistrationsFromPluginSet, r as pluginCatalogConfigFromPluginSet } from "../plugins-egKWjgue.js";
5
5
  import { t as loadAppPluginSet } from "../plugin-module-BKGOXca2.js";
6
6
  import { stderr, stdout } from "node:process";
@@ -1,6 +1,6 @@
1
- import { n as pluginCatalogRuntime } from "../catalog-runtime-0oMD2jas.js";
2
- import { S as disconnectStateAdapter, t as create } from "../profile-VmUpQuOm.js";
3
- import { r as resolve } from "../resolve-Cf79l1H8.js";
1
+ import { n as pluginCatalogRuntime } from "../catalog-runtime-BthunUDD.js";
2
+ import { S as disconnectStateAdapter, t as create } from "../profile-BsNrw8lj.js";
3
+ import { r as resolve } from "../resolve-B38CpJe2.js";
4
4
  //#region src/cli/snapshot-create.ts
5
5
  const DEFAULT_RUNTIME = "node22";
6
6
  const DEFAULT_TIMEOUT_MS = 6e5;
@@ -1,6 +1,6 @@
1
- import { a as getChatConfig } from "../config-CEuC6CFj.js";
2
- import { t as createJuniorSqlExecutor } from "../executor-3IasVOqK.js";
3
- import { t as createPluginCatalogRuntime } from "../registry-BATk1X_v.js";
1
+ import { a as getChatConfig } from "../config-CtoUVs72.js";
2
+ import { t as createJuniorSqlExecutor } from "../executor-AOhG9X1t.js";
3
+ import { t as createPluginCatalogRuntime } from "../registry-Dankt-Pl.js";
4
4
  import { n as pluginCatalogConfigFromEnv, r as pluginCatalogConfigFromPluginSet, t as defineJuniorPlugins } from "../plugins-egKWjgue.js";
5
5
  import { t as loadAppPluginSet } from "../plugin-module-BKGOXca2.js";
6
6
  import { fileURLToPath } from "node:url";
@@ -1,5 +1,5 @@
1
- import { C as withSpan, f as logWarn, h as serializeGenAiAttribute, i as extractGenAiUsageAttributes, p as normalizeGenAiFinishReason, u as logException } from "./logging-gR24QCo_.js";
2
- import { a as toCanonicalInputMessage, n as getCurrentConversationPrivacy, o as toCanonicalOutputMessage, s as toGenAiMessagesTraceAttributes } from "./conversation-privacy-aHn1OwXL.js";
1
+ import { C as withSpan, f as logWarn, h as serializeGenAiAttribute, i as extractGenAiUsageAttributes, p as normalizeGenAiFinishReason, u as logException } from "./logging-DiN3o3nB.js";
2
+ import { a as toCanonicalInputMessage, n as getCurrentConversationPrivacy, o as toCanonicalOutputMessage, s as toGenAiMessagesTraceAttributes } from "./conversation-privacy-xS1t92xa.js";
3
3
  import { calculateCost, completeSimple, getEnvApiKey, getModels, registerApiProvider } from "@earendil-works/pi-ai/compat";
4
4
  import { stream as streamAnthropic, streamSimple as streamSimpleAnthropic } from "@earendil-works/pi-ai/api/anthropic-messages";
5
5
  import { createGatewayProvider } from "@ai-sdk/gateway";
@@ -304,6 +304,31 @@ registerApiProvider({
304
304
  const GATEWAY_PROVIDER = "vercel-ai-gateway";
305
305
  const GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh";
306
306
  const GATEWAY_MODEL_OVERRIDES = {
307
+ "anthropic/claude-opus-5.5": {
308
+ id: "anthropic/claude-opus-5.5",
309
+ name: "Claude Opus 5.5",
310
+ api: "anthropic-messages",
311
+ provider: GATEWAY_PROVIDER,
312
+ baseUrl: GATEWAY_BASE_URL,
313
+ reasoning: true,
314
+ input: ["text", "image"],
315
+ cost: {
316
+ input: 4,
317
+ output: 20,
318
+ cacheRead: .2,
319
+ cacheWrite: 5
320
+ },
321
+ contextWindow: 1e6,
322
+ maxTokens: 128e3,
323
+ thinkingLevelMap: {
324
+ xhigh: "xhigh",
325
+ max: "max"
326
+ },
327
+ compat: {
328
+ forceAdaptiveThinking: true,
329
+ supportsTemperature: false
330
+ }
331
+ },
307
332
  "xai/grok-4.5": {
308
333
  id: "xai/grok-4.5",
309
334
  name: "Grok 4.5",
@@ -321,6 +346,34 @@ const GATEWAY_MODEL_OVERRIDES = {
321
346
  contextWindow: 5e5,
322
347
  maxTokens: 5e5
323
348
  },
349
+ "openai/gpt-6-luna": {
350
+ id: "openai/gpt-6-luna",
351
+ name: "GPT-6 Luna",
352
+ api: "anthropic-messages",
353
+ provider: GATEWAY_PROVIDER,
354
+ baseUrl: GATEWAY_BASE_URL,
355
+ reasoning: true,
356
+ input: ["text", "image"],
357
+ cost: {
358
+ input: .1,
359
+ output: .5,
360
+ cacheRead: .01,
361
+ cacheWrite: .125,
362
+ tiers: [{
363
+ inputTokensAbove: 272e3,
364
+ input: .2,
365
+ output: .75,
366
+ cacheRead: .02,
367
+ cacheWrite: .25
368
+ }]
369
+ },
370
+ contextWindow: 105e4,
371
+ maxTokens: 128e3,
372
+ thinkingLevelMap: {
373
+ xhigh: "xhigh",
374
+ max: "max"
375
+ }
376
+ },
324
377
  "openai/gpt-6-astra": {
325
378
  id: "openai/gpt-6-astra",
326
379
  name: "GPT-6 Astra",
@@ -373,10 +426,7 @@ function embeddingCostUsd(modelId, inputTokens) {
373
426
  function extractText(message) {
374
427
  return (message.content ?? []).filter((part) => part.type === "text" && typeof part.text === "string").map((part) => part.text ?? "").join("").trim();
375
428
  }
376
- /**
377
- * Look up a gateway model by id. Junior-owned overrides let new gateway
378
- * models work before pi-ai publishes an updated bundled catalog.
379
- */
429
+ /** Resolve gateway models through local overrides, then Pi's bundled catalog. */
380
430
  function resolveGatewayModel(modelId) {
381
431
  const matched = GATEWAY_MODEL_OVERRIDES[modelId] ?? getModels(GATEWAY_PROVIDER).find((model) => model.id === modelId);
382
432
  if (!matched) throw new Error(`Unknown AI Gateway model id: ${modelId}`);
@@ -1,8 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
2
- import { o as resolveGatewayModel, w as toOptionalTrimmed } from "./client-BrThxuRI.js";
3
- import { f as logWarn } from "./logging-gR24QCo_.js";
2
+ import { o as resolveGatewayModel, w as toOptionalTrimmed } from "./client-DjC6-6iU.js";
3
+ import { f as logWarn } from "./logging-DiN3o3nB.js";
4
4
  import { c as TURN_REASONING_LEVELS, l as parseTurnReasoningLevel, o as modelProfileSchema } from "./model-profile-CZmVoGdX.js";
5
- import { getModel } from "@earendil-works/pi-ai/compat";
6
5
  //#region src/chat/slack/emoji.ts
7
6
  const SLACK_EMOJI_NAME_RE = /^(?:[a-z0-9_+-]+)(?:::(?:skin-tone-[2-6]))?$/;
8
7
  function normalizeSlackEmojiName(value) {
@@ -126,10 +125,10 @@ function parseCrossActorMidRunMode(rawValue) {
126
125
  throw new Error("JUNIOR_CROSS_ACTOR_MID_RUN_MODE must be follow_up or steer");
127
126
  }
128
127
  const DEFAULT_MODEL_ID = "xai/grok-4.5";
129
- const DEFAULT_FAST_MODEL_ID = getModel("vercel-ai-gateway", "openai/gpt-5.6-luna").id;
130
- const DEFAULT_GUARDIAN_MODEL_ID = getModel("vercel-ai-gateway", "openai/gpt-5.6-luna").id;
131
- const DEFAULT_HANDOFF_MODEL_ID = getModel("vercel-ai-gateway", "openai/gpt-5.6-sol").id;
132
- const DEFAULT_WEB_SEARCH_MODEL_ID = getModel("vercel-ai-gateway", "openai/gpt-5.6-luna").id;
128
+ const DEFAULT_FAST_MODEL_ID = resolveGatewayModel("openai/gpt-6-luna").id;
129
+ const DEFAULT_GUARDIAN_MODEL_ID = resolveGatewayModel("openai/gpt-6-luna").id;
130
+ const DEFAULT_HANDOFF_MODEL_ID = resolveGatewayModel("anthropic/claude-opus-5.5").id;
131
+ const DEFAULT_WEB_SEARCH_MODEL_ID = resolveGatewayModel("openai/gpt-6-luna").id;
133
132
  const DEFAULT_EMBEDDING_MODEL_ID = "openai/text-embedding-3-small";
134
133
  const DEFAULT_IMAGE_GENERATION_MODEL_ID = "google/gemini-3-pro-image";
135
134
  function validateGatewayModelId(raw) {
@@ -1,6 +1,6 @@
1
1
  import { c as TURN_REASONING_LEVELS, o as modelProfileSchema } from "./model-profile-CZmVoGdX.js";
2
2
  import { z } from "zod";
3
- import { actorSchema, codeChangeStateSchema, conversationAnnotationInputSchema, conversationEventPresentationSchema, conversationSidebarAnnotationSchema } from "@sentry/junior-plugin-api";
3
+ import { actorSchema, codeChangeStateSchema, conversationAnnotationInputSchema, conversationEventPresentationSchema, conversationSidebarAnnotationSchema, ownedObjectAnnotationSchema } from "@sentry/junior-plugin-api";
4
4
  //#region src/usage-schema.ts
5
5
  const usageCostSchema = z.object({
6
6
  input: z.number().finite().nonnegative().optional(),
@@ -574,6 +574,76 @@ 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, ownedObjectAnnotationSchema]);
603
+ const storedCardSchema = automationCardSchema.extend({ operation: z.enum([
604
+ "created",
605
+ "updated",
606
+ "deleted"
607
+ ]).optional() });
608
+ /** Read both stored formats while keeping new objects out of the legacy field. */
609
+ function readMessageCards(value) {
610
+ return [...storedCardSchema.array().parse(value.cards ?? []).flatMap(({ operation, ...card }) => operation === "deleted" ? [] : [card]), ...ownedObjectAnnotationSchema.array().parse(value.objectCards ?? [])];
611
+ }
612
+ /** Render each built-in card with its own text format. */
613
+ function messageCardText(card) {
614
+ switch (card.kind) {
615
+ case "object": return [
616
+ card.title,
617
+ card.label !== card.title ? card.label : void 0,
618
+ card.description,
619
+ card.status,
620
+ card.trigger,
621
+ card.warning,
622
+ card.url
623
+ ].filter(Boolean).join("\n");
624
+ case "automation": return automationCardText(card);
625
+ }
626
+ }
627
+ /** Deduplicate object cards across successful tool results. */
628
+ function messageCardKey(card) {
629
+ return card.kind === "object" ? JSON.stringify([card.plugin, card.key]) : JSON.stringify(["junior", card.id]);
630
+ }
631
+ /** Identify a deleted object whose pending card must be omitted. */
632
+ const messageCardRefSchema = z.object({
633
+ plugin: z.string().min(1),
634
+ key: z.string().min(1)
635
+ }).strict();
636
+ /** Copy saved annotation facts without storage timestamps for Message delivery. */
637
+ function annotationCard(annotation) {
638
+ const { createdAt: _createdAt, updatedAt: _updatedAt, ...value } = annotation;
639
+ return value.kind === "object" ? value : {
640
+ ...value,
641
+ kind: "object",
642
+ objectType: "item",
643
+ title: value.label
644
+ };
645
+ }
646
+ //#endregion
577
647
  //#region src/api/schema/conversation.ts
578
648
  const conversationReportStatusSchema = z.enum([
579
649
  "active",
@@ -766,6 +836,7 @@ const conversationReportMessageEventDataSchema = z.object({
766
836
  eventType: z.string().min(1).optional(),
767
837
  explicitMention: z.boolean().optional(),
768
838
  trustedSummary: z.string().min(1).optional(),
839
+ cards: z.array(messageCardSchema).optional(),
769
840
  text: z.string().optional(),
770
841
  redacted: z.literal(true).optional()
771
842
  }).strict().superRefine((data, context) => {
@@ -773,9 +844,9 @@ const conversationReportMessageEventDataSchema = z.object({
773
844
  code: "custom",
774
845
  message: "message content must be text or explicitly redacted"
775
846
  });
776
- if (data.redacted && data.actorIdentity) context.addIssue({
847
+ if (data.redacted && (data.actorIdentity || data.cards)) context.addIssue({
777
848
  code: "custom",
778
- message: "redacted messages must not expose actor identity"
849
+ message: "redacted messages must not expose actor identity or cards"
779
850
  });
780
851
  });
781
852
  const conversationReportMessageHandledEventDataSchema = z.object({
@@ -1162,4 +1233,4 @@ const conversationStatsReportSchema = z.object({
1162
1233
  windowStart: z.string()
1163
1234
  }).strict();
1164
1235
  //#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 };
1236
+ export { messageCardKey as A, agentHistoryItemSchema as B, conversationReportEventSchema as C, createConversationBodySchema as D, conversationSummaryReportSchema as E, briefLinkSchema as F, historyReplacementSchema as G, conversationTurnFailureCodeSchema as H, briefOutcomeStatusSchema as I, instructionActors as J, newConversationEventSchema as K, conversationBriefSchema as L, messageCardText as M, readMessageCards as N, createConversationMessageBodySchema as O, briefCodeChangeSchema as P, parseBriefInput as R, conversationReportEventDataSchema as S, conversationStatsReportSchema as T, conversationTurnFailureReasonSchema as U, conversationEventDataSchema as V, decodeStoredConversationEvent as W, sameActorIdentity as X, instructionProvenanceFor as Y, usageSchema as Z, 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, messageCardRefSchema as j, annotationCard as k, conversationAuxiliaryCostsSchema as l, conversationEventsQuerySchema as m, actorIdentitySchema as n, cancelConversationPendingMessagesResponseSchema as o, conversationEventPageSchema as p, contextProvenance 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, KNOWN_CONVERSATION_EVENT_TYPES as z };
@@ -1,4 +1,4 @@
1
- import { f as logWarn } from "./logging-gR24QCo_.js";
1
+ import { f as logWarn } from "./logging-DiN3o3nB.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-CY49A4pN.js";
2
- import { m as escapeXml } from "./client-BrThxuRI.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-gR24QCo_.js";
4
- import { a as getChatConfig, h as normalizeSlackEmojiName, n as botConfig, o as getRuntimeMetadata } from "./config-CEuC6CFj.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-Bzbf92vv.js";
2
+ import { m as escapeXml } from "./client-DjC6-6iU.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-DiN3o3nB.js";
4
+ import { a as getChatConfig, h as normalizeSlackEmojiName, n as botConfig, o as getRuntimeMetadata } from "./config-CtoUVs72.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-BnZBgDPe.js";
7
+ import { G as isDmChannel, H as getHeaderString, Jt as getSqlExecutor, K as normalizeSlackConversationId, Kt as getConversationStore, Nt as buildSentryConversationUrl, U as getSlackClient, ln as upsertIdentity, mt as getDashboardConversationLink, o as getPluginSlackConversationLink, pn as requireSlackDestination, un as upsertLinkedIdentity, z as SlackActionError } from "./agent-hooks-DZU5nsd1.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-BATk1X_v.js";
10
- import { n as pluginCatalogRuntime } from "./catalog-runtime-0oMD2jas.js";
11
- import { t as discoverSkills } from "./skills-DMQkR1Yu.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-Bl47qAIY.js";
13
- import { E as acquireActiveLock, w as getStateAdapter } from "./profile-VmUpQuOm.js";
14
- import { Pt as requestConversationWork, c as parseSlackThreadId, d as resolveSlackChannelIdFromThreadId, l as readSlackRawMessageContext, u as resolveSlackChannelIdFromMessage, wt as ensureConversationWake } from "./stats-8Bzht8zO.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-Cl4BsopG.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-BC8iSAfE.js";
9
+ import { n as buildOAuthTokenRequest, r as parseOAuthTokenResponse, u as hasRequiredOAuthScope } from "./registry-Dankt-Pl.js";
10
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-BthunUDD.js";
11
+ import { t as discoverSkills } from "./skills-DbP4TDft.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-Deu-OVb3.js";
13
+ import { E as acquireActiveLock, w as getStateAdapter } from "./profile-BsNrw8lj.js";
14
+ import { Pt as requestConversationWork, c as parseSlackThreadId, d as resolveSlackChannelIdFromThreadId, l as readSlackRawMessageContext, u as resolveSlackChannelIdFromMessage, wt as ensureConversationWake } from "./stats-pNGp3G5q.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-D7vmttn_.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-2VQ9WhkG.js";
17
17
  import { t as getVercelConversationWorkQueue } from "./vercel-queue-DIkVcfK4.js";
18
- import { a as getTurnRequestDeadline } from "./job-queue-36liupTq.js";
19
- import { i as resolveTurnSessionRouting, n as scheduleSessionCompletedPluginTasks } from "./task-runner-dQwOhCYs.js";
20
- import { n as getTurnLifecycle } from "./turn-lifecycle-D75pWL8e.js";
21
- import { n as executeTurn, t as AgentRunError } from "./turn-execution-BfLZfabf.js";
22
- import { c as configValueSchema, n as getPersistedSandboxState, o as persistThreadStateById, r as getPersistedThreadState, s as coerceThreadConversationState, t as getLocationConfigurationService } from "./thread-state-D0Ktlch_.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-CJwPs1cT.js";
18
+ import { a as getTurnRequestDeadline } from "./job-queue-CNd9cpIy.js";
19
+ import { i as resolveTurnSessionRouting, n as scheduleSessionCompletedPluginTasks } from "./task-runner-DI1FBJFJ.js";
20
+ import { n as getTurnLifecycle } from "./turn-lifecycle-Bjf6y2GO.js";
21
+ import { n as executeTurn, t as AgentRunError } from "./turn-execution-BNOXrZ-M.js";
22
+ import { c as configValueSchema, n as getPersistedSandboxState, o as persistThreadStateById, r as getPersistedThreadState, s as coerceThreadConversationState, t as getLocationConfigurationService } from "./thread-state-DXgxOYpZ.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-Bn2vX4PA.js";
24
24
  import { n as relayLocalOAuthCallback } from "./oauth-relay-CdCnu80W.js";
25
- import { n as deleteWebAuthorization } from "./web-authorization-IHMPbDay.js";
25
+ import { n as deleteWebAuthorization } from "./web-authorization-6mmfS_o-.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,119 @@ 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/object-card.ts
403
+ /** Render verified annotation facts as a native Task or Item preview. */
404
+ function renderSlackObjectCard(card, conversationId) {
405
+ if (card.objectType === "automation" && card.plugin === "junior") return renderSlackAutomationCard({
406
+ id: card.key,
407
+ title: card.title,
408
+ url: card.url,
409
+ trigger: card.trigger ?? "",
410
+ warning: card.warning ?? null
411
+ });
412
+ const title = card.title.slice(0, 160);
413
+ const text = [
414
+ card.url ? formatSlackLink(card.url, title) : escapeSlackMrkdwnText(title),
415
+ escapeSlackMrkdwnText(card.label),
416
+ card.status ? escapeSlackMrkdwnText(card.status) : null
417
+ ].filter(Boolean).join("\n");
418
+ if (!card.url) return {
419
+ entity: null,
420
+ text
421
+ };
422
+ const task = card.objectType === "task";
423
+ return {
424
+ text,
425
+ entity: {
426
+ entity_type: task ? "slack#/entities/task" : "slack#/entities/item",
427
+ external_ref: {
428
+ id: JSON.stringify([
429
+ conversationId,
430
+ card.plugin,
431
+ card.key
432
+ ]),
433
+ type: "annotation"
434
+ },
435
+ url: card.url,
436
+ entity_payload: {
437
+ attributes: {
438
+ title: { text: title },
439
+ display_id: card.label,
440
+ display_type: card.objectType === "code_change" ? "Pull request" : task ? "Issue" : "Item",
441
+ product_name: card.plugin
442
+ },
443
+ fields: task && card.status ? { status: { value: card.status } } : void 0,
444
+ custom_fields: !task && card.status ? [{
445
+ key: "status",
446
+ label: "Status",
447
+ type: "string",
448
+ value: card.status
449
+ }] : []
450
+ }
451
+ }
452
+ };
453
+ }
454
+ //#endregion
455
+ //#region src/chat/slack/cards.ts
456
+ /** Select the Slack object renderer for a built-in card. */
457
+ function renderSlackCard(card, conversationId) {
458
+ switch (card.kind) {
459
+ case "object": return renderSlackObjectCard(card, conversationId);
460
+ case "automation": return renderSlackAutomationCard(card);
461
+ }
462
+ }
463
+ //#endregion
351
464
  //#region src/chat/slack/footer.ts
352
465
  /** Render compact reply attribution for the Slack footer. */
353
466
  function formatReplyAttribution(attribution) {
@@ -377,11 +490,10 @@ function buildSlackReplyFooter(args) {
377
490
  }
378
491
  /** Build Slack blocks for a reply chunk using the Slack-flavored markdown block for the body. */
379
492
  function buildSlackReplyBlocks(text, footer) {
380
- if (!text.trim()) return;
381
- const blocks = [{
493
+ const blocks = text.trim() ? [{
382
494
  type: "markdown",
383
495
  text
384
- }];
496
+ }] : [];
385
497
  if (footer && (footer.attribution || footer.items.length > 0)) {
386
498
  const attributionElements = footer.attribution ? [{
387
499
  type: "plain_text",
@@ -395,7 +507,7 @@ function buildSlackReplyBlocks(text, footer) {
395
507
  }))]
396
508
  });
397
509
  }
398
- return blocks;
510
+ return blocks.length ? blocks : void 0;
399
511
  }
400
512
  //#endregion
401
513
  //#region src/chat/slack/output.ts
@@ -580,22 +692,47 @@ function buildSlackOutputMessage(text) {
580
692
  * context, and posts through the shared Slack outbound boundary.
581
693
  */
582
694
  async function sendSlackReply(args) {
583
- const chunks = splitSlackReplyText(args.text);
695
+ const posts = splitSlackReplyText(args.text).map((text) => ({
696
+ text,
697
+ cards: []
698
+ }));
699
+ const cards = (args.cards ?? []).map((card) => renderSlackCard(card, args.conversationId));
700
+ for (let index = 0; index < cards.length; index += 5) {
701
+ const group = cards.slice(index, index + 5);
702
+ const lastPost = posts.at(-1);
703
+ if (index === 0 && lastPost) lastPost.cards = group;
704
+ else posts.push({
705
+ text: "",
706
+ cards: group
707
+ });
708
+ }
584
709
  const footer = buildSlackReplyFooter({
585
710
  conversationId: args.conversationId,
586
711
  replyAttribution: args.replyAttribution
587
712
  });
588
713
  const messageTs = [];
589
714
  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;
715
+ for (const [index, post] of posts.entries()) {
716
+ const { text, cards } = post;
717
+ const isFinalChunk = index === posts.length - 1;
718
+ const blocks = buildSlackReplyBlocks(text, void 0) ?? [];
719
+ for (const card of cards) if (!card.entity) blocks.push({
720
+ type: "section",
721
+ text: {
722
+ type: "mrkdwn",
723
+ text: card.text
724
+ }
725
+ });
726
+ if (isFinalChunk || !text.trim()) blocks.push(...buildSlackReplyBlocks("", footer) ?? []);
727
+ const entities = cards.flatMap((card) => card.entity ? [card.entity] : []);
728
+ const accessibleText = [text, ...cards.map((card) => card.text)].filter(Boolean).join("\n\n");
729
+ const fallbackText = isFinalChunk && args.replyAttribution ? `${accessibleText}\n\n${escapeSlackMrkdwnText(formatReplyAttribution(args.replyAttribution))}` : accessibleText;
594
730
  const response = await postSlackMessage({
595
731
  channelId: args.channelId,
596
732
  threadTs,
597
733
  text: fallbackText,
598
- ...blocks ? { blocks } : void 0
734
+ ...blocks.length ? { blocks } : void 0,
735
+ ...entities.length ? { entities } : void 0
599
736
  });
600
737
  if (response.ts) {
601
738
  messageTs.push(response.ts);
@@ -828,6 +965,14 @@ function buildAuthPauseResponse(slackUserId, providerDisplayName, requestText) {
828
965
  }
829
966
  //#endregion
830
967
  //#region src/chat/providers/slack/resume.ts
968
+ /**
969
+ * Resume a Slack Turn from saved Run state.
970
+ *
971
+ * Resumed Turns load their saved Run while holding the Slack thread lock.
972
+ * Status notices are best effort. Completed assistant replies and
973
+ * authorization pause notices use `sendSlackReply` so the footer stays
974
+ * consistent.
975
+ */
831
976
  function resolveReplyTimeoutMs() {
832
977
  const raw = process.env.EVAL_AGENT_REPLY_TIMEOUT_MS?.trim();
833
978
  if (!raw) return;
@@ -1103,11 +1248,13 @@ async function resumeSlackTurnInContext(args) {
1103
1248
  const text = typeof reply === "string" ? reply : getAssistantReplyText(reply);
1104
1249
  if (!text?.trim()) return;
1105
1250
  failureCode = "delivery_failed";
1251
+ const cards = await loadPendingMessageCards(conversationId);
1106
1252
  const deliveryState = await getDeliveryConversation();
1107
1253
  let slackMessageTs = [];
1108
1254
  try {
1109
1255
  const outcomes = runArgs.run?.dispatch?.outcomes;
1110
1256
  if (outcomes) for (const outcome of outcomes) slackMessageTs.push(...await sendSlackReply({
1257
+ cards,
1111
1258
  channelId: outcome.destination.channelId,
1112
1259
  conversationId: runArgs.conversationId,
1113
1260
  replyAttribution: runArgs.run?.dispatch?.replyAttribution,
@@ -1115,6 +1262,7 @@ async function resumeSlackTurnInContext(args) {
1115
1262
  threadTs: outcome.destination.threadTs
1116
1263
  }));
1117
1264
  else slackMessageTs = await sendSlackReply({
1265
+ cards,
1118
1266
  channelId: runArgs.channelId,
1119
1267
  conversationId: runArgs.conversationId,
1120
1268
  replyAttribution: runArgs.run?.dispatch?.replyAttribution,
@@ -1129,6 +1277,7 @@ async function resumeSlackTurnInContext(args) {
1129
1277
  assistantMessageDelivered = true;
1130
1278
  acceptedDeliveryId = messageTs;
1131
1279
  const recordedMessageId = recordDeliveredAssistantMessage({
1280
+ cards,
1132
1281
  conversation: deliveryState.conversation,
1133
1282
  sessionId: deliveryState.sessionId,
1134
1283
  source: "slack",
@@ -2659,4 +2808,4 @@ async function receiveLocalOAuthCredential(request) {
2659
2808
  return new Response(null, { status: 204 });
2660
2809
  }
2661
2810
  //#endregion
2662
- export { isSlackTitlePermissionError as C, createSlackAdapterAssistantStatusSession as D, splitSlackReplyText as E, isRetryableSlackPostError as S, buildSlackOutputMessage as T, getThreadId as _, GET$1 as a, getSlackApiErrorCode as b, wakePausedTurn as c, shouldKeepProcessingReactionForToolInvocation as d, startProcessingReaction as f, getRunId as g, getMessageTs as h, publishAppHomeView as i, resumeSlackTurn as l, getChannelId as m, syncLocalOAuthCredential as n, createPausedTurns as o, getAssistantThreadContext as p, GET as r, getPausedTurnRequest as s, receiveLocalOAuthCredential as t, buildAuthPauseResponse as u, getThreadTs as v, sendSlackReply as w, getSlackErrorObservabilityAttributes as x, stripLeadingBotMention as y };
2811
+ export { isSlackTitlePermissionError as C, createSlackAdapterAssistantStatusSession as D, renderSlackObjectCard as E, isRetryableSlackPostError as S, buildSlackOutputMessage as T, getThreadId as _, GET$1 as a, getSlackApiErrorCode as b, wakePausedTurn as c, shouldKeepProcessingReactionForToolInvocation as d, startProcessingReaction as f, getRunId as g, getMessageTs as h, publishAppHomeView as i, resumeSlackTurn as l, getChannelId as m, syncLocalOAuthCredential as n, createPausedTurns as o, getAssistantThreadContext as p, GET as r, getPausedTurnRequest as s, receiveLocalOAuthCredential as t, buildAuthPauseResponse as u, getThreadTs as v, sendSlackReply as w, getSlackErrorObservabilityAttributes as x, stripLeadingBotMention as y };
@@ -1,6 +1,6 @@
1
- import { f as logWarn } from "./logging-gR24QCo_.js";
2
- import { Gt as getDb, nn as agentTurnTotalTokens, tn as agentTurnCostUsd } from "./agent-hooks-BnZBgDPe.js";
3
- import { E as juniorConversations, s as juniorAutomationExecutions } from "./executor-3IasVOqK.js";
1
+ import { f as logWarn } from "./logging-DiN3o3nB.js";
2
+ import { in as agentTurnTotalTokens, qt as getDb, rn as agentTurnCostUsd } from "./agent-hooks-DZU5nsd1.js";
3
+ import { E as juniorConversations, s as juniorAutomationExecutions } from "./executor-AOhG9X1t.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-CEuC6CFj.js";
2
+ import "./config-CtoUVs72.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";