@sentry/junior 0.96.0 → 0.97.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 (135) hide show
  1. package/dist/{agent-hooks-5URSMY3O.js → agent-hooks-XSUIVRQS.js} +8 -6
  2. package/dist/{reporting → api}/conversations/activity.d.ts +1 -1
  3. package/dist/api/conversations/detail-projection.d.ts +10 -0
  4. package/dist/api/conversations/detail.d.ts +3 -0
  5. package/dist/api/conversations/detail.query.d.ts +3 -0
  6. package/dist/api/conversations/list.d.ts +3 -0
  7. package/dist/api/conversations/list.query.d.ts +94 -0
  8. package/dist/api/conversations/projection.d.ts +14 -0
  9. package/dist/api/conversations/schema.d.ts +683 -0
  10. package/dist/{reporting → api}/conversations/shared.d.ts +1 -5
  11. package/dist/api/conversations/stats.d.ts +3 -0
  12. package/dist/api/conversations/stats.query.d.ts +3 -0
  13. package/dist/api/conversations/subagent.d.ts +3 -0
  14. package/dist/{reporting → api}/conversations/transcript.d.ts +4 -4
  15. package/dist/api/people/list.d.ts +1 -2
  16. package/dist/api/people/list.query.d.ts +3 -4
  17. package/dist/api/people/profile.d.ts +1 -2
  18. package/dist/api/people/profile.query.d.ts +3 -4
  19. package/dist/api/people/schema.d.ts +193 -0
  20. package/dist/api/people/shared.d.ts +31 -9
  21. package/dist/api/schema.d.ts +20 -0
  22. package/dist/api/schema.js +50 -0
  23. package/dist/api-reference.d.ts +4 -3
  24. package/dist/api.d.ts +3 -0
  25. package/dist/api.js +156 -0
  26. package/dist/app.d.ts +1 -4
  27. package/dist/app.js +100 -366
  28. package/dist/build/virtual-config.d.ts +2 -2
  29. package/dist/{catalog-runtime-MSMAYYIK.js → catalog-runtime-PFHVMHDR.js} +3 -2
  30. package/dist/chat/agent/resume.d.ts +3 -1
  31. package/dist/chat/agent/tools.d.ts +2 -1
  32. package/dist/chat/config.d.ts +1 -8
  33. package/dist/chat/conversations/history.d.ts +241 -27
  34. package/dist/chat/conversations/legacy-advisor-session.d.ts +7 -0
  35. package/dist/chat/conversations/legacy-import.d.ts +2 -2
  36. package/dist/chat/conversations/projection.d.ts +19 -3
  37. package/dist/chat/conversations/sql/legacy-history-import.d.ts +1 -1
  38. package/dist/chat/conversations/sql/store.d.ts +15 -9
  39. package/dist/chat/conversations/store.d.ts +9 -4
  40. package/dist/chat/model-profile.d.ts +14 -0
  41. package/dist/chat/pi/transcript.d.ts +5 -3
  42. package/dist/chat/resource-events/store.d.ts +2 -2
  43. package/dist/chat/services/context-compaction.d.ts +15 -0
  44. package/dist/chat/services/turn-result.d.ts +1 -0
  45. package/dist/chat/services/turn-session-record.d.ts +6 -6
  46. package/dist/chat/state/turn-session.d.ts +16 -5
  47. package/dist/chat/task-execution/store.d.ts +2 -2
  48. package/dist/chat/tools/handoff/tool.d.ts +45 -0
  49. package/dist/chat/tools/types.d.ts +7 -2
  50. package/dist/chat/usage.d.ts +25 -25
  51. package/dist/{chunk-RITD7E5L.js → chunk-35BNLDOJ.js} +338 -577
  52. package/dist/{chunk-PMNN6ST4.js → chunk-3ECW2K2O.js} +7 -2
  53. package/dist/{chunk-5C6XTTFI.js → chunk-3F4OPKGF.js} +89 -55
  54. package/dist/chunk-3V7OFJZC.js +264 -0
  55. package/dist/chunk-4ZNGQH7C.js +25 -0
  56. package/dist/{chunk-S5KZ5LPG.js → chunk-5HLDPVYS.js} +14 -447
  57. package/dist/{chunk-DZENG5ML.js → chunk-6U26PYI5.js} +24 -14
  58. package/dist/chunk-AUUCAFDE.js +546 -0
  59. package/dist/{chunk-6APU57E6.js → chunk-B3IT5END.js} +41 -260
  60. package/dist/chunk-CEA3A3UA.js +86 -0
  61. package/dist/{chunk-YDT7SNCN.js → chunk-D5KZYS4T.js} +1 -1
  62. package/dist/{chunk-YDVEH3SB.js → chunk-EEZCY5WX.js} +78 -28
  63. package/dist/{chunk-2NAZZPPS.js → chunk-EOWXRY5E.js} +1 -1
  64. package/dist/{chunk-GQ3GK22G.js → chunk-FBHZJFHI.js} +2 -2
  65. package/dist/{chunk-CZEX6KIQ.js → chunk-G3E7SCME.js} +0 -23
  66. package/dist/chunk-GUAP3H7O.js +319 -0
  67. package/dist/{chunk-BYZWPRJA.js → chunk-H66UCBPW.js} +6 -4
  68. package/dist/{chunk-L7CDEIVJ.js → chunk-LMJPRYHP.js} +4 -2
  69. package/dist/chunk-LUAE4MGW.js +199 -0
  70. package/dist/{chunk-GY34VGP5.js → chunk-LVA4I4H7.js} +3 -1
  71. package/dist/chunk-LVUKF5CE.js +63 -0
  72. package/dist/{chunk-AAZXTVJT.js → chunk-NG2AV7IB.js} +2 -72
  73. package/dist/chunk-ON6YKIQ7.js +260 -0
  74. package/dist/chunk-PDO5BLNM.js +22 -0
  75. package/dist/chunk-QNVHH5PU.js +20 -0
  76. package/dist/{chunk-P3YFQLEN.js → chunk-T533JLM3.js} +8 -10
  77. package/dist/chunk-UAMKJPDF.js +11 -0
  78. package/dist/chunk-VFH4ZKZT.js +66 -0
  79. package/dist/{chunk-UKHVMPX5.js → chunk-WGXMTFNU.js} +15 -17
  80. package/dist/{chunk-MNTINMWR.js → chunk-WJOSZOON.js} +184 -300
  81. package/dist/chunk-WTYEKPXU.js +451 -0
  82. package/dist/{chunk-IYM2SIVG.js → chunk-XIRPQQVE.js} +605 -363
  83. package/dist/cli/chat.js +24 -21
  84. package/dist/cli/check.js +4 -3
  85. package/dist/cli/init.js +12 -0
  86. package/dist/cli/plugins.js +12 -9
  87. package/dist/cli/snapshot-warmup.js +8 -6
  88. package/dist/cli/upgrade.js +265 -137
  89. package/dist/db/db.d.ts +4 -0
  90. package/dist/db/schema/conversations.d.ts +128 -0
  91. package/dist/db/schema.d.ts +129 -60
  92. package/dist/{db-2D6RMG67.js → db-BWXYIKFQ.js} +3 -3
  93. package/dist/detail-GA6NXWQJ.js +43 -0
  94. package/dist/discovery-RMHYSRL7.js +43 -0
  95. package/dist/handlers/health.d.ts +3 -0
  96. package/dist/instrumentation.js +1 -1
  97. package/dist/{legacy-import-VZ2MEGP7.js → legacy-import-3NQJVGQL.js} +4 -4
  98. package/dist/{api/people/list.js → list-A3WFRIYX.js} +26 -16
  99. package/dist/list-UXJI5Q5X.js +27 -0
  100. package/dist/nitro.d.ts +1 -1
  101. package/dist/nitro.js +2 -1
  102. package/dist/plugin-conversations-DDNGC35A.js +36 -0
  103. package/dist/{api/people/profile.js → profile-4RYDXWTF.js} +33 -18
  104. package/dist/reporting/plugin-conversations.d.ts +3 -0
  105. package/dist/reporting-schema.d.ts +140 -0
  106. package/dist/reporting.d.ts +12 -81
  107. package/dist/{runner-JZBRQP4F.js → runner-JALSYH2P.js} +17 -12
  108. package/dist/skills-MAZXZ2KE.js +26 -0
  109. package/dist/stats-XKXH3PTY.js +217 -0
  110. package/dist/subagent-TZ55XY37.js +48 -0
  111. package/dist/usage-schema.d.ts +25 -0
  112. package/dist/{validation-6XOOQGME.js → validation-FMEAEKCY.js} +4 -3
  113. package/migrations/0000_initial.sql +115 -0
  114. package/migrations/0001_conversation_metrics.sql +4 -0
  115. package/migrations/README.md +12 -30
  116. package/migrations/meta/0000_snapshot.json +1 -33
  117. package/migrations/meta/0001_snapshot.json +972 -0
  118. package/migrations/meta/_journal.json +9 -2
  119. package/package.json +14 -18
  120. package/dist/api/people/types.d.ts +0 -85
  121. package/dist/chat/advisor-request.d.ts +0 -4
  122. package/dist/chat/conversations/sql/migrations.d.ts +0 -22
  123. package/dist/chat/tools/advisor/session-store.d.ts +0 -9
  124. package/dist/chat/tools/advisor/tool.d.ts +0 -72
  125. package/dist/chunk-RAIB6WSG.js +0 -142
  126. package/dist/chunk-WM6KHPBQ.js +0 -48
  127. package/dist/db/schema/migrations.d.ts +0 -58
  128. package/dist/reporting/conversations/context.d.ts +0 -8
  129. package/dist/reporting/conversations/details.d.ts +0 -6
  130. package/dist/reporting/conversations/index.d.ts +0 -4
  131. package/dist/reporting/conversations/statistics.d.ts +0 -4
  132. package/dist/reporting/conversations/summaries.d.ts +0 -20
  133. package/dist/reporting/conversations/types.d.ts +0 -191
  134. package/dist/reporting/conversations.d.ts +0 -1
  135. package/dist/reporting.js +0 -1155
