@sentry/junior 0.68.0 → 0.69.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 (65) hide show
  1. package/dist/app.js +1464 -732
  2. package/dist/build/virtual-config.d.ts +2 -2
  3. package/dist/chat/agent-dispatch/heartbeat.d.ts +2 -2
  4. package/dist/chat/agent-dispatch/store.d.ts +4 -1
  5. package/dist/chat/agent-dispatch/types.d.ts +2 -4
  6. package/dist/chat/agent-dispatch/validation.d.ts +3 -2
  7. package/dist/chat/credentials/context.d.ts +49 -24
  8. package/dist/chat/credentials/user-token-store.d.ts +6 -0
  9. package/dist/chat/destination.d.ts +12 -0
  10. package/dist/chat/ingress/message-router.d.ts +1 -1
  11. package/dist/chat/mcp/auth-store.d.ts +2 -0
  12. package/dist/chat/mcp/oauth.d.ts +2 -0
  13. package/dist/chat/oauth-flow.d.ts +7 -0
  14. package/dist/chat/plugins/agent-hooks.d.ts +9 -9
  15. package/dist/chat/plugins/auth/auth-token-placeholder.d.ts +2 -2
  16. package/dist/chat/plugins/auth/oauth-request.d.ts +3 -1
  17. package/dist/chat/plugins/credential-hooks.d.ts +34 -0
  18. package/dist/chat/plugins/logging.d.ts +1 -1
  19. package/dist/chat/plugins/state.d.ts +1 -1
  20. package/dist/chat/plugins/types.d.ts +19 -23
  21. package/dist/chat/respond.d.ts +2 -0
  22. package/dist/chat/runtime/reply-executor.d.ts +3 -1
  23. package/dist/chat/runtime/slack-runtime.d.ts +8 -3
  24. package/dist/chat/sandbox/egress-credentials.d.ts +33 -0
  25. package/dist/chat/sandbox/egress-schemas.d.ts +105 -0
  26. package/dist/chat/sandbox/egress-session.d.ts +17 -17
  27. package/dist/chat/sandbox/sandbox.d.ts +3 -0
  28. package/dist/chat/sandbox/session.d.ts +1 -0
  29. package/dist/chat/services/mcp-auth-orchestration.d.ts +2 -0
  30. package/dist/chat/services/pending-auth.d.ts +2 -0
  31. package/dist/chat/services/plugin-auth-orchestration.d.ts +2 -0
  32. package/dist/chat/services/provider-retry.d.ts +13 -4
  33. package/dist/chat/services/timeout-resume.d.ts +2 -0
  34. package/dist/chat/services/turn-session-record.d.ts +6 -0
  35. package/dist/chat/slack/attachment-fetchers.d.ts +11 -0
  36. package/dist/chat/state/conversation.d.ts +1 -0
  37. package/dist/chat/state/turn-session.d.ts +4 -0
  38. package/dist/chat/task-execution/queue.d.ts +2 -0
  39. package/dist/chat/task-execution/store.d.ts +5 -0
  40. package/dist/chat/task-execution/vercel-callback.d.ts +4 -0
  41. package/dist/chat/task-execution/vercel-queue.d.ts +2 -0
  42. package/dist/chat/task-execution/worker.d.ts +4 -2
  43. package/dist/chat/tools/slack/context.d.ts +3 -0
  44. package/dist/chat/tools/types.d.ts +21 -2
  45. package/dist/chunk-76YMBKW7.js +326 -0
  46. package/dist/{chunk-PIVOJIUD.js → chunk-B5HKWWQB.js} +9 -5
  47. package/dist/chunk-BBXYXOJW.js +1858 -0
  48. package/dist/{chunk-V47RLIO2.js → chunk-GT67ZWZQ.js} +4 -4
  49. package/dist/{chunk-75UZ4JLC.js → chunk-IGLNC5H6.js} +21 -9
  50. package/dist/{chunk-EBVQXCD2.js → chunk-JS4HURDT.js} +362 -280
  51. package/dist/{chunk-UQQSW7QB.js → chunk-N3MORKTH.js} +74 -331
  52. package/dist/chunk-R62YWUNO.js +264 -0
  53. package/dist/{chunk-OIIXZOOC.js → chunk-UXG6TU2U.js} +311 -2015
  54. package/dist/cli/check.js +4 -4
  55. package/dist/cli/snapshot-warmup.js +5 -4
  56. package/dist/nitro.d.ts +1 -1
  57. package/dist/nitro.js +21 -19
  58. package/dist/plugins.d.ts +2 -2
  59. package/dist/reporting.d.ts +2 -2
  60. package/dist/reporting.js +13 -11
  61. package/package.json +6 -4
  62. package/dist/chat/plugins/auth/github-app-broker.d.ts +0 -4
  63. package/dist/chat/plugins/github-permissions.d.ts +0 -11
  64. package/dist/chat/queue/thread-message-dispatcher.d.ts +0 -33
  65. package/dist/chunk-KVZL5NZS.js +0 -519
