@sentry/junior 0.9.4 → 0.10.1

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.
@@ -95,8 +95,8 @@ var CONSOLE_PREVIEW_KEYS = /* @__PURE__ */ new Set([
95
95
  function getSentryEnvironment() {
96
96
  return (process.env.SENTRY_ENVIRONMENT ?? process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT ?? process.env.VERCEL_ENV ?? process.env.NODE_ENV ?? "").trim().toLowerCase();
97
97
  }
98
- function shouldSuppressInfoLog(_level) {
99
- return false;
98
+ function shouldSuppressInfoLog(level) {
99
+ return level === "info";
100
100
  }
101
101
  function shouldEmitConsole(level) {
102
102
  if (process.env.NODE_ENV === "test") {
package/dist/cli/check.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  parseSkillFile
3
- } from "../chunk-WM66QDLA.js";
3
+ } from "../chunk-3KBAD3OR.js";
4
4
  import {
5
5
  parsePluginManifest
6
- } from "../chunk-MY7JNCS2.js";
6
+ } from "../chunk-VWHGDGDH.js";
7
7
  import "../chunk-KCLEEKYX.js";
8
8
 
9
9
  // src/cli/check.ts
package/dist/cli/init.js CHANGED
@@ -2,19 +2,19 @@
2
2
  import fs from "fs";
3
3
  import path from "path";
4
4
  function writeRouteModule(filePath, exportLine) {
5
- fs.writeFileSync(filePath, `${exportLine}
5
+ fs.writeFileSync(
6
+ filePath,
7
+ `${exportLine}
6
8
  export const runtime = "nodejs";
7
- `);
9
+ `
10
+ );
8
11
  }
9
12
  function writeWrapperFiles(targetDir) {
10
13
  const routeDir = path.join(targetDir, "app", "api", "[...path]");
11
14
  fs.mkdirSync(routeDir, { recursive: true });
12
- writeRouteModule(path.join(routeDir, "route.js"), 'export { GET, POST } from "@sentry/junior/handler";');
13
- const queueRouteDir = path.join(targetDir, "app", "api", "queue", "callback");
14
- fs.mkdirSync(queueRouteDir, { recursive: true });
15
15
  writeRouteModule(
16
- path.join(queueRouteDir, "route.js"),
17
- 'export { POST } from "@sentry/junior/handlers/queue-callback";'
16
+ path.join(routeDir, "route.js"),
17
+ 'export { GET, POST } from "@sentry/junior/handler";'
18
18
  );
19
19
  fs.mkdirSync(path.join(targetDir, "app"), { recursive: true });
20
20
  fs.writeFileSync(
@@ -66,14 +66,20 @@ async function runInit(dir, log = console.log) {
66
66
  "@sentry/nextjs": "^10.0.0"
67
67
  }
68
68
  };
69
- fs.writeFileSync(path.join(target, "package.json"), `${JSON.stringify(pkg, null, 2)}
70
- `);
69
+ fs.writeFileSync(
70
+ path.join(target, "package.json"),
71
+ `${JSON.stringify(pkg, null, 2)}
72
+ `
73
+ );
71
74
  const dataDir = path.join(target, "app", "data");
72
75
  fs.mkdirSync(dataDir, { recursive: true });
73
- fs.writeFileSync(path.join(dataDir, "SOUL.md"), `# ${name}
76
+ fs.writeFileSync(
77
+ path.join(dataDir, "SOUL.md"),
78
+ `# ${name}
74
79
 
75
80
  You are ${name}, a helpful assistant.
76
- `);
81
+ `
82
+ );
77
83
  fs.writeFileSync(
78
84
  path.join(dataDir, "ABOUT.md"),
79
85
  `# About ${name}
@@ -87,7 +93,10 @@ Describe what ${name} helps users do.
87
93
  const pluginsDir = path.join(target, "app", "plugins");
88
94
  fs.mkdirSync(pluginsDir, { recursive: true });
89
95
  fs.writeFileSync(path.join(pluginsDir, ".gitkeep"), "");
90
- fs.writeFileSync(path.join(target, ".gitignore"), ["node_modules/", ".next/", ".env", ".env.local", ""].join("\n"));
96
+ fs.writeFileSync(
97
+ path.join(target, ".gitignore"),
98
+ ["node_modules/", ".next/", ".env", ".env.local", ""].join("\n")
99
+ );
91
100
  fs.writeFileSync(
92
101
  path.join(target, ".env.example"),
93
102
  [
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  disconnectStateAdapter,
3
3
  resolveRuntimeDependencySnapshot
4
- } from "../chunk-FS5Y4CF2.js";
4
+ } from "../chunk-LNCWHJH5.js";
5
5
  import {
6
6
  getPluginProviders,
7
7
  getPluginRuntimeDependencies,
8
8
  getPluginRuntimePostinstall
9
- } from "../chunk-MY7JNCS2.js";
9
+ } from "../chunk-VWHGDGDH.js";
10
10
  import "../chunk-KCLEEKYX.js";
11
11
 
12
12
  // src/cli/snapshot-warmup.ts
@@ -1,3 +1,5 @@
1
+ export { maxDuration } from './webhooks.js';
2
+
1
3
  type RouteContext = {
2
4
  params: Promise<unknown>;
3
5
  };
@@ -15,10 +17,6 @@ declare function GET(request: Request, context: RouteContext): Promise<Response>
15
17
  *
16
18
  * Supported routes:
17
19
  * - `api/webhooks/:platform`
18
- * - `api/queue/callback`
19
- *
20
- * `queue/callback` is routed here for local/dev parity, but production queue triggers
21
- * should still target the dedicated `app/api/queue/callback/route.ts` endpoint.
22
20
  */
23
21
  declare function POST(request: Request, context: RouteContext): Promise<Response>;
24
22
 
@@ -1,10 +1,5 @@
1
1
  import {
2
- POST as POST2
3
- } from "../chunk-SO4ORZJR.js";
4
- import {
5
- POST
6
- } from "../chunk-YGERYE7Y.js";
7
- import {
2
+ POST,
8
3
  buildConversationContext,
9
4
  buildSlackOutputMessage,
10
5
  coerceThreadArtifactsState,
@@ -16,14 +11,16 @@ import {
16
11
  formatProviderLabel,
17
12
  generateAssistantReply,
18
13
  generateConversationId,
14
+ getPersistedThreadState,
19
15
  getSlackClient,
20
16
  isRetryableTurnError,
21
17
  markConversationMessage,
22
18
  markTurnCompleted,
23
19
  markTurnFailed,
20
+ maxDuration,
24
21
  mergeArtifactsState,
25
22
  normalizeConversationText,
26
- persistThreadState,
23
+ persistThreadStateById,
27
24
  publishAppHomeView,
28
25
  resolveBaseUrl,
29
26
  resolveReplyDelivery,
@@ -31,15 +28,15 @@ import {
31
28
  updateConversationStats,
32
29
  uploadFilesToThread,
33
30
  upsertConversationMessage
34
- } from "../chunk-FLP5I4NM.js";
35
- import {
36
- botConfig,
37
- getStateAdapter
38
- } from "../chunk-FS5Y4CF2.js";
31
+ } from "../chunk-T66A2F7U.js";
39
32
  import {
40
33
  GET
41
34
  } from "../chunk-4RBEYCOG.js";
42
- import "../chunk-WM66QDLA.js";
35
+ import "../chunk-3KBAD3OR.js";
36
+ import {
37
+ botConfig,
38
+ getStateAdapter
39
+ } from "../chunk-LNCWHJH5.js";
43
40
  import {
44
41
  buildOAuthTokenRequest,
45
42
  getPluginOAuthConfig,
@@ -47,13 +44,12 @@ import {
47
44
  logInfo,
48
45
  logWarn,
49
46
  parseOAuthTokenResponse
50
- } from "../chunk-MY7JNCS2.js";
47
+ } from "../chunk-VWHGDGDH.js";
51
48
  import "../chunk-KCLEEKYX.js";
52
49
 
53
50
  // src/handlers/mcp-oauth-callback.ts
54
51
  import { Buffer } from "buffer";
55
52
  import { after } from "next/server";
56
- import { ThreadImpl } from "chat";
57
53
 
58
54
  // src/handlers/oauth-resume.ts
59
55
  function resolveReplyTimeoutMs(explicitTimeoutMs) {
@@ -328,15 +324,6 @@ async function deliverReplyToThread(channelId, threadTs, reply) {
328
324
  } catch {
329
325
  }
330
326
  }
331
- function createSlackThread(channelId, threadTs) {
332
- return ThreadImpl.fromJSON({
333
- _type: "chat:Thread",
334
- adapterName: "slack",
335
- channelId,
336
- id: `slack:${channelId}:${threadTs}`,
337
- isDM: channelId.startsWith("D")
338
- });
339
- }
340
327
  function buildDeterministicTurnId(messageId) {
341
328
  const sanitized = messageId.replace(/[^a-zA-Z0-9_-]/g, "_");
342
329
  return `turn_${sanitized}`;
@@ -354,16 +341,18 @@ function getUserMessageIdForTurn(conversation, sessionId) {
354
341
  return void 0;
355
342
  }
356
343
  async function buildResumeConversationContext(channelId, threadTs, sessionId) {
357
- const thread = createSlackThread(channelId, threadTs);
358
- const conversation = coerceThreadConversationState(await thread.state);
344
+ const threadId = `slack:${channelId}:${threadTs}`;
345
+ const conversation = coerceThreadConversationState(
346
+ await getPersistedThreadState(threadId)
347
+ );
359
348
  const userMessageId = getUserMessageIdForTurn(conversation, sessionId);
360
349
  return buildConversationContext(conversation, {
361
350
  excludeMessageId: userMessageId
362
351
  });
363
352
  }
364
353
  async function persistCompletedReplyState(channelId, threadTs, sessionId, reply) {
365
- const thread = createSlackThread(channelId, threadTs);
366
- const currentState = await thread.state;
354
+ const threadId = `slack:${channelId}:${threadTs}`;
355
+ const currentState = await getPersistedThreadState(threadId);
367
356
  const conversation = coerceThreadConversationState(currentState);
368
357
  const artifacts = coerceThreadArtifactsState(currentState);
369
358
  const nextArtifacts = reply.artifactStatePatch ? mergeArtifactsState(artifacts, reply.artifactStatePatch) : void 0;
@@ -390,7 +379,7 @@ async function persistCompletedReplyState(channelId, threadTs, sessionId, reply)
390
379
  nowMs: Date.now(),
391
380
  updateConversationStats
392
381
  });
393
- await persistThreadState(thread, {
382
+ await persistThreadStateById(threadId, {
394
383
  artifacts: nextArtifacts,
395
384
  conversation,
396
385
  sandboxId: reply.sandboxId,
@@ -398,8 +387,8 @@ async function persistCompletedReplyState(channelId, threadTs, sessionId, reply)
398
387
  });
399
388
  }
400
389
  async function persistFailedReplyState(channelId, threadTs, sessionId) {
401
- const thread = createSlackThread(channelId, threadTs);
402
- const currentState = await thread.state;
390
+ const threadId = `slack:${channelId}:${threadTs}`;
391
+ const currentState = await getPersistedThreadState(threadId);
403
392
  const conversation = coerceThreadConversationState(currentState);
404
393
  markTurnFailed({
405
394
  conversation,
@@ -408,7 +397,7 @@ async function persistFailedReplyState(channelId, threadTs, sessionId) {
408
397
  markConversationMessage,
409
398
  updateConversationStats
410
399
  });
411
- await persistThreadState(thread, {
400
+ await persistThreadStateById(threadId, {
412
401
  conversation
413
402
  });
414
403
  }
@@ -549,7 +538,6 @@ async function GET2(request, context) {
549
538
 
550
539
  // src/handlers/oauth-callback.ts
551
540
  import { after as after2 } from "next/server";
552
- import { ThreadImpl as ThreadImpl2 } from "chat";
553
541
  function htmlErrorResponse(title, message, status) {
554
542
  const safeTitle = escapeXml(title);
555
543
  const safeMessage = escapeXml(message);
@@ -569,18 +557,10 @@ function htmlErrorResponse(title, message, status) {
569
557
  headers: { "Content-Type": "text/html; charset=utf-8" }
570
558
  });
571
559
  }
572
- function createSlackThread2(channelId, threadTs) {
573
- return ThreadImpl2.fromJSON({
574
- _type: "chat:Thread",
575
- adapterName: "slack",
576
- channelId,
577
- id: `slack:${channelId}:${threadTs}`,
578
- isDM: channelId.startsWith("D")
579
- });
580
- }
581
560
  async function buildResumeConversationContext2(channelId, threadTs) {
582
- const thread = createSlackThread2(channelId, threadTs);
583
- const conversation = coerceThreadConversationState(await thread.state);
561
+ const conversation = coerceThreadConversationState(
562
+ await getPersistedThreadState(`slack:${channelId}:${threadTs}`)
563
+ );
584
564
  const latestUserMessageId = [...conversation.messages].reverse().find((message) => message.role === "user")?.id;
585
565
  return buildConversationContext(conversation, {
586
566
  excludeMessageId: latestUserMessageId
@@ -829,15 +809,12 @@ async function GET4(request, context) {
829
809
  }
830
810
  return new Response("Not Found", { status: 404 });
831
811
  }
832
- async function POST3(request, context) {
812
+ async function POST2(request, context) {
833
813
  const route = normalizeRoutePath(getRoutePathParts(await context.params));
834
- if (route === "queue/callback") {
835
- return POST(request);
836
- }
837
814
  const webhookMatch = route.match(/^webhooks\/([^/]+)$/);
838
815
  if (webhookMatch) {
839
816
  const platform = webhookMatch[1];
840
- return POST2(request, {
817
+ return POST(request, {
841
818
  params: Promise.resolve({ platform })
842
819
  });
843
820
  }
@@ -845,5 +822,6 @@ async function POST3(request, context) {
845
822
  }
846
823
  export {
847
824
  GET4 as GET,
848
- POST3 as POST
825
+ POST2 as POST,
826
+ maxDuration
849
827
  };
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Vercel function timeout in seconds.
3
+ *
4
+ * Agent turns run inside `after()` which shares the function's timeout budget.
5
+ * This must be at least as large as the configured turn timeout plus buffer.
6
+ */
7
+ declare const maxDuration: number;
1
8
  /**
2
9
  * Webhook route contract for `@sentry/junior`.
3
10
  *
@@ -18,4 +25,4 @@ type WebhookRouteContext = {
18
25
  */
19
26
  declare function POST(request: Request, context: WebhookRouteContext): Promise<Response>;
20
27
 
21
- export { POST };
28
+ export { POST, maxDuration };
@@ -1,11 +1,12 @@
1
1
  import {
2
- POST
3
- } from "../chunk-SO4ORZJR.js";
4
- import "../chunk-FLP5I4NM.js";
5
- import "../chunk-FS5Y4CF2.js";
6
- import "../chunk-WM66QDLA.js";
7
- import "../chunk-MY7JNCS2.js";
2
+ POST,
3
+ maxDuration
4
+ } from "../chunk-T66A2F7U.js";
5
+ import "../chunk-3KBAD3OR.js";
6
+ import "../chunk-LNCWHJH5.js";
7
+ import "../chunk-VWHGDGDH.js";
8
8
  import "../chunk-KCLEEKYX.js";
9
9
  export {
10
- POST
10
+ POST,
11
+ maxDuration
11
12
  };
@@ -68,7 +68,6 @@ function applyJuniorConfig(nextConfig, options) {
68
68
  serverExternalPackages: Array.from(
69
69
  /* @__PURE__ */ new Set([
70
70
  ...nextConfig?.serverExternalPackages ?? [],
71
- "@vercel/queue",
72
71
  "@vercel/sandbox",
73
72
  "bash-tool",
74
73
  "just-bash",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior",
3
- "version": "0.9.4",
3
+ "version": "0.10.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -12,7 +12,6 @@
12
12
  "exports": {
13
13
  "./handler": "./dist/handlers/router.js",
14
14
  "./handlers/webhooks": "./dist/handlers/webhooks.js",
15
- "./handlers/queue-callback": "./dist/handlers/queue-callback.js",
16
15
  "./handlers/health": "./dist/handlers/health.js",
17
16
  "./config": "./dist/next-config.js",
18
17
  "./instrumentation": "./dist/instrumentation.js",
@@ -23,23 +22,22 @@
23
22
  "bin"
24
23
  ],
25
24
  "dependencies": {
26
- "@ai-sdk/gateway": "^3.0.66",
27
- "@chat-adapter/slack": "4.20.2",
28
- "@chat-adapter/state-memory": "4.20.2",
29
- "@chat-adapter/state-redis": "4.20.2",
25
+ "@ai-sdk/gateway": "^3.0.83",
26
+ "@chat-adapter/slack": "4.22.0",
27
+ "@chat-adapter/state-memory": "4.22.0",
28
+ "@chat-adapter/state-redis": "4.22.0",
30
29
  "@mariozechner/pi-agent-core": "^0.59.0",
31
30
  "@mariozechner/pi-ai": "^0.59.0",
32
31
  "@modelcontextprotocol/sdk": "1.27.1",
33
32
  "@sinclair/typebox": "^0.34.48",
34
33
  "@slack/web-api": "^7.15.0",
35
- "@vercel/queue": "^0.1.4",
36
- "@vercel/sandbox": "^1.8.1",
37
- "ai": "^6.0.116",
34
+ "@vercel/sandbox": "^1.9.0",
35
+ "ai": "^6.0.141",
38
36
  "bash-tool": "^1.3.15",
39
- "chat": "4.20.2",
40
- "just-bash": "^2.13.1",
37
+ "chat": "4.22.0",
38
+ "just-bash": "^2.14.0",
41
39
  "node-html-markdown": "^2.0.0",
42
- "yaml": "^2.8.2",
40
+ "yaml": "^2.8.3",
43
41
  "zod": "^4.3.6"
44
42
  },
45
43
  "peerDependencies": {
@@ -49,18 +47,18 @@
49
47
  "react-dom": ">=19.0.0"
50
48
  },
51
49
  "devDependencies": {
52
- "@sentry/nextjs": "^10.44.0",
53
- "@types/node": "^25.3.5",
50
+ "@sentry/nextjs": "^10.46.0",
51
+ "@types/node": "^25.5.0",
54
52
  "@types/react": "^19.2.14",
55
53
  "@types/react-dom": "^19.2.3",
56
- "msw": "^2.12.13",
57
- "next": "^16.1.7",
54
+ "msw": "^2.12.14",
55
+ "next": "^16.2.1",
58
56
  "react": "^19.2.4",
59
57
  "react-dom": "^19.2.4",
60
58
  "tsup": "^8.5.1",
61
59
  "typescript": "^5.9.3",
62
- "vercel": "^50.32.5",
63
- "vitest": "^4.1.0"
60
+ "vercel": "^50.37.2",
61
+ "vitest": "^4.1.2"
64
62
  },
65
63
  "scripts": {
66
64
  "build": "tsup",
@@ -1,103 +0,0 @@
1
- import {
2
- getProductionBot
3
- } from "./chunk-FLP5I4NM.js";
4
- import {
5
- createRequestContext,
6
- logException,
7
- logWarn,
8
- setSpanAttributes,
9
- setSpanStatus,
10
- withContext,
11
- withSpan
12
- } from "./chunk-MY7JNCS2.js";
13
-
14
- // src/handlers/webhooks.ts
15
- import { after } from "next/server";
16
- import * as Sentry from "@sentry/nextjs";
17
- async function POST(request, context) {
18
- const bot = getProductionBot();
19
- const { platform } = await context.params;
20
- const handler = bot.webhooks[platform];
21
- const requestContext = createRequestContext(request, { platform });
22
- const requestUrl = new URL(request.url);
23
- return withContext(requestContext, async () => {
24
- if (!handler) {
25
- const error = new Error(`Unknown platform: ${platform}`);
26
- logException(
27
- error,
28
- "webhook_platform_unknown",
29
- {},
30
- {
31
- "http.response.status_code": 404
32
- },
33
- `Unknown platform: ${platform}`
34
- );
35
- return new Response(`Unknown platform: ${platform}`, { status: 404 });
36
- }
37
- try {
38
- return await withSpan(
39
- "http.server.request",
40
- "http.server",
41
- requestContext,
42
- async () => {
43
- try {
44
- const activeSpan = Sentry.getActiveSpan();
45
- const response = await handler(request, {
46
- waitUntil: (task) => after(() => {
47
- const runTask = () => {
48
- const taskOrFactory = task;
49
- return typeof taskOrFactory === "function" ? taskOrFactory() : taskOrFactory;
50
- };
51
- if (activeSpan) {
52
- return Sentry.withActiveSpan(activeSpan, runTask);
53
- }
54
- return runTask();
55
- })
56
- });
57
- if (response.status >= 400) {
58
- let responseBodySnippet;
59
- try {
60
- responseBodySnippet = (await response.clone().text()).slice(
61
- 0,
62
- 300
63
- );
64
- } catch {
65
- responseBodySnippet = void 0;
66
- }
67
- logWarn(
68
- "webhook_non_success_response",
69
- {},
70
- {
71
- "http.response.status_code": response.status,
72
- "http.request.header.x_slack_signature": request.headers.get("x-slack-signature") ?? void 0,
73
- "http.request.header.x_slack_request_timestamp": request.headers.get("x-slack-request-timestamp") ?? void 0,
74
- ...responseBodySnippet ? { "app.webhook.response_body": responseBodySnippet } : {}
75
- },
76
- `Webhook ${platform} returned ${response.status}`
77
- );
78
- }
79
- setSpanAttributes({
80
- "http.response.status_code": response.status
81
- });
82
- setSpanStatus(response.status >= 500 ? "error" : "ok");
83
- return response;
84
- } catch (error) {
85
- setSpanStatus("error");
86
- throw error;
87
- }
88
- },
89
- {
90
- "http.request.method": request.method,
91
- "url.path": requestUrl.pathname
92
- }
93
- );
94
- } catch (error) {
95
- logException(error, "webhook_handler_failed");
96
- throw error;
97
- }
98
- });
99
- }
100
-
101
- export {
102
- POST
103
- };