@sentry/junior-plugin-api 0.121.0 → 0.122.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.
package/dist/hooks.d.ts CHANGED
@@ -1,11 +1,18 @@
1
1
  import type { EgressHookContext, EgressResponseHookContext, IssueCredentialHookContext, PluginCredentialResult, PluginGrant, PluginProviderAccount, ResolveOAuthAccountHookContext } from "./credentials";
2
2
  import type { HeartbeatHookContext, HeartbeatResult, OperationalReportHookContext, ApiRouteRegistrationHookContext, PluginOperationalReportContent, PluginRoute, PluginRouteApp, RouteRegistrationHookContext, SlackConversationLink, SlackConversationLinkHookContext } from "./operations";
3
- import type { BeforeToolExecuteHookContext, PluginToolDefinition, SandboxPrepareHookContext, ToolRegistrationHookContext } from "./tools";
3
+ import type { AfterMcpToolHookContext, BeforeToolExecuteHookContext, PluginToolDefinition, SandboxPrepareHookContext, ToolRegistrationHookContext } from "./tools";
4
4
  import type { PromptMessage, SystemPromptContext, UserPromptContext, UserPromptContribution } from "./prompt";
5
5
  export interface PluginHooks {
6
6
  systemPrompt?(ctx: SystemPromptContext): Promise<PromptMessage[]> | PromptMessage[];
7
7
  userPrompt?(ctx: UserPromptContext): Promise<UserPromptContribution[] | undefined> | UserPromptContribution[] | undefined;
8
8
  beforeToolExecute?(ctx: BeforeToolExecuteHookContext): Promise<void> | void;
9
+ /**
10
+ * Run after a successful hosted MCP tool call.
11
+ *
12
+ * Prefer this for junior-owned side effects such as conversation annotations.
13
+ * Do not use it to invent a parallel tool contract for the provider tool.
14
+ */
15
+ afterMcpTool?(ctx: AfterMcpToolHookContext): Promise<void> | void;
9
16
  grantForEgress?(ctx: EgressHookContext): Promise<PluginGrant | undefined> | PluginGrant | undefined;
10
17
  heartbeat?(ctx: HeartbeatHookContext): Promise<HeartbeatResult | void> | HeartbeatResult | void;
11
18
  issueCredential?(ctx: IssueCredentialHookContext): Promise<PluginCredentialResult> | PluginCredentialResult;
package/dist/index.js CHANGED
@@ -291,6 +291,14 @@ var PluginToolInputError = class extends Error {
291
291
  this.name = "PluginToolInputError";
292
292
  }
293
293
  };
294
+ var pluginToolContentSchema = z6.discriminatedUnion("type", [
295
+ z6.object({ type: z6.literal("text"), text: z6.string() }).strict(),
296
+ z6.object({
297
+ type: z6.literal("image"),
298
+ data: z6.string(),
299
+ mimeType: z6.string()
300
+ }).strict()
301
+ ]);
294
302
  var pluginToolContinuationSchema = z6.object({
295
303
  arguments: z6.record(z6.string(), z6.unknown()),
296
304
  reason: z6.string().min(1).optional()
@@ -310,6 +318,9 @@ var pluginToolResultSchema = z6.object({
310
318
  error: z6.union([pluginToolErrorSchema, z6.string()]).optional()
311
319
  }).passthrough();
312
320
  var toolApprovalModeSchema = z6.enum(["auto", "review", "approve"]);
321
+ function isPluginToolResultEnvelope(value) {
322
+ return value !== null && typeof value === "object" && Array.isArray(value.content) && "details" in value;
323
+ }
313
324
  function formatZodPath(path) {
314
325
  return path.length > 0 ? path.map(String).join(".") : "root";
315
326
  }
@@ -362,6 +373,14 @@ function createZodTool(definition, helperName) {
362
373
  input,
363
374
  options
364
375
  );
376
+ if (isPluginToolResultEnvelope(result)) {
377
+ return {
378
+ content: z6.array(pluginToolContentSchema).parse(result.content),
379
+ details: outputSchema.parse(
380
+ pluginToolResultSchema.parse(result.details)
381
+ )
382
+ };
383
+ }
365
384
  return outputSchema.parse(pluginToolResultSchema.parse(result));
366
385
  }
367
386
  } : {}
