@sentry/junior 0.56.0 → 0.58.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 (62) hide show
  1. package/dist/app.js +4239 -5724
  2. package/dist/chat/agent-dispatch/context.d.ts +1 -0
  3. package/dist/chat/agent-dispatch/types.d.ts +0 -1
  4. package/dist/chat/conversation-privacy.d.ts +23 -0
  5. package/dist/chat/logging.d.ts +2 -0
  6. package/dist/chat/mcp/tool-manager.d.ts +18 -5
  7. package/dist/chat/mcp/tool-name.d.ts +2 -0
  8. package/dist/chat/pi/client.d.ts +2 -0
  9. package/dist/chat/pi/derived-state.d.ts +5 -0
  10. package/dist/chat/pi/traced-stream.d.ts +5 -1
  11. package/dist/chat/plugins/state.d.ts +4 -1
  12. package/dist/chat/prompt.d.ts +3 -9
  13. package/dist/chat/respond-helpers.d.ts +5 -3
  14. package/dist/chat/respond.d.ts +1 -0
  15. package/dist/chat/runtime/conversation-message.d.ts +10 -0
  16. package/dist/chat/runtime/processing-reaction.d.ts +2 -4
  17. package/dist/chat/runtime/reply-executor.d.ts +13 -16
  18. package/dist/chat/runtime/slack-runtime.d.ts +19 -32
  19. package/dist/chat/runtime/thread-state.d.ts +1 -1
  20. package/dist/chat/runtime/turn-input.d.ts +29 -0
  21. package/dist/chat/runtime/turn-preparation.d.ts +4 -24
  22. package/dist/chat/runtime/turn.d.ts +2 -3
  23. package/dist/chat/sentry-links.d.ts +4 -0
  24. package/dist/chat/services/context-compaction.d.ts +3 -4
  25. package/dist/chat/services/pending-auth.d.ts +1 -1
  26. package/dist/chat/services/subscribed-reply-policy.d.ts +2 -13
  27. package/dist/chat/services/timeout-resume.d.ts +1 -2
  28. package/dist/chat/services/turn-session-record.d.ts +82 -0
  29. package/dist/chat/slack/assistant-thread/title.d.ts +4 -1
  30. package/dist/chat/state/artifacts.d.ts +1 -0
  31. package/dist/chat/state/conversation.d.ts +0 -1
  32. package/dist/chat/state/session-log.d.ts +117 -0
  33. package/dist/chat/state/ttl.d.ts +2 -0
  34. package/dist/chat/state/turn-session.d.ts +89 -0
  35. package/dist/chat/tools/advisor/tool.d.ts +2 -0
  36. package/dist/chat/tools/agent-tools.d.ts +2 -1
  37. package/dist/chat/tools/skill/call-mcp-tool.d.ts +7 -3
  38. package/dist/chat/tools/skill/search-mcp-tools.d.ts +15 -3
  39. package/dist/chat/tools/types.d.ts +0 -1
  40. package/dist/{chunk-AA5TIFN5.js → chunk-FKEKRBUB.js} +267 -735
  41. package/dist/{chunk-TTUY467K.js → chunk-H652GMDH.js} +30 -14
  42. package/dist/chunk-I4FDGMFI.js +950 -0
  43. package/dist/{chunk-D3G3YOU4.js → chunk-ITOW4DED.js} +1 -1
  44. package/dist/chunk-QDGD5WVN.js +708 -0
  45. package/dist/cli/check.js +2 -2
  46. package/dist/cli/init.js +0 -1
  47. package/dist/cli/snapshot-warmup.js +5 -3
  48. package/dist/instrumentation.js +3 -0
  49. package/dist/reporting.d.ts +113 -0
  50. package/dist/reporting.js +390 -0
  51. package/package.json +26 -11
  52. package/dist/chat/scheduler/cadence.d.ts +0 -24
  53. package/dist/chat/scheduler/plugin.d.ts +0 -2
  54. package/dist/chat/scheduler/prompt.d.ts +0 -7
  55. package/dist/chat/scheduler/store.d.ts +0 -49
  56. package/dist/chat/scheduler/types.d.ts +0 -86
  57. package/dist/chat/services/turn-checkpoint.d.ts +0 -74
  58. package/dist/chat/state/pi-session-message-store.d.ts +0 -15
  59. package/dist/chat/state/turn-session-store.d.ts +0 -49
  60. package/dist/chat/tools/slack/schedule-tools.d.ts +0 -29
  61. package/dist/handlers/diagnostics-dashboard.d.ts +0 -2
  62. package/dist/handlers/diagnostics.d.ts +0 -2
