@sentry/junior 0.54.0 → 0.55.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 (54) hide show
  1. package/README.md +1 -1
  2. package/dist/app.d.ts +9 -2
  3. package/dist/app.js +13854 -11486
  4. package/dist/chat/agent-dispatch/context.d.ts +6 -0
  5. package/dist/chat/agent-dispatch/heartbeat.d.ts +14 -0
  6. package/dist/chat/agent-dispatch/runner.d.ts +9 -0
  7. package/dist/chat/agent-dispatch/signing.d.ts +5 -0
  8. package/dist/chat/agent-dispatch/store.d.ts +29 -0
  9. package/dist/chat/agent-dispatch/types.d.ts +57 -0
  10. package/dist/chat/agent-dispatch/validation.d.ts +3 -0
  11. package/dist/chat/config.d.ts +1 -0
  12. package/dist/chat/ingress/workspace-membership.d.ts +1 -2
  13. package/dist/chat/logging.d.ts +2 -0
  14. package/dist/chat/plugins/agent-hooks.d.ts +32 -0
  15. package/dist/chat/plugins/logging.d.ts +3 -0
  16. package/dist/chat/plugins/state.d.ts +3 -0
  17. package/dist/chat/respond.d.ts +11 -0
  18. package/dist/chat/runtime/thread-context.d.ts +2 -0
  19. package/dist/chat/sandbox/egress-proxy.d.ts +8 -1
  20. package/dist/chat/sandbox/sandbox.d.ts +2 -0
  21. package/dist/chat/sandbox/session.d.ts +1 -0
  22. package/dist/chat/sandbox/skill-sync.d.ts +1 -2
  23. package/dist/chat/scheduler/cadence.d.ts +24 -0
  24. package/dist/chat/scheduler/plugin.d.ts +2 -0
  25. package/dist/chat/scheduler/prompt.d.ts +7 -0
  26. package/dist/chat/scheduler/store.d.ts +49 -0
  27. package/dist/chat/scheduler/types.d.ts +86 -0
  28. package/dist/chat/services/auth-pause.d.ts +7 -0
  29. package/dist/chat/services/mcp-auth-orchestration.d.ts +2 -1
  30. package/dist/chat/services/plugin-auth-orchestration.d.ts +2 -1
  31. package/dist/chat/slack/ids.d.ts +4 -0
  32. package/dist/chat/slack/reply.d.ts +1 -1
  33. package/dist/chat/slack/user.d.ts +1 -0
  34. package/dist/chat/slack/workspace-context.d.ts +4 -0
  35. package/dist/chat/tools/agent-tools.d.ts +2 -1
  36. package/dist/chat/tools/slack/schedule-tools.d.ts +29 -0
  37. package/dist/chat/tools/types.d.ts +6 -0
  38. package/dist/{chunk-QCHPJ4FD.js → chunk-D3G3YOU4.js} +1 -1
  39. package/dist/chunk-SCQPBJAU.js +21 -0
  40. package/dist/{chunk-YITDDLS3.js → chunk-TTUY467K.js} +13 -9
  41. package/dist/{chunk-7WTXNEPF.js → chunk-XI3CFWTA.js} +55 -7
  42. package/dist/cli/check.js +2 -2
  43. package/dist/cli/init.js +5 -1
  44. package/dist/cli/snapshot-warmup.js +2 -2
  45. package/dist/handlers/agent-dispatch.d.ts +3 -0
  46. package/dist/handlers/heartbeat.d.ts +3 -0
  47. package/dist/handlers/sandbox-egress-proxy.d.ts +6 -1
  48. package/dist/vercel.js +3 -12
  49. package/package.json +8 -2
  50. package/dist/chat/credentials/test-broker.d.ts +0 -19
  51. package/dist/chat/sandbox/eval-gh-stub.d.ts +0 -2
  52. package/dist/chat/sandbox/eval-oauth-stub.d.ts +0 -2
  53. package/dist/chat/sandbox/eval-sentry-stub.d.ts +0 -2
  54. package/dist/chat/sandbox/fault-injection.d.ts +0 -2