@@ -9,12 +9,12 @@ export interface RuntimePluginModule {
9
9
  export declare function renderVirtualConfig(options: {
10
10
  plugins?: PluginCatalogConfig;
11
11
  pluginModule?: RuntimePluginModule;
12
- trustedPluginRegistrations?: string[];
12
+ pluginHookRegistrations?: string[];
13
13
  }): string;
14
14
  /** Inject a virtual module so createApp() can read the plugin list at runtime. */
15
15
  export declare function injectVirtualConfig(nitro: Nitro, options?: {
16
16
  loadPluginSet?: () => Promise<JuniorPluginSet | undefined>;
17
17
  pluginModule?: RuntimePluginModule;
18
18
  plugins?: PluginCatalogConfig;
19
- trustedPluginRegistrations?: string[];
19
+ pluginHookRegistrations?: string[];
20
20
  }): void;
@@ -10,8 +10,8 @@ export declare function recoverStaleDispatches(args: {
10
10
  limit?: number;
11
11
  nowMs: number;
12
12
  }): Promise<number>;
13
- /** Run trusted plugin heartbeat hooks with bounded per-invocation work. */
14
- export declare function runTrustedPluginHeartbeats(args: {
13
+ /** Run plugin heartbeat hooks with bounded per-invocation work. */
14
+ export declare function runPluginHeartbeats(args: {
15
15
  limit?: number;
16
16
  nowMs: number;
17
17
  }): Promise<void>;
@@ -1,9 +1,12 @@
1
1
  import type { StateAdapter } from "chat";
2
+ import { type Destination } from "@sentry/junior-plugin-api";
2
3
  import type { BoundDispatchOptions, DispatchCreateResult, DispatchProjection, DispatchRecord, DispatchStatus } from "./types";
3
4
  /** Keep dispatch persistence keys consistent across callback and recovery paths. */
4
5
  export declare function getDispatchStorageKey(id: string): string;
6
+ /** Parse persisted dispatch records before recovery, callbacks, or projections use them. */
7
+ export declare function parseDispatchRecord(value: unknown): DispatchRecord | undefined;
5
8
  /** Map a dispatch destination to the lock key that serializes Slack delivery. */
6
- export declare function getDispatchDestinationLockId(destination: DispatchRecord["destination"]): string;
9
+ export declare function getDispatchDestinationLockId(destination: Destination): string;
7
10
  /** Return the isolated persisted conversation key for one dispatch run. */
8
11
  export declare function getDispatchConversationId(dispatch: Pick<DispatchRecord, "id">): string;
9
12
  /** Give dispatch slices stable turn ids for resumability and trace correlation. */
@@ -1,8 +1,6 @@
1
- import type { DispatchOptions as AgentPluginDispatchOptions } from "@sentry/junior-plugin-api";
1
+ import type { Destination, DispatchOptions } from "@sentry/junior-plugin-api";
2
2
  import type { CredentialSubject, CredentialSystemActor } from "@/chat/credentials/context";
3
3
  export type DispatchStatus = "pending" | "running" | "awaiting_resume" | "completed" | "failed" | "blocked";
4
- export type DispatchOptions = AgentPluginDispatchOptions;
5
- export type DispatchDestination = DispatchOptions["destination"];
6
4
  export interface BoundDispatchOptions extends Omit<DispatchOptions, "credentialSubject"> {
7
5
  credentialSubject?: CredentialSubject;
8
6
  }
@@ -11,7 +9,7 @@ export interface DispatchRecord {
11
9
  attempt: number;
12
10
  createdAtMs: number;
13
11
  credentialSubject?: CredentialSubject;
14
- destination: DispatchDestination;
12
+ destination: Destination;
15
13
  errorMessage?: string;
16
14
  id: string;
17
15
  idempotencyKey: string;
@@ -1,5 +1,6 @@
1
- import type { BoundDispatchOptions, DispatchOptions } from "./types";
1
+ import { type DispatchOptions } from "@sentry/junior-plugin-api";
2
+ import type { BoundDispatchOptions } from "./types";
2
3
  /** Validate plugin-provided dispatch options before core persists them. */
3
- export declare function validateDispatchOptions(options: DispatchOptions): void;
4
+ export declare function validateDispatchOptions(options: unknown): asserts options is DispatchOptions;
4
5
  /** Verify runtime-owned access requirements for delegated dispatch credentials. */
5
6
  export declare function verifyDispatchCredentialSubjectAccess(options: BoundDispatchOptions): Promise<void>;
@@ -1,28 +1,53 @@
1
- import type { AgentPluginCredentialSubject } from "@sentry/junior-plugin-api";
2
- export interface CredentialSubjectBinding {
3
- type: "slack-direct-conversation";
4
- teamId: string;
5
- channelId: string;
6
- signature: string;
7
- }
8
- export type CredentialSystemActor = {
9
- type: "system";
10
- id: string;
11
- };
12
- export type CredentialSubject = AgentPluginCredentialSubject & {
13
- binding: CredentialSubjectBinding;
14
- };
15
- export type CredentialContext = {
16
- actor: {
17
- type: "user";
18
- userId: string;
19
- };
20
- subject?: never;
21
- } | {
22
- actor: CredentialSystemActor;
23
- subject?: CredentialSubject;
24
- };
1
+ import { z } from "zod";
2
+ declare const credentialSubjectBindingSchema: z.ZodObject<{
3
+ type: z.ZodLiteral<"slack-direct-conversation">;
4
+ teamId: z.ZodString;
5
+ channelId: z.ZodString;
6
+ signature: z.ZodString;
7
+ }, z.core.$strict>;
8
+ declare const credentialSystemActorSchema: z.ZodObject<{
9
+ type: z.ZodLiteral<"system">;
10
+ id: z.ZodString;
11
+ }, z.core.$strict>;
12
+ export declare const credentialSubjectSchema: z.ZodObject<{
13
+ type: z.ZodLiteral<"user">;
14
+ userId: z.ZodString;
15
+ allowedWhen: z.ZodLiteral<"private-direct-conversation">;
16
+ binding: z.ZodObject<{
17
+ type: z.ZodLiteral<"slack-direct-conversation">;
18
+ teamId: z.ZodString;
19
+ channelId: z.ZodString;
20
+ signature: z.ZodString;
21
+ }, z.core.$strict>;
22
+ }, z.core.$strict>;
23
+ export declare const credentialContextSchema: z.ZodUnion<readonly [z.ZodObject<{
24
+ actor: z.ZodObject<{
25
+ type: z.ZodLiteral<"user">;
26
+ userId: z.ZodString;
27
+ }, z.core.$strict>;
28
+ }, z.core.$strict>, z.ZodObject<{
29
+ actor: z.ZodObject<{
30
+ type: z.ZodLiteral<"system">;
31
+ id: z.ZodString;
32
+ }, z.core.$strict>;
33
+ subject: z.ZodOptional<z.ZodObject<{
34
+ type: z.ZodLiteral<"user">;
35
+ userId: z.ZodString;
36
+ allowedWhen: z.ZodLiteral<"private-direct-conversation">;
37
+ binding: z.ZodObject<{
38
+ type: z.ZodLiteral<"slack-direct-conversation">;
39
+ teamId: z.ZodString;
40
+ channelId: z.ZodString;
41
+ signature: z.ZodString;
42
+ }, z.core.$strict>;
43
+ }, z.core.$strict>>;
44
+ }, z.core.$strict>]>;
45
+ export type CredentialSubjectBinding = z.output<typeof credentialSubjectBindingSchema>;
46
+ export type CredentialSystemActor = z.output<typeof credentialSystemActorSchema>;
47
+ export type CredentialSubject = z.output<typeof credentialSubjectSchema>;
48
+ export type CredentialContext = z.output<typeof credentialContextSchema>;
25
49
  /** Return the user whose OAuth token may satisfy this credential request. */
26
50
  export declare function credentialUserSubjectId(context: CredentialContext): string | undefined;
27
51
  /** Parse an untrusted credential context payload from sandbox egress state. */
28
52
  export declare function parseCredentialContext(value: unknown): CredentialContext | undefined;
53
+ export {};
@@ -1,4 +1,10 @@
1
+ export interface StoredProviderAccount {
2
+ id: string;
3
+ label?: string;
4
+ url?: string;
5
+ }
1
6
  export interface StoredTokens {
7
+ account?: StoredProviderAccount;
2
8
  accessToken: string;
3
9
  refreshToken: string;
4
10
  expiresAt?: number;
@@ -0,0 +1,12 @@
1
+ import { type Destination } from "@sentry/junior-plugin-api";
2
+ /** Build Junior's canonical destination from Slack workspace and channel ids. */
3
+ export declare function createSlackDestination(input: {
4
+ channelId: string | undefined;
5
+ teamId: string | undefined;
6
+ }): Destination | undefined;
7
+ /** Parse and validate a serialized destination that crossed a runtime boundary. */
8
+ export declare function parseDestination(value: unknown): Destination | undefined;
9
+ /** Compare two destinations without relying on object identity. */
10
+ export declare function sameDestination(left: Destination, right: Destination): boolean;
11
+ /** Return the lock/index-safe storage key for a destination. */
12
+ export declare function destinationKey(destination: Destination): string;
@@ -1,4 +1,4 @@
1
- import type { ThreadMessageKind } from "@/chat/queue/thread-message-dispatcher";
1
+ export type ThreadMessageKind = "new_mention" | "subscribed_message";
2
2
  /** Derive canonical Slack thread IDs from the raw event payload. */
3
3
  export declare function normalizeIncomingSlackThreadId(threadId: string, message: unknown): string;
4
4
  /** Classify an incoming message as a mention or subscribed message. */
@@ -1,11 +1,13 @@
1
1
  import type { OAuthClientInformationMixed, OAuthTokens } from "@modelcontextprotocol/sdk/shared/auth.js";
2
2
  import type { OAuthDiscoveryState } from "@modelcontextprotocol/sdk/client/auth.js";
3
+ import type { Destination } from "@sentry/junior-plugin-api";
3
4
  import type { ThreadArtifactsState } from "@/chat/state/artifacts";
4
5
  export interface McpAuthSessionState {
5
6
  authSessionId: string;
6
7
  provider: string;
7
8
  userId: string;
8
9
  conversationId: string;
10
+ destination?: Destination;
9
11
  sessionId: string;
10
12
  userMessage: string;
11
13
  channelId?: string;
@@ -1,3 +1,4 @@
1
+ import type { Destination } from "@sentry/junior-plugin-api";
1
2
  import type { ThreadArtifactsState } from "@/chat/state/artifacts";
2
3
  import { type McpAuthSessionState } from "./auth-store";
3
4
  import { StateBackedMcpOAuthClientProvider } from "./oauth-provider";
@@ -5,6 +6,7 @@ export declare function getMcpOAuthCallbackPath(provider: string): string;
5
6
  export declare function createMcpOAuthClientProvider(input: {
6
7
  provider: string;
7
8
  conversationId: string;
9
+ destination?: Destination;
8
10
  sessionId: string;
9
11
  userId: string;
10
12
  userMessage: string;
@@ -1,25 +1,32 @@
1
+ import type { Destination } from "@sentry/junior-plugin-api";
1
2
  import type { ChannelConfigurationService } from "@/chat/configuration/types";
2
3
  type PrivateDeliveryResult = "in_context" | "fallback_dm" | false;
3
4
  export type OAuthStatePayload = {
4
5
  userId: string;
5
6
  provider: string;
6
7
  channelId?: string;
8
+ destination?: Destination;
7
9
  threadTs?: string;
8
10
  pendingMessage?: string;
9
11
  configuration?: Record<string, unknown>;
10
12
  resumeConversationId?: string;
11
13
  resumeSessionId?: string;
14
+ scope?: string;
12
15
  };
13
16
  type OAuthFlowInput = {
14
17
  requesterId: string;
15
18
  channelId?: string;
19
+ destination?: Destination;
16
20
  threadTs?: string;
17
21
  userMessage?: string;
18
22
  channelConfiguration?: ChannelConfigurationService;
19
23
  activeSkillName?: string;
20
24
  resumeConversationId?: string;
21
25
  resumeSessionId?: string;
26
+ scope?: string;
22
27
  };
28
+ /** Parse OAuth callback state that was persisted before a provider redirect. */
29
+ export declare function parseOAuthStatePayload(value: unknown): OAuthStatePayload | undefined;
23
30
  /** Capitalize the first letter of a provider name for display. */
24
31
  export declare function formatProviderLabel(provider: string): string;
25
32
  /** Resolve the public base URL from environment variables (JUNIOR_BASE_URL or Vercel). */
@@ -2,7 +2,7 @@ import type { AgentPluginRequester, AgentPluginRoute, PluginOperationalReport, S
2
2
  import type { ToolDefinition } from "@/chat/tools/definition";
3
3
  import type { ToolRuntimeContext } from "@/chat/tools/types";
4
4
  import type { SandboxInstance } from "@/chat/sandbox/workspace";
5
- /** Signal that a trusted plugin intentionally denied a tool execution. */
5
+ /** Signal that a plugin intentionally denied a tool execution. */
6
6
  export declare class AgentPluginHookDeniedError extends Error {
7
7
  constructor(message: string);
8
8
  }
@@ -21,21 +21,21 @@ export interface AgentPluginHookRunner {
21
21
  beforeToolExecute(input: ToolHookInput): Promise<ToolHookResult>;
22
22
  prepareSandbox(sandbox: SandboxInstance): Promise<void>;
23
23
  }
24
- /** Validate trusted plugin identity before it can affect process-wide hooks. */
24
+ /** Validate plugin identity before it can affect process-wide hooks. */
25
25
  export declare function validateAgentPlugins(plugins: JuniorPluginRegistration[]): void;
26
- /** Replace trusted agent plugins and return the previous list for rollback. */
26
+ /** Replace runtime hook plugins and return the previous list for rollback. */
27
27
  export declare function setAgentPlugins(plugins: JuniorPluginRegistration[]): JuniorPluginRegistration[];
28
- /** Return the current trusted agent plugins without exposing mutable state. */
28
+ /** Return the current runtime hook plugins without exposing mutable state. */
29
29
  export declare function getAgentPlugins(): JuniorPluginRegistration[];
30
- /** Collect turn-scoped tools exposed by trusted plugins. */
30
+ /** Collect turn-scoped tools exposed by plugins. */
31
31
  export declare function getAgentPluginTools(context: ToolRuntimeContext): Record<string, ToolDefinition<any>>;
32
- /** Collect route handlers exposed by trusted plugins for app-level mounting. */
32
+ /** Collect route handlers exposed by plugins for app-level mounting. */
33
33
  export declare function getAgentPluginRoutes(): AgentPluginRouteRegistration[];
34
- /** Resolve the first trusted plugin conversation URL for finalized Slack footers. */
34
+ /** Resolve the first plugin conversation URL for finalized Slack footers. */
35
35
  export declare function getAgentPluginSlackConversationLink(conversationId: string): SlackConversationLink | undefined;
36
- /** Collect read-only operational summaries exposed by trusted plugins. */
36
+ /** Collect read-only operational summaries exposed by plugins. */
37
37
  export declare function getAgentPluginOperationalReports(nowMs?: number): Promise<PluginOperationalReport[]>;
38
- /** Create one runner over trusted agent plugins registered by the app. */
38
+ /** Create one runner over runtime hook plugins registered by the app. */
39
39
  export declare function createAgentPluginHookRunner(input?: {
40
40
  requester?: AgentPluginRequester;
41
41
  }): AgentPluginHookRunner;
@@ -1,3 +1,3 @@
1
- import type { GitHubAppCredentials, OAuthBearerCredentials } from "../types";
1
+ import type { OAuthBearerCredentials } from "../types";
2
2
  /** Resolve the non-secret sandbox token placeholder for token-backed credentials. */
3
- export declare function resolveAuthTokenPlaceholder(credentials: OAuthBearerCredentials | GitHubAppCredentials): string;
3
+ export declare function resolveAuthTokenPlaceholder(credentials: OAuthBearerCredentials): string;
@@ -9,7 +9,9 @@ export declare function buildOAuthTokenRequest(input: OAuthTokenRequestInput): {
9
9
  headers: Record<string, string>;
10
10
  body: BodyInit;
11
11
  };
12
- export declare function parseOAuthTokenResponse(data: Record<string, unknown>, fallbackScope?: string): {
12
+ export declare function parseOAuthTokenResponse(data: Record<string, unknown>, requestedScope?: string, options?: {
13
+ treatEmptyScopeAsUnreported?: boolean;
14
+ }): {
13
15
  accessToken: string;
14
16
  refreshToken: string;
15
17
  expiresAt?: number;
@@ -0,0 +1,34 @@
1
+ import { type AgentPluginCredentialResult, type AgentPluginGrant, type AgentPluginProviderAccount } from "@sentry/junior-plugin-api";
2
+ import type { StoredTokens, UserTokenStore } from "@/chat/credentials/user-token-store";
3
+ export interface EgressGrantInput {
4
+ method: string;
5
+ provider: string;
6
+ upstreamUrl: URL;
7
+ }
8
+ /** Ask a plugin which grant an outbound request needs. */
9
+ export declare function selectPluginGrant(input: EgressGrantInput): Promise<AgentPluginGrant | undefined>;
10
+ /** Return whether a plugin owns credential issuance for egress. */
11
+ export declare function hasEgressCredentialHooks(provider: string): boolean;
12
+ export interface IssueCredentialInput {
13
+ actor: {
14
+ type: "system";
15
+ id: string;
16
+ } | {
17
+ type: "user";
18
+ userId: string;
19
+ };
20
+ credentialSubject?: {
21
+ type: "user";
22
+ userId: string;
23
+ };
24
+ grant: AgentPluginGrant;
25
+ provider: string;
26
+ userTokenStore: UserTokenStore;
27
+ }
28
+ /** Ask a plugin which provider account belongs to an OAuth token. */
29
+ export declare function resolvePluginOAuthAccount(input: {
30
+ provider: string;
31
+ tokens: StoredTokens;
32
+ }): Promise<AgentPluginProviderAccount | undefined>;
33
+ /** Ask a plugin to issue headers or describe why the selected grant is unavailable. */
34
+ export declare function issuePluginCredential(input: IssueCredentialInput): Promise<AgentPluginCredentialResult>;
@@ -1,3 +1,3 @@
1
1
  import type { AgentPluginLogger } from "@sentry/junior-plugin-api";
2
- /** Create the host logger exposed to trusted plugin hooks. */
2
+ /** Create the host logger exposed to plugin hooks. */
3
3
  export declare function createAgentPluginLogger(plugin: string): AgentPluginLogger;
@@ -2,5 +2,5 @@ import type { AgentPluginState } from "@sentry/junior-plugin-api";
2
2
  export interface PluginStateOptions {
3
3
  legacyStatePrefixes?: string[];
4
4
  }
5
- /** Create a durable state namespace scoped to one trusted plugin. */
5
+ /** Create a durable state namespace scoped to one plugin. */
6
6
  export declare function createPluginState(plugin: string, options?: PluginStateOptions): AgentPluginState;
@@ -5,6 +5,14 @@ export interface PluginOAuthConfig {
5
5
  authorizeEndpoint: string;
6
6
  tokenEndpoint: string;
7
7
  scope?: string;
8
+ /**
9
+ * Set true when the provider returns an empty scope string even for authorized
10
+ * grants (e.g. GitHub App user-to-server tokens always return `scope: ""`
11
+ * regardless of what was requested). When enabled, an empty response scope
12
+ * uses the configured `scope` value instead of being treated as
13
+ * "no scopes granted".
14
+ */
15
+ treatEmptyScopeAsUnreported?: boolean;
8
16
  authorizeParams?: Record<string, string>;
9
17
  tokenAuthMethod?: "body" | "basic";
10
18
  tokenExtraHeaders?: Record<string, string>;
@@ -19,18 +27,7 @@ export interface OAuthBearerCredentials {
19
27
  authTokenEnv: string;
20
28
  authTokenPlaceholder?: string;
21
29
  }
22
- export interface GitHubAppCredentials {
23
- type: "github-app";
24
- domains: string[];
25
- apiHeaders?: Record<string, string>;
26
- authTokenEnv: string;
27
- authTokenPlaceholder?: string;
28
- appIdEnv: string;
29
- privateKeyEnv: string;
30
- installationIdEnv: string;
31
- systemReadPermissions?: string[];
32
- }
33
- export type PluginCredentials = OAuthBearerCredentials | GitHubAppCredentials;
30
+ export type PluginCredentials = OAuthBearerCredentials;
34
31
  export interface PluginNpmRuntimeDependency {
35
32
  type: "npm";
36
33
  package: string;
@@ -98,6 +95,15 @@ interface PluginOAuthConfigPatch extends Omit<Partial<PluginOAuthConfig>, "autho
98
95
  authorizeParams?: Record<string, string | null> | null;
99
96
  tokenExtraHeaders?: Record<string, string | null> | null;
100
97
  }
98
+ type PluginCredentialConfigBase = {
99
+ domains?: string[];
100
+ authTokenEnv?: string;
101
+ authTokenPlaceholder?: string | null;
102
+ };
103
+ type PluginCredentialConfig = PluginCredentialConfigBase & {
104
+ apiHeaders?: Record<string, string | null> | null;
105
+ type?: "oauth-bearer";
106
+ };
101
107
  /** Install-level changes applied to one plugin manifest before validation. */
102
108
  export interface PluginManifestConfig {
103
109
  description?: string;
@@ -107,17 +113,7 @@ export interface PluginManifestConfig {
107
113
  apiHeaders?: Record<string, string | null> | null;
108
114
  commandEnv?: Record<string, string | null> | null;
109
115
  envVars?: Record<string, PluginEnvVarDeclaration | null> | null;
110
- credentials?: {
111
- type?: "oauth-bearer" | "github-app";
112
- domains?: string[];
113
- apiHeaders?: Record<string, string | null> | null;
114
- authTokenEnv?: string;
115
- authTokenPlaceholder?: string | null;
116
- appIdEnv?: string;
117
- privateKeyEnv?: string;
118
- installationIdEnv?: string;
119
- systemReadPermissions?: string[];
120
- } | null;
116
+ credentials?: PluginCredentialConfig | null;
121
117
  runtimeDependencies?: PluginRuntimeDependencyConfig[] | null;
122
118
  runtimePostinstall?: PluginRuntimePostinstallCommand[] | null;
123
119
  mcp?: {
@@ -1,3 +1,4 @@
1
+ import type { Destination } from "@sentry/junior-plugin-api";
1
2
  import type { ChannelConfigurationService } from "@/chat/configuration/types";
2
3
  import type { ThreadArtifactsState } from "@/chat/state/artifacts";
3
4
  import type { ConversationPendingAuthState } from "@/chat/state/conversation";
@@ -21,6 +22,7 @@ export interface ReplyRequestContext {
21
22
  email?: string;
22
23
  };
23
24
  slackConversation?: SlackConversationContext;
25
+ destination?: Destination;
24
26
  surface?: AgentTurnSurface;
25
27
  correlation?: {
26
28
  conversationId?: string;
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import type { Message, Thread } from "chat";
10
10
  import type { SlackAdapter } from "@chat-adapter/slack";
11
+ import type { Destination } from "@sentry/junior-plugin-api";
11
12
  import { generateAssistantReply as generateAssistantReplyImpl } from "@/chat/respond";
12
13
  import type { PreparedTurnState } from "@/chat/runtime/turn-preparation";
13
14
  import { type PrepareTurnStateInput, type QueuedTurnMessage, type TurnToolInvocation } from "@/chat/runtime/turn-input";
@@ -45,8 +46,9 @@ interface ReplyExecutorDeps {
45
46
  services: ReplyExecutorServices;
46
47
  }
47
48
  /** Build the Slack reply handler that prepares state, runs Pi, and delivers replies. */
48
- export declare function createReplyToThread(deps: ReplyExecutorDeps): (thread: Thread, message: Message, options?: {
49
+ export declare function createReplyToThread(deps: ReplyExecutorDeps): (thread: Thread, message: Message, options: {
49
50
  beforeFirstResponsePost?: () => Promise<void>;
51
+ destination: Destination;
50
52
  explicitMention?: boolean;
51
53
  onInputCommitted?: () => Promise<void>;
52
54
  onToolInvocation?: (invocation: TurnToolInvocation) => void;
@@ -7,6 +7,7 @@
7
7
  * Pi/MCP internals and durable session storage behind injected services.
8
8
  */
9
9
  import type { Message, MessageContext, Thread } from "chat";
10
+ import type { Destination } from "@sentry/junior-plugin-api";
10
11
  import type { SubscribedReplyDecision, SubscribedReplyPolicy } from "@/chat/services/subscribed-reply-policy";
11
12
  import { type PrepareTurnStateInput, type QueuedTurnMessage, type TurnMessageText, type TurnToolInvocation } from "@/chat/runtime/turn-input";
12
13
  export interface AssistantLifecycleEvent {
@@ -27,6 +28,9 @@ export interface ReplyHooks {
27
28
  onTurnStatePersisted?: () => Promise<void>;
28
29
  shouldYield?: () => boolean;
29
30
  }
31
+ export interface SlackTurnOptions extends ReplyHooks {
32
+ destination: Destination;
33
+ }
30
34
  export interface SlackTurnRuntimeDependencies<TPreparedState> {
31
35
  assistantUserName: string;
32
36
  getChannelId: (thread: Thread, message: Message) => string | undefined;
@@ -68,8 +72,9 @@ export interface SlackTurnRuntimeDependencies<TPreparedState> {
68
72
  thread: Thread;
69
73
  }) => Promise<void>;
70
74
  prepareTurnState: (args: PrepareTurnStateInput) => Promise<TPreparedState>;
71
- replyToThread: (thread: Thread, message: Message, options?: {
75
+ replyToThread: (thread: Thread, message: Message, options: {
72
76
  beforeFirstResponsePost?: () => Promise<void>;
77
+ destination: Destination;
73
78
  explicitMention?: boolean;
74
79
  onInputCommitted?: () => Promise<void>;
75
80
  onToolInvocation?: (invocation: TurnToolInvocation) => void;
@@ -90,8 +95,8 @@ export interface SlackTurnRuntimeDependencies<TPreparedState> {
90
95
  export interface SlackTurnRuntime<_TPreparedState, TAssistantEvent extends AssistantLifecycleEvent = AssistantLifecycleEvent> {
91
96
  handleAssistantContextChanged: (event: TAssistantEvent) => Promise<void>;
92
97
  handleAssistantThreadStarted: (event: TAssistantEvent) => Promise<void>;
93
- handleNewMention: (thread: Thread, message: Message, hooks?: ReplyHooks) => Promise<void>;
94
- handleSubscribedMessage: (thread: Thread, message: Message, hooks?: ReplyHooks) => Promise<void>;
98
+ handleNewMention: (thread: Thread, message: Message, hooks: SlackTurnOptions) => Promise<void>;
99
+ handleSubscribedMessage: (thread: Thread, message: Message, hooks: SlackTurnOptions) => Promise<void>;
95
100
  }
96
101
  /** Build the Slack event runtime that routes mentions and subscribed messages. */
97
102
  export declare function createSlackTurnRuntime<TPreparedState, TAssistantEvent extends AssistantLifecycleEvent = AssistantLifecycleEvent>(deps: SlackTurnRuntimeDependencies<TPreparedState>): SlackTurnRuntime<TPreparedState, TAssistantEvent>;
@@ -0,0 +1,33 @@
1
+ import type { AgentPluginAuthorization, AgentPluginGrant } from "@sentry/junior-plugin-api";
2
+ import { type SandboxEgressCredentialContext, type SandboxEgressCredentialLease } from "@/chat/sandbox/egress-session";
3
+ export type SandboxEgressGrantSelection = {
4
+ grant: AgentPluginGrant;
5
+ source: "plugin";
6
+ } | {
7
+ grant: AgentPluginGrant;
8
+ source: "broker";
9
+ };
10
+ /** Signals that a plugin selected a grant but needs user authorization before issuing headers. */
11
+ export declare class SandboxEgressCredentialNeededError extends Error {
12
+ readonly authorization?: AgentPluginAuthorization;
13
+ readonly grant: AgentPluginGrant;
14
+ readonly provider: string;
15
+ constructor(input: {
16
+ authorization?: AgentPluginAuthorization;
17
+ grant: AgentPluginGrant;
18
+ message: string;
19
+ provider: string;
20
+ });
21
+ }
22
+ /** Select the plugin-defined or default grant needed for one outbound request. */
23
+ export declare function selectSandboxEgressGrant(input: {
24
+ method: string;
25
+ provider: string;
26
+ upstreamUrl: URL;
27
+ }): Promise<SandboxEgressGrantSelection>;
28
+ /** Resolve the authorization flow attached to a broker-selected egress grant. */
29
+ export declare function authorizationForSandboxEgressGrant(provider: string, selection: SandboxEgressGrantSelection): AgentPluginAuthorization | undefined;
30
+ /** Return a cached or newly issued credential lease for a selected grant. */
31
+ export declare function sandboxEgressCredentialLease(provider: string, selection: SandboxEgressGrantSelection, context: SandboxEgressCredentialContext): Promise<SandboxEgressCredentialLease>;
32
+ /** Return whether a credential lease can modify requests to the target host. */
33
+ export declare function hasSandboxEgressLeaseTransformForHost(lease: SandboxEgressCredentialLease, host: string): boolean;
@@ -0,0 +1,105 @@
1
+ import { z } from "zod";
2
+ export declare const sandboxEgressGrantSchema: z.ZodObject<{
3
+ access: z.ZodUnion<readonly [z.ZodLiteral<"read">, z.ZodLiteral<"write">]>;
4
+ name: z.ZodString;
5
+ reason: z.ZodOptional<z.ZodString>;
6
+ requirements: z.ZodOptional<z.ZodArray<z.ZodString>>;
7
+ }, z.core.$strict>;
8
+ export declare const sandboxEgressCredentialContextSchema: z.ZodObject<{
9
+ credentials: z.ZodUnion<readonly [z.ZodObject<{
10
+ actor: z.ZodObject<{
11
+ type: z.ZodLiteral<"user">;
12
+ userId: z.ZodString;
13
+ }, z.core.$strict>;
14
+ }, z.core.$strict>, z.ZodObject<{
15
+ actor: z.ZodObject<{
16
+ type: z.ZodLiteral<"system">;
17
+ id: z.ZodString;
18
+ }, z.core.$strict>;
19
+ subject: z.ZodOptional<z.ZodObject<{
20
+ type: z.ZodLiteral<"user">;
21
+ userId: z.ZodString;
22
+ allowedWhen: z.ZodLiteral<"private-direct-conversation">;
23
+ binding: z.ZodObject<{
24
+ type: z.ZodLiteral<"slack-direct-conversation">;
25
+ teamId: z.ZodString;
26
+ channelId: z.ZodString;
27
+ signature: z.ZodString;
28
+ }, z.core.$strict>;
29
+ }, z.core.$strict>>;
30
+ }, z.core.$strict>]>;
31
+ egressId: z.ZodString;
32
+ expiresAtMs: z.ZodNumber;
33
+ contextId: z.ZodString;
34
+ }, z.core.$strict>;
35
+ export declare const sandboxEgressCredentialLeaseSchema: z.ZodObject<{
36
+ account: z.ZodOptional<z.ZodObject<{
37
+ id: z.ZodString;
38
+ label: z.ZodOptional<z.ZodString>;
39
+ url: z.ZodOptional<z.ZodString>;
40
+ }, z.core.$strict>>;
41
+ authorization: z.ZodOptional<z.ZodObject<{
42
+ provider: z.ZodString;
43
+ scope: z.ZodOptional<z.ZodString>;
44
+ type: z.ZodLiteral<"oauth">;
45
+ }, z.core.$strict>>;
46
+ grant: z.ZodObject<{
47
+ access: z.ZodUnion<readonly [z.ZodLiteral<"read">, z.ZodLiteral<"write">]>;
48
+ name: z.ZodString;
49
+ reason: z.ZodOptional<z.ZodString>;
50
+ requirements: z.ZodOptional<z.ZodArray<z.ZodString>>;
51
+ }, z.core.$strict>;
52
+ provider: z.ZodString;
53
+ expiresAt: z.ZodString;
54
+ headerTransforms: z.ZodArray<z.ZodObject<{
55
+ domain: z.ZodString;
56
+ headers: z.ZodRecord<z.ZodString, z.ZodString>;
57
+ }, z.core.$strict>>;
58
+ }, z.core.$strict>;
59
+ export declare const sandboxEgressAuthRequiredSignalSchema: z.ZodObject<{
60
+ authorization: z.ZodOptional<z.ZodObject<{
61
+ provider: z.ZodString;
62
+ scope: z.ZodOptional<z.ZodString>;
63
+ type: z.ZodLiteral<"oauth">;
64
+ }, z.core.$strict>>;
65
+ grant: z.ZodObject<{
66
+ access: z.ZodUnion<readonly [z.ZodLiteral<"read">, z.ZodLiteral<"write">]>;
67
+ name: z.ZodString;
68
+ reason: z.ZodOptional<z.ZodString>;
69
+ requirements: z.ZodOptional<z.ZodArray<z.ZodString>>;
70
+ }, z.core.$strict>;
71
+ provider: z.ZodString;
72
+ message: z.ZodOptional<z.ZodString>;
73
+ createdAtMs: z.ZodNumber;
74
+ }, z.core.$strict>;
75
+ export declare const sandboxEgressPermissionDeniedSignalSchema: z.ZodObject<{
76
+ account: z.ZodOptional<z.ZodObject<{
77
+ id: z.ZodString;
78
+ label: z.ZodOptional<z.ZodString>;
79
+ url: z.ZodOptional<z.ZodString>;
80
+ }, z.core.$strict>>;
81
+ acceptedPermissions: z.ZodOptional<z.ZodString>;
82
+ grant: z.ZodObject<{
83
+ access: z.ZodUnion<readonly [z.ZodLiteral<"read">, z.ZodLiteral<"write">]>;
84
+ name: z.ZodString;
85
+ reason: z.ZodOptional<z.ZodString>;
86
+ requirements: z.ZodOptional<z.ZodArray<z.ZodString>>;
87
+ }, z.core.$strict>;
88
+ message: z.ZodString;
89
+ provider: z.ZodString;
90
+ source: z.ZodLiteral<"upstream">;
91
+ sso: z.ZodOptional<z.ZodString>;
92
+ status: z.ZodLiteral<403>;
93
+ upstreamHost: z.ZodString;
94
+ upstreamPath: z.ZodString;
95
+ createdAtMs: z.ZodNumber;
96
+ }, z.core.$strict>;
97
+ export type SandboxEgressCredentialContext = z.output<typeof sandboxEgressCredentialContextSchema>;
98
+ export type SandboxEgressGrant = z.output<typeof sandboxEgressGrantSchema>;
99
+ export type SandboxEgressCredentialLease = z.output<typeof sandboxEgressCredentialLeaseSchema>;
100
+ export type SandboxEgressAuthRequiredSignal = z.output<typeof sandboxEgressAuthRequiredSignalSchema>;
101
+ export type SandboxEgressPermissionDeniedSignal = z.output<typeof sandboxEgressPermissionDeniedSignalSchema>;
102
+ /** Parse a host-owned sandbox egress auth signal from state or tool results. */
103
+ export declare function parseSandboxEgressAuthRequiredSignal(value: unknown): SandboxEgressAuthRequiredSignal | undefined;
104
+ /** Parse a host-owned sandbox egress permission-denied signal from state or tool results. */
105
+ export declare function parseSandboxEgressPermissionDeniedSignal(value: unknown): SandboxEgressPermissionDeniedSignal | undefined;