@sentry/junior-plugin-api 0.114.0 → 0.116.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/annotations.d.ts +44 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +159 -133
- package/dist/manifest.d.ts +0 -1
- package/dist/operations.d.ts +2 -0
- package/dist/tools.d.ts +54 -3
- package/package.json +1 -1
- package/src/annotations.ts +46 -0
- package/src/index.ts +1 -0
- package/src/manifest.ts +0 -1
- package/src/operations.ts +2 -0
- package/src/tools.ts +57 -3
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const resourceLinkAnnotationSchema: z.ZodObject<{
|
|
3
|
+
kind: z.ZodLiteral<"resource_link">;
|
|
4
|
+
key: z.ZodString;
|
|
5
|
+
label: z.ZodString;
|
|
6
|
+
url: z.ZodString;
|
|
7
|
+
description: z.ZodOptional<z.ZodString>;
|
|
8
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
9
|
+
open: "open";
|
|
10
|
+
draft: "draft";
|
|
11
|
+
closed: "closed";
|
|
12
|
+
merged: "merged";
|
|
13
|
+
warning: "warning";
|
|
14
|
+
}>>;
|
|
15
|
+
}, z.core.$strict>;
|
|
16
|
+
/** Core-known annotation shapes that plugins may attach to a conversation. */
|
|
17
|
+
export declare const conversationAnnotationInputSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
18
|
+
kind: z.ZodLiteral<"resource_link">;
|
|
19
|
+
key: z.ZodString;
|
|
20
|
+
label: z.ZodString;
|
|
21
|
+
url: z.ZodString;
|
|
22
|
+
description: z.ZodOptional<z.ZodString>;
|
|
23
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
24
|
+
open: "open";
|
|
25
|
+
draft: "draft";
|
|
26
|
+
closed: "closed";
|
|
27
|
+
merged: "merged";
|
|
28
|
+
warning: "warning";
|
|
29
|
+
}>>;
|
|
30
|
+
}, z.core.$strict>], "kind">;
|
|
31
|
+
export type ConversationAnnotationInput = z.output<typeof conversationAnnotationInputSchema>;
|
|
32
|
+
export type ConversationAnnotation = ConversationAnnotationInput & {
|
|
33
|
+
plugin: string;
|
|
34
|
+
createdAt: string;
|
|
35
|
+
updatedAt: string;
|
|
36
|
+
};
|
|
37
|
+
export interface PluginAnnotations {
|
|
38
|
+
upsert(annotation: ConversationAnnotationInput): Promise<void>;
|
|
39
|
+
remove(kind: ConversationAnnotationInput["kind"], key: string): Promise<void>;
|
|
40
|
+
list(): Promise<ConversationAnnotation[]>;
|
|
41
|
+
}
|
|
42
|
+
export interface PluginConversationAnnotations {
|
|
43
|
+
forConversation(conversationId: string): PluginAnnotations;
|
|
44
|
+
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,29 +1,51 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/annotations.ts
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
function usesHttpProtocol(value) {
|
|
4
|
+
try {
|
|
5
|
+
const protocol = new URL(value).protocol;
|
|
6
|
+
return protocol === "http:" || protocol === "https:";
|
|
7
|
+
} catch {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
var resourceLinkAnnotationSchema = z.object({
|
|
12
|
+
kind: z.literal("resource_link"),
|
|
13
|
+
key: z.string().trim().min(1).max(256),
|
|
14
|
+
label: z.string().trim().min(1).max(256),
|
|
15
|
+
url: z.string().url().max(2048).refine(usesHttpProtocol, "URL must use HTTP or HTTPS."),
|
|
16
|
+
description: z.string().trim().min(1).max(512).optional(),
|
|
17
|
+
status: z.enum(["open", "draft", "closed", "merged", "warning"]).optional()
|
|
18
|
+
}).strict();
|
|
19
|
+
var conversationAnnotationInputSchema = z.discriminatedUnion("kind", [
|
|
20
|
+
resourceLinkAnnotationSchema
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
// src/schemas.ts
|
|
24
|
+
import { z as z2 } from "zod";
|
|
25
|
+
var slackTeamIdSchema = z2.string().regex(/^T[A-Z0-9]+$/);
|
|
26
|
+
var slackConversationIdSchema = z2.string().regex(/^(C|G|D)[A-Z0-9]+$/);
|
|
27
|
+
var localConversationIdSchema = z2.string().regex(/^local:[a-z0-9_-]+:[a-z0-9][a-z0-9_-]*$/);
|
|
28
|
+
var exactActorUserIdSchema = z2.string().min(1).refine(
|
|
7
29
|
(value) => value === value.trim() && value.toLowerCase() !== "unknown"
|
|
8
30
|
);
|
|
9
|
-
var nonBlankStringSchema =
|
|
31
|
+
var nonBlankStringSchema = z2.string().refine((value) => value.trim().length > 0);
|
|
10
32
|
var exactNonBlankStringSchema = nonBlankStringSchema.refine(
|
|
11
33
|
(value) => value === value.trim()
|
|
12
34
|
);
|
|
13
|
-
var platformSchema =
|
|
14
|
-
var sourceTypeSchema =
|
|
15
|
-
var destinationVisibilitySchema =
|
|
16
|
-
var slackAddressSchema =
|
|
17
|
-
platform:
|
|
35
|
+
var platformSchema = z2.enum(["slack", "local"]);
|
|
36
|
+
var sourceTypeSchema = z2.enum(["pub", "priv"]);
|
|
37
|
+
var destinationVisibilitySchema = z2.enum(["public", "private"]);
|
|
38
|
+
var slackAddressSchema = z2.object({
|
|
39
|
+
platform: z2.literal("slack"),
|
|
18
40
|
teamId: slackTeamIdSchema,
|
|
19
41
|
channelId: slackConversationIdSchema
|
|
20
42
|
}).strict();
|
|
21
43
|
var slackDestinationSchema = slackAddressSchema;
|
|
22
|
-
var localDestinationSchema =
|
|
23
|
-
platform:
|
|
44
|
+
var localDestinationSchema = z2.object({
|
|
45
|
+
platform: z2.literal("local"),
|
|
24
46
|
conversationId: localConversationIdSchema
|
|
25
47
|
}).strict();
|
|
26
|
-
var destinationSchema =
|
|
48
|
+
var destinationSchema = z2.discriminatedUnion("platform", [
|
|
27
49
|
slackDestinationSchema,
|
|
28
50
|
localDestinationSchema
|
|
29
51
|
]);
|
|
@@ -32,27 +54,27 @@ var slackSourceSchema = slackAddressSchema.extend({
|
|
|
32
54
|
messageTs: nonBlankStringSchema.optional(),
|
|
33
55
|
threadTs: nonBlankStringSchema.optional()
|
|
34
56
|
}).strict();
|
|
35
|
-
var localSourceSchema =
|
|
36
|
-
platform:
|
|
37
|
-
type:
|
|
57
|
+
var localSourceSchema = z2.object({
|
|
58
|
+
platform: z2.literal("local"),
|
|
59
|
+
type: z2.literal("priv"),
|
|
38
60
|
conversationId: localConversationIdSchema
|
|
39
61
|
}).strict();
|
|
40
|
-
var sourceSchema =
|
|
62
|
+
var sourceSchema = z2.discriminatedUnion("platform", [
|
|
41
63
|
slackSourceSchema,
|
|
42
64
|
localSourceSchema
|
|
43
65
|
]);
|
|
44
|
-
var pluginCredentialSubjectSchema =
|
|
66
|
+
var pluginCredentialSubjectSchema = z2.discriminatedUnion(
|
|
45
67
|
"allowedWhen",
|
|
46
68
|
[
|
|
47
|
-
|
|
48
|
-
type:
|
|
69
|
+
z2.object({
|
|
70
|
+
type: z2.literal("user"),
|
|
49
71
|
userId: exactActorUserIdSchema,
|
|
50
|
-
allowedWhen:
|
|
72
|
+
allowedWhen: z2.literal("private-direct-conversation")
|
|
51
73
|
}).strict(),
|
|
52
|
-
|
|
53
|
-
type:
|
|
74
|
+
z2.object({
|
|
75
|
+
type: z2.literal("user"),
|
|
54
76
|
userId: exactActorUserIdSchema,
|
|
55
|
-
allowedWhen:
|
|
77
|
+
allowedWhen: z2.literal("scheduled-task"),
|
|
56
78
|
taskId: exactNonBlankStringSchema
|
|
57
79
|
}).strict()
|
|
58
80
|
]
|
|
@@ -63,29 +85,29 @@ var actorProfileSchema = {
|
|
|
63
85
|
userId: exactActorUserIdSchema,
|
|
64
86
|
userName: nonBlankStringSchema.optional()
|
|
65
87
|
};
|
|
66
|
-
var slackActorSchema =
|
|
88
|
+
var slackActorSchema = z2.object({
|
|
67
89
|
...actorProfileSchema,
|
|
68
|
-
platform:
|
|
90
|
+
platform: z2.literal("slack"),
|
|
69
91
|
teamId: slackTeamIdSchema
|
|
70
92
|
}).strict();
|
|
71
|
-
var localActorSchema =
|
|
93
|
+
var localActorSchema = z2.object({
|
|
72
94
|
...actorProfileSchema,
|
|
73
|
-
platform:
|
|
95
|
+
platform: z2.literal("local")
|
|
74
96
|
}).strict();
|
|
75
|
-
var systemActorSchema =
|
|
76
|
-
platform:
|
|
97
|
+
var systemActorSchema = z2.object({
|
|
98
|
+
platform: z2.literal("system"),
|
|
77
99
|
name: exactActorUserIdSchema
|
|
78
100
|
}).strict();
|
|
79
|
-
var actorSchema =
|
|
101
|
+
var actorSchema = z2.discriminatedUnion("platform", [
|
|
80
102
|
slackActorSchema,
|
|
81
103
|
localActorSchema,
|
|
82
104
|
systemActorSchema
|
|
83
105
|
]);
|
|
84
|
-
var dispatchMetadataSchema =
|
|
106
|
+
var dispatchMetadataSchema = z2.record(z2.string(), z2.string()).superRefine((metadata, ctx) => {
|
|
85
107
|
const entries = Object.entries(metadata);
|
|
86
108
|
if (entries.length > 20) {
|
|
87
109
|
ctx.addIssue({
|
|
88
|
-
code:
|
|
110
|
+
code: z2.ZodIssueCode.custom,
|
|
89
111
|
message: "Dispatch metadata has too many keys"
|
|
90
112
|
});
|
|
91
113
|
return;
|
|
@@ -93,7 +115,7 @@ var dispatchMetadataSchema = z.record(z.string(), z.string()).superRefine((metad
|
|
|
93
115
|
for (const [key, value] of entries) {
|
|
94
116
|
if (!key.trim()) {
|
|
95
117
|
ctx.addIssue({
|
|
96
|
-
code:
|
|
118
|
+
code: z2.ZodIssueCode.custom,
|
|
97
119
|
message: "Dispatch metadata values must be strings",
|
|
98
120
|
path: [key]
|
|
99
121
|
});
|
|
@@ -101,40 +123,40 @@ var dispatchMetadataSchema = z.record(z.string(), z.string()).superRefine((metad
|
|
|
101
123
|
}
|
|
102
124
|
if (key.length > 128) {
|
|
103
125
|
ctx.addIssue({
|
|
104
|
-
code:
|
|
126
|
+
code: z2.ZodIssueCode.custom,
|
|
105
127
|
message: "Dispatch metadata key exceeds the maximum length",
|
|
106
128
|
path: [key]
|
|
107
129
|
});
|
|
108
130
|
}
|
|
109
131
|
if (/[\r\n]/.test(key)) {
|
|
110
132
|
ctx.addIssue({
|
|
111
|
-
code:
|
|
133
|
+
code: z2.ZodIssueCode.custom,
|
|
112
134
|
message: "Dispatch metadata keys must be single-line strings",
|
|
113
135
|
path: [key]
|
|
114
136
|
});
|
|
115
137
|
}
|
|
116
138
|
if (/[\r\n]/.test(value)) {
|
|
117
139
|
ctx.addIssue({
|
|
118
|
-
code:
|
|
140
|
+
code: z2.ZodIssueCode.custom,
|
|
119
141
|
message: "Dispatch metadata values must be single-line strings",
|
|
120
142
|
path: [key]
|
|
121
143
|
});
|
|
122
144
|
}
|
|
123
145
|
if (value.length > 512) {
|
|
124
146
|
ctx.addIssue({
|
|
125
|
-
code:
|
|
147
|
+
code: z2.ZodIssueCode.custom,
|
|
126
148
|
message: "Dispatch metadata value exceeds the maximum length",
|
|
127
149
|
path: [key]
|
|
128
150
|
});
|
|
129
151
|
}
|
|
130
152
|
}
|
|
131
153
|
});
|
|
132
|
-
var dispatchOptionsSchema =
|
|
133
|
-
idempotencyKey: nonBlankStringSchema.pipe(
|
|
154
|
+
var dispatchOptionsSchema = z2.object({
|
|
155
|
+
idempotencyKey: nonBlankStringSchema.pipe(z2.string().max(512)),
|
|
134
156
|
credentialSubject: pluginCredentialSubjectSchema.optional(),
|
|
135
157
|
destination: slackDestinationSchema,
|
|
136
158
|
destinationVisibility: destinationVisibilitySchema,
|
|
137
|
-
input: nonBlankStringSchema.pipe(
|
|
159
|
+
input: nonBlankStringSchema.pipe(z2.string().max(32e3)),
|
|
138
160
|
metadata: dispatchMetadataSchema.optional(),
|
|
139
161
|
source: sourceSchema
|
|
140
162
|
}).strict();
|
|
@@ -175,56 +197,56 @@ function isSlackDestination(destination) {
|
|
|
175
197
|
}
|
|
176
198
|
|
|
177
199
|
// src/prompt.ts
|
|
178
|
-
import { z as
|
|
179
|
-
var promptMessageSchema =
|
|
180
|
-
text:
|
|
200
|
+
import { z as z3 } from "zod";
|
|
201
|
+
var promptMessageSchema = z3.object({
|
|
202
|
+
text: z3.string().trim().min(1).max(8e3)
|
|
181
203
|
}).strict();
|
|
182
204
|
|
|
183
205
|
// src/resource-events.ts
|
|
184
|
-
import { z as
|
|
185
|
-
var subscribableResourceSchema =
|
|
186
|
-
label:
|
|
187
|
-
provider:
|
|
188
|
-
resourceRef:
|
|
189
|
-
suggestedEvents:
|
|
190
|
-
supportedEvents:
|
|
191
|
-
type:
|
|
206
|
+
import { z as z4 } from "zod";
|
|
207
|
+
var subscribableResourceSchema = z4.object({
|
|
208
|
+
label: z4.string().min(1),
|
|
209
|
+
provider: z4.string().min(1),
|
|
210
|
+
resourceRef: z4.string().min(1),
|
|
211
|
+
suggestedEvents: z4.array(z4.string().min(1)).optional(),
|
|
212
|
+
supportedEvents: z4.array(z4.string().min(1)),
|
|
213
|
+
type: z4.string().min(1)
|
|
192
214
|
}).strict();
|
|
193
|
-
var resourceEventSchema =
|
|
194
|
-
eventKey:
|
|
195
|
-
eventType:
|
|
196
|
-
occurredAtMs:
|
|
197
|
-
provider:
|
|
198
|
-
resourceRef:
|
|
199
|
-
terminal:
|
|
200
|
-
trustedSummary:
|
|
201
|
-
untrustedText:
|
|
215
|
+
var resourceEventSchema = z4.object({
|
|
216
|
+
eventKey: z4.string().min(1),
|
|
217
|
+
eventType: z4.string().min(1),
|
|
218
|
+
occurredAtMs: z4.number().finite(),
|
|
219
|
+
provider: z4.string().min(1),
|
|
220
|
+
resourceRef: z4.string().min(1),
|
|
221
|
+
terminal: z4.boolean().optional(),
|
|
222
|
+
trustedSummary: z4.string().min(1),
|
|
223
|
+
untrustedText: z4.string().optional()
|
|
202
224
|
}).strict();
|
|
203
225
|
|
|
204
226
|
// src/tasks.ts
|
|
205
|
-
import { z as
|
|
206
|
-
var pluginRunTranscriptProvenanceSchema =
|
|
207
|
-
authority:
|
|
227
|
+
import { z as z5 } from "zod";
|
|
228
|
+
var pluginRunTranscriptProvenanceSchema = z5.object({
|
|
229
|
+
authority: z5.enum(["instruction", "context"]),
|
|
208
230
|
actor: actorSchema.optional()
|
|
209
231
|
}).strict();
|
|
210
|
-
var pluginRunTranscriptEntrySchema =
|
|
211
|
-
|
|
212
|
-
type:
|
|
213
|
-
role:
|
|
214
|
-
text:
|
|
232
|
+
var pluginRunTranscriptEntrySchema = z5.discriminatedUnion("type", [
|
|
233
|
+
z5.object({
|
|
234
|
+
type: z5.literal("message"),
|
|
235
|
+
role: z5.enum(["user", "assistant"]),
|
|
236
|
+
text: z5.string().min(1),
|
|
215
237
|
provenance: pluginRunTranscriptProvenanceSchema.optional(),
|
|
216
|
-
isRunActor:
|
|
238
|
+
isRunActor: z5.boolean().optional()
|
|
217
239
|
}).strict(),
|
|
218
|
-
|
|
219
|
-
type:
|
|
220
|
-
toolName:
|
|
221
|
-
isError:
|
|
222
|
-
text:
|
|
240
|
+
z5.object({
|
|
241
|
+
type: z5.literal("toolResult"),
|
|
242
|
+
toolName: z5.string().min(1),
|
|
243
|
+
isError: z5.boolean(),
|
|
244
|
+
text: z5.string().min(1).optional()
|
|
223
245
|
}).strict()
|
|
224
246
|
]);
|
|
225
|
-
var pluginRunContextSchema =
|
|
226
|
-
completedAtMs:
|
|
227
|
-
conversationId:
|
|
247
|
+
var pluginRunContextSchema = z5.object({
|
|
248
|
+
completedAtMs: z5.number().finite(),
|
|
249
|
+
conversationId: z5.string().min(1),
|
|
228
250
|
destination: destinationSchema,
|
|
229
251
|
/**
|
|
230
252
|
* All distinct actors annotated on this run's committed instruction-authority
|
|
@@ -234,43 +256,44 @@ var pluginRunContextSchema = z4.object({
|
|
|
234
256
|
* exceed the actors visible in the transcript slice. Usually `[run.actor]`;
|
|
235
257
|
* possibly empty for system runs with no human instructions.
|
|
236
258
|
*/
|
|
237
|
-
actors:
|
|
259
|
+
actors: z5.array(actorSchema),
|
|
238
260
|
/**
|
|
239
261
|
* The single actor this run executes as. Absent only for actor-less legacy
|
|
240
262
|
* system records, so authority-sensitive plugins must fail closed.
|
|
241
263
|
*/
|
|
242
264
|
actor: actorSchema.optional(),
|
|
243
|
-
runId:
|
|
265
|
+
runId: z5.string().min(1),
|
|
244
266
|
source: sourceSchema,
|
|
245
|
-
transcript:
|
|
267
|
+
transcript: z5.array(pluginRunTranscriptEntrySchema)
|
|
246
268
|
}).strict();
|
|
247
269
|
|
|
248
270
|
// src/tools.ts
|
|
249
|
-
import { z as
|
|
271
|
+
import { z as z6 } from "zod";
|
|
250
272
|
var PluginToolInputError = class extends Error {
|
|
251
273
|
constructor(message, options) {
|
|
252
274
|
super(message, options);
|
|
253
275
|
this.name = "PluginToolInputError";
|
|
254
276
|
}
|
|
255
277
|
};
|
|
256
|
-
var pluginToolContinuationSchema =
|
|
257
|
-
arguments:
|
|
258
|
-
reason:
|
|
278
|
+
var pluginToolContinuationSchema = z6.object({
|
|
279
|
+
arguments: z6.record(z6.string(), z6.unknown()),
|
|
280
|
+
reason: z6.string().min(1).optional()
|
|
259
281
|
}).strict();
|
|
260
|
-
var pluginToolErrorSchema =
|
|
261
|
-
kind:
|
|
262
|
-
message:
|
|
263
|
-
retryable:
|
|
282
|
+
var pluginToolErrorSchema = z6.object({
|
|
283
|
+
kind: z6.string().min(1),
|
|
284
|
+
message: z6.string().min(1),
|
|
285
|
+
retryable: z6.boolean().optional()
|
|
264
286
|
}).strict();
|
|
265
|
-
var pluginToolResultSchema =
|
|
266
|
-
ok:
|
|
267
|
-
status:
|
|
268
|
-
target:
|
|
269
|
-
data:
|
|
270
|
-
truncated:
|
|
287
|
+
var pluginToolResultSchema = z6.object({
|
|
288
|
+
ok: z6.boolean(),
|
|
289
|
+
status: z6.enum(["success", "error"]),
|
|
290
|
+
target: z6.string().min(1).optional(),
|
|
291
|
+
data: z6.unknown().optional(),
|
|
292
|
+
truncated: z6.boolean().optional(),
|
|
271
293
|
continuation: pluginToolContinuationSchema.optional(),
|
|
272
|
-
error:
|
|
294
|
+
error: z6.union([pluginToolErrorSchema, z6.string()]).optional()
|
|
273
295
|
}).passthrough();
|
|
296
|
+
var toolApprovalModeSchema = z6.enum(["auto", "review", "approve"]);
|
|
274
297
|
function formatZodPath(path) {
|
|
275
298
|
return path.length > 0 ? path.map(String).join(".") : "root";
|
|
276
299
|
}
|
|
@@ -292,7 +315,7 @@ function createZodTool(definition, helperName) {
|
|
|
292
315
|
let modelInputSchema;
|
|
293
316
|
let modelOutputSchema;
|
|
294
317
|
try {
|
|
295
|
-
modelInputSchema =
|
|
318
|
+
modelInputSchema = z6.toJSONSchema(inputSchema);
|
|
296
319
|
} catch (error) {
|
|
297
320
|
throw new TypeError(
|
|
298
321
|
`${helperName}() inputSchema must be representable as JSON Schema.`,
|
|
@@ -300,7 +323,7 @@ function createZodTool(definition, helperName) {
|
|
|
300
323
|
);
|
|
301
324
|
}
|
|
302
325
|
try {
|
|
303
|
-
modelOutputSchema =
|
|
326
|
+
modelOutputSchema = z6.toJSONSchema(outputSchema);
|
|
304
327
|
} catch (error) {
|
|
305
328
|
throw new TypeError(
|
|
306
329
|
`${helperName}() outputSchema must be representable as JSON Schema.`,
|
|
@@ -336,74 +359,74 @@ function definePluginTool(definition) {
|
|
|
336
359
|
}
|
|
337
360
|
|
|
338
361
|
// src/operations.ts
|
|
339
|
-
import { z as
|
|
340
|
-
var pluginApiRouteRequestContextSchema =
|
|
341
|
-
auth:
|
|
342
|
-
user:
|
|
343
|
-
email:
|
|
344
|
-
emailVerified:
|
|
345
|
-
name:
|
|
362
|
+
import { z as z7 } from "zod";
|
|
363
|
+
var pluginApiRouteRequestContextSchema = z7.object({
|
|
364
|
+
auth: z7.object({
|
|
365
|
+
user: z7.object({
|
|
366
|
+
email: z7.string().nullable().optional(),
|
|
367
|
+
emailVerified: z7.boolean().optional(),
|
|
368
|
+
name: z7.string().nullable().optional()
|
|
346
369
|
}).strict()
|
|
347
370
|
}).strict(),
|
|
348
371
|
pluginName: nonBlankStringSchema
|
|
349
372
|
}).strict();
|
|
350
373
|
|
|
351
374
|
// src/credentials.ts
|
|
352
|
-
import { z as
|
|
353
|
-
var pluginProviderNameSchema =
|
|
354
|
-
var pluginGrantNameSchema =
|
|
355
|
-
var pluginGrantAccessSchema =
|
|
356
|
-
|
|
357
|
-
|
|
375
|
+
import { z as z8 } from "zod";
|
|
376
|
+
var pluginProviderNameSchema = z8.string().regex(/^[a-z][a-z0-9-]*$/);
|
|
377
|
+
var pluginGrantNameSchema = z8.string().regex(/^[a-z][a-z0-9.-]*$/);
|
|
378
|
+
var pluginGrantAccessSchema = z8.union([
|
|
379
|
+
z8.literal("read"),
|
|
380
|
+
z8.literal("write")
|
|
358
381
|
]);
|
|
359
|
-
var pluginAuthorizationSchema =
|
|
382
|
+
var pluginAuthorizationSchema = z8.object({
|
|
360
383
|
provider: pluginProviderNameSchema,
|
|
361
384
|
scope: nonBlankStringSchema.optional(),
|
|
362
|
-
type:
|
|
385
|
+
type: z8.literal("oauth")
|
|
363
386
|
}).strict();
|
|
364
|
-
var pluginProviderAccountSchema =
|
|
387
|
+
var pluginProviderAccountSchema = z8.object({
|
|
365
388
|
id: nonBlankStringSchema,
|
|
366
389
|
label: nonBlankStringSchema.optional(),
|
|
367
390
|
url: nonBlankStringSchema.optional()
|
|
368
391
|
}).strict();
|
|
369
|
-
var pluginStoredTokensSchema =
|
|
392
|
+
var pluginStoredTokensSchema = z8.object({
|
|
370
393
|
account: pluginProviderAccountSchema.optional(),
|
|
371
394
|
accessToken: nonBlankStringSchema,
|
|
372
|
-
expiresAt:
|
|
395
|
+
expiresAt: z8.number().finite().optional(),
|
|
373
396
|
refreshToken: nonBlankStringSchema,
|
|
374
|
-
refreshTokenExpiresAt:
|
|
397
|
+
refreshTokenExpiresAt: z8.number().finite().optional(),
|
|
375
398
|
scope: nonBlankStringSchema.optional()
|
|
376
399
|
}).strict();
|
|
377
|
-
var pluginGrantSchema =
|
|
400
|
+
var pluginGrantSchema = z8.object({
|
|
378
401
|
access: pluginGrantAccessSchema,
|
|
379
402
|
leaseScope: nonBlankStringSchema.optional(),
|
|
380
403
|
name: pluginGrantNameSchema,
|
|
381
404
|
reason: nonBlankStringSchema.optional(),
|
|
382
|
-
requirements:
|
|
405
|
+
requirements: z8.array(nonBlankStringSchema).min(1).optional()
|
|
383
406
|
}).strict();
|
|
384
|
-
var pluginCredentialHeaderTransformSchema =
|
|
385
|
-
domain:
|
|
386
|
-
headers:
|
|
407
|
+
var pluginCredentialHeaderTransformSchema = z8.object({
|
|
408
|
+
domain: z8.string().min(1),
|
|
409
|
+
headers: z8.record(z8.string(), z8.string()).refine((headers) => Object.keys(headers).length > 0)
|
|
387
410
|
}).strict();
|
|
388
|
-
var pluginCredentialLeaseSchema =
|
|
411
|
+
var pluginCredentialLeaseSchema = z8.object({
|
|
389
412
|
account: pluginProviderAccountSchema.optional(),
|
|
390
413
|
authorization: pluginAuthorizationSchema.optional(),
|
|
391
|
-
expiresAt:
|
|
392
|
-
headerTransforms:
|
|
414
|
+
expiresAt: z8.string().refine((value) => Number.isFinite(Date.parse(value))),
|
|
415
|
+
headerTransforms: z8.array(pluginCredentialHeaderTransformSchema).min(1)
|
|
393
416
|
}).strict();
|
|
394
|
-
var pluginCredentialResultSchema =
|
|
395
|
-
|
|
417
|
+
var pluginCredentialResultSchema = z8.discriminatedUnion("type", [
|
|
418
|
+
z8.object({
|
|
396
419
|
lease: pluginCredentialLeaseSchema,
|
|
397
|
-
type:
|
|
420
|
+
type: z8.literal("lease")
|
|
398
421
|
}).strict(),
|
|
399
|
-
|
|
422
|
+
z8.object({
|
|
400
423
|
authorization: pluginAuthorizationSchema.optional(),
|
|
401
424
|
message: nonBlankStringSchema,
|
|
402
|
-
type:
|
|
425
|
+
type: z8.literal("needed")
|
|
403
426
|
}).strict(),
|
|
404
|
-
|
|
427
|
+
z8.object({
|
|
405
428
|
message: nonBlankStringSchema,
|
|
406
|
-
type:
|
|
429
|
+
type: z8.literal("unavailable")
|
|
407
430
|
}).strict()
|
|
408
431
|
]);
|
|
409
432
|
var EgressAuthRequired = class extends Error {
|
|
@@ -466,6 +489,7 @@ export {
|
|
|
466
489
|
EgressPolicyDenied,
|
|
467
490
|
PluginToolInputError,
|
|
468
491
|
actorSchema,
|
|
492
|
+
conversationAnnotationInputSchema,
|
|
469
493
|
createLocalSource,
|
|
470
494
|
createSlackSource,
|
|
471
495
|
defineJuniorPlugin,
|
|
@@ -498,6 +522,7 @@ export {
|
|
|
498
522
|
pluginToolResultSchema,
|
|
499
523
|
promptMessageSchema,
|
|
500
524
|
resourceEventSchema,
|
|
525
|
+
resourceLinkAnnotationSchema,
|
|
501
526
|
slackActorSchema,
|
|
502
527
|
slackDestinationSchema,
|
|
503
528
|
slackSourceSchema,
|
|
@@ -505,5 +530,6 @@ export {
|
|
|
505
530
|
sourceTypeSchema,
|
|
506
531
|
subscribableResourceSchema,
|
|
507
532
|
systemActorSchema,
|
|
533
|
+
toolApprovalModeSchema,
|
|
508
534
|
zodTool
|
|
509
535
|
};
|
package/dist/manifest.d.ts
CHANGED
package/dist/operations.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { PluginContext } from "./context";
|
|
|
3
3
|
import type { Dispatch, DispatchOptions, DispatchResult } from "./dispatch";
|
|
4
4
|
import type { PluginReadState, PluginState } from "./state";
|
|
5
5
|
import type { ResourceEventPublisher } from "./resource-events";
|
|
6
|
+
import type { PluginConversationAnnotations } from "./annotations";
|
|
6
7
|
export interface HeartbeatHookContext extends PluginContext {
|
|
7
8
|
agent: {
|
|
8
9
|
dispatch(options: DispatchOptions): Promise<DispatchResult>;
|
|
@@ -83,6 +84,7 @@ export type PluginRouteApp = {
|
|
|
83
84
|
fetch(request: Request, context?: PluginApiRouteRequestContext): Promise<Response> | Response;
|
|
84
85
|
};
|
|
85
86
|
export interface RouteRegistrationHookContext extends PluginContext {
|
|
87
|
+
annotations: PluginConversationAnnotations;
|
|
86
88
|
/** Core-owned delivery boundary for provider webhook events. */
|
|
87
89
|
resourceEvents: ResourceEventPublisher;
|
|
88
90
|
}
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PluginContext, LocalInvocationContext, PluginEmbedder, PluginModel, Actor, SlackInvocationContext } from "./context";
|
|
2
2
|
import type { PluginCredentialSubject } from "./credentials";
|
|
3
|
+
import type { PluginAnnotations } from "./annotations";
|
|
3
4
|
import type { SlackConversationLink } from "./operations";
|
|
4
5
|
import type { PluginState } from "./state";
|
|
5
6
|
import { z, type ZodType, type ZodTypeAny } from "zod";
|
|
@@ -108,8 +109,57 @@ export type PluginToolResult = z.output<typeof pluginToolResultSchema>;
|
|
|
108
109
|
export type PluginToolExecute<TInput = unknown, TOutput = unknown> = {
|
|
109
110
|
bivarianceHack(input: TInput, options: PluginToolExecuteOptions): Promise<TOutput> | TOutput;
|
|
110
111
|
}["bivarianceHack"];
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
/**
|
|
113
|
+
* Tool-declared approval mode.
|
|
114
|
+
*
|
|
115
|
+
* `auto` delegates to core policy, `review` enters approval review, and
|
|
116
|
+
* `approve` permits execution without review. Omission delegates to core
|
|
117
|
+
* defaults. These values do not select the reviewer.
|
|
118
|
+
*
|
|
119
|
+
* This is declaration metadata only; current tool execution is unchanged.
|
|
120
|
+
* TODO(#1053): Enforce effective approval modes before tool execution.
|
|
121
|
+
*/
|
|
122
|
+
export declare const toolApprovalModeSchema: z.ZodEnum<{
|
|
123
|
+
auto: "auto";
|
|
124
|
+
review: "review";
|
|
125
|
+
approve: "approve";
|
|
126
|
+
}>;
|
|
127
|
+
export type ToolApprovalMode = z.output<typeof toolApprovalModeSchema>;
|
|
128
|
+
/**
|
|
129
|
+
* Reviewer signals describing a tool's side-effect behavior.
|
|
130
|
+
*
|
|
131
|
+
* These hints follow the MCP tool annotation contract. Approval review may use
|
|
132
|
+
* them as signals, but they never grant authority or override deterministic
|
|
133
|
+
* authorization.
|
|
134
|
+
*/
|
|
135
|
+
export interface ToolAnnotations {
|
|
136
|
+
[key: string]: unknown;
|
|
137
|
+
destructiveHint?: boolean;
|
|
138
|
+
idempotentHint?: boolean;
|
|
139
|
+
openWorldHint?: boolean;
|
|
140
|
+
readOnlyHint?: boolean;
|
|
141
|
+
title?: string;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Canonical approval metadata declared by core and plugin tools.
|
|
145
|
+
*
|
|
146
|
+
* This metadata is declaration-only until #1053 adds approval enforcement.
|
|
147
|
+
* Current tool execution is unchanged.
|
|
148
|
+
*/
|
|
149
|
+
export interface ToolApprovalMetadata<TInput = unknown> {
|
|
150
|
+
/** Optional declared approval mode; omission delegates to core defaults. */
|
|
151
|
+
approvalMode?: ToolApprovalMode;
|
|
152
|
+
annotations?: ToolAnnotations;
|
|
153
|
+
/**
|
|
154
|
+
* Describe the exact validated invocation for future approval presentation.
|
|
155
|
+
*
|
|
156
|
+
* Core owns authoritative tool, actor, source, destination, conversation,
|
|
157
|
+
* credential, and input data. This description adds domain-specific context
|
|
158
|
+
* only and is never an authorization grant.
|
|
159
|
+
*/
|
|
160
|
+
describeProposal?(input: TInput): string;
|
|
161
|
+
}
|
|
162
|
+
export interface PluginToolDefinition<TInput = unknown, TOutput = unknown> extends ToolApprovalMetadata<TInput> {
|
|
113
163
|
description: string;
|
|
114
164
|
executionMode?: unknown;
|
|
115
165
|
inputSchema: unknown;
|
|
@@ -119,7 +169,7 @@ export interface PluginToolDefinition<TInput = unknown, TOutput = unknown> {
|
|
|
119
169
|
* Returning `undefined` suppresses private result capture.
|
|
120
170
|
*/
|
|
121
171
|
privateTraceResult?(result: TOutput): unknown;
|
|
122
|
-
prepareArguments?: (args: unknown) =>
|
|
172
|
+
prepareArguments?: (args: unknown) => TInput;
|
|
123
173
|
/**
|
|
124
174
|
* @deprecated Put tool-selection and usage guidance directly in `description`
|
|
125
175
|
* and parameter descriptions. Retained for compatibility; may be removed in a
|
|
@@ -168,6 +218,7 @@ interface BaseToolRegistrationHookContext extends PluginContext {
|
|
|
168
218
|
* Do not parse as Slack unless the value starts with `slack:`.
|
|
169
219
|
*/
|
|
170
220
|
conversationId?: string;
|
|
221
|
+
annotations?: PluginAnnotations;
|
|
171
222
|
embedder: PluginEmbedder;
|
|
172
223
|
egress: PluginEgress;
|
|
173
224
|
model: PluginModel;
|
package/package.json
CHANGED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
function usesHttpProtocol(value: string): boolean {
|
|
4
|
+
try {
|
|
5
|
+
const protocol = new URL(value).protocol;
|
|
6
|
+
return protocol === "http:" || protocol === "https:";
|
|
7
|
+
} catch {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const resourceLinkAnnotationSchema = z
|
|
13
|
+
.object({
|
|
14
|
+
kind: z.literal("resource_link"),
|
|
15
|
+
key: z.string().trim().min(1).max(256),
|
|
16
|
+
label: z.string().trim().min(1).max(256),
|
|
17
|
+
url: z
|
|
18
|
+
.string()
|
|
19
|
+
.url()
|
|
20
|
+
.max(2_048)
|
|
21
|
+
.refine(usesHttpProtocol, "URL must use HTTP or HTTPS."),
|
|
22
|
+
description: z.string().trim().min(1).max(512).optional(),
|
|
23
|
+
status: z.enum(["open", "draft", "closed", "merged", "warning"]).optional(),
|
|
24
|
+
})
|
|
25
|
+
.strict();
|
|
26
|
+
|
|
27
|
+
/** Core-known annotation shapes that plugins may attach to a conversation. */
|
|
28
|
+
export const conversationAnnotationInputSchema = z.discriminatedUnion("kind", [
|
|
29
|
+
resourceLinkAnnotationSchema,
|
|
30
|
+
]);
|
|
31
|
+
export type ConversationAnnotationInput = z.output<
|
|
32
|
+
typeof conversationAnnotationInputSchema
|
|
33
|
+
>;
|
|
34
|
+
export type ConversationAnnotation = ConversationAnnotationInput & {
|
|
35
|
+
plugin: string;
|
|
36
|
+
createdAt: string;
|
|
37
|
+
updatedAt: string;
|
|
38
|
+
};
|
|
39
|
+
export interface PluginAnnotations {
|
|
40
|
+
upsert(annotation: ConversationAnnotationInput): Promise<void>;
|
|
41
|
+
remove(kind: ConversationAnnotationInput["kind"], key: string): Promise<void>;
|
|
42
|
+
list(): Promise<ConversationAnnotation[]>;
|
|
43
|
+
}
|
|
44
|
+
export interface PluginConversationAnnotations {
|
|
45
|
+
forConversation(conversationId: string): PluginAnnotations;
|
|
46
|
+
}
|
package/src/index.ts
CHANGED
package/src/manifest.ts
CHANGED
package/src/operations.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { Dispatch, DispatchOptions, DispatchResult } from "./dispatch";
|
|
|
4
4
|
import { nonBlankStringSchema } from "./schemas";
|
|
5
5
|
import type { PluginReadState, PluginState } from "./state";
|
|
6
6
|
import type { ResourceEventPublisher } from "./resource-events";
|
|
7
|
+
import type { PluginConversationAnnotations } from "./annotations";
|
|
7
8
|
|
|
8
9
|
export interface HeartbeatHookContext extends PluginContext {
|
|
9
10
|
agent: {
|
|
@@ -113,6 +114,7 @@ export type PluginRouteApp = {
|
|
|
113
114
|
};
|
|
114
115
|
|
|
115
116
|
export interface RouteRegistrationHookContext extends PluginContext {
|
|
117
|
+
annotations: PluginConversationAnnotations;
|
|
116
118
|
/** Core-owned delivery boundary for provider webhook events. */
|
|
117
119
|
resourceEvents: ResourceEventPublisher;
|
|
118
120
|
}
|
package/src/tools.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
SlackInvocationContext,
|
|
8
8
|
} from "./context";
|
|
9
9
|
import type { PluginCredentialSubject } from "./credentials";
|
|
10
|
+
import type { PluginAnnotations } from "./annotations";
|
|
10
11
|
import type { SlackConversationLink } from "./operations";
|
|
11
12
|
import type { PluginState } from "./state";
|
|
12
13
|
import { z, type ZodType, type ZodTypeAny } from "zod";
|
|
@@ -129,8 +130,60 @@ export type PluginToolExecute<TInput = unknown, TOutput = unknown> = {
|
|
|
129
130
|
): Promise<TOutput> | TOutput;
|
|
130
131
|
}["bivarianceHack"];
|
|
131
132
|
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Tool-declared approval mode.
|
|
135
|
+
*
|
|
136
|
+
* `auto` delegates to core policy, `review` enters approval review, and
|
|
137
|
+
* `approve` permits execution without review. Omission delegates to core
|
|
138
|
+
* defaults. These values do not select the reviewer.
|
|
139
|
+
*
|
|
140
|
+
* This is declaration metadata only; current tool execution is unchanged.
|
|
141
|
+
* TODO(#1053): Enforce effective approval modes before tool execution.
|
|
142
|
+
*/
|
|
143
|
+
export const toolApprovalModeSchema = z.enum(["auto", "review", "approve"]);
|
|
144
|
+
|
|
145
|
+
export type ToolApprovalMode = z.output<typeof toolApprovalModeSchema>;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Reviewer signals describing a tool's side-effect behavior.
|
|
149
|
+
*
|
|
150
|
+
* These hints follow the MCP tool annotation contract. Approval review may use
|
|
151
|
+
* them as signals, but they never grant authority or override deterministic
|
|
152
|
+
* authorization.
|
|
153
|
+
*/
|
|
154
|
+
export interface ToolAnnotations {
|
|
155
|
+
[key: string]: unknown;
|
|
156
|
+
destructiveHint?: boolean;
|
|
157
|
+
idempotentHint?: boolean;
|
|
158
|
+
openWorldHint?: boolean;
|
|
159
|
+
readOnlyHint?: boolean;
|
|
160
|
+
title?: string;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Canonical approval metadata declared by core and plugin tools.
|
|
165
|
+
*
|
|
166
|
+
* This metadata is declaration-only until #1053 adds approval enforcement.
|
|
167
|
+
* Current tool execution is unchanged.
|
|
168
|
+
*/
|
|
169
|
+
export interface ToolApprovalMetadata<TInput = unknown> {
|
|
170
|
+
/** Optional declared approval mode; omission delegates to core defaults. */
|
|
171
|
+
approvalMode?: ToolApprovalMode;
|
|
172
|
+
annotations?: ToolAnnotations;
|
|
173
|
+
/**
|
|
174
|
+
* Describe the exact validated invocation for future approval presentation.
|
|
175
|
+
*
|
|
176
|
+
* Core owns authoritative tool, actor, source, destination, conversation,
|
|
177
|
+
* credential, and input data. This description adds domain-specific context
|
|
178
|
+
* only and is never an authorization grant.
|
|
179
|
+
*/
|
|
180
|
+
describeProposal?(input: TInput): string;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export interface PluginToolDefinition<
|
|
184
|
+
TInput = unknown,
|
|
185
|
+
TOutput = unknown,
|
|
186
|
+
> extends ToolApprovalMetadata<TInput> {
|
|
134
187
|
description: string;
|
|
135
188
|
executionMode?: unknown;
|
|
136
189
|
inputSchema: unknown;
|
|
@@ -140,7 +193,7 @@ export interface PluginToolDefinition<TInput = unknown, TOutput = unknown> {
|
|
|
140
193
|
* Returning `undefined` suppresses private result capture.
|
|
141
194
|
*/
|
|
142
195
|
privateTraceResult?(result: TOutput): unknown;
|
|
143
|
-
prepareArguments?: (args: unknown) =>
|
|
196
|
+
prepareArguments?: (args: unknown) => TInput;
|
|
144
197
|
/**
|
|
145
198
|
* @deprecated Put tool-selection and usage guidance directly in `description`
|
|
146
199
|
* and parameter descriptions. Retained for compatibility; may be removed in a
|
|
@@ -294,6 +347,7 @@ interface BaseToolRegistrationHookContext extends PluginContext {
|
|
|
294
347
|
* Do not parse as Slack unless the value starts with `slack:`.
|
|
295
348
|
*/
|
|
296
349
|
conversationId?: string;
|
|
350
|
+
annotations?: PluginAnnotations;
|
|
297
351
|
embedder: PluginEmbedder;
|
|
298
352
|
egress: PluginEgress;
|
|
299
353
|
model: PluginModel;
|