@sentry/junior 0.136.1 → 0.138.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 (103) hide show
  1. package/dist/{agent-hooks-2KDSPPO4.js → agent-hooks-SCR74Q3E.js} +11 -9
  2. package/dist/api/conversations/projection.d.ts +1 -0
  3. package/dist/api/conversations/stats.d.ts +1 -0
  4. package/dist/api/schema/conversation.d.ts +2 -0
  5. package/dist/api/schema.js +1 -1
  6. package/dist/api.js +187 -46
  7. package/dist/app.d.ts +8 -1
  8. package/dist/app.js +519 -860
  9. package/dist/{catalog-runtime-WSZQGC4D.js → catalog-runtime-IU3QF4GG.js} +5 -5
  10. package/dist/chat/agent/request.d.ts +32 -2
  11. package/dist/chat/agent-dispatch/heartbeat.d.ts +5 -0
  12. package/dist/chat/agent-dispatch/types.d.ts +1 -1
  13. package/dist/chat/agent-invocations/errors.d.ts +8 -0
  14. package/dist/chat/agent-invocations/spawn.d.ts +12 -0
  15. package/dist/chat/agent-invocations/store.d.ts +44 -0
  16. package/dist/chat/agent-invocations/types.d.ts +449 -0
  17. package/dist/chat/agent-invocations/work.d.ts +31 -0
  18. package/dist/chat/config.d.ts +1 -0
  19. package/dist/chat/configuration/defaults.d.ts +1 -1
  20. package/dist/chat/conversations/sql/store.d.ts +8 -0
  21. package/dist/chat/conversations/store.d.ts +9 -1
  22. package/dist/chat/experimental.d.ts +16 -0
  23. package/dist/chat/pi/client.d.ts +1 -8
  24. package/dist/chat/pi/gateway-auth.d.ts +16 -0
  25. package/dist/chat/runtime/agent-runner.d.ts +2 -1
  26. package/dist/chat/sandbox/docker.d.ts +17 -0
  27. package/dist/chat/services/agent-continue.d.ts +2 -0
  28. package/dist/chat/services/auth-pause.d.ts +0 -1
  29. package/dist/chat/services/mcp-auth-orchestration.d.ts +3 -2
  30. package/dist/chat/services/plugin-auth-orchestration.d.ts +3 -2
  31. package/dist/chat/services/subscribed-reply-router-policy.d.ts +12 -0
  32. package/dist/chat/services/turn-session-routing.d.ts +17 -0
  33. package/dist/chat/slack/message.d.ts +6 -1
  34. package/dist/chat/slack/source-link.d.ts +8 -2
  35. package/dist/chat/slack/team-domain.d.ts +4 -0
  36. package/dist/chat/source.d.ts +5 -5
  37. package/dist/chat/state/turn-session.d.ts +0 -2
  38. package/dist/chat/task-execution/state.d.ts +23 -11
  39. package/dist/chat/task-execution/store.d.ts +20 -11
  40. package/dist/chat/task-execution/worker.d.ts +2 -2
  41. package/dist/chat/tools/runtime/spawn-agent.d.ts +31 -0
  42. package/dist/chat/tools/types.d.ts +2 -0
  43. package/dist/chunk-3Y47VMHV.js +6 -0
  44. package/dist/chunk-5IDFPCON.js +46 -0
  45. package/dist/chunk-5LTJ4ITU.js +1523 -0
  46. package/dist/{chunk-KLBYCSLJ.js → chunk-5MXWHTCK.js} +17 -434
  47. package/dist/{chunk-CZZDCH3Q.js → chunk-A7WCHXZV.js} +206 -78
  48. package/dist/{chunk-4YQ6I6VF.js → chunk-BOLJOV5T.js} +2 -56
  49. package/dist/{chunk-XCZ6COFO.js → chunk-BYW4B4PR.js} +90 -54
  50. package/dist/{chunk-JQRTXJHD.js → chunk-C7ZVPO4Z.js} +2 -1
  51. package/dist/{chunk-MW2QRPGW.js → chunk-DCLLQGS6.js} +119 -50
  52. package/dist/{chunk-CDVCCOMF.js → chunk-E5UYAIKJ.js} +75 -1475
  53. package/dist/{chunk-3SUK3UXX.js → chunk-ELKW5FIB.js} +5 -5
  54. package/dist/chunk-EM225ITJ.js +56 -0
  55. package/dist/{chunk-Y6JNHTRD.js → chunk-FEUNPTGV.js} +34 -70
  56. package/dist/{chunk-TYNMSQKA.js → chunk-FNLBTB4K.js} +1 -1
  57. package/dist/{chunk-TRZSM67C.js → chunk-HCIVH3JS.js} +1 -0
  58. package/dist/chunk-HIWJWWMT.js +668 -0
  59. package/dist/chunk-IUFM5JWV.js +24 -0
  60. package/dist/{chunk-XWPA5KZF.js → chunk-JNNJZURV.js} +1 -1
  61. package/dist/{chunk-6ZK6FZIV.js → chunk-KCBZSJRU.js} +6 -27
  62. package/dist/{chunk-BG3KWWDJ.js → chunk-KDCHVT25.js} +1 -1
  63. package/dist/{chunk-VH6MI4L7.js → chunk-KFRHRSCJ.js} +1 -1
  64. package/dist/chunk-LPVUNO2W.js +320 -0
  65. package/dist/{chunk-G66RYKRS.js → chunk-N7WARMC6.js} +16 -776
  66. package/dist/chunk-PB3CXNVL.js +41 -0
  67. package/dist/chunk-Q6QZTTLS.js +55 -0
  68. package/dist/{chunk-3QNJOHKG.js → chunk-QS527AV5.js} +1 -1
  69. package/dist/chunk-R776HKPK.js +81 -0
  70. package/dist/{chunk-OTJMQYVP.js → chunk-RZIBSCYC.js} +517 -608
  71. package/dist/chunk-SD3OFRWY.js +714 -0
  72. package/dist/{chunk-HIRIWTWD.js → chunk-SIPKWSXK.js} +58 -10
  73. package/dist/chunk-TCS76X5D.js +441 -0
  74. package/dist/{chunk-UX2TNH5D.js → chunk-TDJCLNDH.js} +3 -3
  75. package/dist/{chunk-NVVBEJUB.js → chunk-TUUDXEXU.js} +336 -300
  76. package/dist/{chunk-22Z6MGMK.js → chunk-VPZFVJND.js} +1 -1
  77. package/dist/{chunk-RFDD3Z2I.js → chunk-YU5QUF67.js} +1 -1
  78. package/dist/chunk-ZBSMCXKV.js +710 -0
  79. package/dist/{chunk-FSYXYBWU.js → chunk-ZXNTJJIE.js} +2 -2
  80. package/dist/cli/chat.js +65 -26
  81. package/dist/cli/check.js +7 -7
  82. package/dist/cli/plugins.js +14 -12
  83. package/dist/cli/snapshot-create.js +10 -9
  84. package/dist/cli/upgrade.js +7 -7
  85. package/dist/conversation-work-KATFHLG3.js +56 -0
  86. package/dist/db/schema/agent-invocations.d.ts +544 -0
  87. package/dist/db/schema.d.ts +543 -1
  88. package/dist/{db-Z2NNL2JC.js → db-UO2IWXGA.js} +7 -7
  89. package/dist/experimental-HH6OM6UH.js +13 -0
  90. package/dist/instrumentation.js +4 -4
  91. package/dist/nitro.js +4 -3
  92. package/dist/{oauth-callback-server-PO3M5JMG.js → oauth-callback-server-MAQI43LX.js} +26 -18
  93. package/dist/{runner-QHQYZYJA.js → runner-PIUQEXKE.js} +26 -14
  94. package/dist/{skills-KXMT3DRA.js → skills-4ARJADHQ.js} +6 -6
  95. package/dist/spawn-G2AWPMCT.js +38 -0
  96. package/dist/{validation-Y42ULTT6.js → validation-S3EE3HWL.js} +6 -6
  97. package/dist/version.js +1 -1
  98. package/dist/work-UARRUAW3.js +46 -0
  99. package/dist/worker-DOCIRVD3.js +24 -0
  100. package/migrations/0021_first_warhawk.sql +35 -0
  101. package/migrations/meta/0021_snapshot.json +2176 -0
  102. package/migrations/meta/_journal.json +8 -1
  103. package/package.json +6 -5
