@sentry/junior 0.72.0 → 0.74.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 (109) hide show
  1. package/bin/junior.mjs +12 -10
  2. package/dist/api-reference.d.ts +1 -1
  3. package/dist/app.d.ts +11 -2
  4. package/dist/app.js +1233 -13143
  5. package/dist/chat/agent-dispatch/runner.d.ts +2 -0
  6. package/dist/chat/agent-dispatch/store.d.ts +2 -2
  7. package/dist/chat/agent-dispatch/types.d.ts +6 -3
  8. package/dist/chat/agent-dispatch/validation.d.ts +2 -3
  9. package/dist/chat/app/production.d.ts +11 -1
  10. package/dist/chat/app/services.d.ts +7 -0
  11. package/dist/chat/config.d.ts +3 -0
  12. package/dist/chat/conversations/configured.d.ts +5 -0
  13. package/dist/chat/conversations/sql/migrations.d.ts +11 -0
  14. package/dist/chat/conversations/sql/schema/conversations.d.ts +435 -0
  15. package/dist/chat/conversations/sql/schema/destinations.d.ts +200 -0
  16. package/dist/chat/conversations/sql/schema/identities.d.ts +214 -0
  17. package/dist/chat/conversations/sql/schema/migrations.d.ts +58 -0
  18. package/dist/chat/conversations/sql/schema/timestamps.d.ts +1 -0
  19. package/dist/chat/conversations/sql/schema.d.ts +910 -0
  20. package/dist/chat/conversations/sql/store.d.ts +52 -0
  21. package/dist/chat/conversations/state.d.ts +4 -0
  22. package/dist/chat/conversations/store.d.ts +57 -0
  23. package/dist/chat/destination.d.ts +3 -1
  24. package/dist/chat/ingress/slack-webhook.d.ts +2 -0
  25. package/dist/chat/logging.d.ts +3 -0
  26. package/dist/chat/oauth-flow.d.ts +1 -1
  27. package/dist/chat/plugins/agent-hooks.d.ts +2 -2
  28. package/dist/chat/plugins/registry.d.ts +2 -0
  29. package/dist/chat/plugins/types.d.ts +2 -0
  30. package/dist/chat/prompt.d.ts +4 -1
  31. package/dist/chat/requester.d.ts +19 -12
  32. package/dist/chat/respond.d.ts +7 -3
  33. package/dist/chat/runtime/agent-continue-runner.d.ts +1 -1
  34. package/dist/chat/runtime/reply-executor.d.ts +3 -1
  35. package/dist/chat/runtime/slack-resume.d.ts +3 -3
  36. package/dist/chat/runtime/slack-runtime.d.ts +13 -3
  37. package/dist/chat/runtime/turn.d.ts +15 -1
  38. package/dist/chat/sandbox/egress-credentials.d.ts +5 -2
  39. package/dist/chat/sandbox/egress-policy.d.ts +5 -1
  40. package/dist/chat/sandbox/egress-proxy.d.ts +2 -0
  41. package/dist/chat/sandbox/egress-schemas.d.ts +4 -0
  42. package/dist/chat/sandbox/egress-session.d.ts +3 -1
  43. package/dist/chat/sandbox/egress-tracing.d.ts +7 -0
  44. package/dist/chat/sandbox/sandbox.d.ts +2 -0
  45. package/dist/chat/sandbox/session.d.ts +3 -2
  46. package/dist/chat/services/auth-pause-response.d.ts +1 -1
  47. package/dist/chat/services/auth-pause.d.ts +2 -1
  48. package/dist/chat/services/mcp-auth-orchestration.d.ts +7 -6
  49. package/dist/chat/services/message-actor-identity.d.ts +2 -2
  50. package/dist/chat/services/pending-auth.d.ts +2 -0
  51. package/dist/chat/services/plugin-auth-orchestration.d.ts +14 -12
  52. package/dist/chat/services/turn-result.d.ts +3 -0
  53. package/dist/chat/slack/user.d.ts +2 -2
  54. package/dist/chat/sql/db.d.ts +20 -0
  55. package/dist/chat/sql/neon.d.ts +9 -0
  56. package/dist/chat/sql/schema.d.ts +906 -0
  57. package/dist/chat/state/turn-session.d.ts +3 -0
  58. package/dist/chat/task-execution/slack-work.d.ts +2 -0
  59. package/dist/chat/task-execution/state.d.ts +209 -0
  60. package/dist/chat/task-execution/store.d.ts +30 -114
  61. package/dist/chat/task-execution/vercel-callback.d.ts +2 -0
  62. package/dist/chat/task-execution/worker.d.ts +2 -0
  63. package/dist/chat/tools/slack/canvas-tools.d.ts +3 -2
  64. package/dist/chat/tools/slack/channel-list-messages.d.ts +2 -2
  65. package/dist/chat/tools/slack/channel-post-message.d.ts +3 -2
  66. package/dist/chat/tools/slack/context.d.ts +15 -2
  67. package/dist/chat/tools/slack/message-add-reaction.d.ts +3 -2
  68. package/dist/chat/tools/slack/thread-read.d.ts +2 -2
  69. package/dist/chat/tools/types.d.ts +19 -19
  70. package/dist/chunk-2LUZA3LY.js +275 -0
  71. package/dist/{chunk-6GEYPE6T.js → chunk-3BYAPS6B.js} +30 -6
  72. package/dist/{chunk-VLIO6RQR.js → chunk-6UP2Z2RZ.js} +4 -4
  73. package/dist/{chunk-GB3AL54K.js → chunk-7Q5YOUUT.js} +10 -2
  74. package/dist/{chunk-PP7AGSBU.js → chunk-CYUI7JU5.js} +18 -8
  75. package/dist/{chunk-3FYPXHPL.js → chunk-F6HWCPOC.js} +1 -1
  76. package/dist/{chunk-ZJQPA67D.js → chunk-GM7HTXYC.js} +230 -224
  77. package/dist/{chunk-VSNA5KAB.js → chunk-HYHKTFG2.js} +1338 -1499
  78. package/dist/chunk-JL2SLRAT.js +1970 -0
  79. package/dist/{chunk-4JXCSGSA.js → chunk-M4FLLXXD.js} +1 -1
  80. package/dist/{chunk-55XEZFGD.js → chunk-OR6NQJ5E.js} +2 -2
  81. package/dist/chunk-SJHUF3DP.js +43 -0
  82. package/dist/chunk-SQGMG7OD.js +12801 -0
  83. package/dist/{chunk-QUXPUKBH.js → chunk-Y7X25LFY.js} +1 -1
  84. package/dist/{chunk-ICKIDP7G.js → chunk-YOHFWWBV.js} +1 -1
  85. package/dist/{chunk-XC33FJZN.js → chunk-YRDS7VKO.js} +25 -4
  86. package/dist/cli/chat.js +205 -0
  87. package/dist/cli/check.js +9 -10
  88. package/dist/cli/init.js +1 -1
  89. package/dist/cli/run.js +10 -2
  90. package/dist/cli/snapshot-warmup.js +7 -7
  91. package/dist/cli/upgrade.js +81 -11
  92. package/dist/deployment.d.ts +4 -0
  93. package/dist/handlers/agent-dispatch.d.ts +6 -1
  94. package/dist/handlers/mcp-oauth-callback.d.ts +6 -1
  95. package/dist/handlers/oauth-callback.d.ts +6 -1
  96. package/dist/handlers/sandbox-egress-proxy.d.ts +2 -0
  97. package/dist/handlers/webhooks.d.ts +4 -2
  98. package/dist/instrumentation.js +17 -3
  99. package/dist/nitro.js +9 -10
  100. package/dist/reporting/conversations.d.ts +13 -3
  101. package/dist/reporting.d.ts +9 -2
  102. package/dist/reporting.js +114 -48
  103. package/dist/runner-27NP2TEO.js +259 -0
  104. package/dist/vercel.d.ts +6 -1
  105. package/dist/vercel.js +1 -1
  106. package/package.json +9 -4
  107. package/dist/chunk-6YY4Q3D4.js +0 -12
  108. package/dist/chunk-HNMUVGSR.js +0 -1119
  109. package/dist/chunk-Z3YD6NHK.js +0 -12
