@sentry/junior 0.104.2 → 0.106.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 (39) hide show
  1. package/dist/{agent-hooks-EOFSY2PD.js → agent-hooks-KR5BCWOK.js} +5 -5
  2. package/dist/api/conversations/schema.d.ts +13 -0
  3. package/dist/api/schema.d.ts +1 -1
  4. package/dist/api/schema.js +1 -1
  5. package/dist/api.js +76 -39
  6. package/dist/app.js +68 -17
  7. package/dist/chat/agent/request.d.ts +9 -0
  8. package/dist/chat/agent-dispatch/types.d.ts +2 -1
  9. package/dist/chat/config.d.ts +1 -0
  10. package/dist/chat/no-reply.d.ts +0 -2
  11. package/dist/chat/services/turn-limit.d.ts +6 -0
  12. package/dist/chat/services/turn-session-record.d.ts +0 -1
  13. package/dist/chat/slack/action-token.d.ts +6 -0
  14. package/dist/chat/slack/tools/public-search.d.ts +74 -0
  15. package/dist/chat/tools/definition.d.ts +2 -0
  16. package/dist/chat/tools/index.d.ts +2 -2
  17. package/dist/chat/tools/types.d.ts +3 -0
  18. package/dist/{chunk-CCTCIISK.js → chunk-3MPPVPGZ.js} +1 -1
  19. package/dist/{chunk-7G4J3CR7.js → chunk-3NYUCBLE.js} +1 -1
  20. package/dist/{chunk-U26ZWZCN.js → chunk-3OUSJPR7.js} +1 -1
  21. package/dist/{chunk-M3UAVLEN.js → chunk-4UYIRWDW.js} +2 -0
  22. package/dist/{chunk-QVTVCJR4.js → chunk-4W4O4DCV.js} +7 -7
  23. package/dist/{chunk-4PDVOHXP.js → chunk-AZ5OMSN5.js} +1 -1
  24. package/dist/{chunk-RMZ65YAA.js → chunk-BKM4UXUD.js} +21 -6
  25. package/dist/{chunk-AIRE7Q2W.js → chunk-CCFROYAV.js} +7 -0
  26. package/dist/{chunk-QDKRE3LS.js → chunk-DDRQ4U7I.js} +3 -3
  27. package/dist/{chunk-TMWUGGSA.js → chunk-GPPUTY5M.js} +327 -187
  28. package/dist/{chunk-RYDF4GOX.js → chunk-P4P7O5WG.js} +3 -3
  29. package/dist/{chunk-O7ILGCMJ.js → chunk-R5BFYK2O.js} +1 -1
  30. package/dist/{chunk-BCULHGZK.js → chunk-XTKJPSMF.js} +1 -1
  31. package/dist/{chunk-VDHMFCDY.js → chunk-ZMRLBBD5.js} +4 -4
  32. package/dist/cli/chat.js +13 -13
  33. package/dist/cli/plugins.js +5 -5
  34. package/dist/cli/snapshot-warmup.js +2 -2
  35. package/dist/cli/upgrade.js +6 -6
  36. package/dist/{db-PDMC67T3.js → db-S33LFWG2.js} +2 -2
  37. package/dist/{legacy-import-G333RHJZ.js → legacy-import-TMJISRKO.js} +3 -3
  38. package/dist/{runner-6A7MQRUE.js → runner-HA5XAL6K.js} +9 -9
  39. package/package.json +6 -6
@@ -11,13 +11,13 @@ import {
11
11
  getPlugins,
12
12
  setPlugins,
13
13
  validatePlugins
14
- } from "./chunk-VDHMFCDY.js";
15
- import "./chunk-4PDVOHXP.js";
14
+ } from "./chunk-ZMRLBBD5.js";
15
+ import "./chunk-AZ5OMSN5.js";
16
16
  import "./chunk-G3E7SCME.js";
17
- import "./chunk-CCTCIISK.js";
18
- import "./chunk-BCULHGZK.js";
17
+ import "./chunk-3MPPVPGZ.js";
18
+ import "./chunk-XTKJPSMF.js";
19
19
  import "./chunk-4ZNGQH7C.js";
20
- import "./chunk-M3UAVLEN.js";
20
+ import "./chunk-4UYIRWDW.js";
21
21
  import "./chunk-FXFQNHRU.js";
22
22
  import "./chunk-RT5BUHR5.js";
23
23
  import "./chunk-B7PUBQQM.js";
@@ -673,12 +673,24 @@ export declare const conversationStatsItemSchema: z.ZodObject<{
673
673
  costUsd: z.ZodOptional<z.ZodNumber>;
674
674
  tokens: z.ZodOptional<z.ZodNumber>;
675
675
  }, z.core.$strict>;