@@ -0,0 +1,199 @@
1
+ import {
2
+ usageSchema
3
+ } from "./chunk-PDO5BLNM.js";
4
+
5
+ // src/api/conversations/schema.ts
6
+ import { z } from "zod";
7
+ var conversationReportStatusSchema = z.enum([
8
+ "active",
9
+ "completed",
10
+ "failed",
11
+ "hung"
12
+ ]);
13
+ var conversationSurfaceSchema = z.enum([
14
+ "api",
15
+ "internal",
16
+ "scheduler",
17
+ "slack"
18
+ ]);
19
+ var conversationUsageSchema = usageSchema;
20
+ var actorIdentitySchema = z.object({
21
+ email: z.string().optional(),
22
+ fullName: z.string().optional(),
23
+ slackUserId: z.string().optional(),
24
+ slackUserName: z.string().optional()
25
+ }).strict();
26
+ var conversationSummaryReportSchema = z.object({
27
+ displayTitle: z.string(),
28
+ cumulativeDurationMs: z.number(),
29
+ cumulativeUsage: conversationUsageSchema.optional(),
30
+ conversationId: z.string(),
31
+ status: conversationReportStatusSchema,
32
+ startedAt: z.string(),
33
+ lastSeenAt: z.string(),
34
+ lastProgressAt: z.string(),
35
+ surface: conversationSurfaceSchema,
36
+ actorIdentity: actorIdentitySchema.optional(),
37
+ channel: z.string().optional(),
38
+ channelName: z.string().optional(),
39
+ channelNameRedacted: z.boolean().optional(),
40
+ sentryTraceUrl: z.string().optional(),
41
+ traceId: z.string().optional()
42
+ }).strict();
43
+ var transcriptPartTypeSchema = z.enum([
44
+ "text",
45
+ "thinking",
46
+ "tool_call",
47
+ "tool_result",
48
+ "unknown"
49
+ ]);
50
+ var transcriptPartSchema = z.object({
51
+ bytes: z.number().optional(),
52
+ chars: z.number().optional(),
53
+ id: z.string().optional(),
54
+ input: z.unknown().optional(),
55
+ inputKeys: z.array(z.string()).optional(),
56
+ inputSizeBytes: z.number().optional(),
57
+ inputSizeChars: z.number().optional(),
58
+ inputType: z.string().optional(),
59
+ name: z.string().optional(),
60
+ output: z.unknown().optional(),
61
+ outputKeys: z.array(z.string()).optional(),
62
+ outputSizeBytes: z.number().optional(),
63
+ outputSizeChars: z.number().optional(),
64
+ outputType: z.string().optional(),
65
+ redacted: z.boolean().optional(),
66
+ sourceType: z.string().optional(),
67
+ text: z.string().optional(),
68
+ type: transcriptPartTypeSchema
69
+ }).strict();
70
+ var transcriptRoleSchema = z.enum([
71
+ "assistant",
72
+ "system",
73
+ "tool",
74
+ "toolResult",
75
+ "unknown",
76
+ "user"
77
+ ]);
78
+ var transcriptMessageSchema = z.object({
79
+ parts: z.array(transcriptPartSchema),
80
+ role: transcriptRoleSchema,
81
+ timestamp: z.number().optional()
82
+ }).strict();
83
+ var conversationActivityStatusSchema = z.enum([
84
+ "aborted",
85
+ "completed",
86
+ "error",
87
+ "running",
88
+ "success"
89
+ ]);
90
+ var conversationSubagentActivityReportSchema = z.object({
91
+ type: z.literal("subagent"),
92
+ createdAt: z.string(),
93
+ endedAt: z.string().optional(),
94
+ id: z.string(),
95
+ modelId: z.string().optional(),
96
+ outcome: z.enum(["success", "error", "aborted"]).optional(),
97
+ parentToolCallId: z.string().optional(),
98
+ reasoningLevel: z.string().optional(),
99
+ status: conversationActivityStatusSchema,
100
+ subagentKind: z.string(),
101
+ transcriptAvailable: z.boolean().optional()
102
+ }).strict();
103
+ var conversationToolActivityReportSchema = z.object({
104
+ type: z.literal("tool_execution"),
105
+ args: z.unknown().optional(),
106
+ createdAt: z.string(),
107
+ id: z.string(),
108
+ inputKeys: z.array(z.string()).optional(),
109
+ inputSizeBytes: z.number().optional(),
110
+ inputSizeChars: z.number().optional(),
111
+ inputType: z.string().optional(),
112
+ redacted: z.boolean().optional(),
113
+ status: conversationActivityStatusSchema,
114
+ subagents: z.array(conversationSubagentActivityReportSchema),
115
+ toolCallId: z.string(),
116
+ toolName: z.string()
117
+ }).strict();
118
+ var conversationActivityReportSchema = z.discriminatedUnion("type", [
119
+ conversationToolActivityReportSchema,
120
+ conversationSubagentActivityReportSchema
121
+ ]);
122
+ var conversationDetailReportSchema = conversationSummaryReportSchema.extend({
123
+ activity: z.array(conversationActivityReportSchema).optional(),
124
+ transcriptAvailable: z.boolean(),
125
+ transcriptMetadata: z.array(transcriptMessageSchema).optional(),
126
+ transcriptMessageCount: z.number().optional(),
127
+ transcriptRedacted: z.boolean().optional(),
128
+ transcriptRedactionReason: z.literal("non_public_conversation").optional(),
129
+ transcriptExpired: z.boolean().optional(),
130
+ transcriptExpiredAt: z.string().optional(),
131
+ transcript: z.array(transcriptMessageSchema),
132
+ generatedAt: z.string(),
133
+ sentryConversationUrl: z.string().optional()
134
+ }).strict();
135
+ var conversationSubagentTranscriptReportSchema = z.object({
136
+ type: z.literal("subagent"),
137
+ createdAt: z.string(),
138
+ endedAt: z.string().optional(),
139
+ id: z.string(),
140
+ modelId: z.string().optional(),
141
+ outcome: z.enum(["success", "error", "aborted"]).optional(),
142
+ parentToolCallId: z.string().optional(),
143
+ reasoningLevel: z.string().optional(),
144
+ status: conversationActivityStatusSchema,
145
+ subagentConversationId: z.string().optional(),
146
+ subagentKind: z.string(),
147
+ subagentSentryConversationUrl: z.string().optional(),
148
+ transcript: z.array(transcriptMessageSchema),
149
+ transcriptAvailable: z.boolean(),
150
+ transcriptMessageCount: z.number().optional(),
151
+ transcriptRedacted: z.boolean().optional(),
152
+ transcriptRedactionReason: z.literal("non_public_conversation").optional(),
153
+ transcriptExpired: z.boolean().optional(),
154
+ transcriptExpiredAt: z.string().optional(),
155
+ unavailableReason: z.enum(["missing_transcript_range", "missing_transcript_ref", "not_found"]).optional()
156
+ }).strict();
157
+ var conversationFeedSchema = z.object({
158
+ conversations: z.array(conversationSummaryReportSchema),
159
+ source: z.literal("conversation_index"),
160
+ generatedAt: z.string()
161
+ }).strict();
162
+ var conversationStatsItemSchema = z.object({
163
+ active: z.number(),
164
+ conversations: z.number(),
165
+ durationMs: z.number(),
166
+ failed: z.number(),
167
+ hung: z.number(),
168
+ label: z.string(),
169
+ costUsd: z.number().optional(),
170
+ tokens: z.number().optional()
171
+ }).strict();
172
+ var conversationStatsReportSchema = z.object({
173
+ active: z.number(),
174
+ conversations: z.number(),
175
+ durationMs: z.number(),
176
+ failed: z.number(),
177
+ generatedAt: z.string(),
178
+ hung: z.number(),
179
+ locations: z.array(conversationStatsItemSchema),
180
+ actors: z.array(conversationStatsItemSchema),
181
+ sampleLimit: z.number(),
182
+ sampleSize: z.number(),
183
+ source: z.literal("conversation_index"),
184
+ costUsd: z.number().optional(),
185
+ tokens: z.number().optional(),
186
+ truncated: z.boolean(),
187
+ windowEnd: z.string(),
188
+ windowStart: z.string()
189
+ }).strict();
190
+
191
+ export {
192
+ actorIdentitySchema,
193
+ conversationSummaryReportSchema,
194
+ conversationDetailReportSchema,
195
+ conversationSubagentTranscriptReportSchema,
196
+ conversationFeedSchema,
197
+ conversationStatsItemSchema,
198
+ conversationStatsReportSchema
199
+ };
@@ -7,6 +7,9 @@ import {
7
7
  parseSlackTeamId
8
8
  } from "./chunk-7FBGKXPE.js";