@@ -1,6 +1,6 @@
1
1
  // src/vercel.ts
2
2
  function juniorVercelConfig(options = {}) {
3
- const buildCommand = options.buildCommand === void 0 ? "pnpm build" : options.buildCommand;
3
+ const buildCommand = options.buildCommand === void 0 ? "pnpm exec junior upgrade && pnpm build" : options.buildCommand;
4
4
  const config = {
5
5
  framework: "nitro"
6
6
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  destinationKey,
3
3
  parseDestination
4
- } from "./chunk-XC33FJZN.js";
4
+ } from "./chunk-YRDS7VKO.js";
5
5
 
6
6
  // src/plugins.ts
7
7
  function cloneManifests(manifests) {
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  getSlackBotToken
3
- } from "./chunk-ZJQPA67D.js";
3
+ } from "./chunk-GM7HTXYC.js";
4
4
  import {
5
5
  isSlackConversationId,
6
6
  isSlackTeamId,
7
7
  logWarn
8
- } from "./chunk-6GEYPE6T.js";
8
+ } from "./chunk-3BYAPS6B.js";
9
9
 
10
10
  // src/chat/slack/client.ts
11
11
  import { WebClient } from "@slack/web-api";
@@ -277,7 +277,9 @@ async function downloadPrivateSlackFile(url) {
277
277
  }
278
278
 
279
279
  // src/chat/destination.ts
