@sentry/junior-plugin-api 0.72.0 → 0.73.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/index.d.ts +117 -26
- package/dist/index.js +57 -9
- package/package.json +1 -1
- package/src/index.ts +135 -30
package/dist/index.d.ts
CHANGED
|
@@ -1,25 +1,84 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
/** Runtime-owned Slack address for routing future work or side effects. */
|
|
3
|
+
export declare const slackDestinationSchema: z.ZodObject<{
|
|
4
|
+
platform: z.ZodLiteral<"slack">;
|
|
5
|
+
teamId: z.ZodString;
|
|
6
|
+
channelId: z.ZodString;
|
|
7
|
+
}, z.core.$strict>;
|
|
8
|
+
/** Runtime-owned local CLI conversation address. */
|
|
9
|
+
export declare const localDestinationSchema: z.ZodObject<{
|
|
10
|
+
platform: z.ZodLiteral<"local">;
|
|
11
|
+
conversationId: z.ZodString;
|
|
12
|
+
}, z.core.$strict>;
|
|
2
13
|
/** Runtime-owned provider-neutral address for routing future work or side effects. */
|
|
3
|
-
export declare const destinationSchema: z.ZodObject<{
|
|
14
|
+
export declare const destinationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
4
15
|
platform: z.ZodLiteral<"slack">;
|
|
5
16
|
teamId: z.ZodString;
|
|
6
17
|
channelId: z.ZodString;
|
|
18
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
19
|
+
platform: z.ZodLiteral<"local">;
|
|
20
|
+
conversationId: z.ZodString;
|
|
21
|
+
}, z.core.$strict>], "platform">;
|
|
22
|
+
/** Runtime-owned Slack coordinates for the inbound invocation. */
|
|
23
|
+
export declare const slackSourceSchema: z.ZodObject<{
|
|
24
|
+
platform: z.ZodLiteral<"slack">;
|
|
25
|
+
teamId: z.ZodString;
|
|
26
|
+
channelId: z.ZodString;
|
|
27
|
+
messageTs: z.ZodOptional<z.ZodString>;
|
|
28
|
+
threadTs: z.ZodOptional<z.ZodString>;
|
|
29
|
+
}, z.core.$strict>;
|
|
30
|
+
/** Runtime-owned local CLI coordinates for the inbound invocation. */
|
|
31
|
+
export declare const localSourceSchema: z.ZodObject<{
|
|
32
|
+
platform: z.ZodLiteral<"local">;
|
|
33
|
+
conversationId: z.ZodString;
|
|
7
34
|
}, z.core.$strict>;
|
|
35
|
+
/** Runtime-owned provider-neutral coordinates for the inbound invocation. */
|
|
36
|
+
export declare const sourceSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
37
|
+
platform: z.ZodLiteral<"slack">;
|
|
38
|
+
teamId: z.ZodString;
|
|
39
|
+
channelId: z.ZodString;
|
|
40
|
+
messageTs: z.ZodOptional<z.ZodString>;
|
|
41
|
+
threadTs: z.ZodOptional<z.ZodString>;
|
|
42
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
43
|
+
platform: z.ZodLiteral<"local">;
|
|
44
|
+
conversationId: z.ZodString;
|
|
45
|
+
}, z.core.$strict>], "platform">;
|
|
8
46
|
/** Stable user credential subject shape accepted from plugins. */
|
|
9
47
|
export declare const agentPluginCredentialSubjectSchema: z.ZodObject<{
|
|
10
48
|
type: z.ZodLiteral<"user">;
|
|
11
49
|
userId: z.ZodString;
|
|
12
50
|
allowedWhen: z.ZodLiteral<"private-direct-conversation">;
|
|
13
51
|
}, z.core.$strict>;
|
|
14
|
-
|
|
15
|
-
export declare const requesterSchema: z.ZodObject<{
|
|
52
|
+
export declare const slackRequesterSchema: z.ZodObject<{
|
|
16
53
|
platform: z.ZodLiteral<"slack">;
|
|
17
54
|
teamId: z.ZodString;
|
|
55
|
+
email: z.ZodOptional<z.ZodString>;
|
|
56
|
+
fullName: z.ZodOptional<z.ZodString>;
|
|
18
57
|
userId: z.ZodString;
|
|
19
58
|
userName: z.ZodOptional<z.ZodString>;
|
|
20
|
-
|
|
59
|
+
}, z.core.$strict>;
|
|
60
|
+
export declare const localRequesterSchema: z.ZodObject<{
|
|
61
|
+
platform: z.ZodLiteral<"local">;
|
|
21
62
|
email: z.ZodOptional<z.ZodString>;
|
|
63
|
+
fullName: z.ZodOptional<z.ZodString>;
|
|
64
|
+
userId: z.ZodString;
|
|
65
|
+
userName: z.ZodOptional<z.ZodString>;
|
|
22
66
|
}, z.core.$strict>;
|
|
67
|
+
/** Runtime-provided requester identity visible to plugin hooks. */
|
|
68
|
+
export declare const requesterSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
69
|
+
platform: z.ZodLiteral<"slack">;
|
|
70
|
+
teamId: z.ZodString;
|
|
71
|
+
email: z.ZodOptional<z.ZodString>;
|
|
72
|
+
fullName: z.ZodOptional<z.ZodString>;
|
|
73
|
+
userId: z.ZodString;
|
|
74
|
+
userName: z.ZodOptional<z.ZodString>;
|
|
75
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
76
|
+
platform: z.ZodLiteral<"local">;
|
|
77
|
+
email: z.ZodOptional<z.ZodString>;
|
|
78
|
+
fullName: z.ZodOptional<z.ZodString>;
|
|
79
|
+
userId: z.ZodString;
|
|
80
|
+
userName: z.ZodOptional<z.ZodString>;
|
|
81
|
+
}, z.core.$strict>], "platform">;
|
|
23
82
|
/** Plugin dispatch request accepted by Junior core. */
|
|
24
83
|
export declare const dispatchOptionsSchema: z.ZodObject<{
|
|
25
84
|
idempotencyKey: z.ZodPipe<z.ZodString, z.ZodString>;
|
|
@@ -37,6 +96,15 @@ export declare const dispatchOptionsSchema: z.ZodObject<{
|
|
|
37
96
|
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
38
97
|
}, z.core.$strict>;
|
|
39
98
|
export type Requester = z.output<typeof requesterSchema>;
|
|
99
|
+
export type SlackRequester = z.output<typeof slackRequesterSchema>;
|
|
100
|
+
export type LocalRequester = z.output<typeof localRequesterSchema>;
|
|
101
|
+
export type Source = z.output<typeof sourceSchema>;
|
|
102
|
+
export type SlackSource = Extract<Source, {
|
|
103
|
+
platform: "slack";
|
|
104
|
+
}>;
|
|
105
|
+
export type LocalSource = Extract<Source, {
|
|
106
|
+
platform: "local";
|
|
107
|
+
}>;
|
|
40
108
|
export interface AgentPluginMetadata {
|
|
41
109
|
name: string;
|
|
42
110
|
}
|
|
@@ -63,6 +131,28 @@ export interface AgentPluginContext {
|
|
|
63
131
|
log: AgentPluginLogger;
|
|
64
132
|
plugin: AgentPluginMetadata;
|
|
65
133
|
}
|
|
134
|
+
interface BaseInvocationContext {
|
|
135
|
+
/**
|
|
136
|
+
* Opaque Junior conversation/session identity for this invocation.
|
|
137
|
+
* Interactive Slack turns use `slack:{channelId}:{threadTs}`.
|
|
138
|
+
*/
|
|
139
|
+
conversationId?: string;
|
|
140
|
+
}
|
|
141
|
+
export interface SlackInvocationContext extends BaseInvocationContext {
|
|
142
|
+
/** Runtime-owned default outbound destination for this invocation, if any. */
|
|
143
|
+
destination?: SlackDestination;
|
|
144
|
+
requester?: SlackRequester;
|
|
145
|
+
/** Runtime-owned source where the invocation came from. */
|
|
146
|
+
source: SlackSource;
|
|
147
|
+
}
|
|
148
|
+
export interface LocalInvocationContext extends BaseInvocationContext {
|
|
149
|
+
/** Runtime-owned default outbound destination for this invocation, if any. */
|
|
150
|
+
destination?: LocalDestination;
|
|
151
|
+
requester?: LocalRequester;
|
|
152
|
+
/** Runtime-owned source where the invocation came from. */
|
|
153
|
+
source: LocalSource;
|
|
154
|
+
}
|
|
155
|
+
export type InvocationContext = LocalInvocationContext | SlackInvocationContext;
|
|
66
156
|
export interface AgentPluginSandbox {
|
|
67
157
|
juniorRoot: string;
|
|
68
158
|
root: string;
|
|
@@ -122,23 +212,19 @@ export interface AgentPluginToolDefinition<TInput = unknown> {
|
|
|
122
212
|
promptSnippet?: string;
|
|
123
213
|
execute?: AgentPluginToolExecute<TInput>;
|
|
124
214
|
}
|
|
125
|
-
export interface
|
|
215
|
+
export interface SlackToolRegistrationHookContext {
|
|
126
216
|
/**
|
|
127
|
-
* Capabilities of
|
|
128
|
-
*
|
|
217
|
+
* Capabilities of the source Slack conversation exposed to this plugin.
|
|
218
|
+
* Recomputed from `source.channelId`, not from `destination`.
|
|
129
219
|
*/
|
|
130
|
-
channelCapabilities
|
|
220
|
+
channelCapabilities: {
|
|
131
221
|
canAddReactions: boolean;
|
|
132
222
|
canCreateCanvas: boolean;
|
|
133
223
|
canPostToChannel: boolean;
|
|
134
224
|
};
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
* Use this as the stable binding key for state scoped to a Slack conversation.
|
|
139
|
-
* `channelCapabilities` describes this channel.
|
|
140
|
-
*/
|
|
141
|
-
channelId?: string;
|
|
225
|
+
credentialSubject?: AgentPluginCredentialSubject;
|
|
226
|
+
}
|
|
227
|
+
interface BaseToolRegistrationHookContext extends AgentPluginContext {
|
|
142
228
|
/**
|
|
143
229
|
* Opaque Junior conversation/session identity for this turn.
|
|
144
230
|
* Interactive Slack turns use `slack:{channelId}:{threadTs}`.
|
|
@@ -146,22 +232,26 @@ export interface ToolRegistrationHookContext extends AgentPluginContext {
|
|
|
146
232
|
* Do not parse as Slack unless the value starts with `slack:`.
|
|
147
233
|
*/
|
|
148
234
|
conversationId?: string;
|
|
149
|
-
credentialSubject?: AgentPluginCredentialSubject;
|
|
150
|
-
/**
|
|
151
|
-
* Runtime-owned destination suitable for future autonomous dispatch. For
|
|
152
|
-
* Slack, this is the raw conversation channel, not a thread timestamp or
|
|
153
|
-
* assistant-context source channel.
|
|
154
|
-
*/
|
|
155
|
-
destination?: Destination;
|
|
156
|
-
messageTs?: string;
|
|
157
|
-
requester?: Requester;
|
|
158
235
|
state: AgentPluginState;
|
|
159
|
-
teamId?: string;
|
|
160
|
-
threadTs?: string;
|
|
161
236
|
userText?: string;
|
|
162
237
|
}
|
|
238
|
+
interface SlackToolRegistrationContext extends BaseToolRegistrationHookContext, SlackInvocationContext {
|
|
239
|
+
slack: SlackToolRegistrationHookContext;
|
|
240
|
+
}
|
|
241
|
+
interface LocalToolRegistrationContext extends BaseToolRegistrationHookContext, LocalInvocationContext {
|
|
242
|
+
slack?: never;
|
|
243
|
+
}
|
|
244
|
+
export type ToolRegistrationHookContext = LocalToolRegistrationContext | SlackToolRegistrationContext;
|
|
163
245
|
export type AgentPluginCredentialSubject = z.output<typeof agentPluginCredentialSubjectSchema>;
|
|
164
246
|
export type Destination = z.output<typeof destinationSchema>;
|
|
247
|
+
export type SlackDestination = Extract<Destination, {
|
|
248
|
+
platform: "slack";
|
|
249
|
+
}>;
|
|
250
|
+
export type LocalDestination = Extract<Destination, {
|
|
251
|
+
platform: "local";
|
|
252
|
+
}>;
|
|
253
|
+
/** Narrow a runtime destination to the Slack-specific address shape. */
|
|
254
|
+
export declare function isSlackDestination(destination: Destination | undefined): destination is SlackDestination;
|
|
165
255
|
export type DispatchOptions = z.output<typeof dispatchOptionsSchema>;
|
|
166
256
|
export interface DispatchResult {
|
|
167
257
|
id: string;
|
|
@@ -481,6 +571,7 @@ export interface JuniorPluginManifest {
|
|
|
481
571
|
configKeys?: string[];
|
|
482
572
|
credentials?: JuniorPluginCredentials;
|
|
483
573
|
description: string;
|
|
574
|
+
displayName: string;
|
|
484
575
|
domains?: string[];
|
|
485
576
|
envVars?: Record<string, JuniorPluginEnvVarDeclaration>;
|
|
486
577
|
mcp?: JuniorPluginMcpConfig;
|
package/dist/index.js
CHANGED
|
@@ -2,28 +2,60 @@
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
var slackTeamIdSchema = z.string().regex(/^T[A-Z0-9]+$/);
|
|
4
4
|
var slackConversationIdSchema = z.string().regex(/^(C|G|D)[A-Z0-9]+$/);
|
|
5
|
+
var localConversationIdSchema = z.string().regex(/^local:[a-z0-9_-]+:[a-z0-9][a-z0-9_-]*$/);
|
|
5
6
|
var exactActorUserIdSchema = z.string().min(1).refine(
|
|
6
7
|
(value) => value === value.trim() && value.toLowerCase() !== "unknown"
|
|
7
8
|
);
|
|
8
9
|
var nonBlankStringSchema = z.string().refine((value) => value.trim().length > 0);
|
|
9
|
-
var
|
|
10
|
+
var slackDestinationSchema = z.object({
|
|
10
11
|
platform: z.literal("slack"),
|
|
11
12
|
teamId: slackTeamIdSchema,
|
|
12
13
|
channelId: slackConversationIdSchema
|
|
13
14
|
}).strict();
|
|
15
|
+
var localDestinationSchema = z.object({
|
|
16
|
+
platform: z.literal("local"),
|
|
17
|
+
conversationId: localConversationIdSchema
|
|
18
|
+
}).strict();
|
|
19
|
+
var destinationSchema = z.discriminatedUnion("platform", [
|
|
20
|
+
slackDestinationSchema,
|
|
21
|
+
localDestinationSchema
|
|
22
|
+
]);
|
|
23
|
+
var slackSourceSchema = z.object({
|
|
24
|
+
platform: z.literal("slack"),
|
|
25
|
+
teamId: slackTeamIdSchema,
|
|
26
|
+
channelId: slackConversationIdSchema,
|
|
27
|
+
messageTs: nonBlankStringSchema.optional(),
|
|
28
|
+
threadTs: nonBlankStringSchema.optional()
|
|
29
|
+
}).strict();
|
|
30
|
+
var localSourceSchema = localDestinationSchema;
|
|
31
|
+
var sourceSchema = z.discriminatedUnion("platform", [
|
|
32
|
+
slackSourceSchema,
|
|
33
|
+
localSourceSchema
|
|
34
|
+
]);
|
|
14
35
|
var agentPluginCredentialSubjectSchema = z.object({
|
|
15
36
|
type: z.literal("user"),
|
|
16
37
|
userId: exactActorUserIdSchema,
|
|
17
38
|
allowedWhen: z.literal("private-direct-conversation")
|
|
18
39
|
}).strict();
|
|
19
|
-
var
|
|
20
|
-
|
|
21
|
-
teamId: slackTeamIdSchema,
|
|
22
|
-
userId: exactActorUserIdSchema,
|
|
23
|
-
userName: nonBlankStringSchema.optional(),
|
|
40
|
+
var requesterProfileSchema = {
|
|
41
|
+
email: nonBlankStringSchema.optional(),
|
|
24
42
|
fullName: nonBlankStringSchema.optional(),
|
|
25
|
-
|
|
43
|
+
userId: exactActorUserIdSchema,
|
|
44
|
+
userName: nonBlankStringSchema.optional()
|
|
45
|
+
};
|
|
46
|
+
var slackRequesterSchema = z.object({
|
|
47
|
+
...requesterProfileSchema,
|
|
48
|
+
platform: z.literal("slack"),
|
|
49
|
+
teamId: slackTeamIdSchema
|
|
26
50
|
}).strict();
|
|
51
|
+
var localRequesterSchema = z.object({
|
|
52
|
+
...requesterProfileSchema,
|
|
53
|
+
platform: z.literal("local")
|
|
54
|
+
}).strict();
|
|
55
|
+
var requesterSchema = z.discriminatedUnion("platform", [
|
|
56
|
+
slackRequesterSchema,
|
|
57
|
+
localRequesterSchema
|
|
58
|
+
]);
|
|
27
59
|
var dispatchMetadataSchema = z.record(z.string(), z.string()).superRefine((metadata, ctx) => {
|
|
28
60
|
const entries = Object.entries(metadata);
|
|
29
61
|
if (entries.length > 20) {
|
|
@@ -61,7 +93,7 @@ var dispatchMetadataSchema = z.record(z.string(), z.string()).superRefine((metad
|
|
|
61
93
|
var dispatchOptionsSchema = z.object({
|
|
62
94
|
idempotencyKey: nonBlankStringSchema.pipe(z.string().max(512)),
|
|
63
95
|
credentialSubject: agentPluginCredentialSubjectSchema.optional(),
|
|
64
|
-
destination:
|
|
96
|
+
destination: slackDestinationSchema,
|
|
65
97
|
input: nonBlankStringSchema.pipe(z.string().max(32e3)),
|
|
66
98
|
metadata: dispatchMetadataSchema.optional()
|
|
67
99
|
}).strict();
|
|
@@ -71,6 +103,9 @@ var AgentPluginToolInputError = class extends Error {
|
|
|
71
103
|
this.name = "AgentPluginToolInputError";
|
|
72
104
|
}
|
|
73
105
|
};
|
|
106
|
+
function isSlackDestination(destination) {
|
|
107
|
+
return destination?.platform === "slack";
|
|
108
|
+
}
|
|
74
109
|
var agentPluginProviderNameSchema = z.string().regex(/^[a-z][a-z0-9-]*$/);
|
|
75
110
|
var agentPluginGrantNameSchema = z.string().regex(/^[a-z][a-z0-9.-]*$/);
|
|
76
111
|
var agentPluginGrantAccessSchema = z.union([
|
|
@@ -150,6 +185,11 @@ function defineJuniorPlugin(plugin) {
|
|
|
150
185
|
`Junior plugin registration name "${name}" must be a lowercase plugin identifier.`
|
|
151
186
|
);
|
|
152
187
|
}
|
|
188
|
+
if (typeof manifest.displayName !== "string" || !manifest.displayName.trim()) {
|
|
189
|
+
throw new Error(
|
|
190
|
+
`Junior plugin "${name}" manifest.displayName is required.`
|
|
191
|
+
);
|
|
192
|
+
}
|
|
153
193
|
if (typeof manifest.description !== "string" || !manifest.description.trim()) {
|
|
154
194
|
throw new Error(
|
|
155
195
|
`Junior plugin "${name}" manifest.description is required.`
|
|
@@ -178,5 +218,13 @@ export {
|
|
|
178
218
|
defineJuniorPlugin,
|
|
179
219
|
destinationSchema,
|
|
180
220
|
dispatchOptionsSchema,
|
|
181
|
-
|
|
221
|
+
isSlackDestination,
|
|
222
|
+
localDestinationSchema,
|
|
223
|
+
localRequesterSchema,
|
|
224
|
+
localSourceSchema,
|
|
225
|
+
requesterSchema,
|
|
226
|
+
slackDestinationSchema,
|
|
227
|
+
slackRequesterSchema,
|
|
228
|
+
slackSourceSchema,
|
|
229
|
+
sourceSchema
|
|
182
230
|
};
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -2,6 +2,9 @@ import { z } from "zod";
|
|
|
2
2
|
|
|
3
3
|
const slackTeamIdSchema = z.string().regex(/^T[A-Z0-9]+$/);
|
|
4
4
|
const slackConversationIdSchema = z.string().regex(/^(C|G|D)[A-Z0-9]+$/);
|
|
5
|
+
const localConversationIdSchema = z
|
|
6
|
+
.string()
|
|
7
|
+
.regex(/^local:[a-z0-9_-]+:[a-z0-9][a-z0-9_-]*$/);
|
|
5
8
|
const exactActorUserIdSchema = z
|
|
6
9
|
.string()
|
|
7
10
|
.min(1)
|
|
@@ -12,15 +15,49 @@ const nonBlankStringSchema = z
|
|
|
12
15
|
.string()
|
|
13
16
|
.refine((value) => value.trim().length > 0);
|
|
14
17
|
|
|
18
|
+
/** Runtime-owned Slack address for routing future work or side effects. */
|
|
19
|
+
export const slackDestinationSchema = z
|
|
20
|
+
.object({
|
|
21
|
+
platform: z.literal("slack"),
|
|
22
|
+
teamId: slackTeamIdSchema,
|
|
23
|
+
channelId: slackConversationIdSchema,
|
|
24
|
+
})
|
|
25
|
+
.strict();
|
|
26
|
+
|
|
27
|
+
/** Runtime-owned local CLI conversation address. */
|
|
28
|
+
export const localDestinationSchema = z
|
|
29
|
+
.object({
|
|
30
|
+
platform: z.literal("local"),
|
|
31
|
+
conversationId: localConversationIdSchema,
|
|
32
|
+
})
|
|
33
|
+
.strict();
|
|
34
|
+
|
|
15
35
|
/** Runtime-owned provider-neutral address for routing future work or side effects. */
|
|
16
|
-
export const destinationSchema = z
|
|
36
|
+
export const destinationSchema = z.discriminatedUnion("platform", [
|
|
37
|
+
slackDestinationSchema,
|
|
38
|
+
localDestinationSchema,
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
/** Runtime-owned Slack coordinates for the inbound invocation. */
|
|
42
|
+
export const slackSourceSchema = z
|
|
17
43
|
.object({
|
|
18
44
|
platform: z.literal("slack"),
|
|
19
45
|
teamId: slackTeamIdSchema,
|
|
20
46
|
channelId: slackConversationIdSchema,
|
|
47
|
+
messageTs: nonBlankStringSchema.optional(),
|
|
48
|
+
threadTs: nonBlankStringSchema.optional(),
|
|
21
49
|
})
|
|
22
50
|
.strict();
|
|
23
51
|
|
|
52
|
+
/** Runtime-owned local CLI coordinates for the inbound invocation. */
|
|
53
|
+
export const localSourceSchema = localDestinationSchema;
|
|
54
|
+
|
|
55
|
+
/** Runtime-owned provider-neutral coordinates for the inbound invocation. */
|
|
56
|
+
export const sourceSchema = z.discriminatedUnion("platform", [
|
|
57
|
+
slackSourceSchema,
|
|
58
|
+
localSourceSchema,
|
|
59
|
+
]);
|
|
60
|
+
|
|
24
61
|
/** Stable user credential subject shape accepted from plugins. */
|
|
25
62
|
export const agentPluginCredentialSubjectSchema = z
|
|
26
63
|
.object({
|
|
@@ -30,18 +67,35 @@ export const agentPluginCredentialSubjectSchema = z
|
|
|
30
67
|
})
|
|
31
68
|
.strict();
|
|
32
69
|
|
|
33
|
-
/**
|
|
34
|
-
|
|
70
|
+
/** Shared exact actor profile fields for platform-scoped requesters. */
|
|
71
|
+
const requesterProfileSchema = {
|
|
72
|
+
email: nonBlankStringSchema.optional(),
|
|
73
|
+
fullName: nonBlankStringSchema.optional(),
|
|
74
|
+
userId: exactActorUserIdSchema,
|
|
75
|
+
userName: nonBlankStringSchema.optional(),
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const slackRequesterSchema = z
|
|
35
79
|
.object({
|
|
80
|
+
...requesterProfileSchema,
|
|
36
81
|
platform: z.literal("slack"),
|
|
37
82
|
teamId: slackTeamIdSchema,
|
|
38
|
-
userId: exactActorUserIdSchema,
|
|
39
|
-
userName: nonBlankStringSchema.optional(),
|
|
40
|
-
fullName: nonBlankStringSchema.optional(),
|
|
41
|
-
email: nonBlankStringSchema.optional(),
|
|
42
83
|
})
|
|
43
84
|
.strict();
|
|
44
85
|
|
|
86
|
+
export const localRequesterSchema = z
|
|
87
|
+
.object({
|
|
88
|
+
...requesterProfileSchema,
|
|
89
|
+
platform: z.literal("local"),
|
|
90
|
+
})
|
|
91
|
+
.strict();
|
|
92
|
+
|
|
93
|
+
/** Runtime-provided requester identity visible to plugin hooks. */
|
|
94
|
+
export const requesterSchema = z.discriminatedUnion("platform", [
|
|
95
|
+
slackRequesterSchema,
|
|
96
|
+
localRequesterSchema,
|
|
97
|
+
]);
|
|
98
|
+
|
|
45
99
|
const dispatchMetadataSchema = z
|
|
46
100
|
.record(z.string(), z.string())
|
|
47
101
|
.superRefine((metadata, ctx) => {
|
|
@@ -84,13 +138,18 @@ export const dispatchOptionsSchema = z
|
|
|
84
138
|
.object({
|
|
85
139
|
idempotencyKey: nonBlankStringSchema.pipe(z.string().max(512)),
|
|
86
140
|
credentialSubject: agentPluginCredentialSubjectSchema.optional(),
|
|
87
|
-
destination:
|
|
141
|
+
destination: slackDestinationSchema,
|
|
88
142
|
input: nonBlankStringSchema.pipe(z.string().max(32_000)),
|
|
89
143
|
metadata: dispatchMetadataSchema.optional(),
|
|
90
144
|
})
|
|
91
145
|
.strict();
|
|
92
146
|
|
|
93
147
|
export type Requester = z.output<typeof requesterSchema>;
|
|
148
|
+
export type SlackRequester = z.output<typeof slackRequesterSchema>;
|
|
149
|
+
export type LocalRequester = z.output<typeof localRequesterSchema>;
|
|
150
|
+
export type Source = z.output<typeof sourceSchema>;
|
|
151
|
+
export type SlackSource = Extract<Source, { platform: "slack" }>;
|
|
152
|
+
export type LocalSource = Extract<Source, { platform: "local" }>;
|
|
94
153
|
|
|
95
154
|
export interface AgentPluginMetadata {
|
|
96
155
|
name: string;
|
|
@@ -125,6 +184,32 @@ export interface AgentPluginContext {
|
|
|
125
184
|
plugin: AgentPluginMetadata;
|
|
126
185
|
}
|
|
127
186
|
|
|
187
|
+
interface BaseInvocationContext {
|
|
188
|
+
/**
|
|
189
|
+
* Opaque Junior conversation/session identity for this invocation.
|
|
190
|
+
* Interactive Slack turns use `slack:{channelId}:{threadTs}`.
|
|
191
|
+
*/
|
|
192
|
+
conversationId?: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export interface SlackInvocationContext extends BaseInvocationContext {
|
|
196
|
+
/** Runtime-owned default outbound destination for this invocation, if any. */
|
|
197
|
+
destination?: SlackDestination;
|
|
198
|
+
requester?: SlackRequester;
|
|
199
|
+
/** Runtime-owned source where the invocation came from. */
|
|
200
|
+
source: SlackSource;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export interface LocalInvocationContext extends BaseInvocationContext {
|
|
204
|
+
/** Runtime-owned default outbound destination for this invocation, if any. */
|
|
205
|
+
destination?: LocalDestination;
|
|
206
|
+
requester?: LocalRequester;
|
|
207
|
+
/** Runtime-owned source where the invocation came from. */
|
|
208
|
+
source: LocalSource;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export type InvocationContext = LocalInvocationContext | SlackInvocationContext;
|
|
212
|
+
|
|
128
213
|
export interface AgentPluginSandbox {
|
|
129
214
|
juniorRoot: string;
|
|
130
215
|
root: string;
|
|
@@ -190,23 +275,20 @@ export interface AgentPluginToolDefinition<TInput = unknown> {
|
|
|
190
275
|
execute?: AgentPluginToolExecute<TInput>;
|
|
191
276
|
}
|
|
192
277
|
|
|
193
|
-
export interface
|
|
278
|
+
export interface SlackToolRegistrationHookContext {
|
|
194
279
|
/**
|
|
195
|
-
* Capabilities of
|
|
196
|
-
*
|
|
280
|
+
* Capabilities of the source Slack conversation exposed to this plugin.
|
|
281
|
+
* Recomputed from `source.channelId`, not from `destination`.
|
|
197
282
|
*/
|
|
198
|
-
channelCapabilities
|
|
283
|
+
channelCapabilities: {
|
|
199
284
|
canAddReactions: boolean;
|
|
200
285
|
canCreateCanvas: boolean;
|
|
201
286
|
canPostToChannel: boolean;
|
|
202
287
|
};
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
* `channelCapabilities` describes this channel.
|
|
208
|
-
*/
|
|
209
|
-
channelId?: string;
|
|
288
|
+
credentialSubject?: AgentPluginCredentialSubject;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
interface BaseToolRegistrationHookContext extends AgentPluginContext {
|
|
210
292
|
/**
|
|
211
293
|
* Opaque Junior conversation/session identity for this turn.
|
|
212
294
|
* Interactive Slack turns use `slack:{channelId}:{threadTs}`.
|
|
@@ -214,27 +296,41 @@ export interface ToolRegistrationHookContext extends AgentPluginContext {
|
|
|
214
296
|
* Do not parse as Slack unless the value starts with `slack:`.
|
|
215
297
|
*/
|
|
216
298
|
conversationId?: string;
|
|
217
|
-
credentialSubject?: AgentPluginCredentialSubject;
|
|
218
|
-
/**
|
|
219
|
-
* Runtime-owned destination suitable for future autonomous dispatch. For
|
|
220
|
-
* Slack, this is the raw conversation channel, not a thread timestamp or
|
|
221
|
-
* assistant-context source channel.
|
|
222
|
-
*/
|
|
223
|
-
destination?: Destination;
|
|
224
|
-
messageTs?: string;
|
|
225
|
-
requester?: Requester;
|
|
226
299
|
state: AgentPluginState;
|
|
227
|
-
teamId?: string;
|
|
228
|
-
threadTs?: string;
|
|
229
300
|
userText?: string;
|
|
230
301
|
}
|
|
231
302
|
|
|
303
|
+
interface SlackToolRegistrationContext
|
|
304
|
+
extends BaseToolRegistrationHookContext, SlackInvocationContext {
|
|
305
|
+
slack: SlackToolRegistrationHookContext;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
interface LocalToolRegistrationContext
|
|
309
|
+
extends BaseToolRegistrationHookContext, LocalInvocationContext {
|
|
310
|
+
slack?: never;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export type ToolRegistrationHookContext =
|
|
314
|
+
| LocalToolRegistrationContext
|
|
315
|
+
| SlackToolRegistrationContext;
|
|
316
|
+
|
|
232
317
|
export type AgentPluginCredentialSubject = z.output<
|
|
233
318
|
typeof agentPluginCredentialSubjectSchema
|
|
234
319
|
>;
|
|
235
320
|
|
|
236
321
|
export type Destination = z.output<typeof destinationSchema>;
|
|
237
322
|
|
|
323
|
+
export type SlackDestination = Extract<Destination, { platform: "slack" }>;
|
|
324
|
+
|
|
325
|
+
export type LocalDestination = Extract<Destination, { platform: "local" }>;
|
|
326
|
+
|
|
327
|
+
/** Narrow a runtime destination to the Slack-specific address shape. */
|
|
328
|
+
export function isSlackDestination(
|
|
329
|
+
destination: Destination | undefined,
|
|
330
|
+
): destination is SlackDestination {
|
|
331
|
+
return destination?.platform === "slack";
|
|
332
|
+
}
|
|
333
|
+
|
|
238
334
|
export type DispatchOptions = z.output<typeof dispatchOptionsSchema>;
|
|
239
335
|
|
|
240
336
|
export interface DispatchResult {
|
|
@@ -672,6 +768,7 @@ export interface JuniorPluginManifest {
|
|
|
672
768
|
configKeys?: string[];
|
|
673
769
|
credentials?: JuniorPluginCredentials;
|
|
674
770
|
description: string;
|
|
771
|
+
displayName: string;
|
|
675
772
|
domains?: string[];
|
|
676
773
|
envVars?: Record<string, JuniorPluginEnvVarDeclaration>;
|
|
677
774
|
mcp?: JuniorPluginMcpConfig;
|
|
@@ -726,6 +823,14 @@ export function defineJuniorPlugin(
|
|
|
726
823
|
`Junior plugin registration name "${name}" must be a lowercase plugin identifier.`,
|
|
727
824
|
);
|
|
728
825
|
}
|
|
826
|
+
if (
|
|
827
|
+
typeof manifest.displayName !== "string" ||
|
|
828
|
+
!manifest.displayName.trim()
|
|
829
|
+
) {
|
|
830
|
+
throw new Error(
|
|
831
|
+
`Junior plugin "${name}" manifest.displayName is required.`,
|
|
832
|
+
);
|
|
833
|
+
}
|
|
729
834
|
if (
|
|
730
835
|
typeof manifest.description !== "string" ||
|
|
731
836
|
!manifest.description.trim()
|