9
9
 
10
+ // src/chat/conversation-privacy.ts
11
+ import { AsyncLocalStorage } from "async_hooks";
12
+
10
13
  // src/chat/slack/context.ts
11
14
  import { z } from "zod";
12
15
  function toTrimmedSlackString(value) {
@@ -95,7 +98,6 @@ function resolveSlackChannelIdFromMessage(message) {
95
98
  }
96
99
 
97
100
  // src/chat/conversation-privacy.ts
98
- import { AsyncLocalStorage } from "async_hooks";
99
101
  var SAFE_METADATA_KEY_LIMIT = 20;
100
102
  var conversationPrivacyStorage = new AsyncLocalStorage();
101
103
  function privateNarrowingFromChannelId(channelId) {
@@ -0,0 +1,63 @@
1
+ import {
2
+ getClient
3
+ } from "./chunk-6GWA276C.js";
4
+
5
+ // src/chat/sentry-links.ts
6
+ function getSentryOrgSlug() {
7
+ const slug = process.env.SENTRY_ORG_SLUG?.trim();
8
+ return slug || void 0;
9
+ }
10
+ function isSentrySaasDsnHost(host) {
11
+ return host === "sentry.io" || host.endsWith(".sentry.io");
12
+ }
13
+ function buildSentryWebBaseUrl(dsn) {
14
+ if (isSentrySaasDsnHost(dsn.host)) {
15
+ return "https://sentry.io";
16
+ }
17
+ const port = dsn.port ? `:${dsn.port}` : "";
18
+ const path = dsn.path ? `/${dsn.path}` : "";
19
+ return `${dsn.protocol}://${dsn.host}${port}${path}`;
20
+ }
21
+ function buildSentryConversationUrl(conversationId) {
22
+ const client = getClient();
23
+ const dsn = client?.getDsn();
24
+ if (!dsn?.host || !dsn.projectId) {
25
+ return void 0;
26
+ }
27
+ const orgSlug = getSentryOrgSlug();
28
+ if (!orgSlug) {
29
+ return void 0;
30
+ }
31
+ const encodedId = encodeURIComponent(conversationId);
32
+ const params = new URLSearchParams();
33
+ params.set("project", dsn.projectId);
34
+ const path = `explore/conversations/${encodedId}/?${params.toString()}`;
35
+ if (isSentrySaasDsnHost(dsn.host)) {
36
+ return `https://${orgSlug}.sentry.io/${path}`;
37
+ }
38
+ return `${buildSentryWebBaseUrl(dsn)}/organizations/${orgSlug}/${path}`;
39
+ }
40
+ function buildSentryTraceUrl(traceId) {
41
+ const client = getClient();
42
+ const dsn = client?.getDsn();
43
+ if (!dsn?.host || !dsn.projectId) {
44
+ return void 0;
45
+ }
46
+ const orgSlug = getSentryOrgSlug();
47
+ if (!orgSlug) {
48
+ return void 0;
49
+ }
50
+ const encodedTraceId = encodeURIComponent(traceId);
51
+ const params = new URLSearchParams();
52
+ params.set("project", dsn.projectId);
53
+ const path = `performance/trace/${encodedTraceId}/?${params.toString()}`;
54
+ if (isSentrySaasDsnHost(dsn.host)) {
55
+ return `https://${orgSlug}.sentry.io/${path}`;
56
+ }
57
+ return `${buildSentryWebBaseUrl(dsn)}/organizations/${orgSlug}/${path}`;
58
+ }
59
+
60
+ export {
61
+ buildSentryConversationUrl,
62
+ buildSentryTraceUrl
63
+ };
@@ -1,76 +1,9 @@
1
1
  import {
2
2
  normalizeSlackConversationId
3
- } from "./chunk-S5KZ5LPG.js";
3
+ } from "./chunk-WTYEKPXU.js";
4
4
  import {
5
5
  parseSlackThreadId
6
- } from "./chunk-GY34VGP5.js";
7
- import {
8
- getClient
9
- } from "./chunk-6GWA276C.js";
10
-
11
- // src/handlers/health.ts
12
- function GET() {
13
- return Response.json({
14
- status: "ok",
15
- service: "junior",
16
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
17
- });
18
- }
19
-
20
- // src/chat/sentry-links.ts
21
- function getSentryOrgSlug() {
22
- const slug = process.env.SENTRY_ORG_SLUG?.trim();
23
- return slug || void 0;
24
- }
25
- function isSentrySaasDsnHost(host) {
26
- return host === "sentry.io" || host.endsWith(".sentry.io");
27
- }
28
- function buildSentryWebBaseUrl(dsn) {
29
- if (isSentrySaasDsnHost(dsn.host)) {
30
- return "https://sentry.io";
31
- }
32
- const port = dsn.port ? `:${dsn.port}` : "";
33
- const path = dsn.path ? `/${dsn.path}` : "";
34
- return `${dsn.protocol}://${dsn.host}${port}${path}`;
35
- }
36
- function buildSentryConversationUrl(conversationId) {
37
- const client = getClient();
38
- const dsn = client?.getDsn();
39
- if (!dsn?.host || !dsn.projectId) {
40
- return void 0;
41
- }
42
- const orgSlug = getSentryOrgSlug();
43
- if (!orgSlug) {
44
- return void 0;
45
- }
46
- const encodedId = encodeURIComponent(conversationId);
47
- const params = new URLSearchParams();
48
- params.set("project", dsn.projectId);
49
- const path = `explore/conversations/${encodedId}/?${params.toString()}`;
50
- if (isSentrySaasDsnHost(dsn.host)) {
51
- return `https://${orgSlug}.sentry.io/${path}`;
52
- }
53
- return `${buildSentryWebBaseUrl(dsn)}/organizations/${orgSlug}/${path}`;
54
- }
55
- function buildSentryTraceUrl(traceId) {
56
- const client = getClient();
57
- const dsn = client?.getDsn();
58
- if (!dsn?.host || !dsn.projectId) {
59
- return void 0;
60
- }
61
- const orgSlug = getSentryOrgSlug();
62
- if (!orgSlug) {
63
- return void 0;
64
- }
65
- const encodedTraceId = encodeURIComponent(traceId);
66
- const params = new URLSearchParams();
67
- params.set("project", dsn.projectId);
68
- const path = `performance/trace/${encodedTraceId}/?${params.toString()}`;
69
- if (isSentrySaasDsnHost(dsn.host)) {
70
- return `https://${orgSlug}.sentry.io/${path}`;
71
- }
72
- return `${buildSentryWebBaseUrl(dsn)}/organizations/${orgSlug}/${path}`;
73
- }
6
+ } from "./chunk-LVA4I4H7.js";
74
7
 