280
- import { destinationSchema } from "@sentry/junior-plugin-api";
280
+ import {
281
+ destinationSchema
282
+ } from "@sentry/junior-plugin-api";
281
283
  function createSlackDestination(input) {
282
284
  const channelId = normalizeSlackConversationId(input.channelId);
283
285
  const teamId = input.teamId?.trim();
@@ -293,10 +295,28 @@ function parseDestination(value) {
293
295
  const parsed = destinationSchema.safeParse(value);
294
296
  return parsed.success ? parsed.data : void 0;
295
297
  }
298
+ function requireSlackDestination(destination, action) {
299
+ if (destination?.platform === "slack") {
300
+ return destination;
301
+ }
302
+ throw new Error(`${action} requires a Slack destination`);
303
+ }
296
304
  function sameDestination(left, right) {
297
- return left.platform === right.platform && left.teamId === right.teamId && left.channelId === right.channelId;
305
+ if (left.platform !== right.platform) {
306
+ return false;
307
+ }
308
+ if (left.platform === "local" && right.platform === "local") {
309
+ return left.conversationId === right.conversationId;
310
+ }
311
+ if (left.platform === "slack" && right.platform === "slack") {
312
+ return left.teamId === right.teamId && left.channelId === right.channelId;
313
+ }
314
+ return false;
298
315
  }
299
316
  function destinationKey(destination) {
317
+ if (destination.platform === "local") {
318
+ return destination.conversationId;
319
+ }
300
320
  return `slack:${destination.teamId}:${destination.channelId}`;
301
321
  }
302
322
 
@@ -313,6 +333,7 @@ export {
313
333
  downloadPrivateSlackFile,
314
334
  createSlackDestination,
315
335
  parseDestination,
336
+ requireSlackDestination,
316
337
  sameDestination,
317
338
  destinationKey
318
339
  };
@@ -0,0 +1,205 @@
1
+ import "../chunk-2KG3PWR4.js";
2
+
3
+ // src/cli/chat.ts
4
+ import {
5
+ stdin as defaultStdin,
6
+ stderr as defaultStderr,
7
+ stdout as defaultStdout
8
+ } from "process";
9
+ import { randomUUID } from "crypto";
10
+ import * as readline from "readline/promises";
11
+
12
+ // src/chat/local/conversation.ts
13
+ import { createHash } from "crypto";
14
+ import path from "path";
15
+ var LOCAL_CONVERSATION_ALIAS_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
16
+ function slugifyConversationAlias(alias) {
17
+ const trimmed = alias.trim();
18
+ if (!LOCAL_CONVERSATION_ALIAS_PATTERN.test(trimmed)) {
19
+ return void 0;
20
+ }
21
+ return trimmed.toLowerCase().replaceAll(".", "-");
22
+ }
23
+ function workspaceKey(cwd) {
24
+ return createHash("sha256").update(path.resolve(cwd)).digest("hex").slice(0, 12);
25
+ }
26
+ function normalizeLocalConversationId(input) {
27
+ const slug = slugifyConversationAlias(input.alias);
28
+ if (!slug) {
29
+ return void 0;
30
+ }
31
+ return `local:${workspaceKey(input.cwd ?? process.cwd())}:${slug}`;
32
+ }
33
+
34
+ // src/cli/chat.ts
35
+ var CHAT_USAGE = "usage: junior chat\n junior chat -p <message>";
36
+ var DEFAULT_IO = {
37
+ error: (line) => writeStream(defaultStderr, `${line}
38
+ `),
39
+ input: defaultStdin,
40
+ output: defaultStdout,
41
+ write: (text) => writeStream(defaultStdout, text)
42
+ };
43
+ var ChatOutputError = class extends Error {
44
+ constructor(error) {
45
+ super(errorMessage(error));
46
+ this.name = "ChatOutputError";
47
+ }
48
+ };
49
+ function errorMessage(error) {
50
+ return error instanceof Error ? error.message : String(error);
51
+ }
52
+ async function deliverReply(io, reply) {
53
+ try {
54
+ const files = reply.files ?? [];
55
+ if (files.length > 0) {
56
+ const names = files.map(
57
+ (file) => typeof file.filename === "string" && file.filename.trim() ? file.filename : "generated file"
58
+ ).join(", ");
59
+ throw new Error(`Local chat cannot deliver files yet: ${names}`);
60
+ }
61
+ await io.write(formatReply(reply));
62
+ } catch (error) {
63
+ throw new ChatOutputError(error);
64
+ }
65
+ }
66
+ async function reportStatus(io, status) {
67
+ try {
68
+ await io.error(status);
69
+ } catch (error) {
70
+ throw new ChatOutputError(error);
71
+ }
72
+ }
73
+ function writeStream(stream, text) {
74
+ return new Promise((resolve, reject) => {
75
+ stream.write(text, (error) => {
76
+ if (error) {
77
+ reject(error);
78
+ return;
79
+ }
80
+ resolve();
81
+ });
82
+ });
83
+ }
84
+ function defaultStateAdapterForLocalChat() {
85
+ if (process.env.JUNIOR_STATE_ADAPTER) {
86
+ return;
87
+ }
88
+ process.env.JUNIOR_STATE_ADAPTER = "memory";
89
+ }
90
+ function parseChatArgs(argv) {
91
+ if (argv.length === 0) {
92
+ return { mode: "interactive" };
93
+ }
94
+ if (argv[0] !== "-p") {
95
+ return void 0;
96
+ }
97
+ const message = argv.slice(1).join(" ").trim();
98
+ if (!message) {
99
+ return void 0;
100
+ }
101
+ return { message, mode: "prompt" };
102
+ }
103
+ function formatReply(reply) {
104
+ const lines = [];
105
+ const text = reply.text.trim();
106
+ if (text) {
107
+ lines.push(text);
108
+ }
109
+ return `${lines.join("\n") || "[empty response]"}
110
+ `;
111
+ }
112
+ function newRunConversationId() {
113
+ const conversationId = normalizeLocalConversationId({
114
+ alias: `run-${randomUUID()}`
115
+ });
116
+ if (!conversationId) {
117
+ throw new Error("Invalid local conversation name");
118
+ }
119
+ return conversationId;
120
+ }
121
+ async function runPrompt(options, io) {
122
+ defaultStateAdapterForLocalChat();
123
+ const conversationId = newRunConversationId();
124
+ const { runLocalAgentTurn } = await import("../runner-27NP2TEO.js");
125
+ const result = await runLocalAgentTurn(
126
+ {
127
+ conversationId,
128
+ message: options.message
129
+ },
130
+ {
131
+ deliverReply: async (reply) => {
132
+ await deliverReply(io, reply);
133
+ },
134
+ onStatus: async (status) => {
135
+ await reportStatus(io, status);
136
+ }
137
+ }
138
+ );
139
+ return result.outcome === "success" ? 0 : 1;
140
+ }
141
+ async function runInteractive(io) {
142
+ defaultStateAdapterForLocalChat();
143
+ const conversationId = newRunConversationId();
144
+ const { runLocalAgentTurn } = await import("../runner-27NP2TEO.js");
145
+ const rl = readline.createInterface({
146
+ input: io.input,
147
+ output: io.output,
148
+ terminal: true
149
+ });
150
+ try {
151
+ while (true) {
152
+ const message = (await rl.question("junior> ")).trim();
153
+ if (!message) {
154
+ continue;
155
+ }
156
+ if (message === "/exit" || message === "/quit") {
157
+ break;
158
+ }
159
+ try {
160
+ await runLocalAgentTurn(
161
+ {
162
+ conversationId,
163
+ message
164
+ },
165
+ {
166
+ deliverReply: async (reply) => {
167
+ await deliverReply(io, reply);
168
+ },
169
+ onStatus: async (status) => {
170
+ await reportStatus(io, status);
171
+ }
172
+ }
173
+ );
174
+ } catch (error) {
175
+ if (error instanceof ChatOutputError) {
176
+ throw error;
177
+ }
178
+ await reportStatus(io, errorMessage(error));
179
+ }
180
+ }
181
+ } finally {
182
+ rl.close();
183
+ }
184
+ }
185
+ async function runChat(argv, io = DEFAULT_IO) {
186
+ const options = parseChatArgs(argv);
187
+ if (!options) {
188
+ await io.error(CHAT_USAGE);
189
+ return 1;
190
+ }
191
+ try {
192
+ if (options.mode === "prompt") {
193
+ return await runPrompt(options, io);
194
+ }
195
+ await runInteractive(io);
196
+ return 0;
197
+ } catch (error) {
198
+ await io.error(errorMessage(error));
199
+ return 1;
200
+ }
201
+ }
202
+ export {
203
+ CHAT_USAGE,
204
+ runChat
205
+ };
package/dist/cli/check.js CHANGED
@@ -1,19 +1,18 @@
1
- import {
2
- JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE,
3
- JUNIOR_HEARTBEAT_ROUTE,
4
- LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION
5
- } from "../chunk-6YY4Q3D4.js";
6
1
  import {
7
2
  parseSkillFile
8
- } from "../chunk-55XEZFGD.js";
3
+ } from "../chunk-OR6NQJ5E.js";
9
4
  import {
10
5
  parseInlinePluginManifest,
11
6
  parsePluginManifest
12
- } from "../chunk-GB3AL54K.js";
7
+ } from "../chunk-7Q5YOUUT.js";
13
8
  import "../chunk-KVZL5NZS.js";
