@sentry/junior-plugin-api 0.119.0 → 0.121.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.
package/README.md CHANGED
@@ -45,6 +45,9 @@ reports, and other typed hook surfaces exported by this package.
45
45
  - Tool hooks return model-visible schemas aligned with their executor inputs.
46
46
  - Host-owned structured model and embedding calls do not expose provider
47
47
  credentials to plugins.
48
+ - Authenticated API route apps receive one verified viewer in their request
49
+ context. The registration hook exposes actor resolution for plugins whose
50
+ viewer-owned data spans platform identities.
48
51
  - User page readers receive the signed-in email plus runtime-owned actors linked
49
52
  to that user. Plugins return bounded data and do not mount their own page
50
53
  routes or browser code.
@@ -52,11 +55,12 @@ reports, and other typed hook surfaces exported by this package.
52
55
  ## User Pages
53
56
 
54
57
  Register signed-in pages through `userPages` beside `hooks`, `tasks`, and `cli`.
55
- Each definition owns its navigation metadata and `read(ctx)` function, so a
56
- page cannot be advertised without an implementation. Core owns discovery,
57
- authentication, actor resolution, routing, response validation, and rendering.
58
- The initial response type is the bounded `list` page; add another core-rendered
59
- type only when a concrete product need proves it.
58
+ Each definition owns its navigation metadata and `read(ctx, input)` function,
59
+ so a page cannot be advertised without an implementation. List readers receive
60
+ validated search and cursor input and may return an opaque continuation cursor.
61
+ Records may expose bounded `DELETE` actions inside their own authenticated
62
+ plugin API namespace. Core owns discovery, authentication, actor resolution,
63
+ routing, response validation, rendering, confirmation, and query state.
60
64
 
61
65
  ## Durable Work
62
66
 
package/dist/index.js CHANGED
@@ -541,7 +541,15 @@ var pluginUserPageMetadataSchema = z9.object({
541
541
  label: nonBlankStringSchema.max(80),
542
542
  value: nonBlankStringSchema.max(500)
543
543
  }).strict();
