@sentry/junior-plugin-api 0.115.0 → 0.116.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/annotations.d.ts +44 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +158 -134
- package/dist/manifest.d.ts +0 -1
- package/dist/operations.d.ts +2 -0
- package/dist/tools.d.ts +36 -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 +41 -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,44 +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();
|
|
274
|
-
var toolApprovalModeSchema =
|
|
296
|
+
var toolApprovalModeSchema = z6.enum(["auto", "review", "approve"]);
|
|
275
297
|
function formatZodPath(path) {
|
|
276
298
|
return path.length > 0 ? path.map(String).join(".") : "root";
|
|
277
299
|
}
|
|
@@ -293,7 +315,7 @@ function createZodTool(definition, helperName) {
|
|
|
293
315
|
let modelInputSchema;
|
|
294
316
|
let modelOutputSchema;
|
|
295
317
|
try {
|
|
296
|
-
modelInputSchema =
|
|
318
|
+
modelInputSchema = z6.toJSONSchema(inputSchema);
|
|
297
319
|
} catch (error) {
|
|
298
320
|
throw new TypeError(
|
|
299
321
|
`${helperName}() inputSchema must be representable as JSON Schema.`,
|
|
@@ -301,7 +323,7 @@ function createZodTool(definition, helperName) {
|
|
|
301
323
|
);
|
|
302
324
|
}
|
|
303
325
|
try {
|
|
304
|
-
modelOutputSchema =
|
|
326
|
+
modelOutputSchema = z6.toJSONSchema(outputSchema);
|
|
305
327
|
} catch (error) {
|
|
306
328
|
throw new TypeError(
|
|
307
329
|
`${helperName}() outputSchema must be representable as JSON Schema.`,
|
|
@@ -337,74 +359,74 @@ function definePluginTool(definition) {
|
|
|
337
359
|
}
|
|
338
360
|
|
|
339
361
|
// src/operations.ts
|
|
340
|
-
import { z as
|
|
341
|
-
var pluginApiRouteRequestContextSchema =
|
|
342
|
-
auth:
|
|
343
|
-
user:
|
|
344
|
-
email:
|
|
345
|
-
emailVerified:
|
|
346
|
-
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()
|
|
347
369
|
}).strict()
|
|
348
370
|
}).strict(),
|
|
349
371
|
pluginName: nonBlankStringSchema
|
|
350
372
|
}).strict();
|
|
351
373
|
|
|
352
374
|
// src/credentials.ts
|
|
353
|
-
import { z as
|
|
354
|
-
var pluginProviderNameSchema =
|
|
355
|
-
var pluginGrantNameSchema =
|
|
356
|
-
var pluginGrantAccessSchema =
|
|
357
|
-
|
|
358
|
-
|
|
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")
|
|
359
381
|
]);
|
|
360
|
-
var pluginAuthorizationSchema =
|
|
382
|
+
var pluginAuthorizationSchema = z8.object({
|
|
361
383
|
provider: pluginProviderNameSchema,
|
|
362
384
|
scope: nonBlankStringSchema.optional(),
|
|
363
|
-
type:
|
|
385
|
+
type: z8.literal("oauth")
|
|
364
386
|
}).strict();
|
|
365
|
-
var pluginProviderAccountSchema =
|
|
387
|
+
var pluginProviderAccountSchema = z8.object({
|
|
366
388
|
id: nonBlankStringSchema,
|
|
367
389
|
label: nonBlankStringSchema.optional(),
|
|
368
390
|
url: nonBlankStringSchema.optional()
|
|
369
391
|
}).strict();
|
|
370
|
-
var pluginStoredTokensSchema =
|
|
392
|
+
var pluginStoredTokensSchema = z8.object({
|
|
371
393
|
account: pluginProviderAccountSchema.optional(),
|
|
372
394
|
accessToken: nonBlankStringSchema,
|
|
373
|
-
expiresAt:
|
|
395
|
+
expiresAt: z8.number().finite().optional(),
|
|
374
396
|
refreshToken: nonBlankStringSchema,
|
|
375
|
-
refreshTokenExpiresAt:
|
|
397
|
+
refreshTokenExpiresAt: z8.number().finite().optional(),
|
|
376
398
|
scope: nonBlankStringSchema.optional()
|
|
377
399
|
}).strict();
|
|
378
|
-
var pluginGrantSchema =
|
|
400
|
+
var pluginGrantSchema = z8.object({
|
|
379
401
|
access: pluginGrantAccessSchema,
|
|
380
402
|
leaseScope: nonBlankStringSchema.optional(),
|
|
381
403
|
name: pluginGrantNameSchema,
|
|
382
404
|
reason: nonBlankStringSchema.optional(),
|
|
383
|
-
requirements:
|
|
405
|
+
requirements: z8.array(nonBlankStringSchema).min(1).optional()
|
|
384
406
|
}).strict();
|
|
385
|
-
var pluginCredentialHeaderTransformSchema =
|
|
386
|
-
domain:
|
|
387
|
-
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)
|
|
388
410
|
}).strict();
|
|
389
|
-
var pluginCredentialLeaseSchema =
|
|
411
|
+
var pluginCredentialLeaseSchema = z8.object({
|
|
390
412
|
account: pluginProviderAccountSchema.optional(),
|
|
391
413
|
authorization: pluginAuthorizationSchema.optional(),
|
|
392
|
-
expiresAt:
|
|
393
|
-
headerTransforms:
|
|
414
|
+
expiresAt: z8.string().refine((value) => Number.isFinite(Date.parse(value))),
|
|
415
|
+
headerTransforms: z8.array(pluginCredentialHeaderTransformSchema).min(1)
|
|
394
416
|
}).strict();
|
|
395
|
-
var pluginCredentialResultSchema =
|
|
396
|
-
|
|
417
|
+
var pluginCredentialResultSchema = z8.discriminatedUnion("type", [
|
|
418
|
+
z8.object({
|
|
397
419
|
lease: pluginCredentialLeaseSchema,
|
|
398
|
-
type:
|
|
420
|
+
type: z8.literal("lease")
|
|
399
421
|
}).strict(),
|
|
400
|
-
|
|
422
|
+
z8.object({
|
|
401
423
|
authorization: pluginAuthorizationSchema.optional(),
|
|
402
424
|
message: nonBlankStringSchema,
|
|
403
|
-
type:
|
|
425
|
+
type: z8.literal("needed")
|
|
404
426
|
}).strict(),
|
|
405
|
-
|
|
427
|
+
z8.object({
|
|
406
428
|
message: nonBlankStringSchema,
|
|
407
|
-
type:
|
|
429
|
+
type: z8.literal("unavailable")
|
|
408
430
|
}).strict()
|
|
409
431
|
]);
|
|
410
432
|
var EgressAuthRequired = class extends Error {
|
|
@@ -467,6 +489,7 @@ export {
|
|
|
467
489
|
EgressPolicyDenied,
|
|
468
490
|
PluginToolInputError,
|
|
469
491
|
actorSchema,
|
|
492
|
+
conversationAnnotationInputSchema,
|
|
470
493
|
createLocalSource,
|
|
471
494
|
createSlackSource,
|
|
472
495
|
defineJuniorPlugin,
|
|
@@ -499,6 +522,7 @@ export {
|
|
|
499
522
|
pluginToolResultSchema,
|
|
500
523
|
promptMessageSchema,
|
|
501
524
|
resourceEventSchema,
|
|
525
|
+
resourceLinkAnnotationSchema,
|
|
502
526
|
slackActorSchema,
|
|
503
527
|
slackDestinationSchema,
|
|
504
528
|
slackSourceSchema,
|
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";
|
|
@@ -124,10 +125,41 @@ export declare const toolApprovalModeSchema: z.ZodEnum<{
|
|
|
124
125
|
approve: "approve";
|
|
125
126
|
}>;
|
|
126
127
|
export type ToolApprovalMode = z.output<typeof toolApprovalModeSchema>;
|
|
127
|
-
|
|
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> {
|
|
128
150
|
/** Optional declared approval mode; omission delegates to core defaults. */
|
|
129
151
|
approvalMode?: ToolApprovalMode;
|
|
130
|
-
annotations?:
|
|
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> {
|
|
131
163
|
description: string;
|
|
132
164
|
executionMode?: unknown;
|
|
133
165
|
inputSchema: unknown;
|
|
@@ -137,7 +169,7 @@ export interface PluginToolDefinition<TInput = unknown, TOutput = unknown> {
|
|
|
137
169
|
* Returning `undefined` suppresses private result capture.
|
|
138
170
|
*/
|
|
139
171
|
privateTraceResult?(result: TOutput): unknown;
|
|
140
|
-
prepareArguments?: (args: unknown) =>
|
|
172
|
+
prepareArguments?: (args: unknown) => TInput;
|
|
141
173
|
/**
|
|
142
174
|
* @deprecated Put tool-selection and usage guidance directly in `description`
|
|
143
175
|
* and parameter descriptions. Retained for compatibility; may be removed in a
|
|
@@ -186,6 +218,7 @@ interface BaseToolRegistrationHookContext extends PluginContext {
|
|
|
186
218
|
* Do not parse as Slack unless the value starts with `slack:`.
|
|
187
219
|
*/
|
|
188
220
|
conversationId?: string;
|
|
221
|
+
annotations?: PluginAnnotations;
|
|
189
222
|
embedder: PluginEmbedder;
|
|
190
223
|
egress: PluginEgress;
|
|
191
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";
|
|
@@ -143,10 +144,46 @@ export const toolApprovalModeSchema = z.enum(["auto", "review", "approve"]);
|
|
|
143
144
|
|
|
144
145
|
export type ToolApprovalMode = z.output<typeof toolApprovalModeSchema>;
|
|
145
146
|
|
|
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> {
|
|
147
170
|
/** Optional declared approval mode; omission delegates to core defaults. */
|
|
148
171
|
approvalMode?: ToolApprovalMode;
|
|
149
|
-
annotations?:
|
|
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> {
|
|
150
187
|
description: string;
|
|
151
188
|
executionMode?: unknown;
|
|
152
189
|
inputSchema: unknown;
|
|
@@ -156,7 +193,7 @@ export interface PluginToolDefinition<TInput = unknown, TOutput = unknown> {
|
|
|
156
193
|
* Returning `undefined` suppresses private result capture.
|
|
157
194
|
*/
|
|
158
195
|
privateTraceResult?(result: TOutput): unknown;
|
|
159
|
-
prepareArguments?: (args: unknown) =>
|
|
196
|
+
prepareArguments?: (args: unknown) => TInput;
|
|
160
197
|
/**
|
|
161
198
|
* @deprecated Put tool-selection and usage guidance directly in `description`
|
|
162
199
|
* and parameter descriptions. Retained for compatibility; may be removed in a
|
|
@@ -310,6 +347,7 @@ interface BaseToolRegistrationHookContext extends PluginContext {
|
|
|
310
347
|
* Do not parse as Slack unless the value starts with `slack:`.
|
|
311
348
|
*/
|
|
312
349
|
conversationId?: string;
|
|
350
|
+
annotations?: PluginAnnotations;
|
|
313
351
|
embedder: PluginEmbedder;
|
|
314
352
|
egress: PluginEgress;
|
|
315
353
|
model: PluginModel;
|