14
- import "../chunk-PP7AGSBU.js";
15
- import "../chunk-6GEYPE6T.js";
16
- import "../chunk-Z3YD6NHK.js";
9
+ import "../chunk-CYUI7JU5.js";
10
+ import "../chunk-3BYAPS6B.js";
11
+ import {
12
+ JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE,
13
+ JUNIOR_HEARTBEAT_ROUTE,
14
+ LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION
15
+ } from "../chunk-SJHUF3DP.js";
17
16
  import "../chunk-2KG3PWR4.js";
18
17
 
19
18
  // src/cli/check.ts
package/dist/cli/init.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  juniorVercelConfig
3
- } from "../chunk-QUXPUKBH.js";
3
+ } from "../chunk-Y7X25LFY.js";
4
4
  import "../chunk-2KG3PWR4.js";
5
5
 
6
6
  // src/cli/init.ts
package/dist/cli/run.js CHANGED
@@ -1,12 +1,20 @@
1
1
  import "../chunk-2KG3PWR4.js";
2
2
 
3
3
  // src/cli/run.ts
4
- var CLI_USAGE = "usage: junior init <dir>\n junior snapshot create\n junior check [dir]\n junior upgrade";
4
+ var CLI_USAGE = "usage: junior init <dir>\n junior snapshot create\n junior check [dir]\n junior upgrade\n junior chat\n junior chat -p <message>";
5
5
  var DEFAULT_IO = {
6
6
  error: console.error
7
7
  };