676
+ export declare const conversationMetricDaySchema: z.ZodObject<{
677
+ costUsd: z.ZodOptional<z.ZodNumber>;
678
+ date: z.ZodString;
679
+ durationMs: z.ZodNumber;
680
+ tokens: z.ZodOptional<z.ZodNumber>;
681
+ }, z.core.$strict>;
676
682
  export declare const conversationStatsReportSchema: z.ZodObject<{
677
683
  active: z.ZodNumber;
678
684
  conversations: z.ZodNumber;
679
685
  durationMs: z.ZodNumber;
680
686
  failed: z.ZodNumber;
681
687
  generatedAt: z.ZodString;
688
+ metricDays: z.ZodArray<z.ZodObject<{
689
+ costUsd: z.ZodOptional<z.ZodNumber>;
690
+ date: z.ZodString;
691
+ durationMs: z.ZodNumber;
692
+ tokens: z.ZodOptional<z.ZodNumber>;
693
+ }, z.core.$strict>>;
682
694
  locations: z.ZodArray<z.ZodObject<{
683
695
  active: z.ZodNumber;
684
696
  conversations: z.ZodNumber;
@@ -722,4 +734,5 @@ export type ConversationDetailReport = z.infer<typeof conversationDetailReportSc
722
734
  export type ConversationSubagentTranscriptReport = z.infer<typeof conversationSubagentTranscriptReportSchema>;
723
735
  export type ConversationFeed = z.infer<typeof conversationFeedSchema>;
724
736
  export type ConversationStatsItem = z.infer<typeof conversationStatsItemSchema>;
737
+ export type ConversationMetricDay = z.infer<typeof conversationMetricDaySchema>;
725
738
  export type ConversationStatsReport = z.infer<typeof conversationStatsReportSchema>;
@@ -1,7 +1,7 @@
1
1
  export { dailyConversationActivitySchema } from "./activity";
2
2
  export type { DailyConversationActivity } from "./activity";
3
3
  export { conversationDetailReportSchema, conversationFeedSchema, conversationStatsReportSchema, conversationSubagentTranscriptReportSchema, } from "./conversations/schema";
4
- export type { ActorIdentity, ConversationActivityReport, ConversationActivityStatus, ConversationContextEvent, ConversationCost, ConversationDetailReport, ConversationFeed, ConversationReportStatus, ConversationStatsItem, ConversationStatsReport, ConversationSubagentActivityReport, ConversationSubagentTranscriptReport, ConversationSummaryReport, ConversationSurface, ConversationToolActivityReport, ConversationUsage, TranscriptMessage, TranscriptPart, TranscriptPartType, TranscriptRole, } from "./conversations/schema";
4
+ export type { ActorIdentity, ConversationActivityReport, ConversationActivityStatus, ConversationContextEvent, ConversationCost, ConversationDetailReport, ConversationFeed, ConversationReportStatus, ConversationMetricDay, ConversationStatsItem, ConversationStatsReport, ConversationSubagentActivityReport, ConversationSubagentTranscriptReport, ConversationSummaryReport, ConversationSurface, ConversationToolActivityReport, ConversationUsage, TranscriptMessage, TranscriptPart, TranscriptPartType, TranscriptRole, } from "./conversations/schema";
5
5
  export { actorDirectoryReportSchema, actorProfileReportSchema, } from "./people/schema";
6
6
  export { locationActivityDayReportSchema, locationDetailReportSchema, locationDirectoryReportSchema, } from "./locations/schema";
7
7
  export type { LocationActorSummaryReport, LocationActivityDayReport, LocationDetailReport, LocationDirectoryReport, LocationSummaryReport, } from "./locations/schema";
@@ -14,7 +14,7 @@ import {
14
14
  locationParamsSchema,
15
15
  personParamsSchema,
16
16
  subagentParamsSchema
17
- } from "../chunk-AIRE7Q2W.js";
17
+ } from "../chunk-CCFROYAV.js";
18
18
  import {
19
19
  healthReportSchema,
20
20
  pluginOperationalReportFeedSchema,
package/dist/api.js CHANGED
@@ -13,14 +13,14 @@ import {
13
13
  locationParamsSchema,
14
14
  personParamsSchema,
15
15
  subagentParamsSchema
16
- } from "./chunk-AIRE7Q2W.js";
16
+ } from "./chunk-CCFROYAV.js";
17
17
  import {
18
18
  buildSentryConversationUrl,
19
19
  buildSentryTraceUrl,
20
20
  formatSlackConversationRedactedLabel,
21
21
  readHealthReport,
22
22
  resolveSlackConversationContextFromThreadId
23
- } from "./chunk-O7ILGCMJ.js";
23
+ } from "./chunk-R5BFYK2O.js";
24
24
  import {
25
25
  pluginOperationalReportFeedSchema,
26
26
  pluginReportsSchema,
@@ -31,10 +31,10 @@ import {
31
31
  listBoundedAgentTurnSessionSummariesForConversation,
32
32
  loadProjection,
33
33
  projectSteps
34
- } from "./chunk-QDKRE3LS.js";
35
- import "./chunk-RYDF4GOX.js";
34
+ } from "./chunk-DDRQ4U7I.js";
35
+ import "./chunk-P4P7O5WG.js";
36
36
  import "./chunk-PDO5BLNM.js";
37
- import "./chunk-CCTCIISK.js";
37
+ import "./chunk-3MPPVPGZ.js";
38
38
  import {
39
39
  getAgentStepStore,
40
40
  getConversationMessageStore,
@@ -42,13 +42,13 @@ import {
42
42
  juniorConversations,
43
43
  juniorIdentities,
44
44
  juniorUsers
45
- } from "./chunk-BCULHGZK.js";
45
+ } from "./chunk-XTKJPSMF.js";
46
46
  import "./chunk-4ZNGQH7C.js";