package/dist/cli/check.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  parseSkillFile
3
- } from "../chunk-D3G3YOU4.js";
3
+ } from "../chunk-ITOW4DED.js";
4
4
  import {
5
5
  parsePluginManifest
6
- } from "../chunk-TTUY467K.js";
6
+ } from "../chunk-H652GMDH.js";
7
7
  import "../chunk-Z3YD6NHK.js";
8
8
  import "../chunk-5LUISFEY.js";
9
9
  import "../chunk-2KG3PWR4.js";
package/dist/cli/init.js CHANGED
@@ -118,7 +118,6 @@ async function runInit(dir, log = console.log) {
118
118
  },
119
119
  dependencies: {
120
120
  "@sentry/junior": "latest",
121
- "@sentry/node": "^10.0.0",
122
121
  hono: "^4.12.0"
123
122
  },
124
123
  devDependencies: {
@@ -1,12 +1,14 @@
1
1
  import {
2
- disconnectStateAdapter,
3
2
  resolveRuntimeDependencySnapshot
4
- } from "../chunk-AA5TIFN5.js";
3
+ } from "../chunk-QDGD5WVN.js";
4
+ import {
5
+ disconnectStateAdapter
6
+ } from "../chunk-FKEKRBUB.js";
5
7
  import {
6
8
  getPluginProviders,
7
9
  getPluginRuntimeDependencies,
8
10
  getPluginRuntimePostinstall
9
- } from "../chunk-TTUY467K.js";
11
+ } from "../chunk-H652GMDH.js";
10
12
  import "../chunk-Z3YD6NHK.js";
11
13
  import "../chunk-5LUISFEY.js";
12
14
  import "../chunk-2KG3PWR4.js";
@@ -17,6 +17,9 @@ function getBoolean(value, fallback) {
17
17
  return fallback;
18
18
  }