@@ -11,19 +11,21 @@ import {
11
11
  getPlugins,
12
12
  setPlugins,
13
13
  validatePlugins
14
- } from "./chunk-KLBYCSLJ.js";
15
- import "./chunk-HIRIWTWD.js";
16
- import "./chunk-MW2QRPGW.js";
17
- import "./chunk-4YQ6I6VF.js";
18
- import "./chunk-XCZ6COFO.js";
14
+ } from "./chunk-5MXWHTCK.js";
15
+ import "./chunk-TCS76X5D.js";
16
+ import "./chunk-SIPKWSXK.js";
17
+ import "./chunk-DCLLQGS6.js";
18
+ import "./chunk-EM225ITJ.js";
19
+ import "./chunk-BOLJOV5T.js";
20
+ import "./chunk-BYW4B4PR.js";
19
21
  import "./chunk-VFUK3X5B.js";
20
- import "./chunk-22Z6MGMK.js";
22
+ import "./chunk-VPZFVJND.js";
21
23
  import "./chunk-HZF5P5UN.js";
22
24
  import "./chunk-F3B2YJ76.js";
23
- import "./chunk-XWPA5KZF.js";
25
+ import "./chunk-JNNJZURV.js";
24
26
  import "./chunk-6GWA276C.js";
25
- import "./chunk-BG3KWWDJ.js";
26
- import "./chunk-JQRTXJHD.js";
27
+ import "./chunk-KDCHVT25.js";
28
+ import "./chunk-C7ZVPO4Z.js";
27
29
  import "./chunk-MLKGABMK.js";