@@ -0,0 +1,21 @@
1
+ // src/vercel.ts
2
+ function juniorVercelConfig(options = {}) {
3
+ const buildCommand = options.buildCommand === void 0 ? "pnpm build" : options.buildCommand;
4
+ const config = {
5
+ framework: "nitro",
6
+ crons: [
7
+ {
8
+ path: "/api/internal/heartbeat",
9
+ schedule: "* * * * *"
10
+ }
11
+ ]
12
+ };
13
+ if (buildCommand !== null) {
14
+ config.buildCommand = buildCommand;
15
+ }
16
+ return config;
17
+ }
18
+
19
+ export {
20
+ juniorVercelConfig
21
+ };
@@ -297,6 +297,8 @@ function contextToAttributes(context) {
297
297
  "enduser.id": context.slackUserId,
298
298
  "enduser.pseudo.id": context.slackUserName,
299
299
  "app.run.id": context.runId,
300
+ "app.actor.type": context.actorType,
301
+ "app.actor.id": context.actorId,
300
302
  "gen_ai.agent.name": context.assistantUserName,
301
303
  "gen_ai.request.model": context.modelId,
302
304
  "app.skill.name": context.skillName,
@@ -592,6 +594,10 @@ function pushPrettyConsoleToken(tokens, token) {
592
594
  function numericConsoleToken(label, value) {
593
595
  return typeof value === "number" ? `${label}=${value}` : void 0;
594
596
  }
597
+ function stringConsoleToken(label, value) {
598
+ const normalized = toOptionalString(value);
599
+ return normalized ? `${label}=${normalized}` : void 0;
600
+ }
595
601
  function booleanConsoleToken(label, value) {
596
602
  return typeof value === "boolean" ? `${label}=${value ? "yes" : "no"}` : void 0;
597
603
  }
@@ -606,7 +612,7 @@ function getPrettyConsoleSummaryTokens(level, eventName, attributes) {
606
612
  );
607
613
  pushPrettyConsoleToken(
608
614
  tokens,
609
- toOptionalString(attributes["app.plugin.name"]) ?? void 0
615
+ eventName.startsWith("trusted_plugin_heartbeat") ? stringConsoleToken("plugin", attributes["app.plugin.name"]) : toOptionalString(attributes["app.plugin.name"]) ?? void 0
610
616
  );
611
617
  pushPrettyConsoleToken(
612
618
  tokens,
@@ -624,6 +630,10 @@ function getPrettyConsoleSummaryTokens(level, eventName, attributes) {
624
630
  tokens,
625
631
  numericConsoleToken("plugins", attributes["app.plugin.count"])
626
632
  );
633
+ pushPrettyConsoleToken(
634
+ tokens,
635
+ numericConsoleToken("dispatches", attributes["app.dispatch.count"])
636
+ );
627
637
  pushPrettyConsoleToken(
628
638
  tokens,
629
639
  numericConsoleToken("skills", attributes["app.skill.count"])
@@ -2473,10 +2483,7 @@ function createGitHubAppBroker(manifest, credentials) {
2473
2483
  const normalizedApiDomain = apiDomain.toLowerCase();
2474
2484
  return normalizedDomain === "github.com" || normalizedApiDomain.startsWith("api.") && normalizedDomain === normalizedApiDomain.slice("api.".length);
2475
2485
  }
2476
- const permissions = capabilitiesToPermissions(
2477
- manifest.capabilities,
2478
- provider
2479
- );
2486
+ const permissions = manifest.capabilities?.length ? capabilitiesToPermissions(manifest.capabilities, provider) : void 0;
2480
2487
  function createLease(params) {
2481
2488
  return {
2482
2489
  id: randomUUID2(),
@@ -2516,9 +2523,7 @@ function createGitHubAppBroker(manifest, credentials) {
2516
2523
  return {
2517
2524
  async issue(input) {
2518
2525
  const installationId = resolveInstallationId();
2519
- const tokenRequestBody = {
2520
- permissions
2521
- };
2526
+ const tokenRequestBody = permissions ? { permissions } : {};
2522
2527
  const appId = resolveAppId(appIdEnv);
2523
2528
  const appJwt = createAppJwt(appId, privateKeyEnv);
2524
2529
  const accessTokenResponse = await githubRequest(apiBase, `/app/installations/${installationId}/access_tokens`, {
@@ -3204,7 +3209,6 @@ export {
3204
3209
  serializeGenAiAttribute,
3205
3210
  extractGenAiUsageSummary,
3206
3211
  extractGenAiUsageAttributes,
3207
- mergeHeaderTransforms,
3208
3212
  resolvePluginCommandEnv,
3209
3213
  resolveAuthTokenPlaceholder,
3210
3214
  parsePluginManifest,
@@ -7,7 +7,7 @@ import {
7
7
  serializeGenAiAttribute,
8
8
  setSpanAttributes,
9
9
  withSpan
10
- } from "./chunk-YITDDLS3.js";
10
+ } from "./chunk-TTUY467K.js";
11
11
 
12
12
  // src/chat/state/adapter.ts
13
13
  import { createMemoryState } from "@chat-adapter/state-memory";
@@ -385,6 +385,7 @@ function readChatConfig(env = process.env) {
385
385
  },
386
386
  state: {
387
387
  adapter: env.JUNIOR_STATE_ADAPTER?.trim().toLowerCase() === "memory" ? "memory" : "redis",
388
+ keyPrefix: toOptionalTrimmed(env.JUNIOR_STATE_KEY_PREFIX),
388
389
  redisUrl: toOptionalTrimmed(env.REDIS_URL)
389
390
  }
390
391
  };
@@ -417,6 +418,48 @@ var ACTIVE_LOCK_TTL_MS = 9e4;
417
418
  var ACTIVE_LOCK_HEARTBEAT_MS = 3e4;
418
419
  var stateAdapter;
419
420
  var redisStateAdapter;
421
+ function createPrefixedStateAdapter(base, prefix) {
422
+ const prefixed = (value) => `${prefix}:${value}`;
423
+ const unprefixed = (value) => value.startsWith(`${prefix}:`) ? value.slice(prefix.length + 1) : value;
424
+ const prefixLock = (lock) => ({
425
+ ...lock,
426
+ threadId: prefixed(lock.threadId)
427
+ });
428
+ const unprefixLock = (lock) => ({
429
+ ...lock,
430
+ threadId: unprefixed(lock.threadId)
431
+ });
432
+ return {
433
+ appendToList: (key, value, options) => base.appendToList(prefixed(key), value, options),
434
+ connect: () => base.connect(),
435
+ disconnect: () => base.disconnect(),
436
+ subscribe: (threadId) => base.subscribe(prefixed(threadId)),
437
+ unsubscribe: (threadId) => base.unsubscribe(prefixed(threadId)),
438
+ isSubscribed: (threadId) => base.isSubscribed(prefixed(threadId)),
439
+ acquireLock: async (threadId, ttlMs) => {
440
+ const lock = await base.acquireLock(prefixed(threadId), ttlMs);
441
+ return lock ? unprefixLock(lock) : null;
442
+ },
443
+ releaseLock: (lock) => base.releaseLock(prefixLock(lock)),
444
+ extendLock: async (lock, ttlMs) => {
445
+ const prefixedLock = prefixLock(lock);
446
+ const extended = await base.extendLock(prefixedLock, ttlMs);
447
+ if (extended) {
448
+ lock.expiresAt = prefixedLock.expiresAt;
449
+ }
450
+ return extended;
451
+ },
452
+ forceReleaseLock: (threadId) => base.forceReleaseLock(prefixed(threadId)),
453
+ enqueue: (threadId, entry, maxSize) => base.enqueue(prefixed(threadId), entry, maxSize),
454
+ dequeue: (threadId) => base.dequeue(prefixed(threadId)),
455
+ queueDepth: (threadId) => base.queueDepth(prefixed(threadId)),
456
+ get: (key) => base.get(prefixed(key)),
457
+ getList: (key) => base.getList(prefixed(key)),
458
+ set: (key, value, ttlMs) => base.set(prefixed(key), value, ttlMs),
459
+ setIfNotExists: (key, value, ttlMs) => base.setIfNotExists(prefixed(key), value, ttlMs),
460
+ delete: (key) => base.delete(prefixed(key))
461
+ };
462
+ }
420
463
  function createQueuedStateAdapter(base, options) {
421
464
  const heartbeats = /* @__PURE__ */ new Map();
422
465
  const effectiveLockTtlMs = (ttlMs) => Math.max(ttlMs, ACTIVE_LOCK_TTL_MS);
@@ -541,14 +584,18 @@ function createQueuedStateAdapter(base, options) {
541
584
  delete: (key) => base.delete(key)
542
585
  };
543
586
  }
587
+ function withOptionalPrefix(base, prefix) {
588
+ return prefix ? createPrefixedStateAdapter(base, prefix) : base;
589
+ }
544
590
  function createStateAdapter() {
545
591
  const config = getChatConfig();
546
592
  const activeLockMaxAgeMs = config.bot.turnTimeoutMs + ACTIVE_LOCK_TTL_MS;
547
593
  if (config.state.adapter === "memory") {
548
594
  redisStateAdapter = void 0;
549
- return createQueuedStateAdapter(createMemoryState(), {
550
- activeLockMaxAgeMs
551
- });
595
+ return createQueuedStateAdapter(
596
+ withOptionalPrefix(createMemoryState(), config.state.keyPrefix),
597
+ { activeLockMaxAgeMs }
598
+ );
552
599
  }
553
600
  if (!config.state.redisUrl) {
554
601
  throw new Error("REDIS_URL is required for durable Slack thread state");
@@ -557,9 +604,10 @@ function createStateAdapter() {
557
604
  url: config.state.redisUrl
558
605
  });
559
606
  redisStateAdapter = redisState;
560
- return createQueuedStateAdapter(redisState, {
561
- activeLockMaxAgeMs
562
- });
607
+ return createQueuedStateAdapter(
608
+ withOptionalPrefix(redisState, config.state.keyPrefix),
609
+ { activeLockMaxAgeMs }
610
+ );
563
611
  }
564
612
  function getStateAdapter() {
565
613
  if (!stateAdapter) {
package/dist/cli/check.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  parseSkillFile
3
- } from "../chunk-QCHPJ4FD.js";
3
+ } from "../chunk-D3G3YOU4.js";
4
4
  import {
5
5
  parsePluginManifest
6
- } from "../chunk-YITDDLS3.js";
6
+ } from "../chunk-TTUY467K.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
@@ -1,3 +1,6 @@
1
+ import {
2
+ juniorVercelConfig
3
+ } from "../chunk-SCQPBJAU.js";
1
4
  import "../chunk-2KG3PWR4.js";
2
5
 
3
6
  // src/cli/init.ts
@@ -51,7 +54,7 @@ export default defineConfig({
51
54
  function writeVercelJson(targetDir) {
52
55
  fs.writeFileSync(
53
56
  path.join(targetDir, "vercel.json"),
54
- `${JSON.stringify({ framework: "nitro", buildCommand: "pnpm build" }, null, 2)}
57
+ `${JSON.stringify(juniorVercelConfig(), null, 2)}
55
58
  `
56
59
  );
57
60
  }
@@ -178,6 +181,7 @@ AI_FAST_MODEL=
178
181
  AI_VISION_MODEL=
179
182
  AI_WEB_SEARCH_MODEL=
180
183
  REDIS_URL=
184
+ CRON_SECRET=
181
185
  SENTRY_DSN=
182
186
  SENTRY_ORG_SLUG=
183
187
  `
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  disconnectStateAdapter,
3
3
  resolveRuntimeDependencySnapshot
4
- } from "../chunk-7WTXNEPF.js";
4
+ } from "../chunk-XI3CFWTA.js";
5
5
  import {
6
6
  getPluginProviders,
7
7
  getPluginRuntimeDependencies,
8
8
  getPluginRuntimePostinstall
9
- } from "../chunk-YITDDLS3.js";
9
+ } from "../chunk-TTUY467K.js";
10
10
  import "../chunk-Z3YD6NHK.js";
11
11
  import "../chunk-5LUISFEY.js";
12
12
  import "../chunk-2KG3PWR4.js";
@@ -0,0 +1,3 @@
1
+ import type { WaitUntilFn } from "@/handlers/types";
2
+ /** Handle the authenticated internal agent-dispatch callback. */
3
+ export declare function POST(request: Request, waitUntil: WaitUntilFn): Promise<Response>;
@@ -0,0 +1,3 @@
1
+ import type { WaitUntilFn } from "@/handlers/types";
2
+ /** Handle the authenticated internal heartbeat. */
3
+ export declare function GET(request: Request, waitUntil: WaitUntilFn): Promise<Response>;
@@ -1,4 +1,9 @@
1
+ import { type SandboxEgressHttpInterceptor } from "@/chat/sandbox/egress-proxy";
2
+ interface SandboxEgressProxyOptions {
3
+ interceptHttp?: SandboxEgressHttpInterceptor;
4
+ }
1
5
  /** Handles Vercel Sandbox firewall egress proxy requests. */
2
- export declare function ALL(request: Request): Promise<Response>;
6
+ export declare function ALL(request: Request, options?: SandboxEgressProxyOptions): Promise<Response>;
3
7
  /** Return whether a request should be routed through sandbox egress proxying. */
4
8
  export declare function isSandboxEgressRequest(request: Request): boolean;
9
+ export {};
package/dist/vercel.js CHANGED
@@ -1,16 +1,7 @@
1
+ import {
2
+ juniorVercelConfig
3
+ } from "./chunk-SCQPBJAU.js";
1
4
  import "./chunk-2KG3PWR4.js";
2
-
3
- // src/vercel.ts
4
- function juniorVercelConfig(options = {}) {
5
- const buildCommand = options.buildCommand === void 0 ? "pnpm build" : options.buildCommand;
6
- const config = {
7
- framework: "nitro"
8
- };
9
- if (buildCommand !== null) {
10
- config.buildCommand = buildCommand;
11
- }
12
- return config;
13
- }
14
5
  export {
15
6
  juniorVercelConfig
16
7
  };
package/package.json CHANGED
@@ -1,11 +1,16 @@
1
1
  {
2
2
  "name": "@sentry/junior",
3
- "version": "0.54.0",
3
+ "version": "0.55.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
8
  "type": "module",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/getsentry/junior.git",
12
+ "directory": "packages/junior"
13
+ },
9
14
  "bin": {
10
15
  "junior": "bin/junior.mjs"
11
16
  },
@@ -40,7 +45,8 @@
40
45
  "just-bash": "3.0.1",
41
46
  "node-html-markdown": "^2.0.0",
42
47
  "yaml": "^2.9.0",
43
- "zod": "^4.4.3"
48
+ "zod": "^4.4.3",
49
+ "@sentry/junior-plugin-api": "0.55.0"
44
50
  },
45
51
  "peerDependencies": {
46
52
  "@sentry/node": ">=10.0.0"
@@ -1,19 +0,0 @@
1
- import type { CredentialBroker, CredentialHeaderTransform, CredentialLease } from "@/chat/credentials/broker";
2
- interface TestBrokerConfig {
3
- provider: string;
4
- domains?: string[];
5
- apiHeaders?: Record<string, string>;
6
- headerTransforms?: () => CredentialHeaderTransform[];
7
- env?: Record<string, string>;
8
- envKey?: string;
9
- placeholder?: string;
10
- }
11
- /** Issue deterministic placeholder credential leases for eval runs. */
12
- export declare class TestCredentialBroker implements CredentialBroker {
13
- private readonly config;
14
- constructor(config: TestBrokerConfig);
15
- issue(input: {
16
- reason: string;
17
- }): Promise<CredentialLease>;
18
- }
19
- export {};
@@ -1,2 +0,0 @@
1
- /** Build the eval-only GitHub CLI shim copied into sandbox test environments. */
2
- export declare function buildEvalGitHubCliStub(): string;
@@ -1,2 +0,0 @@
1
- /** Build the eval-only generic OAuth CLI shim copied into sandbox eval environments. */
2
- export declare function buildEvalOauthCliStub(): string;
@@ -1,2 +0,0 @@
1
- /** Build the eval-only Sentry CLI shim copied into sandbox test environments. */
2
- export declare function buildEvalSentryCliStub(): string;
@@ -1,2 +0,0 @@
1
- /** Consume one eval-only sandbox bash stream interruption fault. */
2
- export declare function consumeSandboxBashStreamInterruptFault(): Error | undefined;