@@ -609,6 +628,7 @@ export {
609
628
  pluginRunTranscriptEntrySchema,
610
629
  pluginRunTranscriptProvenanceSchema,
611
630
  pluginStoredTokensSchema,
631
+ pluginToolContentSchema,
612
632
  pluginToolContinuationSchema,
613
633
  pluginToolErrorSchema,
614
634
  pluginToolResultSchema,
package/dist/tools.d.ts CHANGED
@@ -53,14 +53,22 @@ 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
- };
56
+ export declare const pluginToolContentSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
57
+ type: z.ZodLiteral<"text">;
58
+ text: z.ZodString;
59
+ }, z.core.$strict>, z.ZodObject<{
60
+ type: z.ZodLiteral<"image">;
61
+ data: z.ZodString;
62
+ mimeType: z.ZodString;
63
+ }, z.core.$strict>], "type">;
64
+ /** Model-visible content returned by a plugin tool. */
65
+ export type PluginToolContent = z.output<typeof pluginToolContentSchema>;
66
+ /** Standard tool result envelope with separate model content and runtime details. */
67
+ export interface PluginToolResultEnvelope<TDetails = PluginToolResult> {
68
+ content: PluginToolContent[];
69
+ details: TDetails;
70
+ }
71
+ export type PluginMcpContent = PluginToolContent;
64
72
  /** Successful raw provider result returned to a plugin-owned wrapper tool. */
65
73
  export type PluginMcpToolSuccess = {
66
74
  content: PluginMcpContent[];
@@ -115,6 +123,29 @@ export interface BeforeToolExecuteHookContext extends PluginContext {
115
123
  name: string;
116
124
  };
117
125
  }
126
+ /**
127
+ * Context for post-success MCP tool processing.
128
+ *
129
+ * Runs after a hosted MCP tool succeeds on the model-facing path. Use for
130
+ * junior-owned side effects such as conversation annotations without replacing
131
+ * the provider tool contract.
132
+ */
133
+ export interface AfterMcpToolHookContext extends PluginContext {
134
+ /**
135
+ * Opaque Junior conversation/session identity for this turn.
136
+ * Interactive Slack turns use `slack:{channelId}:{threadTs}`.
137
+ */
138
+ conversationId?: string;
139
+ annotations?: PluginAnnotations;
140
+ result: {
141
+ structuredContent?: unknown;
142
+ };
143
+ tool: {
144
+ arguments: Record<string, unknown>;
145
+ /** Provider-local MCP tool name, for example `save_issue`. */
146
+ name: string;
147
+ };
148
+ }
118
149
  export interface PluginToolExecuteOptions {
119
150
  /**
120
151
  * @deprecated Internal compatibility escape hatch for legacy tool bridges.
@@ -206,7 +237,7 @@ export interface ToolApprovalMetadata<TInput = unknown> {
206
237
  */
207
238
  describeProposal?(input: TInput): string;
208
239
  }