75
8
  // src/chat/slack/conversation-context.ts
76
9
  function normalizeConversationName(type, channelName) {
@@ -155,9 +88,6 @@ function formatSlackConversationRedactedLabel(context) {
155
88
  }
156
89
 
157
90
  export {
158
- GET,
159
- buildSentryConversationUrl,
160
- buildSentryTraceUrl,
161
91
  conversationVisibilityFromSlackChannelType,
162
92
  resolveSlackChannelTypeFromMessage,
163
93
  resolveSlackConversationContext,
@@ -0,0 +1,260 @@
1
+ import {
2
+ formatSlackConversationRedactedLabel,
3
+ resolveSlackConversationContextFromThreadId
4
+ } from "./chunk-NG2AV7IB.js";
5
+ import {
6
+ getDb,
7
+ juniorConversations,
8
+ juniorDestinations,
9
+ juniorIdentities
10
+ } from "./chunk-35BNLDOJ.js";
11
+ import {
12
+ parseSlackThreadId,
13
+ resolveConversationPrivacy
14
+ } from "./chunk-LVA4I4H7.js";
15
+
16
+ // src/api/conversations/list.query.ts
17
+ import { asc, desc, eq, isNull } from "drizzle-orm";
18
+
19
+ // src/api/conversations/shared.ts
20
+ function slackStatsLocationLabel(input) {
21
+ const channelId = input.channel;
22
+ if (!channelId) return void 0;
23
+ if (input.channelNameRedacted && input.channelName) {
24
+ return input.channelName;
25
+ }
26
+ const name = input.channelName?.replace(/^#/, "");
27
+ if (channelId.startsWith("D")) return "Direct Message";
28
+ if (channelId.startsWith("C")) return name ? `#${name}` : "Public Channel";
29
+ if (channelId.startsWith("G")) {
30
+ if (name?.startsWith("mpdm-")) return "Group DM";
31
+ return "Private Channel";
32
+ }
33
+ return name || channelId;
34
+ }
35
+ function surfaceFallbackLabel(surface) {
36
+ if (surface === "scheduler") return "Scheduler";
37
+ if (surface === "api") return "API";
38
+ if (surface === "internal") return "Internal";
39
+ return "Conversation";
40
+ }
41
+
42
+ // src/api/conversations/projection.ts
43
+ var HUNG_TURN_PROGRESS_MS = 5 * 60 * 1e3;
44
+ var PRIVATE_CONVERSATION_LABEL = "Private Conversation";
45
+ function privateConversationLabel(slackConversation) {
46
+ if (!slackConversation) {
47
+ return PRIVATE_CONVERSATION_LABEL;
48
+ }
49
+ return slackConversation.visibility === "private" ? formatSlackConversationRedactedLabel(slackConversation) ?? PRIVATE_CONVERSATION_LABEL : PRIVATE_CONVERSATION_LABEL;
50
+ }
51
+ function surfaceFromConversationId(conversationId) {
52
+ if (parseSlackThreadId(conversationId)) return "slack";
53
+ if (conversationId.startsWith("scheduler:")) return "scheduler";
54
+ if (conversationId.startsWith("api:")) return "api";
55
+ return "internal";
56
+ }
57
+ function surfaceFromSource(source, conversationId) {
58
+ if (source === "slack" || source === "api" || source === "scheduler") {
59
+ return source;
60
+ }
61
+ return surfaceFromConversationId(conversationId);
62
+ }
63
+ function actorIdentityReport(actor) {
64
+ if (!actor) return void 0;
65
+ const identity = {
66
+ ...actor.email !== void 0 ? { email: actor.email } : {},
67
+ ...actor.fullName !== void 0 ? { fullName: actor.fullName } : {},
68
+ ...actor.slackUserId !== void 0 ? { slackUserId: actor.slackUserId } : {},
69
+ ...actor.slackUserName !== void 0 ? { slackUserName: actor.slackUserName } : {}
70
+ };
71
+ return Object.keys(identity).length > 0 ? identity : void 0;
72
+ }
73
+ function statusFromConversation(conversation, nowMs) {
74
+ if (conversation.execution.status === "idle") {
75
+ return "completed";
76
+ }
77
+ if (conversation.execution.status === "failed") {
78
+ return "failed";
79
+ }
80
+ const updatedAtMs = conversation.execution.updatedAtMs ?? conversation.updatedAtMs;
81
+ if (conversation.execution.status === "running" && nowMs - updatedAtMs > HUNG_TURN_PROGRESS_MS) {
82
+ return "hung";
83
+ }
84
+ return "active";
85
+ }
86
+ function titleFromConversation(args) {
87
+ const slackThread = parseSlackThreadId(args.conversation.conversationId);
88
+ const effectiveChannelName = args.conversation.channelName;
89
+ const slackConversation = resolveSlackConversationContextFromThreadId({
90
+ threadId: args.conversation.conversationId,
91
+ channelName: effectiveChannelName
92
+ });
93
+ const privateLabel = resolveConversationPrivacy({
94
+ conversationId: args.conversation.conversationId,
95
+ visibility: args.conversation.visibility
96
+ }) !== "public" ? privateConversationLabel(slackConversation) : void 0;
97
+ return privateLabel ?? args.conversation.title ?? slackStatsLocationLabel({
98
+ channel: slackThread?.channelId,
99
+ channelName: effectiveChannelName
100
+ }) ?? surfaceFallbackLabel(args.surface);
101
+ }
102
+ function channelNameFromConversation(conversation) {
103
+ const effectiveChannelName = conversation.channelName;
104
+ const slackThread = parseSlackThreadId(conversation.conversationId);
105
+ if (!effectiveChannelName && !slackThread) {
106
+ return void 0;
107
+ }
108
+ const slackConversation = resolveSlackConversationContextFromThreadId({
109
+ threadId: conversation.conversationId,
110
+ channelName: effectiveChannelName
111
+ });
112
+ if (resolveConversationPrivacy({
113
+ conversationId: conversation.conversationId,
114
+ visibility: conversation.visibility
115
+ }) !== "public") {
116
+ return privateConversationLabel(slackConversation);
117
+ }
118
+ return effectiveChannelName;
119
+ }
120
+ function channelNameRedactedFromConversation(conversation) {
121
+ const effectiveChannelName = conversation.channelName;
122
+ const slackThread = parseSlackThreadId(conversation.conversationId);
123
+ if (!effectiveChannelName && !slackThread) {
124
+ return false;
125
+ }
126
+ return resolveConversationPrivacy({
127
+ conversationId: conversation.conversationId,
128
+ visibility: conversation.visibility
129
+ }) !== "public";
130
+ }
131
+ function conversationSummaryFromStoredConversation(args) {
132
+ const { conversation, durationMs, nowMs, usage } = args;
133
+ const surface = surfaceFromSource(
134
+ conversation.source,
135
+ conversation.conversationId
136
+ );
137
+ const actorIdentity = actorIdentityReport(conversation.actor);
138
+ const slackThread = parseSlackThreadId(conversation.conversationId);
139
+ const channelName = channelNameFromConversation(conversation);
140
+ const channelNameRedacted = channelNameRedactedFromConversation(conversation);
141
+ return {
142
+ conversationId: conversation.conversationId,
143
+ cumulativeDurationMs: durationMs,
144
+ displayTitle: titleFromConversation({ conversation, surface }),
145
+ lastProgressAt: new Date(
146
+ conversation.execution.updatedAtMs ?? conversation.updatedAtMs
147
+ ).toISOString(),
148
+ lastSeenAt: new Date(conversation.lastActivityAtMs).toISOString(),
149
+ startedAt: new Date(conversation.createdAtMs).toISOString(),
150
+ status: statusFromConversation(conversation, nowMs),
151
+ surface,
152
+ ...usage ? { cumulativeUsage: usage } : {},
153
+ ...actorIdentity ? { actorIdentity } : {},
154
+ ...slackThread ? { channel: slackThread.channelId } : {},
155
+ ...channelName ? { channelName } : {},
156
+ ...channelNameRedacted ? { channelNameRedacted: true } : {}
157
+ };
158
+ }
159
+
160
+ // src/api/conversations/list.query.ts
161
+ var CONVERSATION_FEED_LIMIT = 50;
162
+ async function conversationRows(db, limit) {
163
+ return db.select({
164
+ conversation: juniorConversations,
165
+ destinationVisibility: juniorDestinations.visibility,
166
+ identityDisplayName: juniorIdentities.displayName,
167
+ identityEmail: juniorIdentities.email,
168
+ identityHandle: juniorIdentities.handle,
169
+ identityProvider: juniorIdentities.provider,
170
+ identitySubjectId: juniorIdentities.providerSubjectId,
171
+ identityTenantId: juniorIdentities.providerTenantId
172
+ }).from(juniorConversations).leftJoin(
173
+ juniorDestinations,
174
+ eq(juniorDestinations.id, juniorConversations.destinationId)
175
+ ).leftJoin(
176
+ juniorIdentities,
177
+ eq(juniorIdentities.id, juniorConversations.actorIdentityId)
178
+ ).where(isNull(juniorConversations.parentConversationId)).orderBy(
179
+ desc(juniorConversations.lastActivityAt),
180
+ asc(juniorConversations.conversationId)
181
+ ).limit(limit);
182
+ }
183
+ function conversationFromRow(row) {
184
+ const value = row.conversation;
185
+ const actor = row.identityProvider === "slack" ? {
186
+ platform: "slack",
187
+ ...row.identityEmail ? { email: row.identityEmail } : {},
188
+ ...row.identityDisplayName ? { fullName: row.identityDisplayName } : {},
189
+ ...row.identitySubjectId ? { slackUserId: row.identitySubjectId } : {},
190
+ ...row.identityHandle ? { slackUserName: row.identityHandle } : {},
191
+ ...row.identityTenantId ? { teamId: row.identityTenantId } : {}
192
+ } : void 0;
193
+ return {
194
+ schemaVersion: 1,
195
+ conversationId: value.conversationId,
196
+ createdAtMs: value.createdAt.getTime(),
197
+ lastActivityAtMs: value.lastActivityAt.getTime(),
198
+ updatedAtMs: value.updatedAt.getTime(),
199
+ execution: {
200
+ status: value.executionStatus,
201
+ ...value.runId ? { runId: value.runId } : {},
202
+ ...value.executionUpdatedAt ? { updatedAtMs: value.executionUpdatedAt.getTime() } : {}
203
+ },
204
+ ...actor ? { actor } : {},
205
+ ...value.channelName ? { channelName: value.channelName } : {},
206
+ ...value.source ? { source: value.source } : {},
207
+ ...value.title ? { title: value.title } : {},
208
+ ...value.transcriptPurgedAt ? { transcriptPurgedAtMs: value.transcriptPurgedAt.getTime() } : {},
209
+ ...row.destinationVisibility ? {
210
+ visibility: row.destinationVisibility === "public" ? "public" : "private"
211
+ } : {}
212
+ };
213
+ }
214
+ async function readConversationRecordFromSql(conversationId) {
215
+ const db = getDb();
216
+ const rows = await db.select({
217
+ conversation: juniorConversations,
218
+ destinationVisibility: juniorDestinations.visibility,
219
+ identityDisplayName: juniorIdentities.displayName,
220
+ identityEmail: juniorIdentities.email,
221
+ identityHandle: juniorIdentities.handle,
222
+ identityProvider: juniorIdentities.provider,
223
+ identitySubjectId: juniorIdentities.providerSubjectId,
224
+ identityTenantId: juniorIdentities.providerTenantId
225
+ }).from(juniorConversations).leftJoin(
226
+ juniorDestinations,
227
+ eq(juniorDestinations.id, juniorConversations.destinationId)
228
+ ).leftJoin(
229
+ juniorIdentities,
230
+ eq(juniorIdentities.id, juniorConversations.actorIdentityId)
231
+ ).where(eq(juniorConversations.conversationId, conversationId)).limit(1);
232
+ const row = rows[0];
233
+ return row ? {
234
+ conversation: conversationFromRow(row),
235
+ durationMs: row.conversation.durationMs,
236
+ usage: row.conversation.usage
237
+ } : void 0;
238
+ }
239
+ async function readConversationFeedFromSql(limit = CONVERSATION_FEED_LIMIT) {
240
+ const nowMs = Date.now();
241
+ const rows = await conversationRows(getDb(), limit);
242
+ return {
243
+ conversations: rows.map(
244
+ (row) => conversationSummaryFromStoredConversation({
245
+ conversation: conversationFromRow(row),
246
+ durationMs: row.conversation.durationMs,
247
+ nowMs,
248
+ usage: row.conversation.usage ?? void 0
249
+ })
250
+ ),
251
+ generatedAt: new Date(nowMs).toISOString(),
252
+ source: "conversation_index"
253
+ };
254
+ }
255
+
256
+ export {
257
+ conversationSummaryFromStoredConversation,
258
+ readConversationRecordFromSql,
259
+ readConversationFeedFromSql
260
+ };
@@ -0,0 +1,22 @@
1
+ // src/usage-schema.ts
2
+ import { z } from "zod";
3
+ var usageCostSchema = z.object({
4
+ input: z.number().finite().nonnegative().optional(),
5
+ output: z.number().finite().nonnegative().optional(),
6
+ cacheRead: z.number().finite().nonnegative().optional(),
7
+ cacheWrite: z.number().finite().nonnegative().optional(),
8
+ total: z.number().finite().nonnegative().optional()
9
+ }).strict();
10
+ var usageSchema = z.object({
11
+ inputTokens: z.number().int().nonnegative().optional(),
12
+ outputTokens: z.number().int().nonnegative().optional(),
13
+ cachedInputTokens: z.number().int().nonnegative().optional(),
14
+ cacheCreationTokens: z.number().int().nonnegative().optional(),
15
+ reasoningTokens: z.number().int().nonnegative().optional(),
16
+ totalTokens: z.number().int().nonnegative().optional(),
17
+ cost: usageCostSchema.optional()
18
+ }).strict();
19
+
20
+ export {
21
+ usageSchema
22
+ };
@@ -0,0 +1,20 @@
1
+ import {
2
+ healthReportSchema
3
+ } from "./chunk-CEA3A3UA.js";
4
+
5
+ // src/handlers/health.ts
6
+ function readHealthReport() {
7
+ return healthReportSchema.parse({
8
+ status: "ok",
9
+ service: "junior",
10
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
11
+ });
12
+ }
13
+ function GET() {
14
+ return Response.json(readHealthReport());
15
+ }
16
+
17
+ export {
18
+ readHealthReport,
19
+ GET
20
+ };