47
47
  import {
48
48
  stripRuntimeTurnContext,
49
49
  unescapeXml,
50
50
  unwrapCurrentInstruction
51
- } from "./chunk-M3UAVLEN.js";
51
+ } from "./chunk-4UYIRWDW.js";
52
52
  import {
53
53
  juniorDestinations
54
54
  } from "./chunk-FXFQNHRU.js";
@@ -1116,7 +1116,7 @@ var detail_default = {
1116
1116
  };
1117
1117
 
1118
1118
  // src/api/conversations/stats.query.ts
1119
- import { and as and3, eq as eq3, gte, isNull as isNull2, lte } from "drizzle-orm";
1119
+ import { and as and3, eq as eq3, gte, isNull as isNull2, lte, sql as sql2 } from "drizzle-orm";
1120
1120
 
1121
1121
  // src/api/conversations/aggregate.ts
1122
1122
  import { sql } from "drizzle-orm";
@@ -1187,7 +1187,7 @@ function conversationActiveDaysColumn() {
1187
1187
  }
1188
1188
 
1189
1189
  // src/api/conversations/stats.query.ts
1190
- var WINDOW_MS = 90 * 24 * 60 * 60 * 1e3;
1190
+ var WINDOW_DAYS = 90;
1191
1191
  function emptyStatsItem(label) {
1192
1192
  return {
1193
1193
  active: 0,
@@ -1248,9 +1248,39 @@ function statsWhere(start, end) {
1248
1248
  lte(juniorConversations.lastActivityAt, end)
1249
1249
  );
1250
1250
  }
1251
+ function statsWindow(nowMs) {
1252
+ const end = new Date(nowMs);
1253
+ const start = new Date(nowMs);
1254
+ start.setUTCHours(0, 0, 0, 0);
1255
+ start.setUTCDate(start.getUTCDate() - (WINDOW_DAYS - 1));
1256
+ return { end, start };
1257
+ }
1258
+ function metricDays(rows, endMs) {
1259
+ const byDate = new Map(rows.map((row) => [row.date, row]));
1260
+ const end = new Date(endMs);
1261
+ end.setUTCHours(0, 0, 0, 0);
1262
+ const start = new Date(end);
1263
+ start.setUTCDate(start.getUTCDate() - (WINDOW_DAYS - 1));
1264
+ const days = [];
1265
+ for (const cursor = new Date(start); cursor.getTime() <= end.getTime(); cursor.setUTCDate(cursor.getUTCDate() + 1)) {
1266
+ const date = cursor.toISOString().slice(0, 10);
1267
+ const row = byDate.get(date);
1268
+ days.push({
1269
+ date,
1270
+ durationMs: row?.durationMs ?? 0,
1271
+ ...row?.costUsd !== null && row?.costUsd !== void 0 ? { costUsd: row.costUsd } : {},
1272
+ ...row?.tokens !== null && row?.tokens !== void 0 ? { tokens: row.tokens } : {}
1273
+ });
1274
+ }
1275
+ return days;
1276
+ }
1251
1277
  async function aggregateStats(db, start, end) {
1252
1278
  const where = statsWhere(start, end);
1253
- const [totalsRows, actorRows, locationRows] = await Promise.all([
1279
+ const activityDate = sql2`TO_CHAR(
1280
+ ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
1281
+ 'YYYY-MM-DD'
1282
+ )`;
1283
+ const [totalsRows, actorRows, locationRows, metricRows] = await Promise.all([
1254
1284
  db.select(conversationAggregateColumns()).from(juniorConversations).where(where),
1255
1285
  db.select({
1256
1286
  identityDisplayName: juniorIdentities.displayName,
@@ -1289,17 +1319,23 @@ async function aggregateStats(db, start, end) {
1289
1319
  juniorDestinations.kind,
1290
1320
  juniorDestinations.provider,
1291
1321
  juniorDestinations.visibility
1292
- )
1322
+ ),
1323
+ db.select({
1324
+ costUsd: conversationAggregateColumns().costUsd,
1325
+ date: activityDate,
1326
+ durationMs: conversationAggregateColumns().durationMs,
1327
+ tokens: conversationAggregateColumns().tokens
1328
+ }).from(juniorConversations).where(where).groupBy(activityDate)
1293
1329
  ]);
1294
- return { actorRows, locationRows, totals: totalsRows[0] };
1330
+ return { actorRows, locationRows, metricRows, totals: totalsRows[0] };
1295
1331
  }
1296
1332
  async function readConversationStatsFromSql() {
1297
1333
  const nowMs = Date.now();
1298
- const windowStartMs = nowMs - WINDOW_MS;
1299
- const { actorRows, locationRows, totals } = await aggregateStats(
1334
+ const { end, start } = statsWindow(nowMs);
1335
+ const { actorRows, locationRows, metricRows, totals } = await aggregateStats(
1300
1336
  getDb(),
1301
- new Date(windowStartMs),
1302
- new Date(nowMs)
1337
+ start,
1338
+ end
1303
1339
  );
1304
1340
  const actors = /* @__PURE__ */ new Map();
1305
1341
  const locations = /* @__PURE__ */ new Map();
@@ -1315,13 +1351,14 @@ async function readConversationStatsFromSql() {
1315
1351
  durationMs: totals?.durationMs ?? 0,
1316
1352
  failed: totals?.failed ?? 0,
1317
1353
  generatedAt: new Date(nowMs).toISOString(),
1354
+ metricDays: metricDays(metricRows, nowMs),
1318
1355
  locations: statsItems(locations),
1319
1356
  actors: statsItems(actors),
1320
1357
  source: "conversation_index",
1321
1358
  ...totals?.costUsd !== null && totals?.costUsd !== void 0 ? { costUsd: addUsd(void 0, totals.costUsd) } : {},
1322
1359
  ...totals?.tokens !== null && totals?.tokens !== void 0 ? { tokens: totals.tokens } : {},
1323
- windowEnd: new Date(nowMs).toISOString(),
1324
- windowStart: new Date(windowStartMs).toISOString()
1360
+ windowEnd: end.toISOString(),
1361
+ windowStart: start.toISOString()
1325
1362
  };
1326
1363
  }
1327
1364
 
@@ -1387,7 +1424,7 @@ function createConversationRoutes() {
1387
1424
  import { Hono as Hono2 } from "hono";
1388
1425
 
1389
1426
  // src/api/locations/query.ts
1390
- import { and as and4, asc as asc2, desc as desc2, eq as eq4, gte as gte2, isNull as isNull3, sql as sql2 } from "drizzle-orm";
1427
+ import { and as and4, asc as asc2, desc as desc2, eq as eq4, gte as gte2, isNull as isNull3, sql as sql3 } from "drizzle-orm";
1391
1428
 
1392
1429
  // src/api/conversations/reporting.ts
1393
1430
  var PRIVATE_CONVERSATION_LABEL2 = "Private Conversation";
@@ -1579,12 +1616,12 @@ async function directoryRows(db) {
1579
1616
  ).where(topLevelWhere()).groupBy(...locationGroupBy());
1580
1617
  }
1581
1618
  async function directoryActivityRows(db, start) {
1582
- const date = sql2`TO_CHAR(
1619
+ const date = sql3`TO_CHAR(
1583
1620
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
1584
1621
  'YYYY-MM-DD'
1585
1622
  )`;
1586
1623
  return db.select({
1587
- conversations: sql2`COUNT(*)::integer`,
1624
+ conversations: sql3`COUNT(*)::integer`,
1588
1625
  date,
1589
1626
  visibility: juniorDestinations.visibility
1590
1627
  }).from(juniorConversations).leftJoin(
@@ -1664,7 +1701,7 @@ async function recentLocationRows(db, locationId) {
1664
1701
  destinationId: juniorDestinations.id,
1665
1702
  destinationVisibility: juniorDestinations.visibility,
1666
1703
  durationMs: juniorConversations.durationMs,
1667
- email: sql2`COALESCE(
1704
+ email: sql3`COALESCE(
1668
1705
  ${juniorUsers.primaryEmailNormalized},
1669
1706
  ${juniorIdentities.email}
1670
1707
  )`,
@@ -1673,7 +1710,7 @@ async function recentLocationRows(db, locationId) {
1673
1710
  fullName: juniorUsers.displayName,
1674
1711
  handle: juniorIdentities.handle,
1675
1712
  lastActivityAt: juniorConversations.lastActivityAt,
1676
- providerSubjectId: sql2`CASE
1713
+ providerSubjectId: sql3`CASE
1677
1714
  WHEN ${juniorIdentities.provider} = 'slack'
1678
1715
  THEN ${juniorIdentities.providerSubjectId}
1679
1716
  ELSE NULL
@@ -1705,7 +1742,7 @@ async function readLocationDetailFromSql(locationId) {
1705
1742
  const start = new Date(end);
1706
1743
  start.setUTCDate(start.getUTCDate() - (ACTIVITY_DAYS - 1));
1707
1744
  const where = publicLocationWhere(locationId);
1708
- const activityDate = sql2`TO_CHAR(
1745
+ const activityDate = sql3`TO_CHAR(
1709
1746
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
1710
1747
  'YYYY-MM-DD'
1711
1748
  )`;
@@ -1830,10 +1867,10 @@ function createLocationRoutes() {
1830
1867
  import { Hono as Hono3 } from "hono";
1831
1868
 
1832
1869
  // src/api/people/list.query.ts
1833
- import { and as and6, eq as eq6, gte as gte3, sql as sql4 } from "drizzle-orm";
1870
+ import { and as and6, eq as eq6, gte as gte3, sql as sql5 } from "drizzle-orm";
1834
1871
 
1835
1872
  // src/api/people/shared.ts
1836
- import { and as and5, asc as asc3, desc as desc3, eq as eq5, isNull as isNull4, sql as sql3 } from "drizzle-orm";
1873
+ import { and as and5, asc as asc3, desc as desc3, eq as eq5, isNull as isNull4, sql as sql4 } from "drizzle-orm";
1837
1874
  var RECENT_LIMIT2 = 25;
1838
1875
  var ACTIVITY_DAYS2 = 365;
1839
1876
  function normalizeEmail(email) {
@@ -1880,7 +1917,7 @@ function verifiedActorWhere(email) {
1880
1917
  return and5(
1881
1918
  eq5(juniorIdentities.provider, "slack"),
1882
1919
  eq5(juniorIdentities.emailVerified, true),
1883
- sql3`${juniorUsers.primaryEmailNormalized} IS NOT NULL`,
1920
+ sql4`${juniorUsers.primaryEmailNormalized} IS NOT NULL`,
1884
1921
  normalizedEmail ? eq5(juniorUsers.primaryEmailNormalized, normalizedEmail) : void 0
1885
1922
  );
1886
1923
  }
@@ -1939,7 +1976,7 @@ function directoryActivityDays2(rows, nowMs) {
1939
1976
  async function readPeopleListFromSql() {
1940
1977
  const nowMs = Date.now();
1941
1978
  const { end, start } = activityWindow(nowMs);
1942
- const activityDate = sql4`TO_CHAR(
1979
+ const activityDate = sql5`TO_CHAR(
1943
1980
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
1944
1981
  'YYYY-MM-DD'
1945
1982
  )`;
@@ -1947,8 +1984,8 @@ async function readPeopleListFromSql() {
1947
1984
  getDb().select({
1948
1985
  email: juniorUsers.primaryEmailNormalized,
1949
1986
  fullName: juniorUsers.displayName,
1950
- slackUserId: sql4`MAX(${juniorIdentities.providerSubjectId})`,
1951
- slackUserName: sql4`MAX(${juniorIdentities.handle})`,
1987
+ slackUserId: sql5`MAX(${juniorIdentities.providerSubjectId})`,
1988
+ slackUserName: sql5`MAX(${juniorIdentities.handle})`,
1952
1989
  activeDays: conversationActiveDaysColumn(),
1953
1990
  ...conversationAggregateColumns(),
1954
1991
  ...conversationRangeColumns()
@@ -1957,8 +1994,8 @@ async function readPeopleListFromSql() {
1957
1994
  eq6(juniorIdentities.id, juniorConversations.actorIdentityId)
1958
1995
  ).innerJoin(juniorUsers, eq6(juniorUsers.id, juniorIdentities.userId)).where(verifiedActorWhere()).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
1959
1996
  getDb().select({
1960
- activePeople: sql4`COUNT(DISTINCT ${juniorUsers.id})::int`,
1961
- conversations: sql4`COUNT(*)::int`,
1997
+ activePeople: sql5`COUNT(DISTINCT ${juniorUsers.id})::int`,
1998
+ conversations: sql5`COUNT(*)::int`,
1962
1999
  date: activityDate
1963
2000
  }).from(juniorConversations).innerJoin(
1964
2001
  juniorIdentities,
@@ -2012,7 +2049,7 @@ var list_default3 = {
2012
2049
  };
2013
2050
 
2014
2051
  // src/api/people/profile.query.ts
2015
- import { and as and7, eq as eq7, gte as gte4, sql as sql5 } from "drizzle-orm";
2052
+ import { and as and7, eq as eq7, gte as gte4, sql as sql6 } from "drizzle-orm";
2016
2053
  function emptyProfile(email, nowMs) {
2017
2054
  const end = new Date(nowMs);
2018
2055
  end.setUTCHours(0, 0, 0, 0);
@@ -2047,7 +2084,7 @@ function addAggregate2(map, label, row) {
2047
2084
  map.set(label, item);
2048
2085
  }
2049
2086
  function surfaceExpression() {
2050
- return sql5`CASE
2087
+ return sql6`CASE
2051
2088
  WHEN ${juniorConversations.source} IN ('api', 'scheduler', 'slack')
2052
2089
  THEN ${juniorConversations.source}
2053
2090
  WHEN ${juniorConversations.conversationId} LIKE 'slack:%' THEN 'slack'
@@ -2075,17 +2112,17 @@ async function readPeopleProfileFromSql(email) {
2075
2112
  start.setUTCDate(start.getUTCDate() - (ACTIVITY_DAYS2 - 1));
2076
2113
  const where = verifiedActorWhere(normalizedEmail);
2077
2114
  const surface = surfaceExpression();
2078
- const activityDate = sql5`TO_CHAR(
2115
+ const activityDate = sql6`TO_CHAR(
2079
2116
  ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
2080
2117
  'YYYY-MM-DD'
2081
2118
  )`;
2082
- const channel = sql5`SPLIT_PART(${juniorConversations.conversationId}, ':', 2)`;
2119
+ const channel = sql6`SPLIT_PART(${juniorConversations.conversationId}, ':', 2)`;
2083
2120
  const [totalsRows, dayRows, locationRows, surfaceRows, recentRows] = await Promise.all([
2084
2121
  getDb().select({
2085
2122
  email: juniorUsers.primaryEmailNormalized,
2086
2123
  fullName: juniorUsers.displayName,
2087
- slackUserId: sql5`MAX(${juniorIdentities.providerSubjectId})`,
2088
- slackUserName: sql5`MAX(${juniorIdentities.handle})`,
2124
+ slackUserId: sql6`MAX(${juniorIdentities.providerSubjectId})`,
2125
+ slackUserName: sql6`MAX(${juniorIdentities.handle})`,
2089
2126
  activeDays: conversationActiveDaysColumn(),
2090
2127
  ...conversationAggregateColumns()
2091
2128
  }).from(juniorConversations).innerJoin(
@@ -2244,7 +2281,7 @@ async function readRuntimeInfoReport() {
2244
2281
  }
2245
2282
  async function readPluginOperationalReportFeed() {
2246
2283
  const nowMs = Date.now();
2247
- const { getPluginOperationalReports } = await import("./agent-hooks-EOFSY2PD.js");
2284
+ const { getPluginOperationalReports } = await import("./agent-hooks-KR5BCWOK.js");
2248
2285
  return pluginOperationalReportFeedSchema.parse({
2249
2286
  source: "plugins",
2250
2287
  generatedAt: new Date(nowMs).toISOString(),
package/dist/app.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  processPluginTask,
6
6
  requireTurnFailureEventId,
7
7
  scheduleSessionCompletedPluginTasks
8
- } from "./chunk-QVTVCJR4.js";
8
+ } from "./chunk-4W4O4DCV.js";
9
9
  import {
10
10
  CONVERSATION_WORK_CHECK_IN_INTERVAL_MS,
11
11
  CONVERSATION_WORK_STALE_ENQUEUE_MS,
@@ -29,14 +29,14 @@ import {
29
29
  requestConversationContinuation,
30
30
  requestConversationWork,
31
31
  startConversationWork
32
- } from "./chunk-U26ZWZCN.js";
32
+ } from "./chunk-3OUSJPR7.js";
33
33
  import {
34
34
  GET,
35
35
  buildSentryConversationUrl,
36
36
  conversationVisibilityFromSlackChannelType,
37
37
  resolveSlackChannelTypeFromMessage,
38
38
  resolveSlackConversationContext
39
- } from "./chunk-O7ILGCMJ.js";
39
+ } from "./chunk-R5BFYK2O.js";
40
40
  import "./chunk-CEA3A3UA.js";
41
41
  import {
42
42
  getVercelConversationWorkQueue,
@@ -102,12 +102,14 @@ import {
102
102
  splitSlackReplyText,
103
103
  startOAuthFlow,
104
104
  truncateStatusText
105
- } from "./chunk-TMWUGGSA.js";
105
+ } from "./chunk-GPPUTY5M.js";
106
106
  import {
107
107
  CooperativeTurnYieldError,
108
108
  TurnInputCommitLostError,
109
109
  TurnInputDeferredError,
110
+ TurnSliceLimitExceededError,
110
111
  buildDeterministicTurnId,
112
+ buildTurnLimitResponse,
111
113
  clearPendingAuth,
112
114
  coerceThreadArtifactsState,
113
115
  completeDeliveredTurn,
@@ -130,12 +132,12 @@ import {
130
132
  persistWithRetry,
131
133
  persistYieldSessionRecord,
132
134
  startActiveTurn
133
- } from "./chunk-RMZ65YAA.js";
135
+ } from "./chunk-BKM4UXUD.js";
134
136
  import {
135
137
  JUNIOR_THREAD_STATE_TTL_MS,
136
138
  coerceThreadConversationState
137
139
  } from "./chunk-XIMUQ4IU.js";
138
- import "./chunk-7G4J3CR7.js";
140
+ import "./chunk-3NYUCBLE.js";
139
141
  import {
140
142
  abandonAgentTurnSessionRecord,
141
143
  commitMessages,
@@ -146,7 +148,7 @@ import {
146
148
  loadProjection,
147
149
  recordAgentTurnSessionSummary,
148
150
  recordAuthorizationCompleted
149
- } from "./chunk-QDKRE3LS.js";
151
+ } from "./chunk-DDRQ4U7I.js";
150
152
  import {
151
153
  buildConversationContext,
152
154
  createConversationMemoryService,
@@ -161,7 +163,7 @@ import {
161
163
  persistConversationMessages,
162
164
  updateConversationStats,
163
165
  upsertConversationMessage
164
- } from "./chunk-RYDF4GOX.js";
166
+ } from "./chunk-P4P7O5WG.js";
165
167
  import "./chunk-PDO5BLNM.js";
166
168
  import "./chunk-UIE3R5XU.js";
167
169
  import {
@@ -177,11 +179,11 @@ import {
177
179
  validatePlugins,
178
180
  verifyScheduledTaskCredentialSubject,
179
181
  verifySlackDirectCredentialSubject
180
- } from "./chunk-VDHMFCDY.js";
182
+ } from "./chunk-ZMRLBBD5.js";
181
183
  import {
182
184
  createPluginLogger,
183
185
  createPluginState
184
- } from "./chunk-4PDVOHXP.js";
186
+ } from "./chunk-AZ5OMSN5.js";
185
187
  import "./chunk-G3E7SCME.js";
186
188
  import {
187
189
  SlackActionError,
@@ -193,7 +195,7 @@ import {
193
195
  normalizeSlackConversationId,
194
196
  runWithSlackInstallationToken,
195
197
  runWithWorkspaceTeamId
196
- } from "./chunk-CCTCIISK.js";
198
+ } from "./chunk-3MPPVPGZ.js";
197
199
  import {
198
200
  contextProvenance,
199
201
  getConversationStore,
@@ -203,7 +205,7 @@ import {
203
205
  juniorAgentSteps,
204
206
  juniorConversationMessages,
205
207
  juniorConversations
206
- } from "./chunk-BCULHGZK.js";
208
+ } from "./chunk-XTKJPSMF.js";
207
209
  import {
208
210
  sleep
209
211
  } from "./chunk-4ZNGQH7C.js";
@@ -230,7 +232,7 @@ import {
230
232
  setSlackReactionConfig,
231
233
  stripRuntimeTurnContext,
232
234
  trimTrailingAssistantMessages
233
- } from "./chunk-M3UAVLEN.js";
235
+ } from "./chunk-4UYIRWDW.js";
234
236
  import {
235
237
  juniorDestinations
236
238
  } from "./chunk-FXFQNHRU.js";
@@ -520,6 +522,7 @@ async function verifyDispatchCallbackRequest(request) {
520
522
  import { createHash } from "crypto";
521
523
  import {
522
524
  destinationSchema,
525
+ destinationVisibilitySchema,
523
526
  isSlackDestination,
524
527
  sourceSchema
525
528
  } from "@sentry/junior-plugin-api";
@@ -550,6 +553,7 @@ var dispatchRecordSchema = z.object({
550
553
  createdAtMs: z.number().finite(),
551
554
  credentialSubject: credentialSubjectSchema.optional(),
552
555
  destination: destinationSchema,
556
+ destinationVisibility: destinationVisibilitySchema,
553
557
  errorMessage: z.string().optional(),
554
558
  id: nonEmptyExactStringSchema,
555
559
  idempotencyKey: z.string().min(1),
@@ -735,6 +739,7 @@ async function createOrGetDispatch(args) {
735
739
  createdAtMs: args.nowMs,
736
740
  ...args.options.credentialSubject ? { credentialSubject: args.options.credentialSubject } : {},
737
741
  destination: args.options.destination,
742
+ destinationVisibility: args.options.destinationVisibility,
738
743
  id,
739
744
  idempotencyKey: args.options.idempotencyKey,
740
745
  input: args.options.input,
@@ -964,6 +969,7 @@ async function runAgentDispatchSlice(callback, deps) {
964
969
  ...dispatch.credentialSubject ? { subject: dispatch.credentialSubject } : {}
965
970
  },
966
971
  destination: dispatch.destination,
972
+ destinationVisibility: dispatch.destinationVisibility,
967
973
  source: dispatch.source,
968
974
  dispatch: {
969
975
  actor: dispatch.actor,
@@ -1106,6 +1112,7 @@ async function runAgentDispatchSlice(callback, deps) {
1106
1112
  usage: reply.diagnostics.usage,
1107
1113
  reasoningLevel: reply.diagnostics.reasoningLevel,
1108
1114
  destination: dispatch.destination,
1115
+ destinationVisibility: dispatch.destinationVisibility,
1109
1116
  source: dispatch.source,
1110
1117
  actor: dispatch.actor,
1111
1118
  surface: "api",
@@ -3832,7 +3839,9 @@ async function startSlackProcessingReactionForMessage(args) {
3832
3839
  };
3833
3840
  return {
3834
3841
  complete: async () => {
3835
- if (!await removeProcessingReaction()) {
3842
+ const shouldAddCompleted = shouldRemove;
3843
+ await removeProcessingReaction();
3844
+ if (!shouldAddCompleted) {
3836
3845
  return;
3837
3846
  }
3838
3847
  try {
@@ -3985,7 +3994,7 @@ async function postResumeFailureReply(args) {
3985
3994
  await postSlackMessage({
3986
3995
  channelId: args.channelId,
3987
3996
  threadTs: args.threadTs,
3988
- text: buildTurnFailureResponse(args.eventId)
3997
+ text: args.error instanceof TurnSliceLimitExceededError ? buildTurnLimitResponse(args.eventId) : buildTurnFailureResponse(args.eventId)
3989
3998
  });
3990
3999
  } catch (error) {
3991
4000
  logException(
@@ -4015,6 +4024,7 @@ async function handleResumeFailure(args) {
4015
4024
  channelId: args.resumeArgs.channelId,
4016
4025
  threadTs: args.resumeArgs.threadTs,
4017
4026
  eventId,
4027
+ error: args.error,
4018
4028
  logContext
4019
4029
  });
4020
4030
  }
@@ -9197,6 +9207,25 @@ function getSlackMessageTs(message) {
9197
9207
  return void 0;
9198
9208
  }
9199
9209
 
9210
+ // src/chat/slack/action-token.ts
9211
+ import { z as z10 } from "zod";
9212
+ var slackActionTokenSchema = z10.string().trim().min(1).brand();
9213
+ var slackMessageEnvelopeSchema = z10.object({
9214
+ raw: z10.object({
9215
+ action_token: z10.unknown().optional()
9216
+ }).optional()
9217
+ });
9218
+ function readSlackActionToken(message) {
9219
+ const envelope = slackMessageEnvelopeSchema.safeParse(message);
9220
+ if (!envelope.success) {
9221
+ return void 0;
9222
+ }
9223
+ const token = slackActionTokenSchema.safeParse(
9224
+ envelope.data.raw?.action_token
9225
+ );
9226
+ return token.success ? token.data : void 0;
9227
+ }
9228
+
9200
9229
  // src/chat/slack/assistant-thread/title.ts
9201
9230
  function maybeUpdateAssistantTitle(args) {
9202
9231
  const assistantThreadContext = args.assistantThreadContext;
@@ -9490,6 +9519,7 @@ function createReplyToThread(deps) {
9490
9519
  threadTs,
9491
9520
  type: destinationVisibility === "public" ? "pub" : "priv"
9492
9521
  });
9522
+ const slackActionToken = readSlackActionToken(message);
9493
9523
  const runId = getRunId(thread, message);
9494
9524
  const conversationId = threadId ?? runId;
9495
9525
  await withSpan(
@@ -9923,10 +9953,18 @@ function createReplyToThread(deps) {
9923
9953
  let persistedAtLeastOnce = false;
9924
9954
  let shouldPersistFailureState = true;
9925
9955
  let finalReplyDelivered = false;
9956
+ let turnCompletionNotified = false;
9926
9957
  let latestArtifacts = preparedState.artifacts;
9927
9958
  let assistantTitleArtifacts = {};
9928
9959
  let agentContinueScheduleError;
9929
9960
  const hasVisibleSlackDelivery = (post) => post.text.trim().length > 0;
9961
+ const notifyTurnCompleted = async () => {
9962
+ if (turnCompletionNotified) {
9963
+ return;
9964
+ }
9965
+ await options.onTurnCompleted?.();
9966
+ turnCompletionNotified = true;
9967
+ };
9930
9968
  try {
9931
9969
  const loadedPiMessages = await loadPiMessagesForTurn({
9932
9970
  conversationId,
@@ -10082,6 +10120,7 @@ function createReplyToThread(deps) {
10082
10120
  slackConversation,
10083
10121
  source,
10084
10122
  destination,
10123
+ destinationVisibility,
10085
10124
  surface: "slack",
10086
10125
  correlation: {
10087
10126
  conversationId,
@@ -10095,7 +10134,8 @@ function createReplyToThread(deps) {
10095
10134
  channelName,
10096
10135
  actorId: slackActorId
10097
10136
  },
10098
- toolChannelId
10137
+ toolChannelId,
10138
+ slackActionToken
10099
10139
  },
10100
10140
  policy: {
10101
10141
  configuration: preparedState.configuration,
@@ -10399,7 +10439,7 @@ function createReplyToThread(deps) {
10399
10439
  "Agent turn completed"
10400
10440
  );
10401
10441
  }
10402
- await options.onTurnCompleted?.();
10442
+ await notifyTurnCompleted();
10403
10443
  if (reply.diagnostics.outcome === "success" && conversationId) {
10404
10444
  try {
10405
10445
  await deps.services.scheduleSessionCompletedPluginTasks({
@@ -10426,6 +10466,17 @@ function createReplyToThread(deps) {
10426
10466
  messageTs ? { "messaging.message.id": messageTs } : {},
10427
10467
  "Post-delivery turn work failed after Slack accepted the reply"
10428
10468
  );
10469
+ try {
10470
+ await notifyTurnCompleted();
10471
+ } catch (completionError) {
10472
+ logException(
10473
+ completionError,
10474
+ "slack_reply_post_delivery_completion_callback_failed",
10475
+ turnTraceContext,
10476
+ messageTs ? { "messaging.message.id": messageTs } : {},
10477
+ "Post-delivery turn completion callback failed after Slack accepted the reply"
10478
+ );
10479
+ }
10429
10480
  return;
10430
10481
  }
10431
10482
  if (error instanceof CooperativeTurnYieldError) {
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import type { Destination, Source, SystemActor } from "@sentry/junior-plugin-api";
11
11
  import type { ChannelConfigurationService } from "@/chat/configuration/types";
12
+ import type { ConversationPrivacy } from "@/chat/conversation-privacy";
12
13
  import type { CredentialContext } from "@/chat/credentials/context";
13
14
  import type { PiMessage } from "@/chat/pi/messages";
14
15
  import { type Actor } from "@/chat/actor";
@@ -22,6 +23,7 @@ import type { ConversationPendingAuthState } from "@/chat/state/conversation";
22
23
  import type { PiMessageProvenance } from "@/chat/state/session-log";
23
24
  import type { AgentTurnSurface } from "@/chat/state/turn-session";
24
25
  import type { ToolExecutionReport } from "@/chat/tool-support/tool-execution-report";
26
+ import type { SlackActionToken } from "@/chat/slack/action-token";
25
27
  import type { TurnReasoningLevel } from "@/chat/reasoning-level";
26
28
  import type { ImageGenerateToolDeps, WebFetchToolDeps, WebSearchToolDeps } from "@/chat/tools/types";
27
29
  export interface AgentRunAttachment {
@@ -62,7 +64,14 @@ export interface AgentRunRouting {
62
64
  actor?: Actor;
63
65
  source: Source;
64
66
  slackConversation?: SlackConversationContext;
67
+ /**
68
+ * TODO: Move ephemeral Slack credentials into provider-owned turn context so
69
+ * the Slack tool registry can consume them without extending core routing.
70
+ */
71
+ slackActionToken?: SlackActionToken;
65
72
  destination: Destination;
73
+ /** Confirmed visibility of the destination where this run is delivered. */
74
+ destinationVisibility?: ConversationPrivacy;
66
75
  surface?: AgentTurnSurface;
67
76
  dispatch?: {
68
77
  actor?: SystemActor;