209
- export interface PluginToolDefinition<TInput = unknown, TOutput = unknown> extends ToolApprovalMetadata<TInput> {
240
+ export interface PluginToolDefinition<TInput = unknown, TOutput = unknown, TExecuteOutput = TOutput> extends ToolApprovalMetadata<TInput> {
210
241
  description: string;
211
242
  executionMode?: unknown;
212
243
  inputSchema: unknown;
@@ -229,18 +260,19 @@ export interface PluginToolDefinition<TInput = unknown, TOutput = unknown> exten
229
260
  * future major version.
230
261
  */
231
262
  promptSnippet?: string;
232
- execute?: PluginToolExecute<TInput, TOutput>;
263
+ execute?: PluginToolExecute<TInput, TExecuteOutput>;
233
264
  }
234
- type ZodPluginToolDefinition<TInputSchema extends ZodTypeAny, TOutputSchema extends ZodType<PluginToolResult>> = Omit<PluginToolDefinition<z.output<TInputSchema>, z.output<TOutputSchema>>, "inputSchema" | "outputSchema" | "prepareArguments" | "execute"> & {
265
+ type ZodPluginToolDefinition<TInputSchema extends ZodTypeAny, TOutputSchema extends ZodType<PluginToolResult>, TExecuteResult extends z.input<TOutputSchema> | PluginToolResultEnvelope<z.input<TOutputSchema>>> = Omit<PluginToolDefinition<z.output<TInputSchema>, z.output<TOutputSchema>>, "inputSchema" | "outputSchema" | "prepareArguments" | "execute"> & {
235
266
  inputSchema: TInputSchema;
236
267
  outputSchema: TOutputSchema;
237
268
  prepareArguments?: (args: unknown) => z.input<TInputSchema>;
238
- execute?: (input: z.output<TInputSchema>, options: PluginToolExecuteOptions) => Promise<z.input<TOutputSchema>> | z.input<TOutputSchema>;
269
+ execute?: (input: z.output<TInputSchema>, options: PluginToolExecuteOptions) => Promise<TExecuteResult> | TExecuteResult;
239
270
  };
271
+ type ParsedPluginToolExecuteResult<TOutputSchema extends ZodTypeAny, TResult> = TResult extends PluginToolResultEnvelope<unknown> ? PluginToolResultEnvelope<z.output<TOutputSchema>> : z.output<TOutputSchema>;
240
272
  /** Define a plugin tool with Zod input parsing and validated structured results. */
241
- export declare function zodTool<TInputSchema extends ZodTypeAny, TOutputSchema extends ZodType<PluginToolResult>>(definition: ZodPluginToolDefinition<TInputSchema, TOutputSchema>): PluginToolDefinition<z.output<TInputSchema>, z.output<TOutputSchema>>;
273
+ export declare function zodTool<TInputSchema extends ZodTypeAny, TOutputSchema extends ZodType<PluginToolResult>, TExecuteResult extends z.input<TOutputSchema> | PluginToolResultEnvelope<z.input<TOutputSchema>>>(definition: ZodPluginToolDefinition<TInputSchema, TOutputSchema, TExecuteResult>): PluginToolDefinition<z.output<TInputSchema>, z.output<TOutputSchema>, ParsedPluginToolExecuteResult<TOutputSchema, TExecuteResult>>;
242
274
  /** Define a plugin tool with Zod input parsing and the structured result contract. */
243
- export declare function definePluginTool<TInputSchema extends ZodTypeAny, TOutputSchema extends ZodType<PluginToolResult>>(definition: ZodPluginToolDefinition<TInputSchema, TOutputSchema>): PluginToolDefinition<z.output<TInputSchema>, z.output<TOutputSchema>>;
275
+ export declare function definePluginTool<TInputSchema extends ZodTypeAny, TOutputSchema extends ZodType<PluginToolResult>, TExecuteResult extends z.input<TOutputSchema> | PluginToolResultEnvelope<z.input<TOutputSchema>>>(definition: ZodPluginToolDefinition<TInputSchema, TOutputSchema, TExecuteResult>): PluginToolDefinition<z.output<TInputSchema>, z.output<TOutputSchema>, ParsedPluginToolExecuteResult<TOutputSchema, TExecuteResult>>;
244
276
  export interface SlackToolRegistrationHookContext {
245
277
  /**
246
278
  * Capabilities of the source Slack conversation exposed to this plugin.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior-plugin-api",
3
- "version": "0.121.0",
3
+ "version": "0.122.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
package/src/hooks.ts CHANGED
@@ -20,6 +20,7 @@ import type {
20
20
  SlackConversationLinkHookContext,
21
21
  } from "./operations";
22
22
  import type {
23
+ AfterMcpToolHookContext,
23
24
  BeforeToolExecuteHookContext,
24
25
  PluginToolDefinition,
25
26
  SandboxPrepareHookContext,
@@ -43,6 +44,13 @@ export interface PluginHooks {
43
44
  | UserPromptContribution[]
44
45
  | undefined;
45
46
  beforeToolExecute?(ctx: BeforeToolExecuteHookContext): Promise<void> | void;
47
+ /**
48
+ * Run after a successful hosted MCP tool call.
49
+ *
50
+ * Prefer this for junior-owned side effects such as conversation annotations.
51
+ * Do not use it to invent a parallel tool contract for the provider tool.
52
+ */
53
+ afterMcpTool?(ctx: AfterMcpToolHookContext): Promise<void> | void;
46
54
  grantForEgress?(
47
55
  ctx: EgressHookContext,
48
56
  ): Promise<PluginGrant | undefined> | PluginGrant | undefined;
package/src/tools.ts CHANGED
@@ -67,9 +67,27 @@ 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 };
70
+ export const pluginToolContentSchema = z.discriminatedUnion("type", [
71
+ z.object({ type: z.literal("text"), text: z.string() }).strict(),
72
+ z
73
+ .object({
74
+ type: z.literal("image"),
75
+ data: z.string(),
76
+ mimeType: z.string(),
77
+ })
78
+ .strict(),
79
+ ]);
80
+
81
+ /** Model-visible content returned by a plugin tool. */
82
+ export type PluginToolContent = z.output<typeof pluginToolContentSchema>;
83
+
84
+ /** Standard tool result envelope with separate model content and runtime details. */
85
+ export interface PluginToolResultEnvelope<TDetails = PluginToolResult> {
86
+ content: PluginToolContent[];
87
+ details: TDetails;
88
+ }
89
+
90
+ export type PluginMcpContent = PluginToolContent;
73
91
 
74
92
  /** Successful raw provider result returned to a plugin-owned wrapper tool. */
75
93
  export type PluginMcpToolSuccess = {
@@ -135,6 +153,30 @@ export interface BeforeToolExecuteHookContext extends PluginContext {
135
153
  };
136
154
  }
137
155
 
156
+ /**
157
+ * Context for post-success MCP tool processing.
158
+ *
159
+ * Runs after a hosted MCP tool succeeds on the model-facing path. Use for
160
+ * junior-owned side effects such as conversation annotations without replacing
161
+ * the provider tool contract.
162
+ */
163
+ export interface AfterMcpToolHookContext extends PluginContext {
164
+ /**
165
+ * Opaque Junior conversation/session identity for this turn.
166
+ * Interactive Slack turns use `slack:{channelId}:{threadTs}`.
167
+ */
168
+ conversationId?: string;
169
+ annotations?: PluginAnnotations;
170
+ result: {
171
+ structuredContent?: unknown;
172
+ };
173
+ tool: {
174
+ arguments: Record<string, unknown>;
175
+ /** Provider-local MCP tool name, for example `save_issue`. */
176
+ name: string;
177
+ };
178
+ }
179
+
138
180
  export interface PluginToolExecuteOptions {
139
181
  /**
140
182
  * @deprecated Internal compatibility escape hatch for legacy tool bridges.
@@ -234,6 +276,7 @@ export interface ToolApprovalMetadata<TInput = unknown> {
234
276
  export interface PluginToolDefinition<
235
277
  TInput = unknown,
236
278
  TOutput = unknown,
279
+ TExecuteOutput = TOutput,
237
280
  > extends ToolApprovalMetadata<TInput> {
238
281
  description: string;
239
282
  executionMode?: unknown;
@@ -257,12 +300,15 @@ export interface PluginToolDefinition<
257
300
  * future major version.
258
301
  */
259
302
  promptSnippet?: string;
260
- execute?: PluginToolExecute<TInput, TOutput>;
303
+ execute?: PluginToolExecute<TInput, TExecuteOutput>;
261
304
  }
262
305
 
263
306
  type ZodPluginToolDefinition<
264
307
  TInputSchema extends ZodTypeAny,
265
308
  TOutputSchema extends ZodType<PluginToolResult>,
309
+ TExecuteResult extends
310
+ | z.input<TOutputSchema>
311
+ | PluginToolResultEnvelope<z.input<TOutputSchema>>,
266
312
  > = Omit<
267
313
  PluginToolDefinition<z.output<TInputSchema>, z.output<TOutputSchema>>,
268
314
  "inputSchema" | "outputSchema" | "prepareArguments" | "execute"
@@ -273,9 +319,25 @@ type ZodPluginToolDefinition<
273
319
  execute?: (
274
320
  input: z.output<TInputSchema>,
275
321
  options: PluginToolExecuteOptions,
276
- ) => Promise<z.input<TOutputSchema>> | z.input<TOutputSchema>;
322
+ ) => Promise<TExecuteResult> | TExecuteResult;
277
323
  };
