@sentry/junior-plugin-api 0.181.1 → 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 +37 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +305 -197
- package/dist/operations.d.ts +3 -0
- package/dist/resource-events.d.ts +55 -1
- package/package.json +1 -1
- package/src/code.ts +37 -0
- package/src/index.ts +1 -0
- package/src/operations.ts +3 -0
- package/src/resource-events.ts +121 -1
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
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/
|
|
36
|
+
// src/code.ts
|
|
37
37
|
import { z as z2 } from "zod";
|
|
38
|
-
var
|
|
39
|
-
var
|
|
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 =
|
|
52
|
-
content:
|
|
53
|
-
description:
|
|
54
|
-
metadata:
|
|
55
|
-
title:
|
|
56
|
-
}).strict();
|
|
57
|
-
var conversationEventPresentationSchema =
|
|
58
|
-
details:
|
|
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)
|
|
77
|
+
}).strict();
|
|
78
|
+
var conversationEventPresentationSchema = z3.object({
|
|
79
|
+
details: z3.array(conversationEventDetailSchema).max(100).optional(),
|
|
59
80
|
icon: conversationEventIconSchema.optional(),
|
|
60
|
-
preview:
|
|
61
|
-
title:
|
|
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 =
|
|
85
|
+
const identity = z3.object({
|
|
65
86
|
name: conversationEventNameSchema,
|
|
66
|
-
version:
|
|
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
|
|
90
|
-
var slackTeamIdSchema =
|
|
91
|
-
var slackConversationIdSchema =
|
|
92
|
-
var localConversationIdSchema =
|
|
93
|
-
var actorUserIdSchema =
|
|
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 =
|
|
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 =
|
|
102
|
-
var sourceVisibilitySchema =
|
|
103
|
-
var destinationVisibilitySchema =
|
|
104
|
-
var slackAddressSchema =
|
|
105
|
-
platform:
|
|
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 =
|
|
111
|
-
platform:
|
|
131
|
+
var localDestinationSchema = z4.object({
|
|
132
|
+
platform: z4.literal("local"),
|
|
112
133
|
conversationId: localConversationIdSchema
|
|
113
134
|
}).strict();
|
|
114
|
-
var destinationSchema =
|
|
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 =
|
|
124
|
-
platform:
|
|
125
|
-
visibility:
|
|
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 =
|
|
129
|
-
platform:
|
|
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 =
|
|
155
|
+
var sourceSchema = z4.discriminatedUnion("platform", [
|
|
135
156
|
slackSourceSchema,
|
|
136
157
|
localSourceSchema,
|
|
137
158
|
webSourceSchema
|
|
138
159
|
]);
|
|
139
|
-
var pluginCredentialSubjectSchema =
|
|
160
|
+
var pluginCredentialSubjectSchema = z4.discriminatedUnion(
|
|
140
161
|
"allowedWhen",
|
|
141
162
|
[
|
|
142
|
-
|
|
143
|
-
type:
|
|
163
|
+
z4.object({
|
|
164
|
+
type: z4.literal("user"),
|
|
144
165
|
userId: exactActorUserIdSchema,
|
|
145
|
-
allowedWhen:
|
|
166
|
+
allowedWhen: z4.literal("private-direct-conversation")
|
|
146
167
|
}).strict(),
|
|
147
|
-
|
|
148
|
-
type:
|
|
168
|
+
z4.object({
|
|
169
|
+
type: z4.literal("user"),
|
|
149
170
|
userId: exactActorUserIdSchema,
|
|
150
|
-
allowedWhen:
|
|
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 =
|
|
182
|
+
var slackActorSchema = z4.object({
|
|
162
183
|
...actorProfileSchema,
|
|
163
|
-
platform:
|
|
184
|
+
platform: z4.literal("slack"),
|
|
164
185
|
teamId: slackTeamIdSchema
|
|
165
186
|
}).strict();
|
|
166
|
-
var localActorSchema =
|
|
187
|
+
var localActorSchema = z4.object({
|
|
167
188
|
...actorProfileSchema,
|
|
168
|
-
platform:
|
|
189
|
+
platform: z4.literal("local")
|
|
169
190
|
}).strict();
|
|
170
|
-
var webActorSchema =
|
|
191
|
+
var webActorSchema = z4.object({
|
|
171
192
|
...actorProfileSchema,
|
|
172
|
-
platform:
|
|
193
|
+
platform: z4.literal("web")
|
|
173
194
|
}).strict();
|
|
174
|
-
var systemActorSchema =
|
|
175
|
-
platform:
|
|
195
|
+
var systemActorSchema = z4.object({
|
|
196
|
+
platform: z4.literal("system"),
|
|
176
197
|
name: exactActorUserIdSchema
|
|
177
198
|
}).strict();
|
|
178
|
-
var actorSchema =
|
|
199
|
+
var actorSchema = z4.discriminatedUnion("platform", [
|
|
179
200
|
slackActorSchema,
|
|
180
201
|
localActorSchema,
|
|
181
202
|
webActorSchema,
|
|
182
203
|
systemActorSchema
|
|
183
204
|
]);
|
|
184
|
-
var identitySchema =
|
|
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 =
|
|
213
|
+
var userSchema = z4.object({
|
|
193
214
|
displayName: nonBlankStringSchema.optional(),
|
|
194
215
|
email: nonBlankStringSchema.max(320),
|
|
195
216
|
id: exactNonBlankStringSchema,
|
|
196
|
-
identities:
|
|
217
|
+
identities: z4.array(identitySchema).max(100)
|
|
197
218
|
}).strict();
|
|
198
|
-
var dispatchMetadataSchema =
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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 =
|
|
247
|
-
label: exactNonBlankStringSchema.pipe(
|
|
248
|
-
detail: exactNonBlankStringSchema.pipe(
|
|
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 =
|
|
251
|
-
idempotencyKey: nonBlankStringSchema.pipe(
|
|
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(
|
|
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
|
|
309
|
-
var promptContextKindSchema =
|
|
310
|
-
var promptMessageSchema =
|
|
311
|
-
text:
|
|
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 =
|
|
334
|
+
var promptContextSchema = z5.object({
|
|
314
335
|
kind: promptContextKindSchema,
|
|
315
|
-
version:
|
|
316
|
-
content:
|
|
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
|
|
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 =
|
|
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,19 +372,99 @@ var resourceEventDataSchema = z5.record(z5.string(), z5.unknown()).superRefine((
|
|
|
351
372
|
});
|
|
352
373
|
}
|
|
353
374
|
});
|
|
354
|
-
var resourceEventTypeSchema =
|
|
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 =
|
|
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
|
-
var
|
|
381
|
+
var RESOURCE_EVENT_MATCH_FIELD_NAME = /^[a-z][a-zA-Z0-9]*$/;
|
|
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()
|
|
386
|
+
}).strict().superRefine((field, context) => {
|
|
387
|
+
if (field.enum && field.kind !== "string") {
|
|
388
|
+
context.addIssue({
|
|
389
|
+
code: "custom",
|
|
390
|
+
message: 'Resource event match field enum requires kind "string".',
|
|
391
|
+
path: ["enum"]
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
var resourceEventMatchFieldsSchema = z6.record(z6.string().regex(RESOURCE_EVENT_MATCH_FIELD_NAME), resourceEventMatchFieldSchema).superRefine((fields, context) => {
|
|
396
|
+
if (Object.keys(fields).length > RESOURCE_EVENT_DATA_MAX_KEYS) {
|
|
397
|
+
context.addIssue({
|
|
398
|
+
code: "custom",
|
|
399
|
+
message: `Resource event match keys may include at most ${RESOURCE_EVENT_DATA_MAX_KEYS} keys.`
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
});
|
|
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)
|
|
410
|
+
])
|
|
411
|
+
).superRefine((match, context) => {
|
|
412
|
+
if (Object.keys(match).length > RESOURCE_EVENT_DATA_MAX_KEYS) {
|
|
413
|
+
context.addIssue({
|
|
414
|
+
code: "custom",
|
|
415
|
+
message: `Resource event match may include at most ${RESOURCE_EVENT_DATA_MAX_KEYS} keys.`
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
for (const [key, value] of Object.entries(match)) {
|
|
419
|
+
if (!Array.isArray(value)) continue;
|
|
420
|
+
if (value.some((entry) => typeof entry === "boolean")) {
|
|
421
|
+
context.addIssue({
|
|
422
|
+
code: "custom",
|
|
423
|
+
message: `Resource event match field "${key}" cannot use a boolean list.`,
|
|
424
|
+
path: [key]
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
function stableMatchValue(value) {
|
|
430
|
+
if (!Array.isArray(value)) return value;
|
|
431
|
+
return [...value].sort((left, right) => {
|
|
432
|
+
if (typeof left === "number" && typeof right === "number") {
|
|
433
|
+
return left - right;
|
|
434
|
+
}
|
|
435
|
+
return String(left).localeCompare(String(right));
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
function stableResourceEventMatchKey(match) {
|
|
439
|
+
if (!match || Object.keys(match).length === 0) return "";
|
|
440
|
+
return JSON.stringify(
|
|
441
|
+
Object.fromEntries(
|
|
442
|
+
Object.entries(match).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => [key, stableMatchValue(value)])
|
|
443
|
+
)
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
function resourceEventMatches(match, data) {
|
|
447
|
+
if (!match || Object.keys(match).length === 0) return true;
|
|
448
|
+
if (!data) return false;
|
|
449
|
+
for (const [key, expected] of Object.entries(match)) {
|
|
450
|
+
const actual = data[key];
|
|
451
|
+
if (actual === void 0) return false;
|
|
452
|
+
if (Array.isArray(expected)) {
|
|
453
|
+
if (!expected.some((value) => Object.is(value, actual))) return false;
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
if (!Object.is(expected, actual)) return false;
|
|
457
|
+
}
|
|
458
|
+
return true;
|
|
459
|
+
}
|
|
460
|
+
var pluginResourceEventTypeSchema = z6.object({
|
|
361
461
|
type: resourceTypeSchema,
|
|
362
|
-
supportedEvents:
|
|
363
|
-
suggestedEvents:
|
|
364
|
-
|
|
462
|
+
supportedEvents: z6.array(resourceEventTypeSchema).min(1),
|
|
463
|
+
suggestedEvents: z6.array(resourceEventTypeSchema).optional(),
|
|
464
|
+
matchFields: resourceEventMatchFieldsSchema.optional(),
|
|
465
|
+
guidance: z6.record(
|
|
365
466
|
resourceEventTypeSchema,
|
|
366
|
-
|
|
467
|
+
z6.string().trim().min(1).max(RESOURCE_EVENT_GUIDANCE_MAX_LENGTH)
|
|
367
468
|
).optional()
|
|
368
469
|
}).strict().superRefine((resourceType, context) => {
|
|
369
470
|
const supported = /* @__PURE__ */ new Set();
|
|
@@ -405,10 +506,10 @@ var pluginResourceEventTypeSchema = z5.object({
|
|
|
405
506
|
suggested.add(eventType);
|
|
406
507
|
});
|
|
407
508
|
});
|
|
408
|
-
var pluginResourceEventsSchema =
|
|
409
|
-
resourceTypes:
|
|
410
|
-
isEnabled:
|
|
411
|
-
normalizeIdentifier:
|
|
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()
|
|
412
513
|
}).strict().superRefine((registration, context) => {
|
|
413
514
|
const seen = /* @__PURE__ */ new Set();
|
|
414
515
|
registration.resourceTypes.forEach((resourceType, index) => {
|
|
@@ -430,62 +531,62 @@ function normalizeResourceEventIdentifier(registration, identifier) {
|
|
|
430
531
|
}
|
|
431
532
|
return normalized;
|
|
432
533
|
}
|
|
433
|
-
var subscribableResourceSchema =
|
|
434
|
-
identifier:
|
|
435
|
-
label:
|
|
436
|
-
namespace:
|
|
437
|
-
suggestedEvents:
|
|
438
|
-
supportedEvents:
|
|
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),
|
|
439
540
|
type: resourceTypeSchema
|
|
440
541
|
}).strict();
|
|
441
|
-
var resourceEventSubscriptionResultSchema =
|
|
442
|
-
events:
|
|
443
|
-
id:
|
|
542
|
+
var resourceEventSubscriptionResultSchema = z6.object({
|
|
543
|
+
events: z6.array(resourceEventTypeSchema).min(1),
|
|
544
|
+
id: z6.string().min(1)
|
|
444
545
|
}).strict();
|
|
445
|
-
var resourceEventInputSchema =
|
|
446
|
-
eventKey:
|
|
546
|
+
var resourceEventInputSchema = z6.object({
|
|
547
|
+
eventKey: z6.string().min(1),
|
|
447
548
|
eventType: resourceEventTypeSchema,
|
|
448
|
-
identifier:
|
|
449
|
-
occurredAtMs:
|
|
450
|
-
terminal:
|
|
451
|
-
trustedSummary:
|
|
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)),
|
|
452
553
|
/** Trusted structured facts. Prefer ids and urls over long prose. */
|
|
453
554
|
data: resourceEventDataSchema.optional(),
|
|
454
|
-
untrustedText:
|
|
555
|
+
untrustedText: z6.string().transform((value) => value.slice(0, RESOURCE_EVENT_TEXT_MAX_LENGTH)).optional()
|
|
455
556
|
}).strict();
|
|
456
557
|
var resourceEventSchema = resourceEventInputSchema.extend({
|
|
457
|
-
namespace:
|
|
558
|
+
namespace: z6.string().min(1)
|
|
458
559
|
});
|
|
459
560
|
|
|
460
561
|
// src/tasks.ts
|
|
461
|
-
import { z as
|
|
462
|
-
var pluginRunTranscriptProvenanceSchema =
|
|
463
|
-
authority:
|
|
562
|
+
import { z as z7 } from "zod";
|
|
563
|
+
var pluginRunTranscriptProvenanceSchema = z7.object({
|
|
564
|
+
authority: z7.enum(["instruction", "context"]),
|
|
464
565
|
actor: actorSchema.optional()
|
|
465
566
|
}).strict();
|
|
466
|
-
var pluginRunTranscriptEntrySchema =
|
|
467
|
-
|
|
468
|
-
type:
|
|
469
|
-
role:
|
|
470
|
-
text:
|
|
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),
|
|
471
572
|
provenance: pluginRunTranscriptProvenanceSchema.optional(),
|
|
472
|
-
isRunActor:
|
|
573
|
+
isRunActor: z7.boolean().optional()
|
|
473
574
|
}).strict(),
|
|
474
|
-
|
|
475
|
-
type:
|
|
476
|
-
toolName:
|
|
477
|
-
isError:
|
|
478
|
-
text:
|
|
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()
|
|
479
580
|
}).strict()
|
|
480
581
|
]);
|
|
481
|
-
var pluginRunContextSchema =
|
|
582
|
+
var pluginRunContextSchema = z7.object({
|
|
482
583
|
/** User linked to the Actor, when known. */
|
|
483
|
-
actorUserId:
|
|
484
|
-
completedAtMs:
|
|
485
|
-
conversationId:
|
|
584
|
+
actorUserId: z7.string().min(1).optional(),
|
|
585
|
+
completedAtMs: z7.number().finite(),
|
|
586
|
+
conversationId: z7.string().min(1),
|
|
486
587
|
destination: destinationSchema,
|
|
487
588
|
/** Location associated with this Conversation. */
|
|
488
|
-
locationId:
|
|
589
|
+
locationId: z7.string().min(1).optional(),
|
|
489
590
|
/**
|
|
490
591
|
* All distinct actors annotated on this run's committed instruction-authority
|
|
491
592
|
* messages, in first-seen order. Attribution provenance only, never an
|
|
@@ -494,43 +595,43 @@ var pluginRunContextSchema = z6.object({
|
|
|
494
595
|
* exceed the actors visible in the transcript slice. Usually `[run.actor]`;
|
|
495
596
|
* possibly empty for system runs with no human instructions.
|
|
496
597
|
*/
|
|
497
|
-
actors:
|
|
598
|
+
actors: z7.array(actorSchema),
|
|
498
599
|
/**
|
|
499
600
|
* The single actor this run executes as. Absent only for actor-less legacy
|
|
500
601
|
* system records, so authority-sensitive plugins must fail closed.
|
|
501
602
|
*/
|
|
502
603
|
actor: actorSchema.optional(),
|
|
503
|
-
runId:
|
|
604
|
+
runId: z7.string().min(1),
|
|
504
605
|
source: sourceSchema,
|
|
505
|
-
transcript:
|
|
606
|
+
transcript: z7.array(pluginRunTranscriptEntrySchema)
|
|
506
607
|
}).strict();
|
|
507
608
|
|
|
508
609
|
// src/tools.ts
|
|
509
|
-
import { z as
|
|
610
|
+
import { z as z8 } from "zod";
|
|
510
611
|
var PluginToolInputError = class extends Error {
|
|
511
612
|
constructor(message, options) {
|
|
512
613
|
super(message, options);
|
|
513
614
|
this.name = "PluginToolInputError";
|
|
514
615
|
}
|
|
515
616
|
};
|
|
516
|
-
var pluginToolContentSchema =
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
type:
|
|
520
|
-
data:
|
|
521
|
-
mimeType:
|
|
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()
|
|
522
623
|
}).strict()
|
|
523
624
|
]);
|
|
524
|
-
var pluginToolContinuationSchema =
|
|
525
|
-
arguments:
|
|
526
|
-
reason:
|
|
625
|
+
var pluginToolContinuationSchema = z8.object({
|
|
626
|
+
arguments: z8.record(z8.string(), z8.unknown()),
|
|
627
|
+
reason: z8.string().min(1).optional()
|
|
527
628
|
}).strict();
|
|
528
|
-
var pluginToolOutputSchema =
|
|
529
|
-
target:
|
|
530
|
-
truncated:
|
|
629
|
+
var pluginToolOutputSchema = z8.object({
|
|
630
|
+
target: z8.string().min(1).optional(),
|
|
631
|
+
truncated: z8.boolean().optional(),
|
|
531
632
|
continuation: pluginToolContinuationSchema.optional()
|
|
532
633
|
}).passthrough();
|
|
533
|
-
var toolApprovalModeSchema =
|
|
634
|
+
var toolApprovalModeSchema = z8.enum(["auto", "review", "approve"]);
|
|
534
635
|
var REQUIRED_TOOL_ANNOTATION_KEYS = [
|
|
535
636
|
"destructiveHint",
|
|
536
637
|
"idempotentHint",
|
|
@@ -566,7 +667,7 @@ function createZodTool(definition, helperName) {
|
|
|
566
667
|
let modelInputSchema;
|
|
567
668
|
let modelOutputSchema;
|
|
568
669
|
try {
|
|
569
|
-
modelInputSchema =
|
|
670
|
+
modelInputSchema = z8.toJSONSchema(inputSchema);
|
|
570
671
|
} catch (error) {
|
|
571
672
|
throw new TypeError(
|
|
572
673
|
`${helperName}() inputSchema must be representable as JSON Schema.`,
|
|
@@ -574,7 +675,7 @@ function createZodTool(definition, helperName) {
|
|
|
574
675
|
);
|
|
575
676
|
}
|
|
576
677
|
try {
|
|
577
|
-
modelOutputSchema =
|
|
678
|
+
modelOutputSchema = z8.toJSONSchema(outputSchema);
|
|
578
679
|
} catch (error) {
|
|
579
680
|
throw new TypeError(
|
|
580
681
|
`${helperName}() outputSchema must be representable as JSON Schema.`,
|
|
@@ -600,7 +701,7 @@ function createZodTool(definition, helperName) {
|
|
|
600
701
|
);
|
|
601
702
|
if (isPluginToolOutputEnvelope(result)) {
|
|
602
703
|
return {
|
|
603
|
-
content:
|
|
704
|
+
content: z8.array(pluginToolContentSchema).parse(result.content),
|
|
604
705
|
details: outputSchema.parse(result.details)
|
|
605
706
|
};
|
|
606
707
|
}
|
|
@@ -617,76 +718,76 @@ function definePluginTool(definition) {
|
|
|
617
718
|
}
|
|
618
719
|
|
|
619
720
|
// src/operations.ts
|
|
620
|
-
import { z as
|
|
621
|
-
var pluginApiRouteRequestContextSchema =
|
|
622
|
-
auth:
|
|
623
|
-
user:
|
|
624
|
-
email:
|
|
625
|
-
emailVerified:
|
|
626
|
-
name:
|
|
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()
|
|
627
728
|
}).strict()
|
|
628
729
|
}).strict(),
|
|
629
730
|
pluginName: nonBlankStringSchema
|
|
630
731
|
}).strict();
|
|
631
732
|
|
|
632
733
|
// src/credentials.ts
|
|
633
|
-
import { z as
|
|
634
|
-
var pluginProviderNameSchema =
|
|
635
|
-
var pluginGrantNameSchema =
|
|
636
|
-
var pluginGrantAccessSchema =
|
|
637
|
-
|
|
638
|
-
|
|
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")
|
|
639
740
|
]);
|
|
640
|
-
var pluginAuthorizationSchema =
|
|
741
|
+
var pluginAuthorizationSchema = z10.object({
|
|
641
742
|
provider: pluginProviderNameSchema,
|
|
642
743
|
scope: nonBlankStringSchema.optional(),
|
|
643
|
-
type:
|
|
744
|
+
type: z10.literal("oauth")
|
|
644
745
|
}).strict();
|
|
645
|
-
var pluginProviderAccountSchema =
|
|
746
|
+
var pluginProviderAccountSchema = z10.object({
|
|
646
747
|
displayName: nonBlankStringSchema.optional(),
|
|
647
748
|
handle: nonBlankStringSchema.optional(),
|
|
648
749
|
id: nonBlankStringSchema,
|
|
649
750
|
label: nonBlankStringSchema.optional(),
|
|
650
751
|
url: nonBlankStringSchema.optional()
|
|
651
752
|
}).strict();
|
|
652
|
-
var pluginStoredTokensSchema =
|
|
753
|
+
var pluginStoredTokensSchema = z10.object({
|
|
653
754
|
account: pluginProviderAccountSchema.optional(),
|
|
654
755
|
accessToken: nonBlankStringSchema,
|
|
655
|
-
expiresAt:
|
|
756
|
+
expiresAt: z10.number().finite().optional(),
|
|
656
757
|
refreshToken: nonBlankStringSchema,
|
|
657
|
-
refreshTokenExpiresAt:
|
|
758
|
+
refreshTokenExpiresAt: z10.number().finite().optional(),
|
|
658
759
|
scope: nonBlankStringSchema.optional()
|
|
659
760
|
}).strict();
|
|
660
|
-
var pluginGrantSchema =
|
|
761
|
+
var pluginGrantSchema = z10.object({
|
|
661
762
|
access: pluginGrantAccessSchema,
|
|
662
763
|
leaseScope: nonBlankStringSchema.optional(),
|
|
663
764
|
name: pluginGrantNameSchema,
|
|
664
765
|
reason: nonBlankStringSchema.optional(),
|
|
665
|
-
requirements:
|
|
766
|
+
requirements: z10.array(nonBlankStringSchema).min(1).optional()
|
|
666
767
|
}).strict();
|
|
667
|
-
var pluginCredentialHeaderTransformSchema =
|
|
668
|
-
domain:
|
|
669
|
-
headers:
|
|
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)
|
|
670
771
|
}).strict();
|
|
671
|
-
var pluginCredentialLeaseSchema =
|
|
772
|
+
var pluginCredentialLeaseSchema = z10.object({
|
|
672
773
|
account: pluginProviderAccountSchema.optional(),
|
|
673
774
|
authorization: pluginAuthorizationSchema.optional(),
|
|
674
|
-
expiresAt:
|
|
675
|
-
headerTransforms:
|
|
775
|
+
expiresAt: z10.string().refine((value) => Number.isFinite(Date.parse(value))),
|
|
776
|
+
headerTransforms: z10.array(pluginCredentialHeaderTransformSchema).min(1)
|
|
676
777
|
}).strict();
|
|
677
|
-
var pluginCredentialResultSchema =
|
|
678
|
-
|
|
778
|
+
var pluginCredentialResultSchema = z10.discriminatedUnion("type", [
|
|
779
|
+
z10.object({
|
|
679
780
|
lease: pluginCredentialLeaseSchema,
|
|
680
|
-
type:
|
|
781
|
+
type: z10.literal("lease")
|
|
681
782
|
}).strict(),
|
|
682
|
-
|
|
783
|
+
z10.object({
|
|
683
784
|
authorization: pluginAuthorizationSchema.optional(),
|
|
684
785
|
message: nonBlankStringSchema,
|
|
685
|
-
type:
|
|
786
|
+
type: z10.literal("needed")
|
|
686
787
|
}).strict(),
|
|
687
|
-
|
|
788
|
+
z10.object({
|
|
688
789
|
message: nonBlankStringSchema,
|
|
689
|
-
type:
|
|
790
|
+
type: z10.literal("unavailable")
|
|
690
791
|
}).strict()
|
|
691
792
|
]);
|
|
692
793
|
var EgressAuthRequired = class extends Error {
|
|
@@ -822,44 +923,44 @@ function defineJuniorPlugin(plugin) {
|
|
|
822
923
|
}
|
|
823
924
|
|
|
824
925
|
// src/user-pages.ts
|
|
825
|
-
import { z as
|
|
926
|
+
import { z as z11 } from "zod";
|
|
826
927
|
var userPageIdSchema = nonBlankStringSchema.max(64).regex(/^[a-z][a-z0-9-]*$/);
|
|
827
928
|
var userPageLabelSchema = nonBlankStringSchema.max(80);
|
|
828
929
|
var userPageDescriptionSchema = nonBlankStringSchema.max(500);
|
|
829
|
-
var userPageNavigationSchema =
|
|
830
|
-
var pluginUserPageMetricSchema =
|
|
930
|
+
var userPageNavigationSchema = z11.enum(["primary", "profile"]);
|
|
931
|
+
var pluginUserPageMetricSchema = z11.object({
|
|
831
932
|
detail: nonBlankStringSchema.max(500).optional(),
|
|
832
933
|
label: nonBlankStringSchema.max(80),
|
|
833
|
-
tone:
|
|
934
|
+
tone: z11.enum(["good", "neutral", "warning"]).optional(),
|
|
834
935
|
value: nonBlankStringSchema.max(120)
|
|
835
936
|
}).strict();
|
|
836
|
-
var pluginUserPageMetadataSchema =
|
|
937
|
+
var pluginUserPageMetadataSchema = z11.object({
|
|
837
938
|
label: nonBlankStringSchema.max(80),
|
|
838
939
|
value: nonBlankStringSchema.max(500)
|
|
839
940
|
}).strict();
|
|
840
|
-
var pluginUserPageActionSchema =
|
|
941
|
+
var pluginUserPageActionSchema = z11.object({
|
|
841
942
|
confirmation: nonBlankStringSchema.max(500).optional(),
|
|
842
943
|
href: nonBlankStringSchema.max(500).regex(/^\/api\/plugins\/[a-z][a-z0-9-]*(?:\/|$)/),
|
|
843
944
|
label: nonBlankStringSchema.max(80),
|
|
844
|
-
method:
|
|
845
|
-
tone:
|
|
945
|
+
method: z11.literal("DELETE"),
|
|
946
|
+
tone: z11.enum(["danger", "neutral"]).optional()
|
|
846
947
|
}).strict();
|
|
847
|
-
var pluginUserPageRecordSchema =
|
|
848
|
-
actions:
|
|
948
|
+
var pluginUserPageRecordSchema = z11.object({
|
|
949
|
+
actions: z11.array(pluginUserPageActionSchema).max(4).optional(),
|
|
849
950
|
description: nonBlankStringSchema.max(1e3).optional(),
|
|
850
951
|
id: nonBlankStringSchema.max(128),
|
|
851
|
-
metadata:
|
|
952
|
+
metadata: z11.array(pluginUserPageMetadataSchema).max(8).optional(),
|
|
852
953
|
title: nonBlankStringSchema.max(4e3)
|
|
853
954
|
}).strict();
|
|
854
|
-
var pluginUserPageContentSchema =
|
|
955
|
+
var pluginUserPageContentSchema = z11.object({
|
|
855
956
|
emptyText: nonBlankStringSchema.max(500).optional(),
|
|
856
|
-
metrics:
|
|
957
|
+
metrics: z11.array(pluginUserPageMetricSchema).max(6).optional(),
|
|
857
958
|
nextCursor: nonBlankStringSchema.max(1e3).optional(),
|
|
858
|
-
records:
|
|
959
|
+
records: z11.array(pluginUserPageRecordSchema).max(100),
|
|
859
960
|
searchPlaceholder: nonBlankStringSchema.max(120).optional(),
|
|
860
|
-
type:
|
|
961
|
+
type: z11.literal("list")
|
|
861
962
|
}).strict();
|
|
862
|
-
var pluginUserPageLinkSchema =
|
|
963
|
+
var pluginUserPageLinkSchema = z11.object({
|
|
863
964
|
description: userPageDescriptionSchema,
|
|
864
965
|
id: userPageIdSchema,
|
|
865
966
|
label: userPageLabelSchema,
|
|
@@ -867,14 +968,14 @@ var pluginUserPageLinkSchema = z10.object({
|
|
|
867
968
|
pluginDisplayName: nonBlankStringSchema.max(200),
|
|
868
969
|
pluginName: nonBlankStringSchema.max(100)
|
|
869
970
|
}).strict();
|
|
870
|
-
var pluginUserPageLinksSchema =
|
|
971
|
+
var pluginUserPageLinksSchema = z11.array(pluginUserPageLinkSchema);
|
|
871
972
|
var pluginUserPageCursorSchema = nonBlankStringSchema.max(1e3).optional();
|
|
872
973
|
var pluginUserPageFilterSchema = nonBlankStringSchema.max(64).optional();
|
|
873
|
-
var pluginUserPageQuerySchema =
|
|
874
|
-
var pluginUserPageInputSchema =
|
|
974
|
+
var pluginUserPageQuerySchema = z11.string().trim().max(200).optional();
|
|
975
|
+
var pluginUserPageInputSchema = z11.object({
|
|
875
976
|
cursor: pluginUserPageCursorSchema,
|
|
876
977
|
filter: pluginUserPageFilterSchema,
|
|
877
|
-
limit:
|
|
978
|
+
limit: z11.number().int().min(1).max(50),
|
|
878
979
|
query: pluginUserPageQuerySchema
|
|
879
980
|
}).strict();
|
|
880
981
|
export {
|
|
@@ -889,6 +990,8 @@ export {
|
|
|
889
990
|
RESOURCE_EVENT_TEXT_MAX_LENGTH,
|
|
890
991
|
actorSchema,
|
|
891
992
|
actorUserIdSchema,
|
|
993
|
+
codeChangeInputSchema,
|
|
994
|
+
codeChangeStateSchema,
|
|
892
995
|
conversationAnnotationInputSchema,
|
|
893
996
|
conversationEventIconSchema,
|
|
894
997
|
conversationEventPresentationSchema,
|
|
@@ -945,6 +1048,10 @@ export {
|
|
|
945
1048
|
replyAttributionSchema,
|
|
946
1049
|
resourceEventDataSchema,
|
|
947
1050
|
resourceEventInputSchema,
|
|
1051
|
+
resourceEventMatchFieldSchema,
|
|
1052
|
+
resourceEventMatchFieldsSchema,
|
|
1053
|
+
resourceEventMatchSchema,
|
|
1054
|
+
resourceEventMatches,
|
|
948
1055
|
resourceEventSchema,
|
|
949
1056
|
resourceEventSubscriptionResultSchema,
|
|
950
1057
|
resourceEventTypeSchema,
|
|
@@ -955,6 +1062,7 @@ export {
|
|
|
955
1062
|
slackSourceSchema,
|
|
956
1063
|
sourceSchema,
|
|
957
1064
|
sourceVisibilitySchema,
|
|
1065
|
+
stableResourceEventMatchKey,
|
|
958
1066
|
subscribableResourceSchema,
|
|
959
1067
|
systemActorSchema,
|
|
960
1068
|
toolApprovalModeSchema,
|
package/dist/operations.d.ts
CHANGED
|
@@ -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
|
}
|
|
@@ -4,15 +4,51 @@ export declare const RESOURCE_EVENT_TEXT_MAX_LENGTH = 8000;
|
|
|
4
4
|
export declare const RESOURCE_EVENT_DATA_MAX_KEYS = 32;
|
|
5
5
|
export declare const RESOURCE_EVENT_DATA_MAX_JSON_BYTES = 4000;
|
|
6
6
|
export declare const RESOURCE_EVENT_GUIDANCE_MAX_LENGTH = 1000;
|
|
7
|
-
/** Small trusted
|
|
7
|
+
/** Small trusted data from the plugin. The agent should not look these up again. */
|
|
8
8
|
export declare const resourceEventDataSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
9
9
|
/** Canonical dotted event type published and selected across plugins. */
|
|
10
10
|
export declare const resourceEventTypeSchema: z.ZodString;
|
|
11
11
|
export declare const resourceTypeSchema: z.ZodString;
|
|
12
|
+
/** One exact value a watch or event task may require on trusted event data. */
|
|
13
|
+
export declare const resourceEventMatchFieldSchema: z.ZodObject<{
|
|
14
|
+
kind: z.ZodEnum<{
|
|
15
|
+
string: "string";
|
|
16
|
+
number: "number";
|
|
17
|
+
boolean: "boolean";
|
|
18
|
+
}>;
|
|
19
|
+
description: z.ZodString;
|
|
20
|
+
enum: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
21
|
+
}, z.core.$strict>;
|
|
22
|
+
export declare const resourceEventMatchFieldsSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
23
|
+
kind: z.ZodEnum<{
|
|
24
|
+
string: "string";
|
|
25
|
+
number: "number";
|
|
26
|
+
boolean: "boolean";
|
|
27
|
+
}>;
|
|
28
|
+
description: z.ZodString;
|
|
29
|
+
enum: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
30
|
+
}, z.core.$strict>>;
|
|
31
|
+
/** Exact trusted values required before a watch or event task runs. */
|
|
32
|
+
export declare const resourceEventMatchSchema: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodString, z.ZodArray<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>]>>;
|
|
33
|
+
export type ResourceEventMatch = z.output<typeof resourceEventMatchSchema>;
|
|
34
|
+
export type ResourceEventMatchFields = z.output<typeof resourceEventMatchFieldsSchema>;
|
|
35
|
+
/** Stable JSON for one match object. List order does not matter. */
|
|
36
|
+
export declare function stableResourceEventMatchKey(match: ResourceEventMatch | undefined): string;
|
|
37
|
+
/** Return whether trusted event data matches one exact match object. */
|
|
38
|
+
export declare function resourceEventMatches(match: ResourceEventMatch | undefined, data: ResourceEventData | undefined): boolean;
|
|
12
39
|
export declare const pluginResourceEventTypeSchema: z.ZodObject<{
|
|
13
40
|
type: z.ZodString;
|
|
14
41
|
supportedEvents: z.ZodArray<z.ZodString>;
|
|
15
42
|
suggestedEvents: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
43
|
+
matchFields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
44
|
+
kind: z.ZodEnum<{
|
|
45
|
+
string: "string";
|
|
46
|
+
number: "number";
|
|
47
|
+
boolean: "boolean";
|
|
48
|
+
}>;
|
|
49
|
+
description: z.ZodString;
|
|
50
|
+
enum: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
51
|
+
}, z.core.$strict>>>;
|
|
16
52
|
guidance: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
17
53
|
}, z.core.$strict>;
|
|
18
54
|
export declare const pluginResourceEventsSchema: z.ZodObject<{
|
|
@@ -20,6 +56,15 @@ export declare const pluginResourceEventsSchema: z.ZodObject<{
|
|
|
20
56
|
type: z.ZodString;
|
|
21
57
|
supportedEvents: z.ZodArray<z.ZodString>;
|
|
22
58
|
suggestedEvents: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
59
|
+
matchFields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
60
|
+
kind: z.ZodEnum<{
|
|
61
|
+
string: "string";
|
|
62
|
+
number: "number";
|
|
63
|
+
boolean: "boolean";
|
|
64
|
+
}>;
|
|
65
|
+
description: z.ZodString;
|
|
66
|
+
enum: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
67
|
+
}, z.core.$strict>>>;
|
|
23
68
|
guidance: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
24
69
|
}, z.core.$strict>>;
|
|
25
70
|
isEnabled: z.ZodOptional<z.ZodFunction<z.ZodTuple<readonly [], null>, z.ZodBoolean>>;
|
|
@@ -71,4 +116,13 @@ export type ResourceEvent = z.output<typeof resourceEventSchema>;
|
|
|
71
116
|
export interface ResourceEventPublisher {
|
|
72
117
|
/** Publish one normalized event under the owning plugin's namespace. */
|
|
73
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[]>;
|
|
74
128
|
}
|
package/package.json
CHANGED
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
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
|
}
|
package/src/resource-events.ts
CHANGED
|
@@ -6,7 +6,7 @@ export const RESOURCE_EVENT_DATA_MAX_KEYS = 32;
|
|
|
6
6
|
export const RESOURCE_EVENT_DATA_MAX_JSON_BYTES = 4_000;
|
|
7
7
|
export const RESOURCE_EVENT_GUIDANCE_MAX_LENGTH = 1_000;
|
|
8
8
|
|
|
9
|
-
/** Small trusted
|
|
9
|
+
/** Small trusted data from the plugin. The agent should not look these up again. */
|
|
10
10
|
export const resourceEventDataSchema = z
|
|
11
11
|
.record(z.string(), z.unknown())
|
|
12
12
|
.superRefine((value, context) => {
|
|
@@ -43,11 +43,122 @@ export const resourceTypeSchema = z
|
|
|
43
43
|
"Canonical plugin-defined resource type, such as issue or pull_request.",
|
|
44
44
|
);
|
|
45
45
|
|
|
46
|
+
const RESOURCE_EVENT_MATCH_FIELD_NAME =
|
|
47
|
+
/^[a-z][a-zA-Z0-9]*$/;
|
|
48
|
+
|
|
49
|
+
/** One exact value a watch or event task may require on trusted event data. */
|
|
50
|
+
export const resourceEventMatchFieldSchema = z
|
|
51
|
+
.object({
|
|
52
|
+
kind: z.enum(["boolean", "string", "number"]),
|
|
53
|
+
description: z.string().trim().min(1).max(200),
|
|
54
|
+
enum: z.array(z.string().min(1)).min(1).optional(),
|
|
55
|
+
})
|
|
56
|
+
.strict()
|
|
57
|
+
.superRefine((field, context) => {
|
|
58
|
+
if (field.enum && field.kind !== "string") {
|
|
59
|
+
context.addIssue({
|
|
60
|
+
code: "custom",
|
|
61
|
+
message: 'Resource event match field enum requires kind "string".',
|
|
62
|
+
path: ["enum"],
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
export const resourceEventMatchFieldsSchema = z
|
|
68
|
+
.record(z.string().regex(RESOURCE_EVENT_MATCH_FIELD_NAME), resourceEventMatchFieldSchema)
|
|
69
|
+
.superRefine((fields, context) => {
|
|
70
|
+
if (Object.keys(fields).length > RESOURCE_EVENT_DATA_MAX_KEYS) {
|
|
71
|
+
context.addIssue({
|
|
72
|
+
code: "custom",
|
|
73
|
+
message: `Resource event match keys may include at most ${RESOURCE_EVENT_DATA_MAX_KEYS} keys.`,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
/** Exact trusted values required before a watch or event task runs. */
|
|
79
|
+
export const resourceEventMatchSchema = z
|
|
80
|
+
.record(
|
|
81
|
+
z.string().regex(RESOURCE_EVENT_MATCH_FIELD_NAME),
|
|
82
|
+
z.union([
|
|
83
|
+
z.boolean(),
|
|
84
|
+
z.number().finite(),
|
|
85
|
+
z.string().min(1),
|
|
86
|
+
z.array(z.union([z.number().finite(), z.string().min(1)])).min(1),
|
|
87
|
+
]),
|
|
88
|
+
)
|
|
89
|
+
.superRefine((match, context) => {
|
|
90
|
+
if (Object.keys(match).length > RESOURCE_EVENT_DATA_MAX_KEYS) {
|
|
91
|
+
context.addIssue({
|
|
92
|
+
code: "custom",
|
|
93
|
+
message: `Resource event match may include at most ${RESOURCE_EVENT_DATA_MAX_KEYS} keys.`,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
for (const [key, value] of Object.entries(match)) {
|
|
97
|
+
if (!Array.isArray(value)) continue;
|
|
98
|
+
if (value.some((entry) => typeof entry === "boolean")) {
|
|
99
|
+
context.addIssue({
|
|
100
|
+
code: "custom",
|
|
101
|
+
message: `Resource event match field "${key}" cannot use a boolean list.`,
|
|
102
|
+
path: [key],
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
export type ResourceEventMatch = z.output<typeof resourceEventMatchSchema>;
|
|
109
|
+
export type ResourceEventMatchFields = z.output<
|
|
110
|
+
typeof resourceEventMatchFieldsSchema
|
|
111
|
+
>;
|
|
112
|
+
|
|
113
|
+
function stableMatchValue(value: ResourceEventMatch[string]): unknown {
|
|
114
|
+
if (!Array.isArray(value)) return value;
|
|
115
|
+
return [...value].sort((left, right) => {
|
|
116
|
+
if (typeof left === "number" && typeof right === "number") {
|
|
117
|
+
return left - right;
|
|
118
|
+
}
|
|
119
|
+
return String(left).localeCompare(String(right));
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Stable JSON for one match object. List order does not matter. */
|
|
124
|
+
export function stableResourceEventMatchKey(
|
|
125
|
+
match: ResourceEventMatch | undefined,
|
|
126
|
+
): string {
|
|
127
|
+
if (!match || Object.keys(match).length === 0) return "";
|
|
128
|
+
return JSON.stringify(
|
|
129
|
+
Object.fromEntries(
|
|
130
|
+
Object.entries(match)
|
|
131
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
132
|
+
.map(([key, value]) => [key, stableMatchValue(value)]),
|
|
133
|
+
),
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Return whether trusted event data matches one exact match object. */
|
|
138
|
+
export function resourceEventMatches(
|
|
139
|
+
match: ResourceEventMatch | undefined,
|
|
140
|
+
data: ResourceEventData | undefined,
|
|
141
|
+
): boolean {
|
|
142
|
+
if (!match || Object.keys(match).length === 0) return true;
|
|
143
|
+
if (!data) return false;
|
|
144
|
+
for (const [key, expected] of Object.entries(match)) {
|
|
145
|
+
const actual = data[key];
|
|
146
|
+
if (actual === undefined) return false;
|
|
147
|
+
if (Array.isArray(expected)) {
|
|
148
|
+
if (!expected.some((value) => Object.is(value, actual))) return false;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (!Object.is(expected, actual)) return false;
|
|
152
|
+
}
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
|
|
46
156
|
export const pluginResourceEventTypeSchema = z
|
|
47
157
|
.object({
|
|
48
158
|
type: resourceTypeSchema,
|
|
49
159
|
supportedEvents: z.array(resourceEventTypeSchema).min(1),
|
|
50
160
|
suggestedEvents: z.array(resourceEventTypeSchema).optional(),
|
|
161
|
+
matchFields: resourceEventMatchFieldsSchema.optional(),
|
|
51
162
|
guidance: z
|
|
52
163
|
.record(
|
|
53
164
|
resourceEventTypeSchema,
|
|
@@ -197,4 +308,13 @@ export type ResourceEvent = z.output<typeof resourceEventSchema>;
|
|
|
197
308
|
export interface ResourceEventPublisher {
|
|
198
309
|
/** Publish one normalized event under the owning plugin's namespace. */
|
|
199
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[]>;
|
|
200
320
|
}
|