@sentry/junior-plugin-api 0.74.1 → 0.76.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/cli.d.ts +39 -0
- package/dist/context.d.ts +97 -0
- package/dist/credentials.d.ts +167 -0
- package/dist/dispatch.d.ts +13 -0
- package/dist/hooks.d.ts +20 -0
- package/dist/index.d.ts +13 -616
- package/dist/index.js +178 -69
- package/dist/manifest.d.ts +74 -0
- package/dist/operations.d.ts +91 -0
- package/dist/prompt.d.ts +22 -0
- package/dist/registration.d.ts +22 -0
- package/dist/schemas.d.ts +133 -0
- package/dist/state.d.ts +10 -0
- package/dist/tasks.d.ts +98 -0
- package/dist/tools.d.ts +116 -0
- package/package.json +2 -1
- package/src/cli.ts +54 -0
- package/src/context.ts +146 -0
- package/src/credentials.ts +208 -0
- package/src/dispatch.ts +22 -0
- package/src/hooks.ts +78 -0
- package/src/index.ts +18 -875
- package/src/manifest.ts +87 -0
- package/src/operations.ts +124 -0
- package/src/prompt.ts +38 -0
- package/src/registration.ts +72 -0
- package/src/schemas.ts +173 -0
- package/src/state.ts +15 -0
- package/src/tasks.ts +68 -0
- package/src/tools.ts +144 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { PluginContext } from "./context";
|
|
3
|
+
import { nonBlankStringSchema, pluginCredentialSubjectSchema } from "./schemas";
|
|
4
|
+
|
|
5
|
+
const pluginProviderNameSchema = z.string().regex(/^[a-z][a-z0-9-]*$/);
|
|
6
|
+
const pluginGrantNameSchema = z.string().regex(/^[a-z][a-z0-9.-]*$/);
|
|
7
|
+
const pluginGrantAccessSchema = z.union([
|
|
8
|
+
z.literal("read"),
|
|
9
|
+
z.literal("write"),
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
/** Runtime schema for provider authorization a plugin may request. */
|
|
13
|
+
export const pluginAuthorizationSchema = z
|
|
14
|
+
.object({
|
|
15
|
+
provider: pluginProviderNameSchema,
|
|
16
|
+
scope: nonBlankStringSchema.optional(),
|
|
17
|
+
type: z.literal("oauth"),
|
|
18
|
+
})
|
|
19
|
+
.strict();
|
|
20
|
+
|
|
21
|
+
/** Runtime schema for a provider account attached to stored OAuth tokens. */
|
|
22
|
+
export const pluginProviderAccountSchema = z
|
|
23
|
+
.object({
|
|
24
|
+
id: nonBlankStringSchema,
|
|
25
|
+
label: nonBlankStringSchema.optional(),
|
|
26
|
+
url: nonBlankStringSchema.optional(),
|
|
27
|
+
})
|
|
28
|
+
.strict();
|
|
29
|
+
|
|
30
|
+
/** Runtime schema for OAuth tokens stored by the host for plugin credentials. */
|
|
31
|
+
export const pluginStoredTokensSchema = z
|
|
32
|
+
.object({
|
|
33
|
+
account: pluginProviderAccountSchema.optional(),
|
|
34
|
+
accessToken: nonBlankStringSchema,
|
|
35
|
+
expiresAt: z.number().finite().optional(),
|
|
36
|
+
refreshToken: nonBlankStringSchema,
|
|
37
|
+
refreshTokenExpiresAt: z.number().finite().optional(),
|
|
38
|
+
scope: nonBlankStringSchema.optional(),
|
|
39
|
+
})
|
|
40
|
+
.strict();
|
|
41
|
+
|
|
42
|
+
/** Runtime schema for a plugin-defined outbound credential grant. */
|
|
43
|
+
export const pluginGrantSchema = z
|
|
44
|
+
.object({
|
|
45
|
+
access: pluginGrantAccessSchema,
|
|
46
|
+
name: pluginGrantNameSchema,
|
|
47
|
+
reason: nonBlankStringSchema.optional(),
|
|
48
|
+
requirements: z.array(nonBlankStringSchema).min(1).optional(),
|
|
49
|
+
})
|
|
50
|
+
.strict();
|
|
51
|
+
|
|
52
|
+
/** Runtime schema for plugin-issued header mutations. */
|
|
53
|
+
export const pluginCredentialHeaderTransformSchema = z
|
|
54
|
+
.object({
|
|
55
|
+
domain: z.string().min(1),
|
|
56
|
+
headers: z
|
|
57
|
+
.record(z.string(), z.string())
|
|
58
|
+
.refine((headers) => Object.keys(headers).length > 0),
|
|
59
|
+
})
|
|
60
|
+
.strict();
|
|
61
|
+
|
|
62
|
+
/** Runtime schema for a short-lived plugin-issued credential lease. */
|
|
63
|
+
export const pluginCredentialLeaseSchema = z
|
|
64
|
+
.object({
|
|
65
|
+
account: pluginProviderAccountSchema.optional(),
|
|
66
|
+
authorization: pluginAuthorizationSchema.optional(),
|
|
67
|
+
expiresAt: z.string().refine((value) => Number.isFinite(Date.parse(value))),
|
|
68
|
+
headerTransforms: z.array(pluginCredentialHeaderTransformSchema).min(1),
|
|
69
|
+
})
|
|
70
|
+
.strict();
|
|
71
|
+
|
|
72
|
+
/** Runtime schema for the result returned by a plugin credential hook. */
|
|
73
|
+
export const pluginCredentialResultSchema = z.discriminatedUnion("type", [
|
|
74
|
+
z
|
|
75
|
+
.object({
|
|
76
|
+
lease: pluginCredentialLeaseSchema,
|
|
77
|
+
type: z.literal("lease"),
|
|
78
|
+
})
|
|
79
|
+
.strict(),
|
|
80
|
+
z
|
|
81
|
+
.object({
|
|
82
|
+
authorization: pluginAuthorizationSchema.optional(),
|
|
83
|
+
message: nonBlankStringSchema,
|
|
84
|
+
type: z.literal("needed"),
|
|
85
|
+
})
|
|
86
|
+
.strict(),
|
|
87
|
+
z
|
|
88
|
+
.object({
|
|
89
|
+
message: nonBlankStringSchema,
|
|
90
|
+
type: z.literal("unavailable"),
|
|
91
|
+
})
|
|
92
|
+
.strict(),
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
export type PluginCredentialSubject = z.output<
|
|
96
|
+
typeof pluginCredentialSubjectSchema
|
|
97
|
+
>;
|
|
98
|
+
|
|
99
|
+
export type PluginGrantAccess = z.output<typeof pluginGrantAccessSchema>;
|
|
100
|
+
|
|
101
|
+
/** Provider authorization Junior can start when a plugin-owned grant is missing. */
|
|
102
|
+
export type PluginAuthorization = z.output<typeof pluginAuthorizationSchema>;
|
|
103
|
+
|
|
104
|
+
/** Interrupt sandbox egress so Junior can start provider authorization. */
|
|
105
|
+
export class EgressAuthRequired extends Error {
|
|
106
|
+
authorization?: PluginAuthorization;
|
|
107
|
+
|
|
108
|
+
constructor(
|
|
109
|
+
message: string,
|
|
110
|
+
options?: {
|
|
111
|
+
authorization?: PluginAuthorization;
|
|
112
|
+
cause?: unknown;
|
|
113
|
+
},
|
|
114
|
+
) {
|
|
115
|
+
super(message, { cause: options?.cause });
|
|
116
|
+
this.name = "EgressAuthRequired";
|
|
117
|
+
this.authorization = options?.authorization;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Provider account identity resolved by a plugin OAuth hook. */
|
|
122
|
+
export type PluginProviderAccount = z.output<
|
|
123
|
+
typeof pluginProviderAccountSchema
|
|
124
|
+
>;
|
|
125
|
+
|
|
126
|
+
/** Plugin-defined grant required before Junior can forward one outbound request. */
|
|
127
|
+
export type PluginGrant = z.output<typeof pluginGrantSchema>;
|
|
128
|
+
|
|
129
|
+
/** Request details available while selecting the grant for sandbox egress. */
|
|
130
|
+
export interface PluginEgressRequest {
|
|
131
|
+
/** Capped request body text when the host exposes it for provider-specific grant classification. */
|
|
132
|
+
bodyText?: string;
|
|
133
|
+
method: string;
|
|
134
|
+
url: string;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface EgressHookContext extends PluginContext {
|
|
138
|
+
request: PluginEgressRequest;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface PluginEgressResponse {
|
|
142
|
+
/** Snapshot of upstream response headers; mutations do not affect pass-through. */
|
|
143
|
+
headers: Headers;
|
|
144
|
+
readText(maxBytes: number): Promise<string | undefined>;
|
|
145
|
+
status: number;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface EgressResponseHookContext extends PluginContext {
|
|
149
|
+
grant: PluginGrant;
|
|
150
|
+
permissionDenied(message: string): void;
|
|
151
|
+
request: Omit<PluginEgressRequest, "bodyText">;
|
|
152
|
+
response: PluginEgressResponse;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** Header mutations a plugin-issued credential lease may apply to owned domains. */
|
|
156
|
+
export type PluginCredentialHeaderTransform = z.output<
|
|
157
|
+
typeof pluginCredentialHeaderTransformSchema
|
|
158
|
+
>;
|
|
159
|
+
|
|
160
|
+
/** Short-lived credential headers issued by a plugin for a selected grant. */
|
|
161
|
+
export type PluginCredentialLease = z.output<
|
|
162
|
+
typeof pluginCredentialLeaseSchema
|
|
163
|
+
>;
|
|
164
|
+
|
|
165
|
+
export type PluginCredentialResult = z.output<
|
|
166
|
+
typeof pluginCredentialResultSchema
|
|
167
|
+
>;
|
|
168
|
+
|
|
169
|
+
export type PluginCredentialActor =
|
|
170
|
+
| {
|
|
171
|
+
type: "system";
|
|
172
|
+
id: string;
|
|
173
|
+
}
|
|
174
|
+
| {
|
|
175
|
+
type: "user";
|
|
176
|
+
userId: string;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
export interface PluginResolvedCredentialUser {
|
|
180
|
+
type: "user";
|
|
181
|
+
userId: string;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export type PluginStoredTokens = z.output<typeof pluginStoredTokensSchema>;
|
|
185
|
+
|
|
186
|
+
export interface PluginUserTokenSlot {
|
|
187
|
+
get(): Promise<PluginStoredTokens | undefined>;
|
|
188
|
+
set(tokens: PluginStoredTokens): Promise<void>;
|
|
189
|
+
/** Run token refresh work after the host has serialized this user/provider slot, or throw after a bounded wait. */
|
|
190
|
+
withRefresh<T>(callback: () => Promise<T>): Promise<T>;
|
|
191
|
+
userId: string;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface PluginTokenStore {
|
|
195
|
+
credentialSubject?: PluginUserTokenSlot;
|
|
196
|
+
currentUser?: PluginUserTokenSlot;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export interface ResolveOAuthAccountHookContext extends PluginContext {
|
|
200
|
+
tokens: PluginStoredTokens;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export interface IssueCredentialHookContext extends PluginContext {
|
|
204
|
+
actor: PluginCredentialActor;
|
|
205
|
+
credentialSubject?: PluginResolvedCredentialUser;
|
|
206
|
+
grant: PluginGrant;
|
|
207
|
+
tokens: PluginTokenStore;
|
|
208
|
+
}
|
package/src/dispatch.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { dispatchOptionsSchema } from "./schemas";
|
|
3
|
+
|
|
4
|
+
export type DispatchOptions = z.output<typeof dispatchOptionsSchema>;
|
|
5
|
+
|
|
6
|
+
export interface DispatchResult {
|
|
7
|
+
id: string;
|
|
8
|
+
status: "created" | "already_exists";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface Dispatch {
|
|
12
|
+
errorMessage?: string;
|
|
13
|
+
id: string;
|
|
14
|
+
resultMessageTs?: string;
|
|
15
|
+
status:
|
|
16
|
+
| "pending"
|
|
17
|
+
| "running"
|
|
18
|
+
| "awaiting_resume"
|
|
19
|
+
| "completed"
|
|
20
|
+
| "failed"
|
|
21
|
+
| "blocked";
|
|
22
|
+
}
|
package/src/hooks.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
EgressHookContext,
|
|
3
|
+
EgressResponseHookContext,
|
|
4
|
+
IssueCredentialHookContext,
|
|
5
|
+
PluginCredentialResult,
|
|
6
|
+
PluginGrant,
|
|
7
|
+
PluginProviderAccount,
|
|
8
|
+
ResolveOAuthAccountHookContext,
|
|
9
|
+
} from "./credentials";
|
|
10
|
+
import type {
|
|
11
|
+
HeartbeatHookContext,
|
|
12
|
+
HeartbeatResult,
|
|
13
|
+
OperationalReportHookContext,
|
|
14
|
+
PluginOperationalReportContent,
|
|
15
|
+
PluginRoute,
|
|
16
|
+
RouteRegistrationHookContext,
|
|
17
|
+
SlackConversationLink,
|
|
18
|
+
SlackConversationLinkHookContext,
|
|
19
|
+
StorageMigrationContext,
|
|
20
|
+
StorageMigrationResult,
|
|
21
|
+
} from "./operations";
|
|
22
|
+
import type {
|
|
23
|
+
BeforeToolExecuteHookContext,
|
|
24
|
+
PluginToolDefinition,
|
|
25
|
+
SandboxPrepareHookContext,
|
|
26
|
+
ToolRegistrationHookContext,
|
|
27
|
+
} from "./tools";
|
|
28
|
+
import type {
|
|
29
|
+
PromptMessage,
|
|
30
|
+
SystemPromptContext,
|
|
31
|
+
UserPromptContext,
|
|
32
|
+
} from "./prompt";
|
|
33
|
+
|
|
34
|
+
export interface PluginHooks {
|
|
35
|
+
systemPrompt?(
|
|
36
|
+
ctx: SystemPromptContext,
|
|
37
|
+
): Promise<PromptMessage[]> | PromptMessage[];
|
|
38
|
+
userPrompt?(
|
|
39
|
+
ctx: UserPromptContext,
|
|
40
|
+
): Promise<PromptMessage[] | undefined> | PromptMessage[] | undefined;
|
|
41
|
+
beforeToolExecute?(ctx: BeforeToolExecuteHookContext): Promise<void> | void;
|
|
42
|
+
grantForEgress?(
|
|
43
|
+
ctx: EgressHookContext,
|
|
44
|
+
): Promise<PluginGrant | undefined> | PluginGrant | undefined;
|
|
45
|
+
heartbeat?(
|
|
46
|
+
ctx: HeartbeatHookContext,
|
|
47
|
+
): Promise<HeartbeatResult | void> | HeartbeatResult | void;
|
|
48
|
+
issueCredential?(
|
|
49
|
+
ctx: IssueCredentialHookContext,
|
|
50
|
+
): Promise<PluginCredentialResult> | PluginCredentialResult;
|
|
51
|
+
onEgressResponse?(ctx: EgressResponseHookContext): Promise<void> | void;
|
|
52
|
+
operationalReport?(
|
|
53
|
+
ctx: OperationalReportHookContext,
|
|
54
|
+
):
|
|
55
|
+
| Promise<PluginOperationalReportContent | undefined>
|
|
56
|
+
| PluginOperationalReportContent
|
|
57
|
+
| undefined;
|
|
58
|
+
resolveOAuthAccount?(
|
|
59
|
+
ctx: ResolveOAuthAccountHookContext,
|
|
60
|
+
):
|
|
61
|
+
| Promise<PluginProviderAccount | undefined>
|
|
62
|
+
| PluginProviderAccount
|
|
63
|
+
| undefined;
|
|
64
|
+
routes?(ctx: RouteRegistrationHookContext): PluginRoute[];
|
|
65
|
+
sandboxPrepare?(ctx: SandboxPrepareHookContext): Promise<void> | void;
|
|
66
|
+
slackConversationLink?(
|
|
67
|
+
ctx: SlackConversationLinkHookContext,
|
|
68
|
+
): SlackConversationLink | undefined;
|
|
69
|
+
tools?(
|
|
70
|
+
ctx: ToolRegistrationHookContext,
|
|
71
|
+
): Record<string, PluginToolDefinition>;
|
|
72
|
+
migrateStorage?(
|
|
73
|
+
ctx: StorageMigrationContext,
|
|
74
|
+
):
|
|
75
|
+
| Promise<StorageMigrationResult | undefined>
|
|
76
|
+
| StorageMigrationResult
|
|
77
|
+
| undefined;
|
|
78
|
+
}
|