28
30
  export {
29
31
  PluginHookDeniedError,
@@ -14,6 +14,7 @@ export declare function conversationSummaryFromStoredConversation(args: {
14
14
  conversation: ConversationProjectionSource;
15
15
  durationMs: number;
16
16
  locationId?: string;
17
+ teamDomainByTeamId?: ReadonlyMap<string, string>;
17
18
  usage?: ConversationUsage;
18
19
  }): ConversationSummaryReport;
19
20
  export {};
@@ -24,6 +24,7 @@ declare const _default: import("../route").ApiRoute<import("zod").ZodObject<{
24
24
  requests: import("zod").ZodNumber;
25
25
  }, import("zod/v4/core").$strict>;
26
26
  metricDays: import("zod").ZodArray<import("zod").ZodObject<{
27
+ conversations: import("zod").ZodNumber;
27
28
  costUsd: import("zod").ZodOptional<import("zod").ZodNumber>;
28
29
  date: import("zod").ZodString;
29
30
  durationMs: import("zod").ZodNumber;
@@ -1046,6 +1046,7 @@ export declare const conversationStatsItemSchema: z.ZodObject<{
1046
1046
  tokens: z.ZodOptional<z.ZodNumber>;
1047
1047
  }, z.core.$strict>;
1048
1048
  export declare const conversationMetricDaySchema: z.ZodObject<{
1049
+ conversations: z.ZodNumber;
1049
1050
  costUsd: z.ZodOptional<z.ZodNumber>;
1050
1051
  date: z.ZodString;
1051
1052
  durationMs: z.ZodNumber;
@@ -1096,6 +1097,7 @@ export declare const conversationStatsReportSchema: z.ZodObject<{
1096
1097
  requests: z.ZodNumber;
1097
1098
  }, z.core.$strict>;
1098
1099
  metricDays: z.ZodArray<z.ZodObject<{
1100
+ conversations: z.ZodNumber;
1099
1101
  costUsd: z.ZodOptional<z.ZodNumber>;
1100
1102
  date: z.ZodString;
1101
1103
  durationMs: z.ZodNumber;
@@ -37,7 +37,7 @@ import {
37
37
  taskListSchema,
38
38
  taskParamsSchema,
39
39
  taskSummarySchema
40
- } from "../chunk-TRZSM67C.js";
40
+ } from "../chunk-HCIVH3JS.js";
41
41
  import {
42
42
  healthReportSchema,
43
43
  pluginOperationalReportFeedSchema,
package/dist/api.js CHANGED
@@ -27,14 +27,14 @@ import {
27
27
  statsReportSchema,
28
28
  taskListSchema,
29
29
  taskParamsSchema
30
- } from "./chunk-TRZSM67C.js";
30
+ } from "./chunk-HCIVH3JS.js";
31
31
  import {
32
32
  formatSlackConversationRedactedLabel,
33
33
  readHealthReport,
34
34
  readTaskExecutionDays,
35
35
  readTaskExecutionSummaries,
36
36
  resolveSlackConversationContextFromThreadId
37
- } from "./chunk-3SUK3UXX.js";
37
+ } from "./chunk-ELKW5FIB.js";
38
38
  import {
39
39
  buildSentryConversationUrl
40
40
  } from "./chunk-4CODA7P5.js";
@@ -56,10 +56,10 @@ import {
56
56
  listPublicEventTasksForTeams,
57
57
  listPublicScheduledTasksForTeams,
58
58
  readStats
59
- } from "./chunk-UX2TNH5D.js";
59
+ } from "./chunk-TDJCLNDH.js";
60
60
  import {
61
61
  parseSlackThreadId
62
- } from "./chunk-TYNMSQKA.js";
62
+ } from "./chunk-FNLBTB4K.js";
63
63
  import {
64
64
  agentTurnUsageSchema,
65
65
  hasAgentTurnUsage,
@@ -72,38 +72,44 @@ import {
72
72
  listConversationAnnotations,
73
73
  renderPluginConversationEvent,
74
74
  resolveViewerUser
75
- } from "./chunk-KLBYCSLJ.js";
75
+ } from "./chunk-5MXWHTCK.js";
76
+ import {
77
+ getSlackClient,
78
+ withSlackRetries
79
+ } from "./chunk-TCS76X5D.js";
76
80
  import {
77
81
  decodeStoredConversationEvent,
78
82
  getDb,
79
83
  getSqlExecutor,
80
84
  locationFromRow,
81
85
  parseSessionSource
82
- } from "./chunk-HIRIWTWD.js";
86
+ } from "./chunk-SIPKWSXK.js";
83
87
  import {
84
88
  juniorApiTokens,
85
89
  juniorConversationEvents,
86
90
  juniorConversations,
87
91
  juniorIdentities,
88
92
  juniorUsers
89
- } from "./chunk-MW2QRPGW.js";
90
- import "./chunk-4YQ6I6VF.js";
91
- import "./chunk-XCZ6COFO.js";
93
+ } from "./chunk-DCLLQGS6.js";
94
+ import "./chunk-EM225ITJ.js";
95
+ import "./chunk-BOLJOV5T.js";
96
+ import "./chunk-BYW4B4PR.js";
92
97
  import {
93
98
  juniorDestinations
94
99
  } from "./chunk-VFUK3X5B.js";