544
+ var pluginUserPageActionSchema = z9.object({
545
+ confirmation: nonBlankStringSchema.max(500).optional(),
546
+ href: nonBlankStringSchema.max(500).regex(/^\/api\/plugins\/[a-z][a-z0-9-]*(?:\/|$)/),
547
+ label: nonBlankStringSchema.max(80),
548
+ method: z9.literal("DELETE"),
549
+ tone: z9.enum(["danger", "neutral"]).optional()
550
+ }).strict();
544
551
  var pluginUserPageRecordSchema = z9.object({
552
+ actions: z9.array(pluginUserPageActionSchema).max(4).optional(),
545
553
  description: nonBlankStringSchema.max(1e3).optional(),
546
554
  id: nonBlankStringSchema.max(128),
547
555
  metadata: z9.array(pluginUserPageMetadataSchema).max(8).optional(),
@@ -549,7 +557,9 @@ var pluginUserPageRecordSchema = z9.object({
549
557
  }).strict();
550
558
  var pluginUserPageContentSchema = z9.object({
551
559
  emptyText: nonBlankStringSchema.max(500).optional(),
560
+ nextCursor: nonBlankStringSchema.max(1e3).optional(),
552
561
  records: z9.array(pluginUserPageRecordSchema).max(100),
562
+ searchPlaceholder: nonBlankStringSchema.max(120).optional(),
553
563
  type: z9.literal("list")
554
564
  }).strict();
555
565
  var pluginUserPageLinkSchema = z9.object({
@@ -560,6 +570,11 @@ var pluginUserPageLinkSchema = z9.object({
560
570
  pluginName: nonBlankStringSchema.max(100)
561
571
  }).strict();
562
572
  var pluginUserPageLinksSchema = z9.array(pluginUserPageLinkSchema);
573
+ var pluginUserPageInputSchema = z9.object({
574
+ cursor: nonBlankStringSchema.max(1e3).optional(),
575
+ limit: z9.number().int().min(1).max(50),
576
+ query: z9.string().trim().max(200).optional()
577
+ }).strict();
563
578
  export {
564
579
  EgressAuthRequired,
565
580
  EgressPolicyDenied,
@@ -598,6 +613,7 @@ export {
598
613
  pluginToolErrorSchema,
599
614
  pluginToolResultSchema,
600
615
  pluginUserPageContentSchema,
616
+ pluginUserPageInputSchema,
601
617
  pluginUserPageLinkSchema,
602
618
  pluginUserPageLinksSchema,
603
619
  promptContextSchema,
@@ -42,10 +42,13 @@ export interface PluginRuntimePostinstallCommand {
42
42
  sudo?: boolean;
43
43
  }
44
44
  export interface PluginMcpConfig {
45
+ /** Provider tools exposed directly to the model. */
45
46
  allowedTools?: string[];
46
47
  headers?: Record<string, string>;
47
48
  transport: "http";
48
49
  url: string;
50
+ /** Provider tools hidden from the model and callable only by plugin-owned wrapper tools. */
51
+ wrappedTools?: string[];
49
52
  }
50
53
  export interface PluginEnvVarDeclaration {
51
54
  default?: string;
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import type { PluginContext } from "./context";
2
+ import type { LocalActor, PluginContext, SlackActor } from "./context";
3
3
  import type { Dispatch, DispatchOptions, DispatchResult } from "./dispatch";
4
4
  import type { PluginReadState, PluginState } from "./state";
5
5
  import type { ResourceEventPublisher } from "./resource-events";
@@ -89,6 +89,10 @@ export interface RouteRegistrationHookContext extends PluginContext {
89
89
  resourceEvents: ResourceEventPublisher;
90
90
  }
91
91
  export interface ApiRouteRegistrationHookContext extends PluginContext {
92
+ viewer: {
93
+ /** Resolve every runtime actor linked to one authenticated viewer email. */
94
+ actors(email: string): Promise<Array<LocalActor | SlackActor>>;
95
+ };
92
96
  }
93
97
  /** Per-request context Junior passes to authenticated plugin product API routes. */
94
98
  export declare const pluginApiRouteRequestContextSchema: z.ZodObject<{
package/dist/prompt.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import type { Destination, Platform, PluginContext, PluginEmbedder, Actor, Source } from "./context";
2
+ import type { Destination, Platform, PluginContext, PluginEmbedder, PluginModel, Actor, Source } from "./context";
3
3
  import type { PluginState } from "./state";
4
4
  export declare const promptMessageSchema: z.ZodObject<{
5
5
  text: z.ZodString;
@@ -36,6 +36,7 @@ export type UserPromptContext = Pick<PluginContext, "db" | "log" | "plugin"> & {
36
36
  conversationId?: string;
37
37
  destination: Destination;
38
38
  embedder: PluginEmbedder;
39
+ model: PluginModel;
39
40
  actor?: Actor;
40
41
  source: Source;
41
42
  state: PluginState;
package/dist/tools.d.ts CHANGED
@@ -53,6 +53,53 @@ export interface PluginEgress {
53
53
  request: Request;
54
54
  }): Promise<Response>;
55
55
  }
56
+ export type PluginMcpContent = {
57
+ type: "text";
58
+ text: string;
59
+ } | {
60
+ type: "image";
61
+ data: string;
62
+ mimeType: string;
63
+ };
64
+ /** Successful raw provider result returned to a plugin-owned wrapper tool. */
65
+ export type PluginMcpToolSuccess = {
66
+ content: PluginMcpContent[];
67
+ status: "success";
68
+ structuredContent?: unknown;
69
+ };
70
+ /** Handled provider authorization pause with no provider result to consume. */
71
+ export type PluginMcpAuthorizationPending = {
72
+ status: "authorization_pending";
73
+ };
74
+ /** Definitive provider rejection; transport and session failures still throw. */
75
+ export type PluginMcpToolError = {
76
+ message: string;
77
+ status: "error";
78
+ };
79
+ export type PluginMcpToolResult = PluginMcpAuthorizationPending | PluginMcpToolError | PluginMcpToolSuccess;
80
+ /** Access to this plugin's hosted MCP provider without exposing credentials. */
81
+ export interface PluginMcp {
82
+ /**
83
+ * Call a provider tool declared in `wrappedTools`.
84
+ *
85
+ * The host activates the provider when needed. Successful calls return the
86
+ * provider's original content, provider rejections return an error result,
87
+ * and authorization pauses return no tool content. Transport failures throw.
88
+ */
89
+ callTool(input: {
90
+ arguments?: Record<string, unknown>;
91
+ name: string;
92
+ toolCallId?: string;
93
+ }): Promise<PluginMcpToolResult>;
94
+ /**
95
+ * Activate the provider before wrapper-owned state changes.
96
+ *
97
+ * Ordinary wrappers can call `callTool` directly. Durable mutation wrappers
98
+ * may prepare first so an initial authorization pause happens before they
99
+ * record pending work.
100
+ */
101
+ prepare(): Promise<"authorization_pending" | "ready">;
102
+ }
56
103
  export interface SandboxPrepareHookContext extends PluginContext {
57
104
  actor?: Actor;
58
105
  sandbox: PluginSandbox;
@@ -221,6 +268,7 @@ interface BaseToolRegistrationHookContext extends PluginContext {
221
268
  annotations?: PluginAnnotations;
222
269
  embedder: PluginEmbedder;
223
270
  egress: PluginEgress;
271
+ mcp?: PluginMcp;
224
272
  model: PluginModel;
225
273
  state: PluginState;
226
274
  userText?: string;
@@ -9,7 +9,18 @@ import type { LocalActor, PluginContext, SlackActor } from "./context";
9
9
  /** Bounded list content returned by a plugin-owned user page. */
10
10
  export declare const pluginUserPageContentSchema: z.ZodObject<{
11
11
  emptyText: z.ZodOptional<z.ZodString>;
12
+ nextCursor: z.ZodOptional<z.ZodString>;
12
13
  records: z.ZodArray<z.ZodObject<{
14
+ actions: z.ZodOptional<z.ZodArray<z.ZodObject<{
15
+ confirmation: z.ZodOptional<z.ZodString>;
16
+ href: z.ZodString;
17
+ label: z.ZodString;
18
+ method: z.ZodLiteral<"DELETE">;
19
+ tone: z.ZodOptional<z.ZodEnum<{
20
+ danger: "danger";
21
+ neutral: "neutral";
22
+ }>>;
23
+ }, z.core.$strict>>>;
13
24
  description: z.ZodOptional<z.ZodString>;
14
25
  id: z.ZodString;
15
26
  metadata: z.ZodOptional<z.ZodArray<z.ZodObject<{
@@ -18,6 +29,7 @@ export declare const pluginUserPageContentSchema: z.ZodObject<{
18
29
  }, z.core.$strict>>>;
19
30
  title: z.ZodString;
20
31
  }, z.core.$strict>>;
32
+ searchPlaceholder: z.ZodOptional<z.ZodString>;
21
33
  type: z.ZodLiteral<"list">;
22
34
  }, z.core.$strict>;
23
35
  /** Validated content for the current core-rendered list page type. */
@@ -38,6 +50,13 @@ export declare const pluginUserPageLinksSchema: z.ZodArray<z.ZodObject<{
38
50
  }, z.core.$strict>>;
39
51
  /** Safe navigation metadata for one registered plugin user page. */
40
52
  export type PluginUserPageLink = z.output<typeof pluginUserPageLinkSchema>;
53
+ /** Validated query state passed to one plugin user page reader. */
54
+ export declare const pluginUserPageInputSchema: z.ZodObject<{
55
+ cursor: z.ZodOptional<z.ZodString>;
56
+ limit: z.ZodNumber;
57
+ query: z.ZodOptional<z.ZodString>;
58
+ }, z.core.$strict>;
59
+ export type PluginUserPageInput = z.output<typeof pluginUserPageInputSchema>;
41
60
  /** Runtime-owned actor shapes that may belong to an authenticated viewer. */
42
61
  export type PluginUserPageActor = SlackActor | LocalActor;
43
62
  /** Trusted host context supplied while reading one plugin user page. */
@@ -52,5 +71,5 @@ export interface PluginUserPageDefinition {
52
71
  description: string;
53
72
  id: string;
54
73
  label: string;
55
- read(ctx: PluginUserPageContext): Promise<PluginUserPageContent> | PluginUserPageContent;
74
+ read(ctx: PluginUserPageContext, input: PluginUserPageInput): Promise<PluginUserPageContent> | PluginUserPageContent;
56
75
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior-plugin-api",
3
- "version": "0.119.0",
3
+ "version": "0.121.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
package/src/manifest.ts CHANGED
@@ -53,10 +53,13 @@ export interface PluginRuntimePostinstallCommand {
53
53
  }
54
54
 
55
55
  export interface PluginMcpConfig {
56
+ /** Provider tools exposed directly to the model. */
56
57
  allowedTools?: string[];
57
58
  headers?: Record<string, string>;
58
59
  transport: "http";
59
60
  url: string;
61
+ /** Provider tools hidden from the model and callable only by plugin-owned wrapper tools. */
62
+ wrappedTools?: string[];
60
63
  }
61
64
 
62
65
  export interface PluginEnvVarDeclaration {
package/src/operations.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import type { PluginContext } from "./context";
2
+ import type { LocalActor, PluginContext, SlackActor } from "./context";
3
3
  import type { Dispatch, DispatchOptions, DispatchResult } from "./dispatch";
4
4
  import { nonBlankStringSchema } from "./schemas";
5
5
  import type { PluginReadState, PluginState } from "./state";
@@ -119,7 +119,12 @@ export interface RouteRegistrationHookContext extends PluginContext {
119
119
  resourceEvents: ResourceEventPublisher;
120
120
  }
121
121
 
122
- export interface ApiRouteRegistrationHookContext extends PluginContext {}
122
+ export interface ApiRouteRegistrationHookContext extends PluginContext {
123
+ viewer: {
124
+ /** Resolve every runtime actor linked to one authenticated viewer email. */
125
+ actors(email: string): Promise<Array<LocalActor | SlackActor>>;
126
+ };
127
+ }
123
128
 
124
129
  /** Per-request context Junior passes to authenticated plugin product API routes. */
125
130
  export const pluginApiRouteRequestContextSchema = z
package/src/prompt.ts CHANGED
@@ -4,6 +4,7 @@ import type {
4
4
  Platform,
5
5
  PluginContext,
6
6
  PluginEmbedder,
7
+ PluginModel,
7
8
  Actor,
8
9
  Source,
9
10
  } from "./context";
@@ -79,6 +80,7 @@ export type UserPromptContext = Pick<PluginContext, "db" | "log" | "plugin"> & {
79
80
  conversationId?: string;
80
81
  destination: Destination;
81
82
  embedder: PluginEmbedder;
83
+ model: PluginModel;
82
84
  actor?: Actor;
83
85
  source: Source;
84
86
  state: PluginState;
package/src/tools.ts CHANGED
@@ -67,6 +67,57 @@ export interface PluginEgress {
67
67
  }): Promise<Response>;
68
68
  }
69
69
 
70
+ export type PluginMcpContent =
71
+ | { type: "text"; text: string }
72
+ | { type: "image"; data: string; mimeType: string };
73
+
74
+ /** Successful raw provider result returned to a plugin-owned wrapper tool. */
75
+ export type PluginMcpToolSuccess = {
76
+ content: PluginMcpContent[];
77
+ status: "success";
78
+ structuredContent?: unknown;
79
+ };
80
+
81
+ /** Handled provider authorization pause with no provider result to consume. */
82
+ export type PluginMcpAuthorizationPending = {
83
+ status: "authorization_pending";
84
+ };
85
+
86
+ /** Definitive provider rejection; transport and session failures still throw. */
87
+ export type PluginMcpToolError = {
88
+ message: string;
89
+ status: "error";
90
+ };
91
+
92
+ export type PluginMcpToolResult =
93
+ | PluginMcpAuthorizationPending
94
+ | PluginMcpToolError
95
+ | PluginMcpToolSuccess;
96
+
97
+ /** Access to this plugin's hosted MCP provider without exposing credentials. */
98
+ export interface PluginMcp {
99
+ /**
100
+ * Call a provider tool declared in `wrappedTools`.
101
+ *
102
+ * The host activates the provider when needed. Successful calls return the
103
+ * provider's original content, provider rejections return an error result,
104
+ * and authorization pauses return no tool content. Transport failures throw.
105
+ */
106
+ callTool(input: {
107
+ arguments?: Record<string, unknown>;
108
+ name: string;
109
+ toolCallId?: string;
110
+ }): Promise<PluginMcpToolResult>;
111
+ /**
112
+ * Activate the provider before wrapper-owned state changes.
113
+ *
114
+ * Ordinary wrappers can call `callTool` directly. Durable mutation wrappers
115
+ * may prepare first so an initial authorization pause happens before they
116
+ * record pending work.
117
+ */
118
+ prepare(): Promise<"authorization_pending" | "ready">;
119
+ }
120
+
70
121
  export interface SandboxPrepareHookContext extends PluginContext {
71
122
  actor?: Actor;
72
123
  sandbox: PluginSandbox;
@@ -350,6 +401,7 @@ interface BaseToolRegistrationHookContext extends PluginContext {
350
401
  annotations?: PluginAnnotations;
351
402
  embedder: PluginEmbedder;
352
403
  egress: PluginEgress;
404
+ mcp?: PluginMcp;
353
405
  model: PluginModel;
354
406
  state: PluginState;
355
407
  userText?: string;
package/src/user-pages.ts CHANGED
@@ -21,8 +21,21 @@ const pluginUserPageMetadataSchema = z
21
21
  })
22
22
  .strict();
23
23
 
24
+ const pluginUserPageActionSchema = z
25
+ .object({
26
+ confirmation: nonBlankStringSchema.max(500).optional(),
27
+ href: nonBlankStringSchema
28
+ .max(500)
29
+ .regex(/^\/api\/plugins\/[a-z][a-z0-9-]*(?:\/|$)/),
30
+ label: nonBlankStringSchema.max(80),
31
+ method: z.literal("DELETE"),
32
+ tone: z.enum(["danger", "neutral"]).optional(),
33
+ })
34
+ .strict();
35
+
24
36
  const pluginUserPageRecordSchema = z
25
37
  .object({
38
+ actions: z.array(pluginUserPageActionSchema).max(4).optional(),
26
39
  description: nonBlankStringSchema.max(1_000).optional(),
27
40
  id: nonBlankStringSchema.max(128),
28
41
  metadata: z.array(pluginUserPageMetadataSchema).max(8).optional(),
@@ -34,7 +47,9 @@ const pluginUserPageRecordSchema = z
34
47
  export const pluginUserPageContentSchema = z
35
48
  .object({
36
49
  emptyText: nonBlankStringSchema.max(500).optional(),
50
+ nextCursor: nonBlankStringSchema.max(1_000).optional(),
37
51
  records: z.array(pluginUserPageRecordSchema).max(100),
52
+ searchPlaceholder: nonBlankStringSchema.max(120).optional(),
38
53
  type: z.literal("list"),
39
54
  })
40
55
  .strict();
@@ -59,6 +74,17 @@ export const pluginUserPageLinksSchema = z.array(pluginUserPageLinkSchema);
59
74
  /** Safe navigation metadata for one registered plugin user page. */
60
75
  export type PluginUserPageLink = z.output<typeof pluginUserPageLinkSchema>;
61
76
 
77
+ /** Validated query state passed to one plugin user page reader. */
78
+ export const pluginUserPageInputSchema = z
79
+ .object({
80
+ cursor: nonBlankStringSchema.max(1_000).optional(),
81
+ limit: z.number().int().min(1).max(50),
82
+ query: z.string().trim().max(200).optional(),
83
+ })
84
+ .strict();
85
+
86
+ export type PluginUserPageInput = z.output<typeof pluginUserPageInputSchema>;
87
+
62
88
  /** Runtime-owned actor shapes that may belong to an authenticated viewer. */
63
89
  export type PluginUserPageActor = SlackActor | LocalActor;
64
90
 
@@ -77,5 +103,6 @@ export interface PluginUserPageDefinition {
77
103
  label: string;
78
104
  read(
79
105
  ctx: PluginUserPageContext,
106
+ input: PluginUserPageInput,
80
107
  ): Promise<PluginUserPageContent> | PluginUserPageContent;
81
108
  }