278
324
 
325
+ type ParsedPluginToolExecuteResult<TOutputSchema extends ZodTypeAny, TResult> =
326
+ TResult extends PluginToolResultEnvelope<unknown>
327
+ ? PluginToolResultEnvelope<z.output<TOutputSchema>>
328
+ : z.output<TOutputSchema>;
329
+
330
+ function isPluginToolResultEnvelope(
331
+ value: unknown,
332
+ ): value is PluginToolResultEnvelope<unknown> {
333
+ return (
334
+ value !== null &&
335
+ typeof value === "object" &&
336
+ Array.isArray((value as { content?: unknown }).content) &&
337
+ "details" in value
338
+ );
339
+ }
340
+
279
341
  function formatZodPath(path: readonly PropertyKey[]): string {
280
342
  return path.length > 0 ? path.map(String).join(".") : "root";
281
343
  }
@@ -304,10 +366,21 @@ function parsePluginToolInput<TInputSchema extends ZodTypeAny>(
304
366
  function createZodTool<
305
367
  TInputSchema extends ZodTypeAny,
306
368
  TOutputSchema extends ZodType<PluginToolResult>,
369
+ TExecuteResult extends
370
+ | z.input<TOutputSchema>
371
+ | PluginToolResultEnvelope<z.input<TOutputSchema>>,
307
372
  >(
308
- definition: ZodPluginToolDefinition<TInputSchema, TOutputSchema>,
373
+ definition: ZodPluginToolDefinition<
374
+ TInputSchema,
375
+ TOutputSchema,
376
+ TExecuteResult
377
+ >,
309
378
  helperName: "definePluginTool" | "zodTool",
310
- ): PluginToolDefinition<z.output<TInputSchema>, z.output<TOutputSchema>> {
379
+ ): PluginToolDefinition<
380
+ z.output<TInputSchema>,
381
+ z.output<TOutputSchema>,
382
+ ParsedPluginToolExecuteResult<TOutputSchema, TExecuteResult>
383
+ > {
311
384
  const { inputSchema, outputSchema, prepareArguments, execute, ...tool } =
312
385
  definition;
313
386
  let modelInputSchema: unknown;
@@ -345,20 +418,43 @@ function createZodTool<
345
418
  input as z.output<TInputSchema>,
346
419
  options,
347
420
  );
421
+ if (isPluginToolResultEnvelope(result)) {
422
+ return {
423
+ content: z.array(pluginToolContentSchema).parse(result.content),
424
+ details: outputSchema.parse(
425
+ pluginToolResultSchema.parse(result.details),
426
+ ),
427
+ };
428
+ }
348
429
  return outputSchema.parse(pluginToolResultSchema.parse(result));
349
430
  },