8
+ function normalizeCliArgv(argv) {
9
+ return argv[0] === "--" ? argv.slice(1) : argv;
10
+ }
8
11
  async function runCli(argv, handlers, io = DEFAULT_IO) {
9
- const [command, subcommand, ...rest] = argv;
12
+ const [command, subcommand, ...rest] = normalizeCliArgv(argv);
13
+ if (command === "chat") {
14
+ return await handlers.runChat(
15
+ subcommand === void 0 ? [] : [subcommand, ...rest]
16
+ );
17
+ }
10
18
  if (command === "init") {
11
19
  if (!subcommand || rest.length > 0) {
12
20
  io.error(CLI_USAGE);
@@ -1,20 +1,20 @@
1
1
  import {
2
2
  resolveRuntimeDependencySnapshot
3
- } from "../chunk-VLIO6RQR.js";
3
+ } from "../chunk-6UP2Z2RZ.js";
4
4
  import "../chunk-G3E7SCME.js";
5
5
  import {
6
6
  getPluginProviders,
7
7
  getPluginRuntimeDependencies,
8
8
  getPluginRuntimePostinstall
9
- } from "../chunk-GB3AL54K.js";
9
+ } from "../chunk-7Q5YOUUT.js";
10
10
  import "../chunk-KVZL5NZS.js";
11
11
  import {
12
12
  disconnectStateAdapter
13
- } from "../chunk-3FYPXHPL.js";
14
- import "../chunk-ZJQPA67D.js";
15
- import "../chunk-PP7AGSBU.js";
16
- import "../chunk-6GEYPE6T.js";
17
- import "../chunk-Z3YD6NHK.js";
13
+ } from "../chunk-F6HWCPOC.js";
14
+ import "../chunk-GM7HTXYC.js";
15
+ import "../chunk-CYUI7JU5.js";
16
+ import "../chunk-3BYAPS6B.js";
17
+ import "../chunk-SJHUF3DP.js";
18
18
  import "../chunk-2KG3PWR4.js";
19
19
 
20
20
  // src/cli/snapshot-warmup.ts
@@ -1,31 +1,93 @@
1
1
  import {
2
2
  coerceThreadConversationState
3
- } from "../chunk-4JXCSGSA.js";
3
+ } from "../chunk-M4FLLXXD.js";
4
4
  import {
5
5
  JUNIOR_THREAD_STATE_TTL_MS,
6
+ createNeonJuniorSqlExecutor,
7
+ createSqlStore,
8
+ createStateConversationStore,
6
9
  getConversation,
7
10
  requestConversationWork
8
- } from "../chunk-HNMUVGSR.js";
11
+ } from "../chunk-JL2SLRAT.js";
9
12
  import {
10
13
  parseDestination,
11
14
  sameDestination
12
- } from "../chunk-XC33FJZN.js";
15
+ } from "../chunk-YRDS7VKO.js";
13
16
  import {
14
17
  disconnectStateAdapter,
15
18
  getConnectedStateContext
16
- } from "../chunk-3FYPXHPL.js";
19
+ } from "../chunk-F6HWCPOC.js";
17
20
  import {
18
21
  getChatConfig
19
- } from "../chunk-ZJQPA67D.js";
20
- import "../chunk-PP7AGSBU.js";
22
+ } from "../chunk-GM7HTXYC.js";
23
+ import "../chunk-CYUI7JU5.js";
21
24
  import {
22
25
  isRecord,
23
26
  toOptionalNumber,
24
27
  toOptionalString
25
- } from "../chunk-6GEYPE6T.js";
26
- import "../chunk-Z3YD6NHK.js";
28
+ } from "../chunk-3BYAPS6B.js";
29
+ import "../chunk-SJHUF3DP.js";
27
30
  import "../chunk-2KG3PWR4.js";
