@sentry/junior-plugin-api 0.71.3 → 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 +123 -30
- package/dist/index.js +58 -8
- package/package.json +1 -1
- package/src/index.ts +140 -33
package/dist/index.d.ts
CHANGED
|
@@ -1,23 +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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
52
|
+
export declare const slackRequesterSchema: z.ZodObject<{
|
|
53
|
+
platform: z.ZodLiteral<"slack">;
|
|
54
|
+
teamId: z.ZodString;
|
|
55
|
+
email: z.ZodOptional<z.ZodString>;
|
|
18
56
|
fullName: z.ZodOptional<z.ZodString>;
|
|
57
|
+
userId: z.ZodString;
|
|
58
|
+
userName: z.ZodOptional<z.ZodString>;
|
|
59
|
+
}, z.core.$strict>;
|
|
60
|
+
export declare const localRequesterSchema: z.ZodObject<{
|
|
61
|
+
platform: z.ZodLiteral<"local">;
|
|
19
62
|
email: z.ZodOptional<z.ZodString>;
|
|
63
|
+
fullName: z.ZodOptional<z.ZodString>;
|
|
64
|
+
userId: z.ZodString;
|
|
65
|
+
userName: z.ZodOptional<z.ZodString>;
|
|
20
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">;
|
|
21
82
|
/** Plugin dispatch request accepted by Junior core. */
|
|
22
83
|
export declare const dispatchOptionsSchema: z.ZodObject<{
|
|
23
84
|
idempotencyKey: z.ZodPipe<z.ZodString, z.ZodString>;
|
|
@@ -34,7 +95,16 @@ export declare const dispatchOptionsSchema: z.ZodObject<{
|
|
|
34
95
|
input: z.ZodPipe<z.ZodString, z.ZodString>;
|
|
35
96
|
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
36
97
|
}, z.core.$strict>;
|
|
37
|
-
export type
|
|
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
|
+
}>;
|
|
38
108
|
export interface AgentPluginMetadata {
|
|
39
109
|
name: string;
|
|
40
110
|
}
|
|
@@ -61,6 +131,28 @@ export interface AgentPluginContext {
|
|
|
61
131
|
log: AgentPluginLogger;
|
|
62
132
|
plugin: AgentPluginMetadata;
|
|
63
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;
|
|
64
156
|
export interface AgentPluginSandbox {
|
|
65
157
|
juniorRoot: string;
|
|
66
158
|
root: string;
|
|
@@ -83,13 +175,13 @@ export interface AgentPluginSandbox {
|
|
|
83
175
|
}): Promise<void>;
|
|
84
176
|
}
|
|
85
177
|
export interface SandboxPrepareHookContext extends AgentPluginContext {
|
|
86
|
-
requester?:
|
|
178
|
+
requester?: Requester;
|
|
87
179
|
sandbox: AgentPluginSandbox;
|
|
88
180
|
}
|
|
89
181
|
export interface BeforeToolExecuteHookContext extends AgentPluginContext {
|
|
90
182
|
decision: AgentPluginDecision;
|
|
91
183
|
env: AgentPluginEnv;
|
|
92
|
-
requester?:
|
|
184
|
+
requester?: Requester;
|
|
93
185
|
tool: {
|
|
94
186
|
input: Record<string, unknown>;
|
|
95
187
|
name: string;
|
|
@@ -120,23 +212,19 @@ export interface AgentPluginToolDefinition<TInput = unknown> {
|
|
|
120
212
|
promptSnippet?: string;
|
|
121
213
|
execute?: AgentPluginToolExecute<TInput>;
|
|
122
214
|
}
|
|
123
|
-
export interface
|
|
215
|
+
export interface SlackToolRegistrationHookContext {
|
|
124
216
|
/**
|
|
125
|
-
* Capabilities of
|
|
126
|
-
*
|
|
217
|
+
* Capabilities of the source Slack conversation exposed to this plugin.
|
|
218
|
+
* Recomputed from `source.channelId`, not from `destination`.
|
|
127
219
|
*/
|
|
128
|
-
channelCapabilities
|
|
220
|
+
channelCapabilities: {
|
|
129
221
|
canAddReactions: boolean;
|
|
130
222
|
canCreateCanvas: boolean;
|
|
131
223
|
canPostToChannel: boolean;
|
|
132
224
|
};
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
* Use this as the stable binding key for state scoped to a Slack conversation.
|
|
137
|
-
* `channelCapabilities` describes this channel.
|
|
138
|
-
*/
|
|
139
|
-
channelId?: string;
|
|
225
|
+
credentialSubject?: AgentPluginCredentialSubject;
|
|
226
|
+
}
|
|
227
|
+
interface BaseToolRegistrationHookContext extends AgentPluginContext {
|
|
140
228
|
/**
|
|
141
229
|
* Opaque Junior conversation/session identity for this turn.
|
|
142
230
|
* Interactive Slack turns use `slack:{channelId}:{threadTs}`.
|
|
@@ -144,22 +232,26 @@ export interface ToolRegistrationHookContext extends AgentPluginContext {
|
|
|
144
232
|
* Do not parse as Slack unless the value starts with `slack:`.
|
|
145
233
|
*/
|
|
146
234
|
conversationId?: string;
|
|
147
|
-
credentialSubject?: AgentPluginCredentialSubject;
|
|
148
|
-
/**
|
|
149
|
-
* Runtime-owned destination suitable for future autonomous dispatch. For
|
|
150
|
-
* Slack, this is the raw conversation channel, not a thread timestamp or
|
|
151
|
-
* assistant-context source channel.
|
|
152
|
-
*/
|
|
153
|
-
destination?: Destination;
|
|
154
|
-
messageTs?: string;
|
|
155
|
-
requester?: AgentPluginRequester;
|
|
156
235
|
state: AgentPluginState;
|
|
157
|
-
teamId?: string;
|
|
158
|
-
threadTs?: string;
|
|
159
236
|
userText?: string;
|
|
160
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;
|
|
161
245
|
export type AgentPluginCredentialSubject = z.output<typeof agentPluginCredentialSubjectSchema>;
|
|
162
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;
|
|
163
255
|
export type DispatchOptions = z.output<typeof dispatchOptionsSchema>;
|
|
164
256
|
export interface DispatchResult {
|
|
165
257
|
id: string;
|
|
@@ -479,6 +571,7 @@ export interface JuniorPluginManifest {
|
|
|
479
571
|
configKeys?: string[];
|
|
480
572
|
credentials?: JuniorPluginCredentials;
|
|
481
573
|
description: string;
|
|
574
|
+
displayName: string;
|
|
482
575
|
domains?: string[];
|
|
483
576
|
envVars?: Record<string, JuniorPluginEnvVarDeclaration>;
|
|
484
577
|
mcp?: JuniorPluginMcpConfig;
|
package/dist/index.js
CHANGED
|
@@ -2,26 +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
|
-
userName: nonBlankStringSchema.optional(),
|
|
40
|
+
var requesterProfileSchema = {
|
|
41
|
+
email: nonBlankStringSchema.optional(),
|
|
22
42
|
fullName: nonBlankStringSchema.optional(),
|
|
23
|
-
|
|
43
|
+
userId: exactActorUserIdSchema,
|
|
44
|
+
userName: nonBlankStringSchema.optional()
|
|
45
|
+
};
|
|
46
|
+
var slackRequesterSchema = z.object({
|
|
47
|
+
...requesterProfileSchema,
|
|
48
|
+
platform: z.literal("slack"),
|
|
49
|
+
teamId: slackTeamIdSchema
|
|
50
|
+
}).strict();
|
|
51
|
+
var localRequesterSchema = z.object({
|
|
52
|
+
...requesterProfileSchema,
|
|
53
|
+
platform: z.literal("local")
|
|
24
54
|
}).strict();
|
|
55
|
+
var requesterSchema = z.discriminatedUnion("platform", [
|
|
56
|
+
slackRequesterSchema,
|
|
57
|
+
localRequesterSchema
|
|
58
|
+
]);
|
|
25
59
|
var dispatchMetadataSchema = z.record(z.string(), z.string()).superRefine((metadata, ctx) => {
|
|
26
60
|
const entries = Object.entries(metadata);
|
|
27
61
|
if (entries.length > 20) {
|
|
@@ -59,7 +93,7 @@ var dispatchMetadataSchema = z.record(z.string(), z.string()).superRefine((metad
|
|
|
59
93
|
var dispatchOptionsSchema = z.object({
|
|
60
94
|
idempotencyKey: nonBlankStringSchema.pipe(z.string().max(512)),
|
|
61
95
|
credentialSubject: agentPluginCredentialSubjectSchema.optional(),
|
|
62
|
-
destination:
|
|
96
|
+
destination: slackDestinationSchema,
|
|
63
97
|
input: nonBlankStringSchema.pipe(z.string().max(32e3)),
|
|
64
98
|
metadata: dispatchMetadataSchema.optional()
|
|
65
99
|
}).strict();
|
|
@@ -69,6 +103,9 @@ var AgentPluginToolInputError = class extends Error {
|
|
|
69
103
|
this.name = "AgentPluginToolInputError";
|
|
70
104
|
}
|
|
71
105
|
};
|
|
106
|
+
function isSlackDestination(destination) {
|
|
107
|
+
return destination?.platform === "slack";
|
|
108
|
+
}
|
|
72
109
|
var agentPluginProviderNameSchema = z.string().regex(/^[a-z][a-z0-9-]*$/);
|
|
73
110
|
var agentPluginGrantNameSchema = z.string().regex(/^[a-z][a-z0-9.-]*$/);
|
|
74
111
|
var agentPluginGrantAccessSchema = z.union([
|
|
@@ -148,6 +185,11 @@ function defineJuniorPlugin(plugin) {
|
|
|
148
185
|
`Junior plugin registration name "${name}" must be a lowercase plugin identifier.`
|
|
149
186
|
);
|
|
150
187
|
}
|
|
188
|
+
if (typeof manifest.displayName !== "string" || !manifest.displayName.trim()) {
|
|
189
|
+
throw new Error(
|
|
190
|
+
`Junior plugin "${name}" manifest.displayName is required.`
|
|
191
|
+
);
|
|
192
|
+
}
|
|
151
193
|
if (typeof manifest.description !== "string" || !manifest.description.trim()) {
|
|
152
194
|
throw new Error(
|
|
153
195
|
`Junior plugin "${name}" manifest.description is required.`
|
|
@@ -173,8 +215,16 @@ export {
|
|
|
173
215
|
agentPluginCredentialSubjectSchema,
|
|
174
216
|
agentPluginGrantSchema,
|
|
175
217
|
agentPluginProviderAccountSchema,
|
|
176
|
-
agentPluginRequesterSchema,
|
|
177
218
|
defineJuniorPlugin,
|
|
178
219
|
destinationSchema,
|
|
179
|
-
dispatchOptionsSchema
|
|
220
|
+
dispatchOptionsSchema,
|
|
221
|
+
isSlackDestination,
|
|
222
|
+
localDestinationSchema,
|
|
223
|
+
localRequesterSchema,
|
|
224
|
+
localSourceSchema,
|
|
225
|
+
requesterSchema,
|
|
226
|
+
slackDestinationSchema,
|
|
227
|
+
slackRequesterSchema,
|
|
228
|
+
slackSourceSchema,
|
|
229
|
+
sourceSchema
|
|
180
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,16 +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({
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
email: nonBlankStringSchema.optional(),
|
|
80
|
+
...requesterProfileSchema,
|
|
81
|
+
platform: z.literal("slack"),
|
|
82
|
+
teamId: slackTeamIdSchema,
|
|
40
83
|
})
|
|
41
84
|
.strict();
|
|
42
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
|
+
|
|
43
99
|
const dispatchMetadataSchema = z
|
|
44
100
|
.record(z.string(), z.string())
|
|
45
101
|
.superRefine((metadata, ctx) => {
|
|
@@ -82,13 +138,18 @@ export const dispatchOptionsSchema = z
|
|
|
82
138
|
.object({
|
|
83
139
|
idempotencyKey: nonBlankStringSchema.pipe(z.string().max(512)),
|
|
84
140
|
credentialSubject: agentPluginCredentialSubjectSchema.optional(),
|
|
85
|
-
destination:
|
|
141
|
+
destination: slackDestinationSchema,
|
|
86
142
|
input: nonBlankStringSchema.pipe(z.string().max(32_000)),
|
|
87
143
|
metadata: dispatchMetadataSchema.optional(),
|
|
88
144
|
})
|
|
89
145
|
.strict();
|
|
90
146
|
|
|
91
|
-
export type
|
|
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" }>;
|
|
92
153
|
|
|
93
154
|
export interface AgentPluginMetadata {
|
|
94
155
|
name: string;
|
|
@@ -123,6 +184,32 @@ export interface AgentPluginContext {
|
|
|
123
184
|
plugin: AgentPluginMetadata;
|
|
124
185
|
}
|
|
125
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
|
+
|
|
126
213
|
export interface AgentPluginSandbox {
|
|
127
214
|
juniorRoot: string;
|
|
128
215
|
root: string;
|
|
@@ -146,14 +233,14 @@ export interface AgentPluginSandbox {
|
|
|
146
233
|
}
|
|
147
234
|
|
|
148
235
|
export interface SandboxPrepareHookContext extends AgentPluginContext {
|
|
149
|
-
requester?:
|
|
236
|
+
requester?: Requester;
|
|
150
237
|
sandbox: AgentPluginSandbox;
|
|
151
238
|
}
|
|
152
239
|
|
|
153
240
|
export interface BeforeToolExecuteHookContext extends AgentPluginContext {
|
|
154
241
|
decision: AgentPluginDecision;
|
|
155
242
|
env: AgentPluginEnv;
|
|
156
|
-
requester?:
|
|
243
|
+
requester?: Requester;
|
|
157
244
|
tool: {
|
|
158
245
|
input: Record<string, unknown>;
|
|
159
246
|
name: string;
|
|
@@ -188,23 +275,20 @@ export interface AgentPluginToolDefinition<TInput = unknown> {
|
|
|
188
275
|
execute?: AgentPluginToolExecute<TInput>;
|
|
189
276
|
}
|
|
190
277
|
|
|
191
|
-
export interface
|
|
278
|
+
export interface SlackToolRegistrationHookContext {
|
|
192
279
|
/**
|
|
193
|
-
* Capabilities of
|
|
194
|
-
*
|
|
280
|
+
* Capabilities of the source Slack conversation exposed to this plugin.
|
|
281
|
+
* Recomputed from `source.channelId`, not from `destination`.
|
|
195
282
|
*/
|
|
196
|
-
channelCapabilities
|
|
283
|
+
channelCapabilities: {
|
|
197
284
|
canAddReactions: boolean;
|
|
198
285
|
canCreateCanvas: boolean;
|
|
199
286
|
canPostToChannel: boolean;
|
|
200
287
|
};
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
* `channelCapabilities` describes this channel.
|
|
206
|
-
*/
|
|
207
|
-
channelId?: string;
|
|
288
|
+
credentialSubject?: AgentPluginCredentialSubject;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
interface BaseToolRegistrationHookContext extends AgentPluginContext {
|
|
208
292
|
/**
|
|
209
293
|
* Opaque Junior conversation/session identity for this turn.
|
|
210
294
|
* Interactive Slack turns use `slack:{channelId}:{threadTs}`.
|
|
@@ -212,27 +296,41 @@ export interface ToolRegistrationHookContext extends AgentPluginContext {
|
|
|
212
296
|
* Do not parse as Slack unless the value starts with `slack:`.
|
|
213
297
|
*/
|
|
214
298
|
conversationId?: string;
|
|
215
|
-
credentialSubject?: AgentPluginCredentialSubject;
|
|
216
|
-
/**
|
|
217
|
-
* Runtime-owned destination suitable for future autonomous dispatch. For
|
|
218
|
-
* Slack, this is the raw conversation channel, not a thread timestamp or
|
|
219
|
-
* assistant-context source channel.
|
|
220
|
-
*/
|
|
221
|
-
destination?: Destination;
|
|
222
|
-
messageTs?: string;
|
|
223
|
-
requester?: AgentPluginRequester;
|
|
224
299
|
state: AgentPluginState;
|
|
225
|
-
teamId?: string;
|
|
226
|
-
threadTs?: string;
|
|
227
300
|
userText?: string;
|
|
228
301
|
}
|
|
229
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
|
+
|
|
230
317
|
export type AgentPluginCredentialSubject = z.output<
|
|
231
318
|
typeof agentPluginCredentialSubjectSchema
|
|
232
319
|
>;
|
|
233
320
|
|
|
234
321
|
export type Destination = z.output<typeof destinationSchema>;
|
|
235
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
|
+
|
|
236
334
|
export type DispatchOptions = z.output<typeof dispatchOptionsSchema>;
|
|
237
335
|
|
|
238
336
|
export interface DispatchResult {
|
|
@@ -670,6 +768,7 @@ export interface JuniorPluginManifest {
|
|
|
670
768
|
configKeys?: string[];
|
|
671
769
|
credentials?: JuniorPluginCredentials;
|
|
672
770
|
description: string;
|
|
771
|
+
displayName: string;
|
|
673
772
|
domains?: string[];
|
|
674
773
|
envVars?: Record<string, JuniorPluginEnvVarDeclaration>;
|
|
675
774
|
mcp?: JuniorPluginMcpConfig;
|
|
@@ -724,6 +823,14 @@ export function defineJuniorPlugin(
|
|
|
724
823
|
`Junior plugin registration name "${name}" must be a lowercase plugin identifier.`,
|
|
725
824
|
);
|
|
726
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
|
+
}
|
|
727
834
|
if (
|
|
728
835
|
typeof manifest.description !== "string" ||
|
|
729
836
|
!manifest.description.trim()
|