350
431
  }
351
432
  : {}),
352
- };
433
+ } as PluginToolDefinition<
434
+ z.output<TInputSchema>,
435
+ z.output<TOutputSchema>,
436
+ ParsedPluginToolExecuteResult<TOutputSchema, TExecuteResult>
437
+ >;
353
438
  }
354
439
 
355
440
  /** Define a plugin tool with Zod input parsing and validated structured results. */
356
441
  export function zodTool<
357
442
  TInputSchema extends ZodTypeAny,
358
443
  TOutputSchema extends ZodType<PluginToolResult>,
444
+ TExecuteResult extends
445
+ | z.input<TOutputSchema>
446
+ | PluginToolResultEnvelope<z.input<TOutputSchema>>,
359
447
  >(
360
- definition: ZodPluginToolDefinition<TInputSchema, TOutputSchema>,
361
- ): PluginToolDefinition<z.output<TInputSchema>, z.output<TOutputSchema>> {
448
+ definition: ZodPluginToolDefinition<
449
+ TInputSchema,
450
+ TOutputSchema,
451
+ TExecuteResult
452
+ >,
453
+ ): PluginToolDefinition<
454
+ z.output<TInputSchema>,
455
+ z.output<TOutputSchema>,
456
+ ParsedPluginToolExecuteResult<TOutputSchema, TExecuteResult>
457
+ > {
362
458
  return createZodTool(definition, "zodTool");
363
459
  }
364
460
 
@@ -366,9 +462,20 @@ export function zodTool<
366
462
  export function definePluginTool<
367
463
  TInputSchema extends ZodTypeAny,
368
464
  TOutputSchema extends ZodType<PluginToolResult>,
465
+ TExecuteResult extends
466
+ | z.input<TOutputSchema>
467
+ | PluginToolResultEnvelope<z.input<TOutputSchema>>,
369
468
  >(
370
- definition: ZodPluginToolDefinition<TInputSchema, TOutputSchema>,
371
- ): PluginToolDefinition<z.output<TInputSchema>, z.output<TOutputSchema>> {
469
+ definition: ZodPluginToolDefinition<
470
+ TInputSchema,
471
+ TOutputSchema,
472
+ TExecuteResult
473
+ >,
474
+ ): PluginToolDefinition<
475
+ z.output<TInputSchema>,
476
+ z.output<TOutputSchema>,
477
+ ParsedPluginToolExecuteResult<TOutputSchema, TExecuteResult>
478
+ > {
372
479
  return createZodTool(definition, "definePluginTool");
373
480
  }
374
481