19
19
  function initSentry() {
20
+ if (sentry_exports.getClient()) {
21
+ return;
22
+ }
20
23
  const dsn = process.env.SENTRY_DSN;
21
24
  const enableLogs = getBoolean(process.env.SENTRY_ENABLE_LOGS, Boolean(dsn));
22
25
  sentry_exports.init({
@@ -0,0 +1,113 @@
1
+ import type { AgentTurnUsage } from "@/chat/usage";
2
+ import { getPluginPackageContent } from "@/chat/plugins/registry";
3
+ import { type AgentTurnRequester } from "@/chat/state/turn-session";
4
+ export interface HealthReport {
5
+ status: "ok";
6
+ service: string;
7
+ timestamp: string;
8
+ }
9
+ export interface PluginReport {
10
+ name: string;
11
+ }
12
+ export interface SkillReport {
13
+ name: string;
14
+ pluginProvider?: string;
15
+ }
16
+ export interface RuntimeInfoReport {
17
+ cwd: string;
18
+ homeDir: string;
19
+ descriptionText?: string;
20
+ providers: string[];
21
+ skills: SkillReport[];
22
+ packagedContent: ReturnType<typeof getPluginPackageContent>;
23
+ }
24
+ export interface DashboardSessionReport {
25
+ conversationTitle?: string;
26
+ cumulativeDurationMs?: number;
27
+ cumulativeUsage?: AgentTurnUsage;
28
+ conversationId: string;
29
+ id: string;
30
+ status: "active" | "completed" | "failed" | "hung" | "superseded";
31
+ startedAt: string;
32
+ lastSeenAt: string;
33
+ lastProgressAt: string;
34
+ completedAt?: string;
35
+ surface?: "slack" | "api" | "scheduler" | "internal";
36
+ title?: string;
37
+ requester?: string;
38
+ requesterIdentity?: AgentTurnRequester;
39
+ channel?: string;
40
+ channelName?: string;
41
+ sentryConversationUrl?: string;
42
+ sentryTraceUrl?: string;
43
+ traceId?: string;
44
+ }
45
+ export interface DashboardTranscriptPart {
46
+ bytes?: number;
47
+ chars?: number;
48
+ id?: string;
49
+ input?: unknown;
50
+ inputKeys?: string[];
51
+ inputSizeBytes?: number;
52
+ inputSizeChars?: number;
53
+ inputType?: string;
54
+ name?: string;
55
+ output?: unknown;
56
+ outputKeys?: string[];
57
+ outputSizeBytes?: number;
58
+ outputSizeChars?: number;
59
+ outputType?: string;
60
+ redacted?: boolean;
61
+ text?: string;
62
+ type: string;
63
+ }
64
+ export interface DashboardTranscriptMessage {
65
+ parts: DashboardTranscriptPart[];
66
+ role: string;
67
+ timestamp?: number;
68
+ }
69
+ export interface DashboardTurnReport extends DashboardSessionReport {
70
+ transcriptAvailable: boolean;
71
+ transcriptMetadata?: DashboardTranscriptMessage[];
72
+ transcriptMessageCount?: number;
73
+ transcriptRedacted?: boolean;
74
+ transcriptRedactionReason?: "non_public_conversation";
75
+ transcript: DashboardTranscriptMessage[];
76
+ }
77
+ export interface DashboardConversationReport {
78
+ conversationId: string;
79
+ generatedAt: string;
80
+ turns: DashboardTurnReport[];
81
+ }
82
+ export interface DashboardSessionFeed {
83
+ sessions: DashboardSessionReport[];
84
+ source: "turn_session_records";
85
+ generatedAt: string;
86
+ }
87
+ export interface JuniorReporting {
88
+ /** Read the public runtime health snapshot without exposing discovery data. */
89
+ getHealth(): Promise<HealthReport>;
90
+ /** Read authenticated dashboard runtime discovery data. */
91
+ getRuntimeInfo(): Promise<RuntimeInfoReport>;
92
+ /** Read configured plugin names for authenticated dashboard views. */
93
+ getPlugins(): Promise<PluginReport[]>;
94
+ /** Read discovered skill names for authenticated dashboard views. */
95
+ getSkills(): Promise<SkillReport[]>;
96
+ /**
97
+ * Read recent turn metadata for authenticated dashboard views.
98
+ *
99
+ * Keep this API trace-shaped: callers should rely on timestamps, status,
100
+ * actor, route, usage, and links that can later be reconstructed from spans.
101
+ */
102
+ getSessions(): Promise<DashboardSessionFeed>;
103
+ /**
104
+ * Read one conversation transcript for the dashboard.
105
+ *
106
+ * The current implementation joins turn-session records with expiring session
107
+ * logs, but the API should stay compatible with a future Sentry trace-history
108
+ * source. Avoid adding fields that require Redis-only transcript internals.
109
+ */
110
+ getConversation(conversationId: string): Promise<DashboardConversationReport>;
111
+ }
112
+ /** Create the read-only reporting boundary used by authenticated dashboard routes. */
113
+ export declare function createJuniorReporting(): JuniorReporting;
@@ -0,0 +1,390 @@
1
+ import {
2
+ GET,
3
+ buildSentryConversationUrl,
4
+ buildSentryTraceUrl,
5
+ getAgentTurnSessionRecord,
6
+ listAgentTurnSessionSummaries,
7
+ listAgentTurnSessionSummariesForConversation
8
+ } from "./chunk-I4FDGMFI.js";
9
+ import {
10
+ discoverSkills
11
+ } from "./chunk-ITOW4DED.js";
12
+ import {
13
+ canExposeConversationPayload,
14
+ parseSlackThreadId,
15
+ resolveConversationPrivacy
16
+ } from "./chunk-FKEKRBUB.js";
17
+ import {
18
+ getPluginPackageContent,
19
+ getPluginProviders,
20
+ isRecord
21
+ } from "./chunk-H652GMDH.js";
22
+ import "./chunk-Z3YD6NHK.js";
23
+ import {
24
+ homeDir
25
+ } from "./chunk-5LUISFEY.js";
26
+ import "./chunk-2KG3PWR4.js";
27
+
28
+ // src/reporting.ts
29
+ import { readFileSync } from "fs";
30
+ import path from "path";
31
+ var HUNG_TURN_PROGRESS_MS = 5 * 60 * 1e3;
32
+ var SAFE_METADATA_KEY_LIMIT = 20;
33
+ function readDescriptionText() {
34
+ try {
35
+ const raw = readFileSync(
36
+ path.join(homeDir(), "DESCRIPTION.md"),
37
+ "utf8"
38
+ ).trim();
39
+ return raw || void 0;
40
+ } catch {
41
+ return void 0;
42
+ }
43
+ }
44
+ async function readHealth() {
45
+ const res = GET();
46
+ return await res.json();
47
+ }
48
+ async function readSkills() {
49
+ const skills = await discoverSkills();
50
+ return skills.map((skill) => ({
51
+ name: skill.name,
52
+ pluginProvider: skill.pluginProvider
53
+ }));
54
+ }
55
+ async function readPlugins() {
56
+ return getPluginProviders().map((plugin) => ({
57
+ name: plugin.manifest.name
58
+ }));
59
+ }
60
+ function statusFromCheckpoint(summary) {
61
+ const state = summary.state;
62
+ if (state === "running" && Date.now() - summary.lastProgressAtMs > HUNG_TURN_PROGRESS_MS) {
63
+ return "hung";
64
+ }
65
+ if (state === "running" || state === "awaiting_resume") {
66
+ return "active";
67
+ }
68
+ if (state === "abandoned") {
69
+ return "superseded";
70
+ }
71
+ return state;
72
+ }
73
+ function surfaceFromConversationId(conversationId) {
74
+ return parseSlackThreadId(conversationId) ? "slack" : "internal";
75
+ }
76
+ function titleFromSummary(summary) {
77
+ if (summary.state === "awaiting_resume" && summary.resumeReason) {
78
+ return `Awaiting ${summary.resumeReason} resume`;
79
+ }
80
+ return `Turn ${summary.sessionId}`;
81
+ }
82
+ function requesterLabel(requester) {
83
+ if (!requester) return void 0;
84
+ return requester.email ?? requester.slackUserName ?? requester.fullName ?? requester.slackUserId;
85
+ }
86
+ function safePrivateLabel(summary) {
87
+ const slackThread = parseSlackThreadId(summary.conversationId);
88
+ if (slackThread?.channelId.startsWith("D")) {
89
+ return "Direct Message";
90
+ }
91
+ if (slackThread?.channelId.startsWith("G")) {
92
+ return summary.channelName?.startsWith("mpdm-") ? "Group DM" : "Private Channel";
93
+ }
94
+ return "Private Channel";
95
+ }
96
+ function sessionReportFromSummary(summary) {
97
+ const slackThread = parseSlackThreadId(summary.conversationId);
98
+ const privacy = resolveConversationPrivacy({
99
+ conversationId: summary.conversationId
100
+ });
101
+ const privateLabel = privacy !== "public" ? safePrivateLabel(summary) : void 0;
102
+ const conversationTitle = privateLabel ?? summary.conversationTitle;
103
+ const channelName = privateLabel ?? summary.channelName;
104
+ const requester = requesterLabel(summary.requester);
105
+ const sentryConversationUrl = buildSentryConversationUrl(
106
+ summary.conversationId
107
+ );
108
+ const sentryTraceUrl = summary.traceId ? buildSentryTraceUrl(summary.traceId) : void 0;
109
+ return {
110
+ conversationId: summary.conversationId,
111
+ ...conversationTitle ? { conversationTitle } : {},
112
+ id: summary.sessionId,
113
+ status: statusFromCheckpoint(summary),
114
+ startedAt: new Date(summary.startedAtMs).toISOString(),
115
+ lastProgressAt: new Date(summary.lastProgressAtMs).toISOString(),
116
+ lastSeenAt: new Date(summary.updatedAtMs).toISOString(),
117
+ ...summary.state === "completed" ? { completedAt: new Date(summary.updatedAtMs).toISOString() } : {},
118
+ ...summary.cumulativeDurationMs !== void 0 ? { cumulativeDurationMs: summary.cumulativeDurationMs } : {},
119
+ ...summary.cumulativeUsage ? { cumulativeUsage: summary.cumulativeUsage } : {},
120
+ surface: surfaceFromConversationId(summary.conversationId),
121
+ title: titleFromSummary(summary),
122
+ ...requester ? { requester } : {},
123
+ ...summary.requester ? { requesterIdentity: summary.requester } : {},
124
+ ...slackThread ? { channel: slackThread.channelId } : {},
125
+ ...channelName ? { channelName } : {},
126
+ ...sentryConversationUrl ? { sentryConversationUrl } : {},
127
+ ...summary.traceId ? { traceId: summary.traceId } : {},
128
+ ...sentryTraceUrl ? { sentryTraceUrl } : {}
129
+ };
130
+ }
131
+ function canExposeConversationTranscript(summary) {
132
+ return canExposeConversationPayload({
133
+ conversationId: summary.conversationId
134
+ });
135
+ }
136
+ function textPart(text) {
137
+ return { type: "text", text };
138
+ }
139
+ function recordField(value, names) {
140
+ for (const name of names) {
141
+ if (value[name] !== void 0) {
142
+ return value[name];
143
+ }
144
+ }
145
+ return void 0;
146
+ }
147
+ function normalizeTranscriptPart(part) {
148
+ if (typeof part === "string") {
149
+ return textPart(part);
150
+ }
151
+ if (!isRecord(part)) {
152
+ return { type: "unknown", output: part };
153
+ }
154
+ const rawType = typeof part.type === "string" ? part.type : "unknown";
155
+ if (rawType === "text") {
156
+ const text = recordField(part, ["text", "content"]);
157
+ return textPart(
158
+ typeof text === "string" ? text : JSON.stringify(text) ?? ""
159
+ );
160
+ }
161
+ if (rawType === "toolCall") {
162
+ return {
163
+ type: "tool_call",
164
+ ...typeof part.id === "string" ? { id: part.id } : {},
165
+ ...typeof part.name === "string" ? { name: part.name } : {},
166
+ input: recordField(part, ["arguments", "input", "args"])
167
+ };
168
+ }
169
+ if (rawType === "toolResult") {
170
+ return {
171
+ type: "tool_result",
172
+ ...typeof part.id === "string" ? { id: part.id } : {},
173
+ ...typeof part.name === "string" ? { name: part.name } : {},
174
+ output: recordField(part, ["result", "output", "content"])
175
+ };
176
+ }
177
+ if (rawType === "thinking") {
178
+ return {
179
+ type: "thinking",
180
+ output: recordField(part, ["thinking", "text", "content", "output"])
181
+ };
182
+ }
183
+ return {
184
+ type: rawType,
185
+ output: part
186
+ };
187
+ }
188
+ function normalizeToolResultMessage(record) {
189
+ const content = record.content;
190
+ let output = content;
191
+ if (Array.isArray(content) && content.length === 1 && isRecord(content[0])) {
192
+ const extracted = recordField(content[0], [
193
+ "text",
194
+ "content",
195
+ "output",
196
+ "result"
197
+ ]);
198
+ output = extracted !== void 0 ? extracted : content;
199
+ }
200
+ return {
201
+ type: "tool_result",
202
+ ...typeof record.toolCallId === "string" ? { id: record.toolCallId } : {},
203
+ ...typeof record.name === "string" ? { name: record.name } : typeof record.toolName === "string" ? { name: record.toolName } : {},
204
+ output
205
+ };
206
+ }
207
+ function normalizeTranscriptMessage(message) {
208
+ const record = message;
209
+ const content = record.content;
210
+ const role = typeof record.role === "string" ? record.role : "unknown";
211
+ return {
212
+ role,
213
+ ...typeof record.timestamp === "number" ? { timestamp: record.timestamp } : {},
214
+ parts: role === "toolResult" ? [normalizeToolResultMessage(record)] : Array.isArray(content) ? content.map(normalizeTranscriptPart) : [normalizeTranscriptPart(content)]
215
+ };
216
+ }
217
+ function serializedChars(value) {
218
+ if (typeof value === "string") return value.length;
219
+ return JSON.stringify(value)?.length ?? 0;
220
+ }
221
+ function serializedBytes(value) {
222
+ const serialized = typeof value === "string" ? value : JSON.stringify(value);
223
+ return new TextEncoder().encode(serialized ?? "").byteLength;
224
+ }
225
+ function payloadType(value) {
226
+ return Array.isArray(value) ? "array" : typeof value;
227
+ }
228
+ function payloadKeys(value) {
229
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
230
+ return void 0;
231
+ }
232
+ const keys = Object.keys(value).slice(
233
+ 0,
234
+ SAFE_METADATA_KEY_LIMIT
235
+ );
236
+ return keys.length > 0 ? keys : void 0;
237
+ }
238
+ function redactedPayloadFields(prefix, value) {
239
+ const keys = payloadKeys(value);
240
+ return {
241
+ [`${prefix}Type`]: payloadType(value),
242
+ [`${prefix}SizeBytes`]: serializedBytes(value),
243
+ [`${prefix}SizeChars`]: serializedChars(value),
244
+ ...keys ? { [`${prefix}Keys`]: keys } : {}
245
+ };
246
+ }
247
+ function redactTranscriptPart(part) {
248
+ if (part.type === "text") {
249
+ return {
250
+ type: "text",
251
+ redacted: true,
252
+ bytes: serializedBytes(part.text ?? ""),
253
+ chars: serializedChars(part.text ?? "")
254
+ };
255
+ }
256
+ if (part.type === "thinking") {
257
+ return {
258
+ type: "thinking",
259
+ redacted: true,
260
+ ...redactedPayloadFields("output", part.output)
261
+ };
262
+ }
263
+ if (part.type === "tool_call") {
264
+ return {
265
+ type: "tool_call",
266
+ redacted: true,
267
+ ...part.id ? { id: part.id } : {},
268
+ ...part.name ? { name: part.name } : {},
269
+ ...redactedPayloadFields("input", part.input)
270
+ };
271
+ }
272
+ if (part.type === "tool_result") {
273
+ return {
274
+ type: "tool_result",
275
+ redacted: true,
276
+ ...part.id ? { id: part.id } : {},
277
+ ...part.name ? { name: part.name } : {},
278
+ ...redactedPayloadFields("output", part.output)
279
+ };
280
+ }
281
+ return {
282
+ type: part.type,
283
+ redacted: true,
284
+ ...redactedPayloadFields("output", part.output ?? part.input ?? part.text)
285
+ };
286
+ }
287
+ function redactTranscriptMessage(message) {
288
+ return {
289
+ role: message.role,
290
+ ...typeof message.timestamp === "number" ? { timestamp: message.timestamp } : {},
291
+ parts: message.parts.map(redactTranscriptPart)
292
+ };
293
+ }
294
+ function turnScopedMessages(messages) {
295
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
296
+ const record = messages[index];
297
+ if (record.role === "user") {
298
+ return messages.slice(index);
299
+ }
300
+ }
301
+ return messages;
302
+ }
303
+ function traceIdFromTranscript(transcript) {
304
+ for (const message of transcript) {
305
+ for (const part of message.parts) {
306
+ const text = part.text ?? (typeof part.output === "string" ? part.output : typeof part.input === "string" ? part.input : void 0);
307
+ const match = text?.match(
308
+ /\btrace[_-]?id["']?\s*[:=]\s*["']?([a-f0-9]{16,32})\b/i
309
+ );
310
+ if (match?.[1]) {
311
+ return match[1];
312
+ }
313
+ }
314
+ }
315
+ return void 0;
316
+ }
317
+ async function readSessions() {
318
+ const summaries = await listAgentTurnSessionSummaries(50);
319
+ return {
320
+ source: "turn_session_records",
321
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
322
+ sessions: summaries.map(sessionReportFromSummary)
323
+ };
324
+ }
325
+ async function readConversation(conversationId) {
326
+ const summaries = (await listAgentTurnSessionSummariesForConversation(conversationId)).sort(
327
+ (left, right) => left.startedAtMs - right.startedAtMs || left.updatedAtMs - right.updatedAtMs || left.sessionId.localeCompare(right.sessionId)
328
+ );
329
+ const turns = await Promise.all(
330
+ summaries.map(async (summary) => {
331
+ const sessionRecord = await getAgentTurnSessionRecord(
332
+ summary.conversationId,
333
+ summary.sessionId
334
+ );
335
+ const scopedMessages = sessionRecord?.piMessages ? turnScopedMessages(sessionRecord.piMessages) : [];
336
+ const canExposeTranscript = canExposeConversationTranscript(summary);
337
+ const normalizedTranscript = scopedMessages.map(
338
+ normalizeTranscriptMessage
339
+ );
340
+ const transcript = canExposeTranscript ? normalizedTranscript : [];
341
+ const transcriptMetadata = canExposeTranscript ? void 0 : normalizedTranscript.map(redactTranscriptMessage);
342
+ const traceId = summary.traceId ?? sessionRecord?.traceId ?? (canExposeTranscript ? traceIdFromTranscript(transcript) : void 0);
343
+ const sentryTraceUrl = traceId ? buildSentryTraceUrl(traceId) : void 0;
344
+ return {
345
+ ...sessionReportFromSummary(summary),
346
+ ...traceId ? { traceId } : {},
347
+ ...sentryTraceUrl ? { sentryTraceUrl } : {},
348
+ transcriptAvailable: Boolean(sessionRecord) && canExposeTranscript,
349
+ ...sessionRecord && scopedMessages.length > 0 ? { transcriptMessageCount: scopedMessages.length } : {},
350
+ ...!canExposeTranscript ? {
351
+ transcriptMetadata,
352
+ transcriptRedacted: true,
353
+ transcriptRedactionReason: "non_public_conversation"
354
+ } : {},
355
+ transcript
356
+ };
357
+ })
358
+ );
359
+ return {
360
+ conversationId,
361
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
362
+ turns
363
+ };
364
+ }
365
+ function createJuniorReporting() {
366
+ return {
367
+ getHealth: readHealth,
368
+ async getRuntimeInfo() {
369
+ const [plugins, skills] = await Promise.all([
370
+ readPlugins(),
371
+ readSkills()
372
+ ]);
373
+ return {
374
+ cwd: process.cwd(),
375
+ homeDir: homeDir(),
376
+ descriptionText: readDescriptionText(),
377
+ providers: plugins.map((plugin) => plugin.name),
378
+ skills,
379
+ packagedContent: getPluginPackageContent()
380
+ };
381
+ },
382
+ getPlugins: readPlugins,
383
+ getSkills: readSkills,
384
+ getSessions: readSessions,
385
+ getConversation: readConversation
386
+ };
387
+ }
388
+ export {
389
+ createJuniorReporting
390
+ };
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@sentry/junior",
3
- "version": "0.56.0",
3
+ "version": "0.58.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
8
  "type": "module",
9
+ "types": "./dist/app.d.ts",
9
10
  "repository": {
10
11
  "type": "git",
11
12
  "url": "git+https://github.com/getsentry/junior.git",
@@ -15,10 +16,26 @@
15
16
  "junior": "bin/junior.mjs"
16
17
  },
17
18
  "exports": {
18
- ".": "./dist/app.js",
19
- "./instrumentation": "./dist/instrumentation.js",
20
- "./nitro": "./dist/nitro.js",
21
- "./vercel": "./dist/vercel.js"
19
+ ".": {
20
+ "types": "./dist/app.d.ts",
21
+ "default": "./dist/app.js"
22
+ },
23
+ "./instrumentation": {
24
+ "types": "./dist/instrumentation.d.ts",
25
+ "default": "./dist/instrumentation.js"
26
+ },
27
+ "./nitro": {
28
+ "types": "./dist/nitro.d.ts",
29
+ "default": "./dist/nitro.js"
30
+ },
31
+ "./reporting": {
32
+ "types": "./dist/reporting.d.ts",
33
+ "default": "./dist/reporting.js"
34
+ },
35
+ "./vercel": {
36
+ "types": "./dist/vercel.d.ts",
37
+ "default": "./dist/vercel.js"
38
+ }
22
39
  },
23
40
  "files": [
24
41
  "dist",
@@ -35,6 +52,7 @@
35
52
  "@modelcontextprotocol/sdk": "1.29.0",
36
53
  "@sinclair/typebox": "^0.34.49",
37
54
  "@slack/web-api": "^7.16.0",
55
+ "@sentry/node": "10.53.1",
38
56
  "@vercel/functions": "^3.6.0",
39
57
  "@vercel/sandbox": "2.0.0",
40
58
  "ai": "^6.0.190",
@@ -46,13 +64,9 @@
46
64
  "node-html-markdown": "^2.0.0",
47
65
  "yaml": "^2.9.0",
48
66
  "zod": "^4.4.3",
49
- "@sentry/junior-plugin-api": "0.56.0"
50
- },
51
- "peerDependencies": {
52
- "@sentry/node": ">=10.0.0"
67
+ "@sentry/junior-plugin-api": "0.58.0"
53
68
  },
54
69
  "devDependencies": {
55
- "@sentry/node": "10.53.1",
56
70
  "@types/node": "^25.9.1",
57
71
  "dependency-cruiser": "^17.4.0",
58
72
  "msw": "^2.14.6",
@@ -61,7 +75,8 @@
61
75
  "tsup": "^8.5.1",
62
76
  "typescript": "^6.0.3",
63
77
  "vercel": "^54.4.0",
64
- "vitest": "^4.1.7"
78
+ "vitest": "^4.1.7",
79
+ "@sentry/junior-scheduler": "0.58.0"
65
80
  },
66
81
  "scripts": {
67
82
  "build": "tsup && tsc -p tsconfig.build.json --emitDeclarationOnly",
@@ -1,24 +0,0 @@
1
- import type { ScheduledCalendarFrequency, ScheduledTask, ScheduledTaskRecurrence } from "@/chat/scheduler/types";
2
- /** Parse an ISO timestamp into a finite Unix timestamp in milliseconds. */
3
- export declare function parseScheduleTimestamp(value: string): number | undefined;
4
- export interface ZonedDateTimeParts {
5
- day: number;
6
- hour: number;
7
- minute: number;
8
- month: number;
9
- second: number;
10
- weekday: number;
11
- year: number;
12
- }
13
- /** Resolve a UTC timestamp into calendar parts for a named time zone. */
14
- export declare function getZonedDateTimeParts(timestampMs: number, timezone: string): ZonedDateTimeParts;
15
- /** Build a calendar recurrence anchored to an exact first run timestamp. */
16
- export declare function buildCalendarRecurrence(args: {
17
- frequency: ScheduledCalendarFrequency;
18
- interval?: number;
19
- nextRunAtMs: number;
20
- timezone: string;
21
- weekdays?: number[];
22
- }): ScheduledTaskRecurrence;
23
- /** Return the next fire time after a completed run, when the task recurs. */
24
- export declare function getNextRunAtMs(task: ScheduledTask, scheduledForMs: number, afterMs?: number): number | undefined;
@@ -1,2 +0,0 @@
1
- /** Create Junior's built-in trusted scheduler plugin. */
2
- export declare function createSchedulerPlugin(): import("@sentry/junior-plugin-api").JuniorPlugin;
@@ -1,7 +0,0 @@
1
- import { type ScheduledRun, type ScheduledTask } from "@/chat/scheduler/types";
2
- /** Build the marker-delimited user prompt for one scheduled task execution. */
3
- export declare function buildScheduledTaskRunPrompt(args: {
4
- nowMs: number;
5
- run: ScheduledRun;
6
- task: ScheduledTask;
7
- }): string;