@sentry/junior-plugin-api 0.72.0 → 0.74.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 +133 -26
- package/dist/index.js +57 -9
- package/package.json +1 -1
- package/src/index.ts +159 -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;
|
|
@@ -183,6 +273,21 @@ export interface AgentPluginState {
|
|
|
183
273
|
export interface AgentPluginReadState {
|
|
184
274
|
get<T = unknown>(key: string): Promise<T | undefined>;
|
|
185
275
|
}
|
|
276
|
+
export type AgentPluginConversationStatus = "active" | "completed" | "failed" | "hung" | "superseded";
|
|
277
|
+
export interface AgentPluginConversationSummary {
|
|
278
|
+
channelName?: string;
|
|
279
|
+
conversationId: string;
|
|
280
|
+
displayTitle: string;
|
|
281
|
+
lastActivityAt: string;
|
|
282
|
+
lastUpdatedAt: string;
|
|
283
|
+
source?: "api" | "internal" | "local" | "plugin" | "scheduler" | "slack";
|
|
284
|
+
status: AgentPluginConversationStatus;
|
|
285
|
+
}
|
|
286
|
+
export interface AgentPluginConversations {
|
|
287
|
+
listRecent(options?: {
|
|
288
|
+
limit?: number;
|
|
289
|
+
}): Promise<AgentPluginConversationSummary[]>;
|
|
290
|
+
}
|
|
186
291
|
export interface HeartbeatHookContext extends AgentPluginContext {
|
|
187
292
|
agent: {
|
|
188
293
|
dispatch(options: DispatchOptions): Promise<DispatchResult>;
|
|
@@ -225,6 +330,7 @@ export interface PluginOperationalReport extends PluginOperationalReportContent
|
|
|
225
330
|
pluginName: string;
|
|
226
331
|
}
|
|
227
332
|
export interface OperationalReportHookContext extends AgentPluginContext {
|
|
333
|
+
conversations: AgentPluginConversations;
|
|
228
334
|
nowMs: number;
|
|
229
335
|
state: AgentPluginReadState;
|
|
230
336
|
}
|
|
@@ -481,6 +587,7 @@ export interface JuniorPluginManifest {
|
|
|
481
587
|
configKeys?: string[];
|
|
482
588
|
credentials?: JuniorPluginCredentials;
|
|
483
589
|
description: string;
|
|
590
|
+
displayName: string;
|
|
484
591
|
domains?: string[];
|
|
485
592
|
envVars?: Record<string, JuniorPluginEnvVarDeclaration>;
|
|
486
593
|
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 {
|
|
@@ -271,6 +367,29 @@ export interface AgentPluginReadState {
|
|
|
271
367
|
get<T = unknown>(key: string): Promise<T | undefined>;
|
|
272
368
|
}
|
|
273
369
|
|
|
370
|
+
export type AgentPluginConversationStatus =
|
|
371
|
+
| "active"
|
|
372
|
+
| "completed"
|
|
373
|
+
| "failed"
|
|
374
|
+
| "hung"
|
|
375
|
+
| "superseded";
|
|
376
|
+
|
|
377
|
+
export interface AgentPluginConversationSummary {
|
|
378
|
+
channelName?: string;
|
|
379
|
+
conversationId: string;
|
|
380
|
+
displayTitle: string;
|
|
381
|
+
lastActivityAt: string;
|
|
382
|
+
lastUpdatedAt: string;
|
|
383
|
+
source?: "api" | "internal" | "local" | "plugin" | "scheduler" | "slack";
|
|
384
|
+
status: AgentPluginConversationStatus;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export interface AgentPluginConversations {
|
|
388
|
+
listRecent(options?: {
|
|
389
|
+
limit?: number;
|
|
390
|
+
}): Promise<AgentPluginConversationSummary[]>;
|
|
391
|
+
}
|
|
392
|
+
|
|
274
393
|
export interface HeartbeatHookContext extends AgentPluginContext {
|
|
275
394
|
agent: {
|
|
276
395
|
dispatch(options: DispatchOptions): Promise<DispatchResult>;
|
|
@@ -322,6 +441,7 @@ export interface PluginOperationalReport extends PluginOperationalReportContent
|
|
|
322
441
|
}
|
|
323
442
|
|
|
324
443
|
export interface OperationalReportHookContext extends AgentPluginContext {
|
|
444
|
+
conversations: AgentPluginConversations;
|
|
325
445
|
nowMs: number;
|
|
326
446
|
state: AgentPluginReadState;
|
|
327
447
|
}
|
|
@@ -672,6 +792,7 @@ export interface JuniorPluginManifest {
|
|
|
672
792
|
configKeys?: string[];
|
|
673
793
|
credentials?: JuniorPluginCredentials;
|
|
674
794
|
description: string;
|
|
795
|
+
displayName: string;
|
|
675
796
|
domains?: string[];
|
|
676
797
|
envVars?: Record<string, JuniorPluginEnvVarDeclaration>;
|
|
677
798
|
mcp?: JuniorPluginMcpConfig;
|
|
@@ -726,6 +847,14 @@ export function defineJuniorPlugin(
|
|
|
726
847
|
`Junior plugin registration name "${name}" must be a lowercase plugin identifier.`,
|
|
727
848
|
);
|
|
728
849
|
}
|
|
850
|
+
if (
|
|
851
|
+
typeof manifest.displayName !== "string" ||
|
|
852
|
+
!manifest.displayName.trim()
|
|
853
|
+
) {
|
|
854
|
+
throw new Error(
|
|
855
|
+
`Junior plugin "${name}" manifest.displayName is required.`,
|
|
856
|
+
);
|
|
857
|
+
}
|
|
729
858
|
if (
|
|
730
859
|
typeof manifest.description !== "string" ||
|
|
731
860
|
!manifest.description.trim()
|