28
31
 
32
+ // src/chat/conversations/sql/backfill.ts
33
+ async function backfillToSql(args) {
34
+ const limit = Math.max(0, args.limit ?? 500);
35
+ const conversations = await args.source.listByActivity({
36
+ limit
37
+ });
38
+ await args.target.migrate();
39
+ for (const conversation of conversations) {
40
+ await args.target.backfillConversation(conversation);
41
+ }
42
+ return {
43
+ copiedCount: conversations.length
44
+ };
45
+ }
46
+
47
+ // src/cli/upgrade/migrations/conversations-sql.ts
48
+ var CONVERSATION_BACKFILL_LIMIT = 1e4;
49
+ var REQUIRED_SQL_DATABASE_URL_MESSAGE = "Junior SQL database URL is required for conversation metadata upgrade. Set JUNIOR_DATABASE_URL or DATABASE_URL.";
50
+ function requireConversationSqlDatabaseUrl(context) {
51
+ const databaseUrl = context.sqlDatabaseUrl ?? getChatConfig().sql.databaseUrl;
52
+ if (!databaseUrl) {
53
+ throw new Error(REQUIRED_SQL_DATABASE_URL_MESSAGE);
54
+ }
55
+ return databaseUrl;
56
+ }
57
+ async function migrateConversationsToSql(context, options = {}) {
58
+ const source = createStateConversationStore(context.stateAdapter);
59
+ let target = options.target;
60
+ let closeTarget;
61
+ if (!target) {
62
+ const databaseUrl = requireConversationSqlDatabaseUrl(context);
63
+ const executor = createNeonJuniorSqlExecutor({
64
+ connectionString: databaseUrl
65
+ });
66
+ target = createSqlStore(executor);
67
+ closeTarget = () => executor.close();
68
+ }
69
+ const limit = Math.max(1, options.batchSize ?? CONVERSATION_BACKFILL_LIMIT);
70
+ try {
71
+ const result = await backfillToSql({
72
+ limit,
73
+ source,
74
+ target
75
+ });
76
+ return {
77
+ existing: 0,
78
+ migrated: result.copiedCount,
79
+ missing: 0,
80
+ scanned: result.copiedCount
81
+ };
82
+ } finally {
83
+ await closeTarget?.();
84
+ }
85
+ }
86
+ var sqlConversationMigration = {
87
+ name: "backfill-conversations-sql",
88
+ run: migrateConversationsToSql
89
+ };
90
+
29
91
  // src/cli/upgrade/migrations/redis-conversation-state.ts
30
92
  var CONVERSATION_PREFIX = "junior:conversation";
31
93
  var CONVERSATION_SCHEMA_VERSION = 1;