95
100
  import {
96
101
  canExposeConversationPayload
97
- } from "./chunk-22Z6MGMK.js";
102
+ } from "./chunk-VPZFVJND.js";
98
103
  import "./chunk-HZF5P5UN.js";
99
104
  import {
100
105
  parseSlackChannelId,
106
+ parseSlackMessageTs,
101
107
  parseSlackTeamId
102
108
  } from "./chunk-F3B2YJ76.js";
103
- import "./chunk-XWPA5KZF.js";
109
+ import "./chunk-JNNJZURV.js";
104
110
  import "./chunk-6GWA276C.js";
105
- import "./chunk-BG3KWWDJ.js";
106
- import "./chunk-JQRTXJHD.js";
111
+ import "./chunk-KDCHVT25.js";
112
+ import "./chunk-C7ZVPO4Z.js";
107
113
  import "./chunk-MLKGABMK.js";
108
114
 
109
115
  // src/api.ts
@@ -200,6 +206,120 @@ var archive_default = defineApiRoute({
200
206
  }
201
207
  });
202
208
 
209
+ // src/chat/slack/source-link.ts
210
+ function parseSlackTeamDomain(value) {
211
+ if (typeof value !== "string") return void 0;
212
+ const domain = value.trim().toLowerCase();
213
+ if (!/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(domain)) {
214
+ return void 0;
215
+ }
216
+ return domain;
217
+ }
218
+ function archivePathFromThreadTs(threadTs) {
219
+ const [seconds, fraction = ""] = threadTs.split(".");
220
+ return `p${seconds}${(fraction ?? "").padEnd(6, "0").slice(0, 6)}`;
221
+ }
222
+ function buildSlackSourceUrl(args) {
223
+ const channelId = parseSlackChannelId(args.channelId);
224
+ const teamDomain = parseSlackTeamDomain(args.teamDomain);
225
+ const threadTs = parseSlackMessageTs(args.threadTs);
226
+ if (!channelId || !teamDomain || !threadTs) return void 0;
227
+ const url = new URL(
228
+ `https://${teamDomain}.slack.com/archives/${channelId}/${archivePathFromThreadTs(threadTs)}`
229
+ );
230
+ url.searchParams.set("thread_ts", threadTs);
231
+ url.searchParams.set("cid", channelId);
232
+ return url.toString();
233
+ }
234
+
235
+ // src/chat/slack/team-domain.ts
236
+ var TEAM_DOMAIN_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
237
+ var TEAM_DOMAIN_NEGATIVE_CACHE_TTL_MS = 60 * 1e3;
238
+ var teamDomainCache = /* @__PURE__ */ new Map();
239
+ var teamDomainInflight = /* @__PURE__ */ new Map();
240
+ function readTeamDomainCache(teamId) {
241
+ const hit = teamDomainCache.get(teamId);
242
+ if (!hit) return void 0;
243
+ if (hit.expiresAt < Date.now()) {
244
+ teamDomainCache.delete(teamId);
245
+ return void 0;
246
+ }
247
+ return hit.kind === "hit" ? hit.domain : null;
248
+ }
249
+ function writeTeamDomainCache(teamId, domain) {
250
+ if (domain) {
251
+ teamDomainCache.set(teamId, {
252
+ kind: "hit",
253
+ domain,
254
+ expiresAt: Date.now() + TEAM_DOMAIN_CACHE_TTL_MS
255
+ });
256
+ return;
257
+ }
258
+ teamDomainCache.set(teamId, {
259
+ kind: "miss",
260
+ expiresAt: Date.now() + TEAM_DOMAIN_NEGATIVE_CACHE_TTL_MS
261
+ });
262
+ }
263
+ async function fetchSlackTeamDomain(teamId) {
264
+ try {
265
+ const response = await withSlackRetries(
266
+ () => getSlackClient().team.info({ team: teamId }),
267
+ 3,
268
+ {
269
+ action: "team.info",
270
+ idempotent: true,
271
+ spanAttributes: {
272
+ "app.slack.team_id": teamId
273
+ }
274
+ }
275
+ );
276
+ const responseTeamId = parseSlackTeamId(response.team?.id);
277
+ const domain = parseSlackTeamDomain(response.team?.domain);
278
+ if (!domain || !responseTeamId || responseTeamId !== teamId) {
279
+ writeTeamDomainCache(teamId, void 0);
280
+ return void 0;
281
+ }
282
+ writeTeamDomainCache(teamId, domain);
283
+ return domain;
284
+ } catch {
285
+ writeTeamDomainCache(teamId, void 0);
286
+ return void 0;
287
+ }
288
+ }
289
+ async function resolveSlackTeamDomain(teamId) {
290
+ const parsedTeamId = parseSlackTeamId(teamId);
291
+ if (!parsedTeamId) return void 0;
292
+ const cached = readTeamDomainCache(parsedTeamId);
293
+ if (cached !== void 0) {
294
+ return cached ?? void 0;
295
+ }
296
+ const pending = teamDomainInflight.get(parsedTeamId);
297
+ if (pending) return pending;
298
+ const lookup = fetchSlackTeamDomain(parsedTeamId).finally(() => {
299
+ teamDomainInflight.delete(parsedTeamId);
300
+ });
301
+ teamDomainInflight.set(parsedTeamId, lookup);
302
+ return lookup;
303
+ }
304
+ async function resolveSlackTeamDomains(teamIds) {
305
+ const uniqueTeamIds = [
306
+ ...new Set(
307
+ [...teamIds].map((teamId) => parseSlackTeamId(teamId)).filter((teamId) => teamId !== void 0)
308
+ )
309
+ ];
310
+ const resolved = await Promise.all(
311
+ uniqueTeamIds.map(async (teamId) => {
312
+ const domain = await resolveSlackTeamDomain(teamId);
313
+ return domain ? [teamId, domain] : void 0;
314
+ })
315
+ );
316
+ return new Map(
317
+ resolved.filter(
318
+ (entry) => entry !== void 0
319
+ )
320
+ );
321
+ }
322
+
203
323
  // src/chat/pi/sql-model-usage.ts
