@sentry/junior-plugin-api 0.182.0 → 0.183.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/dist/code.d.ts ADDED
@@ -0,0 +1,37 @@
1
+ import { z } from "zod";
2
+ export declare const codeChangeStateSchema: z.ZodEnum<{
3
+ open: "open";
4
+ closed: "closed";
5
+ merged: "merged";
6
+ }>;
7
+ export type CodeChangeState = z.output<typeof codeChangeStateSchema>;
8
+ export declare const codeChangeInputSchema: z.ZodObject<{
9
+ closedAt: z.ZodOptional<z.ZodDate>;
10
+ conversationIds: z.ZodDefault<z.ZodArray<z.ZodString>>;
11
+ mergedAt: z.ZodOptional<z.ZodDate>;
12
+ number: z.ZodNumber;
13
+ openedAt: z.ZodDate;
14
+ providerId: z.ZodString;
15
+ repository: z.ZodObject<{
16
+ name: z.ZodString;
17
+ providerId: z.ZodString;
18
+ url: z.ZodOptional<z.ZodString>;
19
+ }, z.core.$strict>;
20
+ state: z.ZodEnum<{
21
+ open: "open";
22
+ closed: "closed";
23
+ merged: "merged";
24
+ }>;
25
+ title: z.ZodOptional<z.ZodString>;
26
+ updatedAt: z.ZodDate;
27
+ url: z.ZodOptional<z.ZodString>;
28
+ }, z.core.$strict>;
29
+ export type CodeChangeInput = z.input<typeof codeChangeInputSchema>;
30
+ /** Write code changes from a plugin to Junior's code records. */
31
+ export interface CodeChangePublisher {
32
+ associateConversations(input: {
33
+ conversationIds: string[];
34
+ providerId: string;
35
+ }): Promise<void>;
36
+ record(input: CodeChangeInput): Promise<void>;
37
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./annotations";
2
+ export * from "./code";
2
3
  export * from "./conversation-events";
3
4
  export * from "./schemas";
4
5
  export * from "./context";
package/dist/index.js CHANGED
@@ -33,10 +33,31 @@ var conversationSidebarAnnotationSchema = z.object({
33
33
  label: z.string().trim().min(1).max(256)
34
34
  }).strict();
35
35
 
36
- // src/conversation-events.ts
36
+ // src/code.ts
37
37
  import { z as z2 } from "zod";
38
- var conversationEventNameSchema = z2.string().trim().min(1).max(64).regex(/^[a-z][a-z0-9_]*$/);
39
- var conversationEventIconSchema = z2.enum([
38
+ var codeChangeStateSchema = z2.enum(["closed", "merged", "open"]);
39
+ var codeChangeInputSchema = z2.object({
40
+ closedAt: z2.date().optional(),
41
+ conversationIds: z2.array(z2.string().min(1)).default([]),
42
+ mergedAt: z2.date().optional(),
43
+ number: z2.number().int().positive(),
44
+ openedAt: z2.date(),
45
+ providerId: z2.string().min(1),
46
+ repository: z2.object({
47
+ name: z2.string().min(1),
48
+ providerId: z2.string().min(1),
49
+ url: z2.string().url().optional()
50
+ }).strict(),
51
+ state: codeChangeStateSchema,
52
+ title: z2.string().min(1).optional(),
53
+ updatedAt: z2.date(),
54
+ url: z2.string().url().optional()
55
+ }).strict();
56
+
57
+ // src/conversation-events.ts
58
+ import { z as z3 } from "zod";
59
+ var conversationEventNameSchema = z3.string().trim().min(1).max(64).regex(/^[a-z][a-z0-9_]*$/);
60
+ var conversationEventIconSchema = z3.enum([
40
61
  "activity",
41
62
  "brain",
42
63
  "calendar",
@@ -48,22 +69,22 @@ var conversationEventIconSchema = z2.enum([
48
69
  "sparkles",
49
70
  "warning"
50
71
  ]);
51
- var conversationEventDetailSchema = z2.object({
52
- content: z2.string().min(1).max(32 * 1024).optional(),
53
- description: z2.string().trim().min(1).max(2e3).optional(),
54
- metadata: z2.array(z2.string().trim().min(1).max(120)).max(8).optional(),
55
- title: z2.string().trim().min(1).max(4e3)
72
+ var conversationEventDetailSchema = z3.object({
73
+ content: z3.string().min(1).max(32 * 1024).optional(),
74
+ description: z3.string().trim().min(1).max(2e3).optional(),
75
+ metadata: z3.array(z3.string().trim().min(1).max(120)).max(8).optional(),
76
+ title: z3.string().trim().min(1).max(4e3)
56
77
  }).strict();
57
- var conversationEventPresentationSchema = z2.object({
58
- details: z2.array(conversationEventDetailSchema).max(100).optional(),
78
+ var conversationEventPresentationSchema = z3.object({
79
+ details: z3.array(conversationEventDetailSchema).max(100).optional(),
59
80
  icon: conversationEventIconSchema.optional(),
60
- preview: z2.string().trim().min(1).max(500).optional(),
61
- title: z2.string().trim().min(1).max(120)
81
+ preview: z3.string().trim().min(1).max(500).optional(),
82
+ title: z3.string().trim().min(1).max(120)
62
83
  }).strict();
63
84
  function defineConversationEvent(definition) {
64
- const identity = z2.object({
85
+ const identity = z3.object({
65
86
  name: conversationEventNameSchema,
66
- version: z2.number().int().positive()
87
+ version: z3.number().int().positive()
67
88
  }).strict().parse({ name: definition.name, version: definition.version });
68
89
  let eventDefinition;
69
90
  const createEvent = (data) => ({
@@ -86,32 +107,32 @@ function defineConversationEvent(definition) {
86
107
  }
87
108
 
88
109
  // src/schemas.ts
89
- import { z as z3 } from "zod";
90
- var slackTeamIdSchema = z3.string().regex(/^T[A-Z0-9]+$/);
91
- var slackConversationIdSchema = z3.string().regex(/^(C|G|D)[A-Z0-9]+$/);
92
- var localConversationIdSchema = z3.string().regex(/^local:[a-z0-9_-]+:[a-z0-9][a-z0-9_-]*$/);
93
- var actorUserIdSchema = z3.string().min(1).refine(
110
+ import { z as z4 } from "zod";
111
+ var slackTeamIdSchema = z4.string().regex(/^T[A-Z0-9]+$/);
112
+ var slackConversationIdSchema = z4.string().regex(/^(C|G|D)[A-Z0-9]+$/);
113
+ var localConversationIdSchema = z4.string().regex(/^local:[a-z0-9_-]+:[a-z0-9][a-z0-9_-]*$/);
114
+ var actorUserIdSchema = z4.string().min(1).refine(
94
115
  (value) => value === value.trim() && value.toLowerCase() !== "unknown"
95
116
  );
96
117
  var exactActorUserIdSchema = actorUserIdSchema;
97
- var nonBlankStringSchema = z3.string().refine((value) => value.trim().length > 0);
118
+ var nonBlankStringSchema = z4.string().refine((value) => value.trim().length > 0);
98
119
  var exactNonBlankStringSchema = nonBlankStringSchema.refine(
99
120
  (value) => value === value.trim()
100
121
  );
101
- var platformSchema = z3.enum(["slack", "local"]);
102
- var sourceVisibilitySchema = z3.enum(["public", "private"]);
103
- var destinationVisibilitySchema = z3.enum(["public", "private"]);
104
- var slackAddressSchema = z3.object({
105
- platform: z3.literal("slack"),
122
+ var platformSchema = z4.enum(["slack", "local"]);
123
+ var sourceVisibilitySchema = z4.enum(["public", "private"]);
124
+ var destinationVisibilitySchema = z4.enum(["public", "private"]);
125
+ var slackAddressSchema = z4.object({
126
+ platform: z4.literal("slack"),
106
127
  teamId: slackTeamIdSchema,
107
128
  channelId: slackConversationIdSchema
108
129
  }).strict();
109
130
  var slackDestinationSchema = slackAddressSchema;
110
- var localDestinationSchema = z3.object({
111
- platform: z3.literal("local"),
131
+ var localDestinationSchema = z4.object({
132
+ platform: z4.literal("local"),
112
133
  conversationId: localConversationIdSchema
113
134
  }).strict();
114
- var destinationSchema = z3.discriminatedUnion("platform", [
135
+ var destinationSchema = z4.discriminatedUnion("platform", [
115
136
  slackDestinationSchema,
116
137
  localDestinationSchema
117
138
  ]);
@@ -120,34 +141,34 @@ var slackSourceSchema = slackAddressSchema.extend({
120
141
  messageTs: nonBlankStringSchema.optional(),
121
142
  threadTs: nonBlankStringSchema.optional()
122
143
  }).strict();
123
- var localSourceSchema = z3.object({
124
- platform: z3.literal("local"),
125
- visibility: z3.literal("private"),
144
+ var localSourceSchema = z4.object({
145
+ platform: z4.literal("local"),
146
+ visibility: z4.literal("private"),
126
147
  conversationId: localConversationIdSchema
127
148
  }).strict();
128
- var webSourceSchema = z3.object({
129
- platform: z3.literal("web"),
149
+ var webSourceSchema = z4.object({
150
+ platform: z4.literal("web"),
130
151
  visibility: sourceVisibilitySchema,
131
152
  // Web can continue any existing conversation id, including Slack roots.
132
153
  conversationId: exactNonBlankStringSchema
133
154
  }).strict();
134
- var sourceSchema = z3.discriminatedUnion("platform", [
155
+ var sourceSchema = z4.discriminatedUnion("platform", [
135
156
  slackSourceSchema,
136
157
  localSourceSchema,
137
158
  webSourceSchema
138
159
  ]);
139
- var pluginCredentialSubjectSchema = z3.discriminatedUnion(
160
+ var pluginCredentialSubjectSchema = z4.discriminatedUnion(
140
161
  "allowedWhen",
141
162
  [
142
- z3.object({
143
- type: z3.literal("user"),
163
+ z4.object({
164
+ type: z4.literal("user"),
144
165
  userId: exactActorUserIdSchema,
145
- allowedWhen: z3.literal("private-direct-conversation")
166
+ allowedWhen: z4.literal("private-direct-conversation")
146
167
  }).strict(),
147
- z3.object({
148
- type: z3.literal("user"),
168
+ z4.object({
169
+ type: z4.literal("user"),
149
170
  userId: exactActorUserIdSchema,
150
- allowedWhen: z3.literal("scheduled-task"),
171
+ allowedWhen: z4.literal("scheduled-task"),
151
172
  taskId: exactNonBlankStringSchema
152
173
  }).strict()
153
174
  ]
@@ -158,30 +179,30 @@ var actorProfileSchema = {
158
179
  userId: exactActorUserIdSchema,
159
180
  userName: nonBlankStringSchema.optional()
160
181
  };
161
- var slackActorSchema = z3.object({
182
+ var slackActorSchema = z4.object({
162
183
  ...actorProfileSchema,
163
- platform: z3.literal("slack"),
184
+ platform: z4.literal("slack"),
164
185
  teamId: slackTeamIdSchema
165
186
  }).strict();
166
- var localActorSchema = z3.object({
187
+ var localActorSchema = z4.object({
167
188
  ...actorProfileSchema,
168
- platform: z3.literal("local")
189
+ platform: z4.literal("local")
169
190
  }).strict();
170
- var webActorSchema = z3.object({
191
+ var webActorSchema = z4.object({
171
192
  ...actorProfileSchema,
172
- platform: z3.literal("web")
193
+ platform: z4.literal("web")
173
194
  }).strict();
174
- var systemActorSchema = z3.object({
175
- platform: z3.literal("system"),
195
+ var systemActorSchema = z4.object({
196
+ platform: z4.literal("system"),
176
197
  name: exactActorUserIdSchema
177
198
  }).strict();
178
- var actorSchema = z3.discriminatedUnion("platform", [
199
+ var actorSchema = z4.discriminatedUnion("platform", [
179
200
  slackActorSchema,
180
201
  localActorSchema,
181
202
  webActorSchema,
182
203
  systemActorSchema
183
204
  ]);
184
- var identitySchema = z3.object({
205
+ var identitySchema = z4.object({
185
206
  displayName: nonBlankStringSchema.optional(),
186
207
  handle: nonBlankStringSchema.optional(),
187
208
  id: exactNonBlankStringSchema,
@@ -189,17 +210,17 @@ var identitySchema = z3.object({
189
210
  providerSubjectId: exactNonBlankStringSchema,
190
211
  providerTenantId: exactNonBlankStringSchema.optional()
191
212
  }).strict();
192
- var userSchema = z3.object({
213
+ var userSchema = z4.object({
193
214
  displayName: nonBlankStringSchema.optional(),
194
215
  email: nonBlankStringSchema.max(320),
195
216
  id: exactNonBlankStringSchema,
196
- identities: z3.array(identitySchema).max(100)
217
+ identities: z4.array(identitySchema).max(100)
197
218
  }).strict();
198
- var dispatchMetadataSchema = z3.record(z3.string(), z3.string()).superRefine((metadata, ctx) => {
219
+ var dispatchMetadataSchema = z4.record(z4.string(), z4.string()).superRefine((metadata, ctx) => {
199
220
  const entries = Object.entries(metadata);
200
221
  if (entries.length > 20) {
201
222
  ctx.addIssue({
202
- code: z3.ZodIssueCode.custom,
223
+ code: z4.ZodIssueCode.custom,
203
224
  message: "Dispatch metadata has too many keys"
204
225
  });
205
226
  return;
@@ -207,7 +228,7 @@ var dispatchMetadataSchema = z3.record(z3.string(), z3.string()).superRefine((me
207
228
  for (const [key, value] of entries) {
208
229
  if (!key.trim()) {
209
230
  ctx.addIssue({
210
- code: z3.ZodIssueCode.custom,
231
+ code: z4.ZodIssueCode.custom,
211
232
  message: "Dispatch metadata values must be strings",
212
233
  path: [key]
213
234
  });
@@ -215,44 +236,44 @@ var dispatchMetadataSchema = z3.record(z3.string(), z3.string()).superRefine((me
215
236
  }
216
237
  if (key.length > 128) {
217
238
  ctx.addIssue({
218
- code: z3.ZodIssueCode.custom,
239
+ code: z4.ZodIssueCode.custom,
219
240
  message: "Dispatch metadata key exceeds the maximum length",
220
241
  path: [key]
221
242
  });
222
243
  }
223
244
  if (/[\r\n]/.test(key)) {
224
245
  ctx.addIssue({
225
- code: z3.ZodIssueCode.custom,
246
+ code: z4.ZodIssueCode.custom,
226
247
  message: "Dispatch metadata keys must be single-line strings",
227
248
  path: [key]
228
249
  });
229
250
  }
230
251
  if (/[\r\n]/.test(value)) {
231
252
  ctx.addIssue({
232
- code: z3.ZodIssueCode.custom,
253
+ code: z4.ZodIssueCode.custom,
233
254
  message: "Dispatch metadata values must be single-line strings",
234
255
  path: [key]
235
256
  });
236
257
  }
237
258
  if (value.length > 512) {
238
259
  ctx.addIssue({
239
- code: z3.ZodIssueCode.custom,
260
+ code: z4.ZodIssueCode.custom,
240
261
  message: "Dispatch metadata value exceeds the maximum length",
241
262
  path: [key]
242
263
  });
243
264
  }
244
265
  }
245
266
  });
246
- var replyAttributionSchema = z3.object({
247
- label: exactNonBlankStringSchema.pipe(z3.string().max(48)).refine((value) => !/[\r\n]/.test(value)),
248
- detail: exactNonBlankStringSchema.pipe(z3.string().max(128)).refine((value) => !/[\r\n]/.test(value)).optional()
267
+ var replyAttributionSchema = z4.object({
268
+ label: exactNonBlankStringSchema.pipe(z4.string().max(48)).refine((value) => !/[\r\n]/.test(value)),
269
+ detail: exactNonBlankStringSchema.pipe(z4.string().max(128)).refine((value) => !/[\r\n]/.test(value)).optional()
249
270
  }).strict();
250
- var dispatchOptionsSchema = z3.object({
251
- idempotencyKey: nonBlankStringSchema.pipe(z3.string().max(512)),
271
+ var dispatchOptionsSchema = z4.object({
272
+ idempotencyKey: nonBlankStringSchema.pipe(z4.string().max(512)),
252
273
  credentialSubject: pluginCredentialSubjectSchema.optional(),
253
274
  destination: slackDestinationSchema,
254
275
  destinationVisibility: destinationVisibilitySchema,
255
- input: nonBlankStringSchema.pipe(z3.string().max(32e3)),
276
+ input: nonBlankStringSchema.pipe(z4.string().max(32e3)),
256
277
  metadata: dispatchMetadataSchema.optional(),
257
278
  replyAttribution: replyAttributionSchema.optional(),
258
279
  source: sourceSchema
@@ -305,15 +326,15 @@ function isSlackDestination(destination) {
305
326
  }
306
327
 
307
328
  // src/prompt.ts
308
- import { z as z4 } from "zod";
309
- var promptContextKindSchema = z4.string().trim().min(1).max(64).regex(/^[a-z][a-z0-9_-]*$/);
310
- var promptMessageSchema = z4.object({
311
- text: z4.string().trim().min(1).max(8e3)
329
+ import { z as z5 } from "zod";
330
+ var promptContextKindSchema = z5.string().trim().min(1).max(64).regex(/^[a-z][a-z0-9_-]*$/);
331
+ var promptMessageSchema = z5.object({
332
+ text: z5.string().trim().min(1).max(8e3)
312
333
  }).strict();
313
- var promptContextSchema = z4.object({
334
+ var promptContextSchema = z5.object({
314
335
  kind: promptContextKindSchema,
315
- version: z4.number().int().positive(),
316
- content: z4.record(z4.string(), z4.unknown())
336
+ version: z5.number().int().positive(),
337
+ content: z5.record(z5.string(), z5.unknown())
317
338
  }).strict();
318
339
  function definePromptContext(definition) {
319
340
  const identity = promptContextSchema.pick({ kind: true, version: true }).parse({ kind: definition.kind, version: definition.version });
@@ -327,13 +348,13 @@ function definePromptContext(definition) {
327
348
  }
328
349
 
329
350
  // src/resource-events.ts
330
- import { z as z5 } from "zod";
351
+ import { z as z6 } from "zod";
331
352
  var RESOURCE_EVENT_SUMMARY_MAX_LENGTH = 4e3;
332
353
  var RESOURCE_EVENT_TEXT_MAX_LENGTH = 8e3;
333
354
  var RESOURCE_EVENT_DATA_MAX_KEYS = 32;
334
355
  var RESOURCE_EVENT_DATA_MAX_JSON_BYTES = 4e3;
335
356
  var RESOURCE_EVENT_GUIDANCE_MAX_LENGTH = 1e3;
336
- var resourceEventDataSchema = z5.record(z5.string(), z5.unknown()).superRefine((value, context) => {
357
+ var resourceEventDataSchema = z6.record(z6.string(), z6.unknown()).superRefine((value, context) => {
337
358
  const keys = Object.keys(value);
338
359
  if (keys.length > RESOURCE_EVENT_DATA_MAX_KEYS) {
339
360
  context.addIssue({
@@ -351,17 +372,17 @@ var resourceEventDataSchema = z5.record(z5.string(), z5.unknown()).superRefine((
351
372
  });
352
373
  }
353
374
  });
354
- var resourceEventTypeSchema = z5.string().regex(/^[a-z][a-z0-9_-]*(?:\.[a-z][a-z0-9_-]*)+$/).describe(
375
+ var resourceEventTypeSchema = z6.string().regex(/^[a-z][a-z0-9_-]*(?:\.[a-z][a-z0-9_-]*)+$/).describe(
355
376
  "Canonical dotted event type, such as issue.closed or pull_request.review.changes_requested."
356
377
  );
357
- var resourceTypeSchema = z5.string().regex(/^[a-z][a-z0-9_]*$/).describe(
378
+ var resourceTypeSchema = z6.string().regex(/^[a-z][a-z0-9_]*$/).describe(
358
379
  "Canonical plugin-defined resource type, such as issue or pull_request."
359
380
  );
360
381
  var RESOURCE_EVENT_MATCH_FIELD_NAME = /^[a-z][a-zA-Z0-9]*$/;
361
- var resourceEventMatchFieldSchema = z5.object({
362
- kind: z5.enum(["boolean", "string", "number"]),
363
- description: z5.string().trim().min(1).max(200),
364
- enum: z5.array(z5.string().min(1)).min(1).optional()
382
+ var resourceEventMatchFieldSchema = z6.object({
383
+ kind: z6.enum(["boolean", "string", "number"]),
384
+ description: z6.string().trim().min(1).max(200),
385
+ enum: z6.array(z6.string().min(1)).min(1).optional()
365
386
  }).strict().superRefine((field, context) => {
366
387
  if (field.enum && field.kind !== "string") {
367
388
  context.addIssue({
@@ -371,7 +392,7 @@ var resourceEventMatchFieldSchema = z5.object({
371
392
  });
372
393
  }
373
394
  });
374
- var resourceEventMatchFieldsSchema = z5.record(z5.string().regex(RESOURCE_EVENT_MATCH_FIELD_NAME), resourceEventMatchFieldSchema).superRefine((fields, context) => {
395
+ var resourceEventMatchFieldsSchema = z6.record(z6.string().regex(RESOURCE_EVENT_MATCH_FIELD_NAME), resourceEventMatchFieldSchema).superRefine((fields, context) => {
375
396
  if (Object.keys(fields).length > RESOURCE_EVENT_DATA_MAX_KEYS) {
376
397
  context.addIssue({
377
398
  code: "custom",
@@ -379,13 +400,13 @@ var resourceEventMatchFieldsSchema = z5.record(z5.string().regex(RESOURCE_EVENT_
379
400
  });
380
401
  }
381
402
  });
382
- var resourceEventMatchSchema = z5.record(
383
- z5.string().regex(RESOURCE_EVENT_MATCH_FIELD_NAME),
384
- z5.union([
385
- z5.boolean(),
386
- z5.number().finite(),
387
- z5.string().min(1),
388
- z5.array(z5.union([z5.number().finite(), z5.string().min(1)])).min(1)
403
+ var resourceEventMatchSchema = z6.record(
404
+ z6.string().regex(RESOURCE_EVENT_MATCH_FIELD_NAME),
405
+ z6.union([
406
+ z6.boolean(),
407
+ z6.number().finite(),
408
+ z6.string().min(1),
409
+ z6.array(z6.union([z6.number().finite(), z6.string().min(1)])).min(1)
389
410
  ])
390
411
  ).superRefine((match, context) => {
391
412
  if (Object.keys(match).length > RESOURCE_EVENT_DATA_MAX_KEYS) {
@@ -436,14 +457,14 @@ function resourceEventMatches(match, data) {
436
457
  }
437
458
  return true;
438
459
  }
439
- var pluginResourceEventTypeSchema = z5.object({
460
+ var pluginResourceEventTypeSchema = z6.object({
440
461
  type: resourceTypeSchema,
441
- supportedEvents: z5.array(resourceEventTypeSchema).min(1),
442
- suggestedEvents: z5.array(resourceEventTypeSchema).optional(),
462
+ supportedEvents: z6.array(resourceEventTypeSchema).min(1),
463
+ suggestedEvents: z6.array(resourceEventTypeSchema).optional(),
443
464
  matchFields: resourceEventMatchFieldsSchema.optional(),
444
- guidance: z5.record(
465
+ guidance: z6.record(
445
466
  resourceEventTypeSchema,
446
- z5.string().trim().min(1).max(RESOURCE_EVENT_GUIDANCE_MAX_LENGTH)
467
+ z6.string().trim().min(1).max(RESOURCE_EVENT_GUIDANCE_MAX_LENGTH)
447
468
  ).optional()
448
469
  }).strict().superRefine((resourceType, context) => {
449
470
  const supported = /* @__PURE__ */ new Set();
@@ -485,10 +506,10 @@ var pluginResourceEventTypeSchema = z5.object({
485
506
  suggested.add(eventType);
486
507
  });
487
508
  });
488
- var pluginResourceEventsSchema = z5.object({
489
- resourceTypes: z5.array(pluginResourceEventTypeSchema).min(1),
490
- isEnabled: z5.function({ input: [], output: z5.boolean() }).optional(),
491
- normalizeIdentifier: z5.function({ input: [z5.string()], output: z5.string() }).optional()
509
+ var pluginResourceEventsSchema = z6.object({
510
+ resourceTypes: z6.array(pluginResourceEventTypeSchema).min(1),
511
+ isEnabled: z6.function({ input: [], output: z6.boolean() }).optional(),
512
+ normalizeIdentifier: z6.function({ input: [z6.string()], output: z6.string() }).optional()
492
513
  }).strict().superRefine((registration, context) => {
493
514
  const seen = /* @__PURE__ */ new Set();
494
515
  registration.resourceTypes.forEach((resourceType, index) => {
@@ -510,62 +531,62 @@ function normalizeResourceEventIdentifier(registration, identifier) {
510
531
  }
511
532
  return normalized;
512
533
  }
513
- var subscribableResourceSchema = z5.object({
514
- identifier: z5.string().min(1),
515
- label: z5.string().min(1),
516
- namespace: z5.string().min(1),
517
- suggestedEvents: z5.array(resourceEventTypeSchema).optional(),
518
- supportedEvents: z5.array(resourceEventTypeSchema),
534
+ var subscribableResourceSchema = z6.object({
535
+ identifier: z6.string().min(1),
536
+ label: z6.string().min(1),
537
+ namespace: z6.string().min(1),
538
+ suggestedEvents: z6.array(resourceEventTypeSchema).optional(),
539
+ supportedEvents: z6.array(resourceEventTypeSchema),
519
540
  type: resourceTypeSchema
520
541
  }).strict();
521
- var resourceEventSubscriptionResultSchema = z5.object({
522
- events: z5.array(resourceEventTypeSchema).min(1),
523
- id: z5.string().min(1)
542
+ var resourceEventSubscriptionResultSchema = z6.object({
543
+ events: z6.array(resourceEventTypeSchema).min(1),
544
+ id: z6.string().min(1)
524
545
  }).strict();
525
- var resourceEventInputSchema = z5.object({
526
- eventKey: z5.string().min(1),
546
+ var resourceEventInputSchema = z6.object({
547
+ eventKey: z6.string().min(1),
527
548
  eventType: resourceEventTypeSchema,
528
- identifier: z5.string().min(1),
529
- occurredAtMs: z5.number().finite(),
530
- terminal: z5.boolean().optional(),
531
- trustedSummary: z5.string().min(1).transform((value) => value.slice(0, RESOURCE_EVENT_SUMMARY_MAX_LENGTH)),
549
+ identifier: z6.string().min(1),
550
+ occurredAtMs: z6.number().finite(),
551
+ terminal: z6.boolean().optional(),
552
+ trustedSummary: z6.string().min(1).transform((value) => value.slice(0, RESOURCE_EVENT_SUMMARY_MAX_LENGTH)),
532
553
  /** Trusted structured facts. Prefer ids and urls over long prose. */
533
554
  data: resourceEventDataSchema.optional(),
534
- untrustedText: z5.string().transform((value) => value.slice(0, RESOURCE_EVENT_TEXT_MAX_LENGTH)).optional()
555
+ untrustedText: z6.string().transform((value) => value.slice(0, RESOURCE_EVENT_TEXT_MAX_LENGTH)).optional()
535
556
  }).strict();
536
557
  var resourceEventSchema = resourceEventInputSchema.extend({
537
- namespace: z5.string().min(1)
558
+ namespace: z6.string().min(1)
538
559
  });
539
560
 
540
561
  // src/tasks.ts
541
- import { z as z6 } from "zod";
542
- var pluginRunTranscriptProvenanceSchema = z6.object({
543
- authority: z6.enum(["instruction", "context"]),
562
+ import { z as z7 } from "zod";
563
+ var pluginRunTranscriptProvenanceSchema = z7.object({
564
+ authority: z7.enum(["instruction", "context"]),
544
565
  actor: actorSchema.optional()
545
566
  }).strict();
546
- var pluginRunTranscriptEntrySchema = z6.discriminatedUnion("type", [
547
- z6.object({
548
- type: z6.literal("message"),
549
- role: z6.enum(["user", "assistant"]),
550
- text: z6.string().min(1),
567
+ var pluginRunTranscriptEntrySchema = z7.discriminatedUnion("type", [
568
+ z7.object({
569
+ type: z7.literal("message"),
570
+ role: z7.enum(["user", "assistant"]),
571
+ text: z7.string().min(1),
551
572
  provenance: pluginRunTranscriptProvenanceSchema.optional(),
552
- isRunActor: z6.boolean().optional()
573
+ isRunActor: z7.boolean().optional()
553
574
  }).strict(),
554
- z6.object({
555
- type: z6.literal("toolResult"),
556
- toolName: z6.string().min(1),
557
- isError: z6.boolean(),
558
- text: z6.string().min(1).optional()
575
+ z7.object({
576
+ type: z7.literal("toolResult"),
577
+ toolName: z7.string().min(1),
578
+ isError: z7.boolean(),
579
+ text: z7.string().min(1).optional()
559
580
  }).strict()
560
581
  ]);
561
- var pluginRunContextSchema = z6.object({
582
+ var pluginRunContextSchema = z7.object({
562
583
  /** User linked to the Actor, when known. */
563
- actorUserId: z6.string().min(1).optional(),
564
- completedAtMs: z6.number().finite(),
565
- conversationId: z6.string().min(1),
584
+ actorUserId: z7.string().min(1).optional(),
585
+ completedAtMs: z7.number().finite(),
586
+ conversationId: z7.string().min(1),
566
587
  destination: destinationSchema,
567
588
  /** Location associated with this Conversation. */
568
- locationId: z6.string().min(1).optional(),
589
+ locationId: z7.string().min(1).optional(),
569
590
  /**
570
591
  * All distinct actors annotated on this run's committed instruction-authority
571
592
  * messages, in first-seen order. Attribution provenance only, never an
@@ -574,43 +595,43 @@ var pluginRunContextSchema = z6.object({
574
595
  * exceed the actors visible in the transcript slice. Usually `[run.actor]`;
575
596
  * possibly empty for system runs with no human instructions.
576
597
  */
577
- actors: z6.array(actorSchema),
598
+ actors: z7.array(actorSchema),
578
599
  /**
579
600
  * The single actor this run executes as. Absent only for actor-less legacy
580
601
  * system records, so authority-sensitive plugins must fail closed.
581
602
  */
582
603
  actor: actorSchema.optional(),
583
- runId: z6.string().min(1),
604
+ runId: z7.string().min(1),
584
605
  source: sourceSchema,
585
- transcript: z6.array(pluginRunTranscriptEntrySchema)
606
+ transcript: z7.array(pluginRunTranscriptEntrySchema)
586
607
  }).strict();
587
608
 
588
609
  // src/tools.ts
589
- import { z as z7 } from "zod";
610
+ import { z as z8 } from "zod";
590
611
  var PluginToolInputError = class extends Error {
591
612
  constructor(message, options) {
592
613
  super(message, options);
593
614
  this.name = "PluginToolInputError";
594
615
  }
595
616
  };
596
- var pluginToolContentSchema = z7.discriminatedUnion("type", [
597
- z7.object({ type: z7.literal("text"), text: z7.string() }).strict(),
598
- z7.object({
599
- type: z7.literal("image"),
600
- data: z7.string(),
601
- mimeType: z7.string()
617
+ var pluginToolContentSchema = z8.discriminatedUnion("type", [
618
+ z8.object({ type: z8.literal("text"), text: z8.string() }).strict(),
619
+ z8.object({
620
+ type: z8.literal("image"),
621
+ data: z8.string(),
622
+ mimeType: z8.string()
602
623
  }).strict()
603
624
  ]);
604
- var pluginToolContinuationSchema = z7.object({
605
- arguments: z7.record(z7.string(), z7.unknown()),
606
- reason: z7.string().min(1).optional()
625
+ var pluginToolContinuationSchema = z8.object({
626
+ arguments: z8.record(z8.string(), z8.unknown()),
627
+ reason: z8.string().min(1).optional()
607
628
  }).strict();
608
- var pluginToolOutputSchema = z7.object({
609
- target: z7.string().min(1).optional(),
610
- truncated: z7.boolean().optional(),
629
+ var pluginToolOutputSchema = z8.object({
630
+ target: z8.string().min(1).optional(),
631
+ truncated: z8.boolean().optional(),
611
632
  continuation: pluginToolContinuationSchema.optional()
612
633
  }).passthrough();
613
- var toolApprovalModeSchema = z7.enum(["auto", "review", "approve"]);
634
+ var toolApprovalModeSchema = z8.enum(["auto", "review", "approve"]);
614
635
  var REQUIRED_TOOL_ANNOTATION_KEYS = [
615
636
  "destructiveHint",
616
637
  "idempotentHint",
@@ -646,7 +667,7 @@ function createZodTool(definition, helperName) {
646
667
  let modelInputSchema;
647
668
  let modelOutputSchema;
648
669
  try {
649
- modelInputSchema = z7.toJSONSchema(inputSchema);
670
+ modelInputSchema = z8.toJSONSchema(inputSchema);
650
671
  } catch (error) {
651
672
  throw new TypeError(
652
673
  `${helperName}() inputSchema must be representable as JSON Schema.`,
@@ -654,7 +675,7 @@ function createZodTool(definition, helperName) {
654
675
  );
655
676
  }
656
677
  try {
657
- modelOutputSchema = z7.toJSONSchema(outputSchema);
678
+ modelOutputSchema = z8.toJSONSchema(outputSchema);
658
679
  } catch (error) {
659
680
  throw new TypeError(
660
681
  `${helperName}() outputSchema must be representable as JSON Schema.`,
@@ -680,7 +701,7 @@ function createZodTool(definition, helperName) {
680
701
  );
681
702
  if (isPluginToolOutputEnvelope(result)) {
682
703
  return {
683
- content: z7.array(pluginToolContentSchema).parse(result.content),
704
+ content: z8.array(pluginToolContentSchema).parse(result.content),
684
705
  details: outputSchema.parse(result.details)
685
706
  };
686
707
  }
@@ -697,76 +718,76 @@ function definePluginTool(definition) {
697
718
  }
698
719
 
699
720
  // src/operations.ts
700
- import { z as z8 } from "zod";
701
- var pluginApiRouteRequestContextSchema = z8.object({
702
- auth: z8.object({
703
- user: z8.object({
704
- email: z8.string().nullable().optional(),
705
- emailVerified: z8.boolean().optional(),
706
- name: z8.string().nullable().optional()
721
+ import { z as z9 } from "zod";
722
+ var pluginApiRouteRequestContextSchema = z9.object({
723
+ auth: z9.object({
724
+ user: z9.object({
725
+ email: z9.string().nullable().optional(),
726
+ emailVerified: z9.boolean().optional(),
727
+ name: z9.string().nullable().optional()
707
728
  }).strict()
708
729
  }).strict(),
709
730
  pluginName: nonBlankStringSchema
710
731
  }).strict();
711
732
 
712
733
  // src/credentials.ts
713
- import { z as z9 } from "zod";
714
- var pluginProviderNameSchema = z9.string().regex(/^[a-z][a-z0-9-]*$/);
715
- var pluginGrantNameSchema = z9.string().regex(/^[a-z][a-z0-9.-]*$/);
716
- var pluginGrantAccessSchema = z9.union([
717
- z9.literal("read"),
718
- z9.literal("write")
734
+ import { z as z10 } from "zod";
735
+ var pluginProviderNameSchema = z10.string().regex(/^[a-z][a-z0-9-]*$/);
736
+ var pluginGrantNameSchema = z10.string().regex(/^[a-z][a-z0-9.-]*$/);
737
+ var pluginGrantAccessSchema = z10.union([
738
+ z10.literal("read"),
739
+ z10.literal("write")
719
740
  ]);
720
- var pluginAuthorizationSchema = z9.object({
741
+ var pluginAuthorizationSchema = z10.object({
721
742
  provider: pluginProviderNameSchema,
722
743
  scope: nonBlankStringSchema.optional(),
723
- type: z9.literal("oauth")
744
+ type: z10.literal("oauth")
724
745
  }).strict();
725
- var pluginProviderAccountSchema = z9.object({
746
+ var pluginProviderAccountSchema = z10.object({
726
747
  displayName: nonBlankStringSchema.optional(),
727
748
  handle: nonBlankStringSchema.optional(),
728
749
  id: nonBlankStringSchema,
729
750
  label: nonBlankStringSchema.optional(),
730
751
  url: nonBlankStringSchema.optional()
731
752
  }).strict();
732
- var pluginStoredTokensSchema = z9.object({
753
+ var pluginStoredTokensSchema = z10.object({
733
754
  account: pluginProviderAccountSchema.optional(),
734
755
  accessToken: nonBlankStringSchema,
735
- expiresAt: z9.number().finite().optional(),
756
+ expiresAt: z10.number().finite().optional(),
736
757
  refreshToken: nonBlankStringSchema,
737
- refreshTokenExpiresAt: z9.number().finite().optional(),
758
+ refreshTokenExpiresAt: z10.number().finite().optional(),
738
759
  scope: nonBlankStringSchema.optional()
739
760
  }).strict();
740
- var pluginGrantSchema = z9.object({
761
+ var pluginGrantSchema = z10.object({
741
762
  access: pluginGrantAccessSchema,
742
763
  leaseScope: nonBlankStringSchema.optional(),
743
764
  name: pluginGrantNameSchema,
744
765
  reason: nonBlankStringSchema.optional(),
745
- requirements: z9.array(nonBlankStringSchema).min(1).optional()
766
+ requirements: z10.array(nonBlankStringSchema).min(1).optional()
746
767
  }).strict();
747
- var pluginCredentialHeaderTransformSchema = z9.object({
748
- domain: z9.string().min(1),
749
- headers: z9.record(z9.string(), z9.string()).refine((headers) => Object.keys(headers).length > 0)
768
+ var pluginCredentialHeaderTransformSchema = z10.object({
769
+ domain: z10.string().min(1),
770
+ headers: z10.record(z10.string(), z10.string()).refine((headers) => Object.keys(headers).length > 0)
750
771
  }).strict();
751
- var pluginCredentialLeaseSchema = z9.object({
772
+ var pluginCredentialLeaseSchema = z10.object({
752
773
  account: pluginProviderAccountSchema.optional(),
753
774
  authorization: pluginAuthorizationSchema.optional(),
754
- expiresAt: z9.string().refine((value) => Number.isFinite(Date.parse(value))),
755
- headerTransforms: z9.array(pluginCredentialHeaderTransformSchema).min(1)
775
+ expiresAt: z10.string().refine((value) => Number.isFinite(Date.parse(value))),
776
+ headerTransforms: z10.array(pluginCredentialHeaderTransformSchema).min(1)
756
777
  }).strict();
757
- var pluginCredentialResultSchema = z9.discriminatedUnion("type", [
758
- z9.object({
778
+ var pluginCredentialResultSchema = z10.discriminatedUnion("type", [
779
+ z10.object({
759
780
  lease: pluginCredentialLeaseSchema,
760
- type: z9.literal("lease")
781
+ type: z10.literal("lease")
761
782
  }).strict(),
762
- z9.object({
783
+ z10.object({
763
784
  authorization: pluginAuthorizationSchema.optional(),
764
785
  message: nonBlankStringSchema,
765
- type: z9.literal("needed")
786
+ type: z10.literal("needed")
766
787
  }).strict(),
767
- z9.object({
788
+ z10.object({
768
789
  message: nonBlankStringSchema,
769
- type: z9.literal("unavailable")
790
+ type: z10.literal("unavailable")
770
791
  }).strict()
771
792
  ]);
772
793
  var EgressAuthRequired = class extends Error {
@@ -902,44 +923,44 @@ function defineJuniorPlugin(plugin) {
902
923
  }
903
924
 
904
925
  // src/user-pages.ts
905
- import { z as z10 } from "zod";
926
+ import { z as z11 } from "zod";
906
927
  var userPageIdSchema = nonBlankStringSchema.max(64).regex(/^[a-z][a-z0-9-]*$/);
907
928
  var userPageLabelSchema = nonBlankStringSchema.max(80);
908
929
  var userPageDescriptionSchema = nonBlankStringSchema.max(500);
909
- var userPageNavigationSchema = z10.enum(["primary", "profile"]);
910
- var pluginUserPageMetricSchema = z10.object({
930
+ var userPageNavigationSchema = z11.enum(["primary", "profile"]);
931
+ var pluginUserPageMetricSchema = z11.object({
911
932
  detail: nonBlankStringSchema.max(500).optional(),
912
933
  label: nonBlankStringSchema.max(80),
913
- tone: z10.enum(["good", "neutral", "warning"]).optional(),
934
+ tone: z11.enum(["good", "neutral", "warning"]).optional(),
914
935
  value: nonBlankStringSchema.max(120)
915
936
  }).strict();
916
- var pluginUserPageMetadataSchema = z10.object({
937
+ var pluginUserPageMetadataSchema = z11.object({
917
938
  label: nonBlankStringSchema.max(80),
918
939
  value: nonBlankStringSchema.max(500)
919
940
  }).strict();
920
- var pluginUserPageActionSchema = z10.object({
941
+ var pluginUserPageActionSchema = z11.object({
921
942
  confirmation: nonBlankStringSchema.max(500).optional(),
922
943
  href: nonBlankStringSchema.max(500).regex(/^\/api\/plugins\/[a-z][a-z0-9-]*(?:\/|$)/),
923
944
  label: nonBlankStringSchema.max(80),
924
- method: z10.literal("DELETE"),
925
- tone: z10.enum(["danger", "neutral"]).optional()
945
+ method: z11.literal("DELETE"),
946
+ tone: z11.enum(["danger", "neutral"]).optional()
926
947
  }).strict();
927
- var pluginUserPageRecordSchema = z10.object({
928
- actions: z10.array(pluginUserPageActionSchema).max(4).optional(),
948
+ var pluginUserPageRecordSchema = z11.object({
949
+ actions: z11.array(pluginUserPageActionSchema).max(4).optional(),
929
950
  description: nonBlankStringSchema.max(1e3).optional(),
930
951
  id: nonBlankStringSchema.max(128),
931
- metadata: z10.array(pluginUserPageMetadataSchema).max(8).optional(),
952
+ metadata: z11.array(pluginUserPageMetadataSchema).max(8).optional(),
932
953
  title: nonBlankStringSchema.max(4e3)
933
954
  }).strict();
934
- var pluginUserPageContentSchema = z10.object({
955
+ var pluginUserPageContentSchema = z11.object({
935
956
  emptyText: nonBlankStringSchema.max(500).optional(),
936
- metrics: z10.array(pluginUserPageMetricSchema).max(6).optional(),
957
+ metrics: z11.array(pluginUserPageMetricSchema).max(6).optional(),
937
958
  nextCursor: nonBlankStringSchema.max(1e3).optional(),
938
- records: z10.array(pluginUserPageRecordSchema).max(100),
959
+ records: z11.array(pluginUserPageRecordSchema).max(100),
939
960
  searchPlaceholder: nonBlankStringSchema.max(120).optional(),
940
- type: z10.literal("list")
961
+ type: z11.literal("list")
941
962
  }).strict();
942
- var pluginUserPageLinkSchema = z10.object({
963
+ var pluginUserPageLinkSchema = z11.object({
943
964
  description: userPageDescriptionSchema,
944
965
  id: userPageIdSchema,
945
966
  label: userPageLabelSchema,
@@ -947,14 +968,14 @@ var pluginUserPageLinkSchema = z10.object({
947
968
  pluginDisplayName: nonBlankStringSchema.max(200),
948
969
  pluginName: nonBlankStringSchema.max(100)
949
970
  }).strict();
950
- var pluginUserPageLinksSchema = z10.array(pluginUserPageLinkSchema);
971
+ var pluginUserPageLinksSchema = z11.array(pluginUserPageLinkSchema);
951
972
  var pluginUserPageCursorSchema = nonBlankStringSchema.max(1e3).optional();
952
973
  var pluginUserPageFilterSchema = nonBlankStringSchema.max(64).optional();
953
- var pluginUserPageQuerySchema = z10.string().trim().max(200).optional();
954
- var pluginUserPageInputSchema = z10.object({
974
+ var pluginUserPageQuerySchema = z11.string().trim().max(200).optional();
975
+ var pluginUserPageInputSchema = z11.object({
955
976
  cursor: pluginUserPageCursorSchema,
956
977
  filter: pluginUserPageFilterSchema,
957
- limit: z10.number().int().min(1).max(50),
978
+ limit: z11.number().int().min(1).max(50),
958
979
  query: pluginUserPageQuerySchema
959
980
  }).strict();
960
981
  export {
@@ -969,6 +990,8 @@ export {
969
990
  RESOURCE_EVENT_TEXT_MAX_LENGTH,
970
991
  actorSchema,
971
992
  actorUserIdSchema,
993
+ codeChangeInputSchema,
994
+ codeChangeStateSchema,
972
995
  conversationAnnotationInputSchema,
973
996
  conversationEventIconSchema,
974
997
  conversationEventPresentationSchema,
@@ -5,6 +5,7 @@ import type { PluginReadState, PluginState } from "./state";
5
5
  import type { ResourceEventPublisher } from "./resource-events";
6
6
  import type { PluginConversationAnnotations } from "./annotations";
7
7
  import type { PluginConversationEventStats } from "./conversation-events";
8
+ import type { CodeChangePublisher } from "./code";
8
9
  export interface HeartbeatHookContext extends PluginContext {
9
10
  agent: {
10
11
  dispatch(options: DispatchOptions): Promise<DispatchResult>;
@@ -120,6 +121,8 @@ export type PluginRouteApp = {
120
121
  };
121
122
  export interface RouteRegistrationHookContext extends PluginContext {
122
123
  annotations: PluginConversationAnnotations;
124
+ /** Provider-neutral write boundary for Junior's native code index. */
125
+ codeChanges: CodeChangePublisher;
123
126
  /** Core-owned delivery boundary for provider webhook events. */
124
127
  resourceEvents: ResourceEventPublisher;
125
128
  }
@@ -116,4 +116,13 @@ export type ResourceEvent = z.output<typeof resourceEventSchema>;
116
116
  export interface ResourceEventPublisher {
117
117
  /** Publish one normalized event under the owning plugin's namespace. */
118
118
  publish(event: ResourceEventInput): Promise<void>;
119
+ /**
120
+ * Return match keys used by active watches or event tasks for these
121
+ * identifiers and event types. Plugins use this to load optional trusted
122
+ * data only when a filter needs it.
123
+ */
124
+ neededMatchKeys?(input: {
125
+ eventTypes: string[];
126
+ identifiers: string[];
127
+ }): Promise<string[]>;
119
128
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior-plugin-api",
3
- "version": "0.182.0",
3
+ "version": "0.183.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
package/src/code.ts ADDED
@@ -0,0 +1,37 @@
1
+ import { z } from "zod";
2
+
3
+ export const codeChangeStateSchema = z.enum(["closed", "merged", "open"]);
4
+ export type CodeChangeState = z.output<typeof codeChangeStateSchema>;
5
+
6
+ export const codeChangeInputSchema = z
7
+ .object({
8
+ closedAt: z.date().optional(),
9
+ conversationIds: z.array(z.string().min(1)).default([]),
10
+ mergedAt: z.date().optional(),
11
+ number: z.number().int().positive(),
12
+ openedAt: z.date(),
13
+ providerId: z.string().min(1),
14
+ repository: z
15
+ .object({
16
+ name: z.string().min(1),
17
+ providerId: z.string().min(1),
18
+ url: z.string().url().optional(),
19
+ })
20
+ .strict(),
21
+ state: codeChangeStateSchema,
22
+ title: z.string().min(1).optional(),
23
+ updatedAt: z.date(),
24
+ url: z.string().url().optional(),
25
+ })
26
+ .strict();
27
+
28
+ export type CodeChangeInput = z.input<typeof codeChangeInputSchema>;
29
+
30
+ /** Write code changes from a plugin to Junior's code records. */
31
+ export interface CodeChangePublisher {
32
+ associateConversations(input: {
33
+ conversationIds: string[];
34
+ providerId: string;
35
+ }): Promise<void>;
36
+ record(input: CodeChangeInput): Promise<void>;
37
+ }
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./annotations";
2
+ export * from "./code";
2
3
  export * from "./conversation-events";
3
4
  export * from "./schemas";
4
5
  export * from "./context";
package/src/operations.ts CHANGED
@@ -6,6 +6,7 @@ import type { PluginReadState, PluginState } from "./state";
6
6
  import type { ResourceEventPublisher } from "./resource-events";
7
7
  import type { PluginConversationAnnotations } from "./annotations";
8
8
  import type { PluginConversationEventStats } from "./conversation-events";
9
+ import type { CodeChangePublisher } from "./code";
9
10
 
10
11
  export interface HeartbeatHookContext extends PluginContext {
11
12
  agent: {
@@ -153,6 +154,8 @@ export type PluginRouteApp = {
153
154
 
154
155
  export interface RouteRegistrationHookContext extends PluginContext {
155
156
  annotations: PluginConversationAnnotations;
157
+ /** Provider-neutral write boundary for Junior's native code index. */
158
+ codeChanges: CodeChangePublisher;
156
159
  /** Core-owned delivery boundary for provider webhook events. */
157
160
  resourceEvents: ResourceEventPublisher;
158
161
  }
@@ -308,4 +308,13 @@ export type ResourceEvent = z.output<typeof resourceEventSchema>;
308
308
  export interface ResourceEventPublisher {
309
309
  /** Publish one normalized event under the owning plugin's namespace. */
310
310
  publish(event: ResourceEventInput): Promise<void>;
311
+ /**
312
+ * Return match keys used by active watches or event tasks for these
313
+ * identifiers and event types. Plugins use this to load optional trusted
314
+ * data only when a filter needs it.
315
+ */
316
+ neededMatchKeys?(input: {
317
+ eventTypes: string[];
318
+ identifiers: string[];
319
+ }): Promise<string[]>;
311
320
  }