@@ -562,16 +624,24 @@ var redisConversationStateMigration = {
562
624
  var DEFAULT_IO = {
563
625
  info: console.log
564
626
  };
565
- var MIGRATIONS = [redisConversationStateMigration];
627
+ var MIGRATIONS = [
628
+ redisConversationStateMigration,
629
+ sqlConversationMigration
630
+ ];
566
631
  function formatMigrationResult(result) {
567
- return [
632
+ const fields = [
568
633
  `scanned=${result.scanned}`,
569
634
  `migrated=${result.migrated}`,
570
635
  `existing=${result.existing}`,
571
636
  `missing=${result.missing}`
572
- ].join(" ");
637
+ ];
638
+ if (result.skipped !== void 0) {
639
+ fields.push(`skipped=${result.skipped}`);
640
+ }
641
+ return fields.join(" ");
573
642
  }
574
643
  async function runUpgradeMigrations(context) {
644
+ requireConversationSqlDatabaseUrl(context);
575
645
  const results = [];
576
646
  for (const migration of MIGRATIONS) {
577
647
  context.io.info(`Running migration ${migration.name}...`);
@@ -2,3 +2,7 @@ export declare const JUNIOR_HEARTBEAT_ROUTE = "/api/internal/heartbeat";
2
2
  export declare const JUNIOR_HEARTBEAT_CRON_SCHEDULE = "* * * * *";
3
3
  export declare const JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE = "/api/internal/agent/continue";
4
4
  export declare const LEGACY_JUNIOR_CONVERSATION_WORK_FUNCTION = "api/internal/agent/continue.ts";
5
+ /** Resolve the deployment version used for release and telemetry correlation. */
6
+ export declare function getDeploymentServiceVersion(): string | undefined;
7
+ /** Resolve deployment-scoped telemetry attributes from host environment. */
8
+ export declare function getDeploymentTelemetryAttributes(): Record<string, string>;
@@ -1,3 +1,8 @@
1
+ import type { SandboxEgressTracePropagationConfig } from "@/chat/sandbox/egress-tracing";
1
2
  import type { WaitUntilFn } from "@/handlers/types";
3
+ interface AgentDispatchHandlerOptions {
4
+ tracePropagation?: SandboxEgressTracePropagationConfig;
5
+ }
2
6
  /** Handle the authenticated internal agent-dispatch callback. */
3
- export declare function POST(request: Request, waitUntil: WaitUntilFn): Promise<Response>;
7
+ export declare function POST(request: Request, waitUntil: WaitUntilFn, options?: AgentDispatchHandlerOptions): Promise<Response>;
8
+ export {};
@@ -1,2 +1,7 @@
1
+ import type { generateAssistantReply } from "@/chat/respond";
1
2
  import type { WaitUntilFn } from "@/handlers/types";
2
- export declare function GET(request: Request, provider: string, waitUntil: WaitUntilFn): Promise<Response>;
3
+ interface McpOAuthCallbackOptions {
4
+ generateReply?: typeof generateAssistantReply;
5
+ }
6
+ export declare function GET(request: Request, provider: string, waitUntil: WaitUntilFn, options?: McpOAuthCallbackOptions): Promise<Response>;
7
+ export {};
@@ -1,2 +1,7 @@
1
1
  import type { WaitUntilFn } from "@/handlers/types";
2
- export declare function GET(request: Request, provider: string, waitUntil: WaitUntilFn): Promise<Response>;
2
+ import type { generateAssistantReply } from "@/chat/respond";
3
+ interface OAuthCallbackOptions {
4
+ generateReply?: typeof generateAssistantReply;
5
+ }
6
+ export declare function GET(request: Request, provider: string, waitUntil: WaitUntilFn, options?: OAuthCallbackOptions): Promise<Response>;
7
+ export {};
@@ -1,6 +1,8 @@
1
1
  import { type SandboxEgressHttpInterceptor } from "@/chat/sandbox/egress-proxy";
2
+ import type { SandboxEgressTracePropagationConfig } from "@/chat/sandbox/egress-tracing";
2
3
  interface SandboxEgressProxyOptions {
3
4
  interceptHttp?: SandboxEgressHttpInterceptor;
5
+ tracePropagation?: SandboxEgressTracePropagationConfig;
4
6
  }
5
7
  /** Handles Vercel Sandbox firewall egress proxy requests. */
6
8
  export declare function ALL(request: Request, options?: SandboxEgressProxyOptions): Promise<Response>;
@@ -1,4 +1,5 @@
1
1
  import type { SlackAdapter } from "@chat-adapter/slack";
2
+ import { type SlackWebhookServices } from "@/chat/ingress/slack-webhook";
2
3
  import { JuniorChat } from "@/chat/ingress/junior-chat";
3
4
  import type { WaitUntilFn } from "@/handlers/types";
4
5
  type LegacyChatSdkBot = JuniorChat<{
@@ -10,8 +11,9 @@ type LegacyChatSdkBot = JuniorChat<{
10
11
  * Slack production ingress persists messages into the durable conversation
11
12
  * mailbox and wakes the queue worker. The optional `legacyBot` parameter is
12
13
  * kept for integration tests that still exercise Chat SDK fixtures directly.
14
+ * The optional `services` parameter carries app-scoped runtime services.
13
15
  */
14
- export declare function handlePlatformWebhook(request: Request, platform: string, waitUntil: WaitUntilFn, legacyBot?: LegacyChatSdkBot): Promise<Response>;
16
+ export declare function handlePlatformWebhook(request: Request, platform: string, waitUntil: WaitUntilFn, legacyBot?: LegacyChatSdkBot, services?: SlackWebhookServices): Promise<Response>;
15
17
  /** Handle a platform webhook request from the app route. */
16
- export declare function POST(request: Request, platform: string, waitUntil: WaitUntilFn): Promise<Response>;
18
+ export declare function POST(request: Request, platform: string, waitUntil: WaitUntilFn, services?: SlackWebhookServices): Promise<Response>;
17
19
  export {};
@@ -1,6 +1,8 @@
1
1
  import {
2
+ getDeploymentServiceVersion,
3
+ getDeploymentTelemetryAttributes,
2
4
  sentry_exports
3
- } from "./chunk-Z3YD6NHK.js";
5
+ } from "./chunk-SJHUF3DP.js";
4
6
  import "./chunk-2KG3PWR4.js";
5
7
 
6
8
  // src/instrumentation.ts
@@ -22,16 +24,28 @@ function initSentry() {
22
24
  }
23
25
  const dsn = process.env.SENTRY_DSN;
24
26
  const enableLogs = getBoolean(process.env.SENTRY_ENABLE_LOGS, Boolean(dsn));
27
+ const serviceVersion = getDeploymentServiceVersion();
28
+ const deploymentSpanAttributes = getDeploymentTelemetryAttributes();
25
29
  sentry_exports.init({
26
30
  dsn,
27
31
  environment: process.env.SENTRY_ENVIRONMENT ?? process.env.VERCEL_ENV ?? process.env.NODE_ENV,
28
- release: process.env.SENTRY_RELEASE ?? process.env.VERCEL_GIT_COMMIT_SHA,
32
+ release: serviceVersion,
29
33
  tracesSampleRate: getSampleRate(process.env.SENTRY_TRACES_SAMPLE_RATE, 1),
30
34
  sendDefaultPii: true,
31
- enabled: Boolean(dsn),
32
35
  enableLogs,
33
36
  registerEsmLoaderHooks: false,
34
37
  streamGenAiSpans: true,
38
+ // Keep deployment identity centralized so every emitted Sentry span carries it.
39
+ beforeSendSpan(span) {
40
+ if (Object.keys(deploymentSpanAttributes).length === 0) {
41
+ return span;
42
+ }
43
+ span.data = {
44
+ ...span.data,
45
+ ...deploymentSpanAttributes
46
+ };
47
+ return span;
48
+ },
35
49
  integrations: [
36
50
  sentry_exports.vercelAIIntegration({
37
51
  recordInputs: true,
package/dist/nitro.js CHANGED
@@ -2,21 +2,20 @@ import {
2
2
  pluginCatalogConfigFromPluginSet,
3
3
  pluginHookRegistrationsFromPluginSet,
4
4
  resolveConversationWorkQueueTopic
5
- } from "./chunk-ICKIDP7G.js";
6
- import {
7
- JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE,
8
- JUNIOR_HEARTBEAT_CRON_SCHEDULE,
9
- JUNIOR_HEARTBEAT_ROUTE
10
- } from "./chunk-6YY4Q3D4.js";
11
- import "./chunk-XC33FJZN.js";
5
+ } from "./chunk-YOHFWWBV.js";
6
+ import "./chunk-YRDS7VKO.js";
12
7
  import {
13
8
  discoverInstalledPluginPackageContent,
14
9
  isValidPackageName,
15
10
  resolvePackageDir
16
11
  } from "./chunk-KVZL5NZS.js";
17
- import "./chunk-ZJQPA67D.js";
18
- import "./chunk-6GEYPE6T.js";
19
- import "./chunk-Z3YD6NHK.js";
12
+ import "./chunk-GM7HTXYC.js";
13
+ import "./chunk-3BYAPS6B.js";
14
+ import {
15
+ JUNIOR_CONVERSATION_WORK_CALLBACK_ROUTE,
16
+ JUNIOR_HEARTBEAT_CRON_SCHEDULE,
17
+ JUNIOR_HEARTBEAT_ROUTE
18
+ } from "./chunk-SJHUF3DP.js";
20
19
  import "./chunk-2KG3PWR4.js";
21
20
 
22
21
  // src/nitro.ts
@@ -1,3 +1,9 @@
1
+ import type { AgentPluginConversationStatus, AgentPluginConversations, AgentPluginConversationSummary } from "@sentry/junior-plugin-api";
2
+ import type { ConversationStore } from "@/chat/conversations/store";
3
+ export type { AgentPluginConversationStatus, AgentPluginConversations, AgentPluginConversationSummary, };
4
+ interface ConversationReaderOptions {
5
+ conversationStore?: ConversationStore;
6
+ }
1
7
  export type ConversationReportStatus = "active" | "completed" | "failed" | "hung" | "superseded";
2
8
  export type ConversationSurface = "api" | "internal" | "scheduler" | "slack";
3
9
  export interface ConversationUsage {
@@ -109,8 +115,12 @@ export interface ConversationStatsReport {
109
115
  windowStart: string;
110
116
  }
111
117
  /** Read the recent conversation feed for reporting consumers. */
112
- export declare function readConversationFeed(): Promise<ConversationFeed>;
118
+ export declare function readConversationFeed(options?: ConversationReaderOptions): Promise<ConversationFeed>;
113
119
  /** Read aggregate conversation statistics for reporting consumers. */
114
- export declare function readConversationStatsReport(): Promise<ConversationStatsReport>;
120
+ export declare function readConversationStatsReport(options?: ConversationReaderOptions): Promise<ConversationStatsReport>;
121
+ /** List recent conversation summaries for plugin operational reports. */
122
+ export declare function listRecentConversationSummaries(options?: {
123
+ limit?: number;
124
+ } & ConversationReaderOptions): Promise<AgentPluginConversationSummary[]>;
115
125
  /** Read one conversation transcript for reporting consumers. */
116
- export declare function readConversationReport(conversationId: string): Promise<ConversationReport>;
126
+ export declare function readConversationReport(conversationId: string, options?: ConversationReaderOptions): Promise<ConversationReport>;