204
324
  import { and as and2, eq as eq2, sql } from "drizzle-orm";
205
325
  var message = sql`${juniorConversationEvents.payload}`;
@@ -873,17 +993,6 @@ async function readConversationEventPage(executor, args) {
873
993
  // src/api/conversations/list.ts
874
994
  import { and as and6, asc as asc2, desc as desc2, eq as eq7, isNull as isNull3 } from "drizzle-orm";
875
995
 
876
- // src/chat/slack/source-link.ts
877
- function buildSlackSourceUrl(args) {
878
- const channelId = parseSlackChannelId(args.channelId);
879
- const teamId = parseSlackTeamId(args.teamId);
880
- if (!channelId || !teamId) return void 0;
881
- const url = new URL("https://slack.com/app_redirect");
882
- url.searchParams.set("channel", channelId);
883
- url.searchParams.set("team", teamId);
884
- return url.toString();
885
- }
886
-
887
996
  // src/api/conversations/shared.ts
888
997
  function slackStatsLocationLabel(input) {
889
998
  const channelId = input.channel;
@@ -927,11 +1036,21 @@ function surfaceFromSource(source, conversationId) {
927
1036
  }
928
1037
  return surfaceFromConversationId(conversationId);
929
1038
  }
930
- function sourceUrlFromConversation(conversation, canViewPrivateContent) {
931
- if (!canViewPrivateContent || conversation.sessionSource?.platform !== "slack") {
1039
+ function sourceUrlFromConversation(args) {
1040
+ const { conversation } = args;
1041
+ if (!args.canViewPrivateContent || conversation.sessionSource?.platform !== "slack") {
932
1042
  return void 0;
933
1043
  }
934
- return buildSlackSourceUrl(conversation.sessionSource);
1044
+ const teamDomain = args.teamDomainByTeamId?.get(
1045
+ conversation.sessionSource.teamId
1046
+ );
1047
+ const threadTs = conversation.sessionSource.threadTs;
1048
+ if (!teamDomain || !threadTs) return void 0;
1049
+ return buildSlackSourceUrl({
1050
+ channelId: conversation.sessionSource.channelId,
1051
+ teamDomain,
1052
+ threadTs
1053
+ });
935
1054
  }
936
1055
  function actorIdentityReport(actor) {
937
1056
  if (!actor) return void 0;
@@ -1009,10 +1128,11 @@ function conversationSummaryFromStoredConversation(args) {
1009
1128
  conversation.conversationId
1010
1129
  );
1011
1130
  const actorIdentity = actorIdentityReport(conversation.actor);
1012
- const sourceUrl = sourceUrlFromConversation(
1131
+ const sourceUrl = sourceUrlFromConversation({
1132
+ canViewPrivateContent,
1013
1133
  conversation,
1014
- canViewPrivateContent
1015
- );
1134
+ ...args.teamDomainByTeamId ? { teamDomainByTeamId: args.teamDomainByTeamId } : {}
1135
+ });
1016
1136
  const slackThread = parseSlackThreadId(conversation.conversationId);
1017
1137
  const channelName = channelNameFromConversation(
1018
1138
  conversation,
@@ -1420,8 +1540,16 @@ async function readConversationFeedFromSql(options = {}) {
1420
1540
  options.limit ?? CONVERSATION_FEED_LIMIT,
1421
1541
  options.actorEmail
1422
1542
  );
1423
- const conversationIds = rows.map((row) => row.conversation.conversationId);
1424
- const [accessByConversation, auxiliaryCostsByRoot, metricsByRoot] = await Promise.all([
1543
+ const conversations = rows.map((row) => conversationFromRow(row));
1544
+ const conversationIds = conversations.map(
1545
+ (conversation) => conversation.conversationId
1546
+ );
1547
+ const [
1548
+ accessByConversation,
1549
+ auxiliaryCostsByRoot,
1550
+ metricsByRoot,
1551
+ teamDomainByTeamId
1552
+ ] = await Promise.all([
1425
1553
  readConversationAccessFromSql(
1426
1554
  db,
1427
1555
  conversationIds,
@@ -1430,18 +1558,23 @@ async function readConversationFeedFromSql(options = {}) {
1430
1558
  readConversationAuxiliaryCostsFromSql(db, conversationIds, {
1431
1559
  includeDescendants: true
1432
1560
  }),
1433
- readRootConversationMetricsFromSql(db, conversationIds)
1561
+ readRootConversationMetricsFromSql(db, conversationIds),
1562
+ resolveSlackTeamDomains(
1563
+ conversations.flatMap(
1564
+ (conversation) => conversation.sessionSource?.platform === "slack" ? [conversation.sessionSource.teamId] : []
1565
+ )
1566
+ )
1434
1567
  ]);
1435
1568
  return {
1436
- conversations: rows.map((row) => {
1437
- const metrics = metricsByRoot.get(row.conversation.conversationId);
1569
+ conversations: conversations.map((conversation, index) => {
1570
+ const row = rows[index];
1571
+ const metrics = metricsByRoot.get(conversation.conversationId);
1438
1572
  return conversationSummaryFromStoredConversation({
1439
- conversation: conversationFromRow(row),
1440
- access: accessByConversation.get(row.conversation.conversationId),
1441
- auxiliaryCosts: auxiliaryCostsByRoot.get(
1442
- row.conversation.conversationId
1443
- ),
1573
+ conversation,
1574
+ access: accessByConversation.get(conversation.conversationId),
1575
+ auxiliaryCosts: auxiliaryCostsByRoot.get(conversation.conversationId),
1444
1576
  durationMs: metrics?.durationMs ?? row.conversation.durationMs,
1577
+ teamDomainByTeamId,
1445
1578
  ...row.destination?.visibility === "public" ? { locationId: row.destination.id } : {},
1446
1579
  usage: metrics?.usage ?? row.conversation.usage ?? void 0
1447
1580
  });
@@ -1487,6 +1620,7 @@ function projectConversationDetail(args) {
1487
1620
  conversation,
1488
1621
  durationMs: args.durationMs,
1489
1622
  ...args.locationId ? { locationId: args.locationId } : {},
1623
+ ...args.teamDomainByTeamId ? { teamDomainByTeamId: args.teamDomainByTeamId } : {},
1490
1624
  usage: args.usage
1491
1625
  }),
1492
1626
  annotations: canExposePayload ? args.annotations : [],
@@ -1516,7 +1650,8 @@ async function readConversationDetailFromSql(conversationId, options) {
1516
1650
  annotations,
1517
1651
  auxiliaryCostsByConversation,
1518
1652
  modelUsage,
1519
- metricsByRoot
1653
+ metricsByRoot,
1654
+ teamDomainByTeamId
1520
1655
  ] = await Promise.all([
1521
1656
  readConversationAccessFromSql(
1522
1657
  getDb(),
@@ -1534,6 +1669,9 @@ async function readConversationDetailFromSql(conversationId, options) {
1534
1669
  readRootConversationMetricsFromSql(
1535
1670
  getDb(),
1536
1671
  includeDescendantMetrics ? [conversationId] : []
1672
+ ),
1673
+ resolveSlackTeamDomains(
1674
+ record.conversation.sessionSource?.platform === "slack" ? [record.conversation.sessionSource.teamId] : []
1537
1675
  )
1538
1676
  ]);
1539
1677
  const access = accessByConversation.get(conversationId);
@@ -1551,6 +1689,7 @@ async function readConversationDetailFromSql(conversationId, options) {
1551
1689
  durationMs: metrics?.durationMs ?? record.durationMs,
1552
1690
  events: page.events,
1553
1691
  modelUsage,
1692
+ teamDomainByTeamId,
1554
1693
  ...page.previousSeq === void 0 ? {} : { previousSeq: page.previousSeq },
1555
1694
  usage: metrics?.usage ?? record.usage ?? void 0
1556
1695
  });
@@ -1803,9 +1942,10 @@ function metricDays(rows, endMs) {
1803
1942
  const date = cursor.toISOString().slice(0, 10);
1804
1943
  const row = byDate.get(date);
1805
1944
  days.push({
1945
+ conversations: row?.conversations ?? 0,
1806
1946
  date,
1807
1947
  durationMs: row?.durationMs ?? 0,
1808
- ...row?.costUsd !== null && row?.costUsd !== void 0 ? { costUsd: row.costUsd } : {},
1948
+ ...row?.costUsd !== null && row?.costUsd !== void 0 ? { costUsd: addUsd(void 0, row.costUsd) } : {},
1809
1949
  ...row?.tokens !== null && row?.tokens !== void 0 ? { tokens: row.tokens } : {}
1810
1950
  });
1811
1951
  }
@@ -1916,6 +2056,7 @@ async function aggregateStats(db, start, end) {
1916
2056
  juniorDestinations.visibility
1917
2057
  ),
1918
2058
  db.select({
2059
+ conversations: treeAggregateColumns.conversations,
1919
2060
  costUsd: treeAggregateColumns.costUsd,
1920
2061
  date: activityDate,
1921
2062
  durationMs: treeAggregateColumns.durationMs,
@@ -2029,7 +2170,7 @@ function readDescriptionText(home) {
2029
2170
  }
2030
2171
  }
2031
2172
  async function readSkillReports() {
2032
- const { discoverSkills } = await import("./skills-KXMT3DRA.js");
2173
+ const { discoverSkills } = await import("./skills-4ARJADHQ.js");
2033
2174
  const skills = await discoverSkills();
2034
2175
  return skillReportsSchema.parse(
2035
2176
  skills.map((skill) => ({
@@ -2039,7 +2180,7 @@ async function readSkillReports() {
2039
2180
  );
2040
2181
  }
2041
2182
  async function readPlugins() {
2042
- const { pluginCatalogRuntime } = await import("./catalog-runtime-WSZQGC4D.js");
2183
+ const { pluginCatalogRuntime } = await import("./catalog-runtime-IU3QF4GG.js");
2043
2184
  return pluginsSchema.parse(
2044
2185
  pluginCatalogRuntime.getProviders().map((plugin) => ({
2045
2186
  configKeys: plugin.manifest.configKeys ?? [],
@@ -2052,7 +2193,7 @@ async function readPlugins() {
2052
2193
  async function readRuntimeInfoReport() {
2053
2194
  const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
2054
2195
  import("./discovery-GUFTFBTL.js"),
2055
- import("./catalog-runtime-WSZQGC4D.js"),
2196
+ import("./catalog-runtime-IU3QF4GG.js"),
2056
2197
  readPlugins(),
2057
2198
  readSkillReports()
2058
2199
  ]);
@@ -2068,7 +2209,7 @@ async function readRuntimeInfoReport() {
2068
2209
  }
2069
2210
  async function readPluginOperationalReportFeed() {
2070
2211
  const nowMs = Date.now();
2071
- const { getPluginOperationalReports } = await import("./agent-hooks-2KDSPPO4.js");
2212
+ const { getPluginOperationalReports } = await import("./agent-hooks-SCR74Q3E.js");
2072
2213
  return pluginOperationalReportFeedSchema.parse({
2073
2214
  source: "plugins",
2074
2215
  generatedAt: new Date(nowMs).toISOString(),
package/dist/app.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Hono } from "hono";
2
+ import { type ExperimentalFeaturesConfig } from "@/chat/experimental";
2
3
  import { type SandboxResourceConfig } from "@/chat/sandbox/resources";
3
4
  import { type JuniorPluginSet } from "./plugins";
4
5
  import { type VercelConversationWorkCallbackOptions } from "@/chat/task-execution/vercel-callback";
@@ -9,6 +10,12 @@ export type { JuniorPluginInput, JuniorPluginSet, JuniorPluginSetOptions, } from
9
10
  export interface JuniorAppOptions {
10
11
  /** Authenticated dashboard mounted by core when configured. */
11
12
  dashboard?: JuniorDashboardOptions;
13
+ /**
14
+ * Opt into unstable product features. Experimental keys may change or be
15
+ * removed without a stable migration path; leave unset in production unless
16
+ * you are deliberately dogfooding a pre-stable surface.
17
+ */
18
+ experimental?: ExperimentalFeaturesConfig;
12
19
  /** Slack-specific overrides applied after env parsing. */
13
20
  slack?: {
14
21
  /** Slack emoji shown while Junior is processing. Defaults to `eyes`. */
@@ -16,7 +23,7 @@ export interface JuniorAppOptions {
16
23
  /** Slack emoji shown after a turn completes. Defaults to `white_check_mark`. */
17
24
  completedReactionEmoji?: string;
18
25
  };
19
- /** Install-wide provider defaults (`provider.key` format). Channel overrides take precedence. */
26
+ /** Install-wide provider defaults. Unregistered `provider.key` entries warn at startup. */
20
27
  configDefaults?: Record<string, unknown>;
21
28
  /** Queue consumer wiring for the durable conversation worker. */
22
29
  conversationWork?: VercelConversationWorkCallbackOptions;