@slates/provider 1.0.0-rc.29 → 1.0.0-rc.31
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.cjs +119 -2
- package/dist/index.d.cts +62 -26
- package/dist/index.d.ts +62 -26
- package/dist/index.module.js +117 -2
- package/package.json +1 -1
- package/src/action/index.ts +1 -0
- package/src/action/toolCategory.ts +40 -0
- package/src/auth/types.ts +52 -25
- package/src/specification/slate.test.ts +153 -1
- package/src/specification/slate.ts +105 -3
package/dist/index.cjs
CHANGED
|
@@ -52,6 +52,7 @@ __export(index_exports, {
|
|
|
52
52
|
SlatePublicTool: () => SlatePublicTool,
|
|
53
53
|
SlateSpecification: () => SlateSpecification,
|
|
54
54
|
SlateTool: () => SlateTool,
|
|
55
|
+
SlateToolCategory: () => SlateToolCategory,
|
|
55
56
|
SlateTrigger: () => SlateTrigger,
|
|
56
57
|
SlateTriggerGroup: () => SlateTriggerGroup,
|
|
57
58
|
SlateTriggerGroupBuilder: () => SlateTriggerGroupBuilder,
|
|
@@ -112,6 +113,7 @@ __export(index_exports, {
|
|
|
112
113
|
spec: () => spec,
|
|
113
114
|
statusLabelForApiError: () => statusLabelForApiError,
|
|
114
115
|
tool: () => tool,
|
|
116
|
+
toolCategory: () => toolCategory,
|
|
115
117
|
trigger: () => trigger,
|
|
116
118
|
triggerGroup: () => triggerGroup,
|
|
117
119
|
truncateApiErrorMessage: () => truncateApiErrorMessage,
|
|
@@ -2178,6 +2180,33 @@ var SlatePublicTool = class {
|
|
|
2178
2180
|
};
|
|
2179
2181
|
var publicTool = (spec2, params) => SlatePublicTool.create(spec2, params);
|
|
2180
2182
|
|
|
2183
|
+
// src/action/toolCategory.ts
|
|
2184
|
+
var SlateToolCategory = class _SlateToolCategory {
|
|
2185
|
+
constructor(_params) {
|
|
2186
|
+
this._params = _params;
|
|
2187
|
+
}
|
|
2188
|
+
_params;
|
|
2189
|
+
static create(params) {
|
|
2190
|
+
return new _SlateToolCategory(params);
|
|
2191
|
+
}
|
|
2192
|
+
get key() {
|
|
2193
|
+
return this._params.key;
|
|
2194
|
+
}
|
|
2195
|
+
get name() {
|
|
2196
|
+
return this._params.name;
|
|
2197
|
+
}
|
|
2198
|
+
get description() {
|
|
2199
|
+
return this._params.description;
|
|
2200
|
+
}
|
|
2201
|
+
get imageUrl() {
|
|
2202
|
+
return this._params.imageUrl;
|
|
2203
|
+
}
|
|
2204
|
+
get tools() {
|
|
2205
|
+
return this._params.tools;
|
|
2206
|
+
}
|
|
2207
|
+
};
|
|
2208
|
+
var toolCategory = (params) => SlateToolCategory.create(params);
|
|
2209
|
+
|
|
2181
2210
|
// src/action/trigger.ts
|
|
2182
2211
|
var SlateTrigger = class _SlateTrigger extends SlateAction {
|
|
2183
2212
|
#triggerGroup;
|
|
@@ -3201,16 +3230,20 @@ var setIfDefined = (target, key, value) => {
|
|
|
3201
3230
|
|
|
3202
3231
|
// src/specification/slate.ts
|
|
3203
3232
|
var Slate = class _Slate {
|
|
3204
|
-
constructor(_spec, _actions, _adapters, _triggerGroups) {
|
|
3233
|
+
constructor(_spec, _actions, _adapters, _triggerGroups, _toolCategories, _toolCategoryKeysByActionKey) {
|
|
3205
3234
|
this._spec = _spec;
|
|
3206
3235
|
this._actions = _actions;
|
|
3207
3236
|
this._adapters = _adapters;
|
|
3208
3237
|
this._triggerGroups = _triggerGroups;
|
|
3238
|
+
this._toolCategories = _toolCategories;
|
|
3239
|
+
this._toolCategoryKeysByActionKey = _toolCategoryKeysByActionKey;
|
|
3209
3240
|
}
|
|
3210
3241
|
_spec;
|
|
3211
3242
|
_actions;
|
|
3212
3243
|
_adapters;
|
|
3213
3244
|
_triggerGroups;
|
|
3245
|
+
_toolCategories;
|
|
3246
|
+
_toolCategoryKeysByActionKey;
|
|
3214
3247
|
static create(params) {
|
|
3215
3248
|
let adapters = params.adapters ?? [];
|
|
3216
3249
|
let actions = [...params.triggers, ...params.tools];
|
|
@@ -3254,7 +3287,16 @@ var Slate = class _Slate {
|
|
|
3254
3287
|
`Only one trigger group may use manual webhook registration, but found: ${manualWebhookTriggerGroups.map((group) => group.key).join(", ")}`
|
|
3255
3288
|
);
|
|
3256
3289
|
}
|
|
3257
|
-
|
|
3290
|
+
let toolCategories = params.toolCategories ?? [];
|
|
3291
|
+
let toolCategoryKeysByActionKey = resolveToolCategoryMembership(toolCategories, actions);
|
|
3292
|
+
return new _Slate(
|
|
3293
|
+
params.spec,
|
|
3294
|
+
actions,
|
|
3295
|
+
adapters,
|
|
3296
|
+
triggerGroups,
|
|
3297
|
+
toolCategories,
|
|
3298
|
+
toolCategoryKeysByActionKey
|
|
3299
|
+
);
|
|
3258
3300
|
}
|
|
3259
3301
|
get spec() {
|
|
3260
3302
|
return this._spec;
|
|
@@ -3268,6 +3310,79 @@ var Slate = class _Slate {
|
|
|
3268
3310
|
get triggerGroups() {
|
|
3269
3311
|
return this._triggerGroups ?? [];
|
|
3270
3312
|
}
|
|
3313
|
+
get toolCategories() {
|
|
3314
|
+
return this._toolCategories ?? [];
|
|
3315
|
+
}
|
|
3316
|
+
// Keys of the tool categories an action belongs to, in declared category order.
|
|
3317
|
+
getToolCategoryKeys(actionKey) {
|
|
3318
|
+
return [...this._toolCategoryKeysByActionKey?.get(actionKey) ?? []];
|
|
3319
|
+
}
|
|
3320
|
+
};
|
|
3321
|
+
var TOOL_CATEGORY_KEY_PATTERN = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
3322
|
+
var isHttpUrl = (value) => {
|
|
3323
|
+
try {
|
|
3324
|
+
let url = new URL(value);
|
|
3325
|
+
return url.protocol === "https:" || url.protocol === "http:";
|
|
3326
|
+
} catch {
|
|
3327
|
+
return false;
|
|
3328
|
+
}
|
|
3329
|
+
};
|
|
3330
|
+
var resolveToolCategoryMembership = (toolCategories, actions) => {
|
|
3331
|
+
let effectiveActions = /* @__PURE__ */ new Map();
|
|
3332
|
+
for (let action of actions) {
|
|
3333
|
+
if (!effectiveActions.has(action.key)) effectiveActions.set(action.key, action);
|
|
3334
|
+
}
|
|
3335
|
+
let registeredActions = new Set(actions);
|
|
3336
|
+
let membersByCategoryKey = /* @__PURE__ */ new Map();
|
|
3337
|
+
for (let category of toolCategories) {
|
|
3338
|
+
if (!TOOL_CATEGORY_KEY_PATTERN.test(category.key)) {
|
|
3339
|
+
throw new SlateDeclarationError(
|
|
3340
|
+
`Tool category key "${category.key}" must match ${TOOL_CATEGORY_KEY_PATTERN}`
|
|
3341
|
+
);
|
|
3342
|
+
}
|
|
3343
|
+
if (membersByCategoryKey.has(category.key)) {
|
|
3344
|
+
throw new SlateDeclarationError(
|
|
3345
|
+
`Tool category "${category.key}" is registered more than once`
|
|
3346
|
+
);
|
|
3347
|
+
}
|
|
3348
|
+
if (!category.name?.trim()) {
|
|
3349
|
+
throw new SlateDeclarationError(`Tool category "${category.key}" must have a name`);
|
|
3350
|
+
}
|
|
3351
|
+
if (category.imageUrl !== void 0 && !isHttpUrl(category.imageUrl)) {
|
|
3352
|
+
throw new SlateDeclarationError(
|
|
3353
|
+
`Tool category "${category.key}" imageUrl must be an absolute http(s) URL`
|
|
3354
|
+
);
|
|
3355
|
+
}
|
|
3356
|
+
if (!category.tools?.length) {
|
|
3357
|
+
throw new SlateDeclarationError(
|
|
3358
|
+
`Tool category "${category.key}" must list at least one tool`
|
|
3359
|
+
);
|
|
3360
|
+
}
|
|
3361
|
+
let members = /* @__PURE__ */ new Set();
|
|
3362
|
+
for (let tool2 of category.tools) {
|
|
3363
|
+
if (!registeredActions.has(tool2)) {
|
|
3364
|
+
throw new SlateDeclarationError(
|
|
3365
|
+
`Tool category "${category.key}" lists tool "${tool2.key}", which is not registered in this slate`
|
|
3366
|
+
);
|
|
3367
|
+
}
|
|
3368
|
+
if (tool2.type !== "tool") {
|
|
3369
|
+
throw new SlateDeclarationError(
|
|
3370
|
+
`Tool category "${category.key}" lists trigger "${tool2.key}", but only tools can belong to a tool category`
|
|
3371
|
+
);
|
|
3372
|
+
}
|
|
3373
|
+
if (effectiveActions.get(tool2.key) === tool2) members.add(tool2.key);
|
|
3374
|
+
}
|
|
3375
|
+
membersByCategoryKey.set(category.key, members);
|
|
3376
|
+
}
|
|
3377
|
+
let keysByActionKey = /* @__PURE__ */ new Map();
|
|
3378
|
+
for (let category of toolCategories) {
|
|
3379
|
+
for (let actionKey of membersByCategoryKey.get(category.key) ?? []) {
|
|
3380
|
+
let keys = keysByActionKey.get(actionKey) ?? [];
|
|
3381
|
+
keys.push(category.key);
|
|
3382
|
+
keysByActionKey.set(actionKey, keys);
|
|
3383
|
+
}
|
|
3384
|
+
}
|
|
3385
|
+
return keysByActionKey;
|
|
3271
3386
|
};
|
|
3272
3387
|
|
|
3273
3388
|
// src/specification/specification.ts
|
|
@@ -3397,6 +3512,7 @@ var skipWebhook = (reason, response) => ({
|
|
|
3397
3512
|
SlatePublicTool,
|
|
3398
3513
|
SlateSpecification,
|
|
3399
3514
|
SlateTool,
|
|
3515
|
+
SlateToolCategory,
|
|
3400
3516
|
SlateTrigger,
|
|
3401
3517
|
SlateTriggerGroup,
|
|
3402
3518
|
SlateTriggerGroupBuilder,
|
|
@@ -3457,6 +3573,7 @@ var skipWebhook = (reason, response) => ({
|
|
|
3457
3573
|
spec,
|
|
3458
3574
|
statusLabelForApiError,
|
|
3459
3575
|
tool,
|
|
3576
|
+
toolCategory,
|
|
3460
3577
|
trigger,
|
|
3461
3578
|
triggerGroup,
|
|
3462
3579
|
truncateApiErrorMessage,
|
package/dist/index.d.cts
CHANGED
|
@@ -147,6 +147,35 @@ type SlateActionDocsReference = SlateTypedDocsReference<'docs.action.general'>;
|
|
|
147
147
|
type SlateAuthDocsReference = SlateTypedDocsReference<'docs.auth.oauth' | 'docs.auth.oauth_scopes' | 'docs.auth.token' | 'docs.auth.service_account' | 'docs.auth.custom'>;
|
|
148
148
|
|
|
149
149
|
type SlateAuthCallbackConfig = Record<string, any>;
|
|
150
|
+
type SlateOauthAuthorizationUrlContext<InputType> = {
|
|
151
|
+
redirectUri: string;
|
|
152
|
+
state: string;
|
|
153
|
+
input: InputType;
|
|
154
|
+
clientId: string;
|
|
155
|
+
clientSecret: string;
|
|
156
|
+
scopes: string[];
|
|
157
|
+
config?: SlateAuthCallbackConfig;
|
|
158
|
+
};
|
|
159
|
+
type SlateOauthAuthorizationUrlResult<InputType> = {
|
|
160
|
+
url: string;
|
|
161
|
+
input?: InputType;
|
|
162
|
+
callbackState?: Record<string, any>;
|
|
163
|
+
};
|
|
164
|
+
type SlateOauthCallbackContext<InputType> = {
|
|
165
|
+
code: string;
|
|
166
|
+
state: string;
|
|
167
|
+
redirectUri: string;
|
|
168
|
+
input: InputType;
|
|
169
|
+
clientId: string;
|
|
170
|
+
clientSecret: string;
|
|
171
|
+
scopes: string[];
|
|
172
|
+
callbackParams?: Record<string, string>;
|
|
173
|
+
callbackState: Record<string, any>;
|
|
174
|
+
config?: SlateAuthCallbackConfig;
|
|
175
|
+
};
|
|
176
|
+
type SlateOauthAdminCallbackContext<InputType> = Omit<SlateOauthCallbackContext<InputType>, 'code'> & {
|
|
177
|
+
code?: string;
|
|
178
|
+
};
|
|
150
179
|
type SlateAuthWithOauth<InputType extends {}, OutputType extends {
|
|
151
180
|
token: string;
|
|
152
181
|
refreshToken?: string;
|
|
@@ -162,6 +191,12 @@ type SlateAuthWithOauth<InputType extends {}, OutputType extends {
|
|
|
162
191
|
}[];
|
|
163
192
|
adapters?: string[];
|
|
164
193
|
syncTokensAcrossConnections?: boolean;
|
|
194
|
+
adminSetup?: {
|
|
195
|
+
getAuthorizationUrl?: (ctx: SlateOauthAuthorizationUrlContext<InputType>) => Promise<SlateOauthAuthorizationUrlResult<InputType>>;
|
|
196
|
+
handleCallback?: (ctx: SlateOauthAdminCallbackContext<InputType>) => Promise<{
|
|
197
|
+
instructions?: string;
|
|
198
|
+
}>;
|
|
199
|
+
};
|
|
165
200
|
docs?: SlateAuthDocsReference[];
|
|
166
201
|
inputSchema?: z.ZodType<InputType>;
|
|
167
202
|
onInputChanged?: (params: {
|
|
@@ -171,31 +206,8 @@ type SlateAuthWithOauth<InputType extends {}, OutputType extends {
|
|
|
171
206
|
input?: InputType;
|
|
172
207
|
} | undefined>;
|
|
173
208
|
getDefaultInput?: () => Promise<InputType>;
|
|
174
|
-
getAuthorizationUrl: (ctx:
|
|
175
|
-
|
|
176
|
-
state: string;
|
|
177
|
-
input: InputType;
|
|
178
|
-
clientId: string;
|
|
179
|
-
clientSecret: string;
|
|
180
|
-
scopes: string[];
|
|
181
|
-
config?: SlateAuthCallbackConfig;
|
|
182
|
-
}) => Promise<{
|
|
183
|
-
url: string;
|
|
184
|
-
input?: InputType;
|
|
185
|
-
callbackState?: Record<string, any>;
|
|
186
|
-
}>;
|
|
187
|
-
handleCallback: (ctx: {
|
|
188
|
-
code: string;
|
|
189
|
-
state: string;
|
|
190
|
-
redirectUri: string;
|
|
191
|
-
input: InputType;
|
|
192
|
-
clientId: string;
|
|
193
|
-
clientSecret: string;
|
|
194
|
-
scopes: string[];
|
|
195
|
-
callbackParams?: Record<string, string>;
|
|
196
|
-
callbackState: Record<string, any>;
|
|
197
|
-
config?: SlateAuthCallbackConfig;
|
|
198
|
-
}) => Promise<{
|
|
209
|
+
getAuthorizationUrl: (ctx: SlateOauthAuthorizationUrlContext<InputType>) => Promise<SlateOauthAuthorizationUrlResult<InputType>>;
|
|
210
|
+
handleCallback: (ctx: SlateOauthCallbackContext<InputType>) => Promise<{
|
|
199
211
|
output: OutputType;
|
|
200
212
|
input?: InputType;
|
|
201
213
|
scopes?: string[];
|
|
@@ -857,6 +869,25 @@ declare let allOf: (...inputs: SlateActionScopesInput[]) => SlateActionScopes;
|
|
|
857
869
|
declare let mergeScopes: (...inputs: Array<SlateActionScopes | null | undefined | false>) => SlateActionScopes | undefined;
|
|
858
870
|
declare let validateScopes: (scopes: SlateActionScopes) => SlateActionScopes;
|
|
859
871
|
|
|
872
|
+
interface SlateToolCategoryParameters {
|
|
873
|
+
key: string;
|
|
874
|
+
name: string;
|
|
875
|
+
description?: string;
|
|
876
|
+
imageUrl?: string;
|
|
877
|
+
tools: SlateTool<any, any, any, any>[];
|
|
878
|
+
}
|
|
879
|
+
declare class SlateToolCategory {
|
|
880
|
+
private readonly _params;
|
|
881
|
+
private constructor();
|
|
882
|
+
static create(params: SlateToolCategoryParameters): SlateToolCategory;
|
|
883
|
+
get key(): string;
|
|
884
|
+
get name(): string;
|
|
885
|
+
get description(): string | undefined;
|
|
886
|
+
get imageUrl(): string | undefined;
|
|
887
|
+
get tools(): SlateTool<any, any, any, any>[];
|
|
888
|
+
}
|
|
889
|
+
declare let toolCategory: (params: SlateToolCategoryParameters) => SlateToolCategory;
|
|
890
|
+
|
|
860
891
|
interface SlateTriggerParameters<ConfigType extends {}, AuthType extends {}, InputType extends {}, OutputType extends {
|
|
861
892
|
type: string;
|
|
862
893
|
}> extends SlateActionParameters {
|
|
@@ -1123,6 +1154,8 @@ declare class Slate<ConfigType extends {}, AuthType extends {}> {
|
|
|
1123
1154
|
private readonly _actions;
|
|
1124
1155
|
private readonly _adapters;
|
|
1125
1156
|
private readonly _triggerGroups;
|
|
1157
|
+
private readonly _toolCategories;
|
|
1158
|
+
private readonly _toolCategoryKeysByActionKey;
|
|
1126
1159
|
private constructor();
|
|
1127
1160
|
static create<ConfigType extends {}, AuthType extends {}>(params: {
|
|
1128
1161
|
spec: SlateSpecification<ConfigType, AuthType>;
|
|
@@ -1130,11 +1163,14 @@ declare class Slate<ConfigType extends {}, AuthType extends {}> {
|
|
|
1130
1163
|
tools: SlateTool<ConfigType, AuthType, any, any>[];
|
|
1131
1164
|
adapters?: SlateAdapter<ConfigType, AuthType>[];
|
|
1132
1165
|
triggerGroups?: SlateTriggerGroup<ConfigType, AuthType>[];
|
|
1166
|
+
toolCategories?: SlateToolCategory[];
|
|
1133
1167
|
}): Slate<ConfigType, AuthType>;
|
|
1134
1168
|
get spec(): SlateSpecification<ConfigType, AuthType>;
|
|
1135
1169
|
get actions(): (SlateTrigger<ConfigType, AuthType, any, any> | SlateTool<ConfigType, AuthType, any, any>)[];
|
|
1136
1170
|
get adapters(): SlateAdapter<ConfigType, AuthType>[];
|
|
1137
1171
|
get triggerGroups(): SlateTriggerGroup<ConfigType, AuthType, Record<string, unknown>>[];
|
|
1172
|
+
get toolCategories(): SlateToolCategory[];
|
|
1173
|
+
getToolCategoryKeys(actionKey: string): string[];
|
|
1138
1174
|
}
|
|
1139
1175
|
|
|
1140
1176
|
declare const graphWebhookHttp: {
|
|
@@ -1168,4 +1204,4 @@ declare let skipWebhook: (reason: string, response?: Response | SlateWebhookHttp
|
|
|
1168
1204
|
response: Response | SlateWebhookHttpResponseInit;
|
|
1169
1205
|
};
|
|
1170
1206
|
|
|
1171
|
-
export { API_ERROR_MAX_DETAILS, API_ERROR_MAX_MESSAGE_LENGTH, API_ERROR_TRUNCATED_PLACEHOLDER, AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX, type ApiErrorBuildHelpers, type ApiErrorDetailOptions, type ApiErrorResponse, type ApiErrorStatus, type ApiErrorTextOptions, type ApiServiceError, type AuthConfigSecretFilter, AuthConfigSecretRedactor, type BoundedApiErrorDetailOptions, type BuildApiServiceErrorOptions, type CreateHmacSignatureOptions, type DecodeApiErrorBodyOptions, GET_FILE_URL_TOOL_ID, type GetFileUrlHandler, type GetFileUrlToolInput, type GetFileUrlToolOutput, type NormalizeOAuthTokenResponseOptions, type OAuthExpiresAtOptions, type OAuthRefreshTokenFallbackMode, type OAuthTokenResponse, Slate, SlateAction, SlateActionBuilder, type SlateActionCreateParameters, type SlateActionDocsReference, type SlateActionParameters, type SlateActionParametersAny, type SlateActionParametersTool, type SlateActionParametersTrigger, type SlateActionScopeClause, type SlateActionScopeClauseInput, type SlateActionScopeValue, type SlateActionScopes, type SlateActionScopesInput, type SlateActionType, SlateAdapter, type SlateAdapterCapability, SlateAdapterSpec, type SlateAdapterSpecParameters, type SlateAddAttachmentContent, type SlateAddAttachmentInput, type SlateAttachment, type SlateAttachmentInlineContent, type SlateAttachmentUploadReferenceContent, type SlateAttachmentUrlContent, SlateAuth, type SlateAuthDocsReference, type SlateAuthType, type SlateAuthWithCustomData, type SlateAuthWithNone, type SlateAuthWithOauth, type SlateAuthWithServiceAccount, type SlateAuthWithToken, type SlateAuthenticatedAxiosDefaults, type SlateAxiosDefaults, type SlateAxiosErrorAdapter, type SlateAxiosErrorOptions, SlateConfig, type SlateConfigDocsReference, SlateContext, SlateDeclarationError, SlateDefaultPollingIntervalSeconds, type SlateDirectUploadInput, type SlateDocsReference, SlateError, type SlateErrorInput, type SlateErrorIssue, type SlateErrorKind, type SlateErrorProviderInfo, type SlateErrorResponse, type SlateErrorUpstreamInfo, type SlateGatewayEvent, type SlateLiveInvocationInfo, type SlateLogEntry, type SlateLogFields, type SlateLogListener, type SlateLogMessageInput, type SlateLogType, SlateLogger, type SlateProviderDocsReference, SlatePublicContext, SlatePublicTool, type SlatePublicToolInvocationHandler, type SlatePublicToolParameters, type SlateServiceErrorData, SlateSpecification, type SlateSpecificationCreateParameters, type SlateSpecificationParameters, SlateTool, type SlateToolInvocationHandler, type SlateToolParameters, SlateTrigger, SlateTriggerGroup, SlateTriggerGroupBuilder, type SlateTriggerGroupCreateParameters, type SlateTriggerGroupGatewayConnectHandler, type SlateTriggerGroupGatewayParameters, type SlateTriggerGroupGatewayReceiveHandler, type SlateTriggerGroupParameters, type SlateTriggerGroupPollHandler, type SlateTriggerGroupPollingParameters, type SlateTriggerGroupRoutingMatchersHandler, type SlateTriggerGroupWebhookAutoRegistrationParameters, type SlateTriggerGroupWebhookManualRegistrationParameters, type SlateTriggerGroupWebhookParameters, type SlateTriggerMappingHandler, type SlateTriggerMatchesHandler, type SlateTriggerParameters, type SlateTriggerRoutingMatcher, type SlateTypedDocsReference, type SlateWebhookHttpResponseInit, type SlateWebhookManualFinishHandler, type SlateWebhookManualSetupHandler, type SlateWebhookProcessHandler, type SlateWebhookRegisterHandler, type SlateWebhookSkipped, type SlateWebhookTarget, type SlateWebhookTargetListHandler, type SlateWebhookTargetOwnership, type SlateWebhookUnregisterHandler, type VerifyHmacSignatureOptions, adapterSpec, allOf, anyOf, auth, axios, buildApiServiceError, collectApiErrorDetails, config, createApiServiceError, createAuthenticatedAxios, createAxios, createBase64Attachment, createHmacSignature, createSlateError, createTextAttachment, createUrlAttachment, decodeApiErrorBody, extractApiErrorMessage, getApiErrorResponse, getApiErrorResponseWithBody, getApiErrorStatus, getBase64ByteLength, getCurrentContext, getFileUrlTool, getFileUrlToolInputSchema, getFileUrlToolOutputSchema, getGraphWebhookValidationResponse, getMetaWebhookVerificationResponse, getOAuthExpiresAtFromExpiresIn, getResponseHeaderValue, getServiceErrorData, graphWebhookHttp, inferSlateErrorFromAxios, isApiErrorRecord, isAxiosErrorLike, isServiceErrorData, isUrlEmbeddedCredential, looksLikeHtmlErrorBody, mapServiceErrorCode, mapServiceErrorToSlateErrorInput, mergeScopes, metaWebhookHttp, normalizeOAuthTokenResponse, pickDefined, publicTool, pushBoundedApiErrorDetail, readApiErrorText, redactUrlAttachmentSecrets, requestAxios, requestAxiosData, runWithContext, scopeClause, setIfDefined, skipWebhook, spec, statusLabelForApiError, tool, trigger, triggerGroup, truncateApiErrorMessage, uploadAttachmentDirect, validateScopes, verifyHmacSignature };
|
|
1207
|
+
export { API_ERROR_MAX_DETAILS, API_ERROR_MAX_MESSAGE_LENGTH, API_ERROR_TRUNCATED_PLACEHOLDER, AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX, type ApiErrorBuildHelpers, type ApiErrorDetailOptions, type ApiErrorResponse, type ApiErrorStatus, type ApiErrorTextOptions, type ApiServiceError, type AuthConfigSecretFilter, AuthConfigSecretRedactor, type BoundedApiErrorDetailOptions, type BuildApiServiceErrorOptions, type CreateHmacSignatureOptions, type DecodeApiErrorBodyOptions, GET_FILE_URL_TOOL_ID, type GetFileUrlHandler, type GetFileUrlToolInput, type GetFileUrlToolOutput, type NormalizeOAuthTokenResponseOptions, type OAuthExpiresAtOptions, type OAuthRefreshTokenFallbackMode, type OAuthTokenResponse, Slate, SlateAction, SlateActionBuilder, type SlateActionCreateParameters, type SlateActionDocsReference, type SlateActionParameters, type SlateActionParametersAny, type SlateActionParametersTool, type SlateActionParametersTrigger, type SlateActionScopeClause, type SlateActionScopeClauseInput, type SlateActionScopeValue, type SlateActionScopes, type SlateActionScopesInput, type SlateActionType, SlateAdapter, type SlateAdapterCapability, SlateAdapterSpec, type SlateAdapterSpecParameters, type SlateAddAttachmentContent, type SlateAddAttachmentInput, type SlateAttachment, type SlateAttachmentInlineContent, type SlateAttachmentUploadReferenceContent, type SlateAttachmentUrlContent, SlateAuth, type SlateAuthDocsReference, type SlateAuthType, type SlateAuthWithCustomData, type SlateAuthWithNone, type SlateAuthWithOauth, type SlateAuthWithServiceAccount, type SlateAuthWithToken, type SlateAuthenticatedAxiosDefaults, type SlateAxiosDefaults, type SlateAxiosErrorAdapter, type SlateAxiosErrorOptions, SlateConfig, type SlateConfigDocsReference, SlateContext, SlateDeclarationError, SlateDefaultPollingIntervalSeconds, type SlateDirectUploadInput, type SlateDocsReference, SlateError, type SlateErrorInput, type SlateErrorIssue, type SlateErrorKind, type SlateErrorProviderInfo, type SlateErrorResponse, type SlateErrorUpstreamInfo, type SlateGatewayEvent, type SlateLiveInvocationInfo, type SlateLogEntry, type SlateLogFields, type SlateLogListener, type SlateLogMessageInput, type SlateLogType, SlateLogger, type SlateProviderDocsReference, SlatePublicContext, SlatePublicTool, type SlatePublicToolInvocationHandler, type SlatePublicToolParameters, type SlateServiceErrorData, SlateSpecification, type SlateSpecificationCreateParameters, type SlateSpecificationParameters, SlateTool, SlateToolCategory, type SlateToolCategoryParameters, type SlateToolInvocationHandler, type SlateToolParameters, SlateTrigger, SlateTriggerGroup, SlateTriggerGroupBuilder, type SlateTriggerGroupCreateParameters, type SlateTriggerGroupGatewayConnectHandler, type SlateTriggerGroupGatewayParameters, type SlateTriggerGroupGatewayReceiveHandler, type SlateTriggerGroupParameters, type SlateTriggerGroupPollHandler, type SlateTriggerGroupPollingParameters, type SlateTriggerGroupRoutingMatchersHandler, type SlateTriggerGroupWebhookAutoRegistrationParameters, type SlateTriggerGroupWebhookManualRegistrationParameters, type SlateTriggerGroupWebhookParameters, type SlateTriggerMappingHandler, type SlateTriggerMatchesHandler, type SlateTriggerParameters, type SlateTriggerRoutingMatcher, type SlateTypedDocsReference, type SlateWebhookHttpResponseInit, type SlateWebhookManualFinishHandler, type SlateWebhookManualSetupHandler, type SlateWebhookProcessHandler, type SlateWebhookRegisterHandler, type SlateWebhookSkipped, type SlateWebhookTarget, type SlateWebhookTargetListHandler, type SlateWebhookTargetOwnership, type SlateWebhookUnregisterHandler, type VerifyHmacSignatureOptions, adapterSpec, allOf, anyOf, auth, axios, buildApiServiceError, collectApiErrorDetails, config, createApiServiceError, createAuthenticatedAxios, createAxios, createBase64Attachment, createHmacSignature, createSlateError, createTextAttachment, createUrlAttachment, decodeApiErrorBody, extractApiErrorMessage, getApiErrorResponse, getApiErrorResponseWithBody, getApiErrorStatus, getBase64ByteLength, getCurrentContext, getFileUrlTool, getFileUrlToolInputSchema, getFileUrlToolOutputSchema, getGraphWebhookValidationResponse, getMetaWebhookVerificationResponse, getOAuthExpiresAtFromExpiresIn, getResponseHeaderValue, getServiceErrorData, graphWebhookHttp, inferSlateErrorFromAxios, isApiErrorRecord, isAxiosErrorLike, isServiceErrorData, isUrlEmbeddedCredential, looksLikeHtmlErrorBody, mapServiceErrorCode, mapServiceErrorToSlateErrorInput, mergeScopes, metaWebhookHttp, normalizeOAuthTokenResponse, pickDefined, publicTool, pushBoundedApiErrorDetail, readApiErrorText, redactUrlAttachmentSecrets, requestAxios, requestAxiosData, runWithContext, scopeClause, setIfDefined, skipWebhook, spec, statusLabelForApiError, tool, toolCategory, trigger, triggerGroup, truncateApiErrorMessage, uploadAttachmentDirect, validateScopes, verifyHmacSignature };
|
package/dist/index.d.ts
CHANGED
|
@@ -147,6 +147,35 @@ type SlateActionDocsReference = SlateTypedDocsReference<'docs.action.general'>;
|
|
|
147
147
|
type SlateAuthDocsReference = SlateTypedDocsReference<'docs.auth.oauth' | 'docs.auth.oauth_scopes' | 'docs.auth.token' | 'docs.auth.service_account' | 'docs.auth.custom'>;
|
|
148
148
|
|
|
149
149
|
type SlateAuthCallbackConfig = Record<string, any>;
|
|
150
|
+
type SlateOauthAuthorizationUrlContext<InputType> = {
|
|
151
|
+
redirectUri: string;
|
|
152
|
+
state: string;
|
|
153
|
+
input: InputType;
|
|
154
|
+
clientId: string;
|
|
155
|
+
clientSecret: string;
|
|
156
|
+
scopes: string[];
|
|
157
|
+
config?: SlateAuthCallbackConfig;
|
|
158
|
+
};
|
|
159
|
+
type SlateOauthAuthorizationUrlResult<InputType> = {
|
|
160
|
+
url: string;
|
|
161
|
+
input?: InputType;
|
|
162
|
+
callbackState?: Record<string, any>;
|
|
163
|
+
};
|
|
164
|
+
type SlateOauthCallbackContext<InputType> = {
|
|
165
|
+
code: string;
|
|
166
|
+
state: string;
|
|
167
|
+
redirectUri: string;
|
|
168
|
+
input: InputType;
|
|
169
|
+
clientId: string;
|
|
170
|
+
clientSecret: string;
|
|
171
|
+
scopes: string[];
|
|
172
|
+
callbackParams?: Record<string, string>;
|
|
173
|
+
callbackState: Record<string, any>;
|
|
174
|
+
config?: SlateAuthCallbackConfig;
|
|
175
|
+
};
|
|
176
|
+
type SlateOauthAdminCallbackContext<InputType> = Omit<SlateOauthCallbackContext<InputType>, 'code'> & {
|
|
177
|
+
code?: string;
|
|
178
|
+
};
|
|
150
179
|
type SlateAuthWithOauth<InputType extends {}, OutputType extends {
|
|
151
180
|
token: string;
|
|
152
181
|
refreshToken?: string;
|
|
@@ -162,6 +191,12 @@ type SlateAuthWithOauth<InputType extends {}, OutputType extends {
|
|
|
162
191
|
}[];
|
|
163
192
|
adapters?: string[];
|
|
164
193
|
syncTokensAcrossConnections?: boolean;
|
|
194
|
+
adminSetup?: {
|
|
195
|
+
getAuthorizationUrl?: (ctx: SlateOauthAuthorizationUrlContext<InputType>) => Promise<SlateOauthAuthorizationUrlResult<InputType>>;
|
|
196
|
+
handleCallback?: (ctx: SlateOauthAdminCallbackContext<InputType>) => Promise<{
|
|
197
|
+
instructions?: string;
|
|
198
|
+
}>;
|
|
199
|
+
};
|
|
165
200
|
docs?: SlateAuthDocsReference[];
|
|
166
201
|
inputSchema?: z.ZodType<InputType>;
|
|
167
202
|
onInputChanged?: (params: {
|
|
@@ -171,31 +206,8 @@ type SlateAuthWithOauth<InputType extends {}, OutputType extends {
|
|
|
171
206
|
input?: InputType;
|
|
172
207
|
} | undefined>;
|
|
173
208
|
getDefaultInput?: () => Promise<InputType>;
|
|
174
|
-
getAuthorizationUrl: (ctx:
|
|
175
|
-
|
|
176
|
-
state: string;
|
|
177
|
-
input: InputType;
|
|
178
|
-
clientId: string;
|
|
179
|
-
clientSecret: string;
|
|
180
|
-
scopes: string[];
|
|
181
|
-
config?: SlateAuthCallbackConfig;
|
|
182
|
-
}) => Promise<{
|
|
183
|
-
url: string;
|
|
184
|
-
input?: InputType;
|
|
185
|
-
callbackState?: Record<string, any>;
|
|
186
|
-
}>;
|
|
187
|
-
handleCallback: (ctx: {
|
|
188
|
-
code: string;
|
|
189
|
-
state: string;
|
|
190
|
-
redirectUri: string;
|
|
191
|
-
input: InputType;
|
|
192
|
-
clientId: string;
|
|
193
|
-
clientSecret: string;
|
|
194
|
-
scopes: string[];
|
|
195
|
-
callbackParams?: Record<string, string>;
|
|
196
|
-
callbackState: Record<string, any>;
|
|
197
|
-
config?: SlateAuthCallbackConfig;
|
|
198
|
-
}) => Promise<{
|
|
209
|
+
getAuthorizationUrl: (ctx: SlateOauthAuthorizationUrlContext<InputType>) => Promise<SlateOauthAuthorizationUrlResult<InputType>>;
|
|
210
|
+
handleCallback: (ctx: SlateOauthCallbackContext<InputType>) => Promise<{
|
|
199
211
|
output: OutputType;
|
|
200
212
|
input?: InputType;
|
|
201
213
|
scopes?: string[];
|
|
@@ -857,6 +869,25 @@ declare let allOf: (...inputs: SlateActionScopesInput[]) => SlateActionScopes;
|
|
|
857
869
|
declare let mergeScopes: (...inputs: Array<SlateActionScopes | null | undefined | false>) => SlateActionScopes | undefined;
|
|
858
870
|
declare let validateScopes: (scopes: SlateActionScopes) => SlateActionScopes;
|
|
859
871
|
|
|
872
|
+
interface SlateToolCategoryParameters {
|
|
873
|
+
key: string;
|
|
874
|
+
name: string;
|
|
875
|
+
description?: string;
|
|
876
|
+
imageUrl?: string;
|
|
877
|
+
tools: SlateTool<any, any, any, any>[];
|
|
878
|
+
}
|
|
879
|
+
declare class SlateToolCategory {
|
|
880
|
+
private readonly _params;
|
|
881
|
+
private constructor();
|
|
882
|
+
static create(params: SlateToolCategoryParameters): SlateToolCategory;
|
|
883
|
+
get key(): string;
|
|
884
|
+
get name(): string;
|
|
885
|
+
get description(): string | undefined;
|
|
886
|
+
get imageUrl(): string | undefined;
|
|
887
|
+
get tools(): SlateTool<any, any, any, any>[];
|
|
888
|
+
}
|
|
889
|
+
declare let toolCategory: (params: SlateToolCategoryParameters) => SlateToolCategory;
|
|
890
|
+
|
|
860
891
|
interface SlateTriggerParameters<ConfigType extends {}, AuthType extends {}, InputType extends {}, OutputType extends {
|
|
861
892
|
type: string;
|
|
862
893
|
}> extends SlateActionParameters {
|
|
@@ -1123,6 +1154,8 @@ declare class Slate<ConfigType extends {}, AuthType extends {}> {
|
|
|
1123
1154
|
private readonly _actions;
|
|
1124
1155
|
private readonly _adapters;
|
|
1125
1156
|
private readonly _triggerGroups;
|
|
1157
|
+
private readonly _toolCategories;
|
|
1158
|
+
private readonly _toolCategoryKeysByActionKey;
|
|
1126
1159
|
private constructor();
|
|
1127
1160
|
static create<ConfigType extends {}, AuthType extends {}>(params: {
|
|
1128
1161
|
spec: SlateSpecification<ConfigType, AuthType>;
|
|
@@ -1130,11 +1163,14 @@ declare class Slate<ConfigType extends {}, AuthType extends {}> {
|
|
|
1130
1163
|
tools: SlateTool<ConfigType, AuthType, any, any>[];
|
|
1131
1164
|
adapters?: SlateAdapter<ConfigType, AuthType>[];
|
|
1132
1165
|
triggerGroups?: SlateTriggerGroup<ConfigType, AuthType>[];
|
|
1166
|
+
toolCategories?: SlateToolCategory[];
|
|
1133
1167
|
}): Slate<ConfigType, AuthType>;
|
|
1134
1168
|
get spec(): SlateSpecification<ConfigType, AuthType>;
|
|
1135
1169
|
get actions(): (SlateTrigger<ConfigType, AuthType, any, any> | SlateTool<ConfigType, AuthType, any, any>)[];
|
|
1136
1170
|
get adapters(): SlateAdapter<ConfigType, AuthType>[];
|
|
1137
1171
|
get triggerGroups(): SlateTriggerGroup<ConfigType, AuthType, Record<string, unknown>>[];
|
|
1172
|
+
get toolCategories(): SlateToolCategory[];
|
|
1173
|
+
getToolCategoryKeys(actionKey: string): string[];
|
|
1138
1174
|
}
|
|
1139
1175
|
|
|
1140
1176
|
declare const graphWebhookHttp: {
|
|
@@ -1168,4 +1204,4 @@ declare let skipWebhook: (reason: string, response?: Response | SlateWebhookHttp
|
|
|
1168
1204
|
response: Response | SlateWebhookHttpResponseInit;
|
|
1169
1205
|
};
|
|
1170
1206
|
|
|
1171
|
-
export { API_ERROR_MAX_DETAILS, API_ERROR_MAX_MESSAGE_LENGTH, API_ERROR_TRUNCATED_PLACEHOLDER, AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX, type ApiErrorBuildHelpers, type ApiErrorDetailOptions, type ApiErrorResponse, type ApiErrorStatus, type ApiErrorTextOptions, type ApiServiceError, type AuthConfigSecretFilter, AuthConfigSecretRedactor, type BoundedApiErrorDetailOptions, type BuildApiServiceErrorOptions, type CreateHmacSignatureOptions, type DecodeApiErrorBodyOptions, GET_FILE_URL_TOOL_ID, type GetFileUrlHandler, type GetFileUrlToolInput, type GetFileUrlToolOutput, type NormalizeOAuthTokenResponseOptions, type OAuthExpiresAtOptions, type OAuthRefreshTokenFallbackMode, type OAuthTokenResponse, Slate, SlateAction, SlateActionBuilder, type SlateActionCreateParameters, type SlateActionDocsReference, type SlateActionParameters, type SlateActionParametersAny, type SlateActionParametersTool, type SlateActionParametersTrigger, type SlateActionScopeClause, type SlateActionScopeClauseInput, type SlateActionScopeValue, type SlateActionScopes, type SlateActionScopesInput, type SlateActionType, SlateAdapter, type SlateAdapterCapability, SlateAdapterSpec, type SlateAdapterSpecParameters, type SlateAddAttachmentContent, type SlateAddAttachmentInput, type SlateAttachment, type SlateAttachmentInlineContent, type SlateAttachmentUploadReferenceContent, type SlateAttachmentUrlContent, SlateAuth, type SlateAuthDocsReference, type SlateAuthType, type SlateAuthWithCustomData, type SlateAuthWithNone, type SlateAuthWithOauth, type SlateAuthWithServiceAccount, type SlateAuthWithToken, type SlateAuthenticatedAxiosDefaults, type SlateAxiosDefaults, type SlateAxiosErrorAdapter, type SlateAxiosErrorOptions, SlateConfig, type SlateConfigDocsReference, SlateContext, SlateDeclarationError, SlateDefaultPollingIntervalSeconds, type SlateDirectUploadInput, type SlateDocsReference, SlateError, type SlateErrorInput, type SlateErrorIssue, type SlateErrorKind, type SlateErrorProviderInfo, type SlateErrorResponse, type SlateErrorUpstreamInfo, type SlateGatewayEvent, type SlateLiveInvocationInfo, type SlateLogEntry, type SlateLogFields, type SlateLogListener, type SlateLogMessageInput, type SlateLogType, SlateLogger, type SlateProviderDocsReference, SlatePublicContext, SlatePublicTool, type SlatePublicToolInvocationHandler, type SlatePublicToolParameters, type SlateServiceErrorData, SlateSpecification, type SlateSpecificationCreateParameters, type SlateSpecificationParameters, SlateTool, type SlateToolInvocationHandler, type SlateToolParameters, SlateTrigger, SlateTriggerGroup, SlateTriggerGroupBuilder, type SlateTriggerGroupCreateParameters, type SlateTriggerGroupGatewayConnectHandler, type SlateTriggerGroupGatewayParameters, type SlateTriggerGroupGatewayReceiveHandler, type SlateTriggerGroupParameters, type SlateTriggerGroupPollHandler, type SlateTriggerGroupPollingParameters, type SlateTriggerGroupRoutingMatchersHandler, type SlateTriggerGroupWebhookAutoRegistrationParameters, type SlateTriggerGroupWebhookManualRegistrationParameters, type SlateTriggerGroupWebhookParameters, type SlateTriggerMappingHandler, type SlateTriggerMatchesHandler, type SlateTriggerParameters, type SlateTriggerRoutingMatcher, type SlateTypedDocsReference, type SlateWebhookHttpResponseInit, type SlateWebhookManualFinishHandler, type SlateWebhookManualSetupHandler, type SlateWebhookProcessHandler, type SlateWebhookRegisterHandler, type SlateWebhookSkipped, type SlateWebhookTarget, type SlateWebhookTargetListHandler, type SlateWebhookTargetOwnership, type SlateWebhookUnregisterHandler, type VerifyHmacSignatureOptions, adapterSpec, allOf, anyOf, auth, axios, buildApiServiceError, collectApiErrorDetails, config, createApiServiceError, createAuthenticatedAxios, createAxios, createBase64Attachment, createHmacSignature, createSlateError, createTextAttachment, createUrlAttachment, decodeApiErrorBody, extractApiErrorMessage, getApiErrorResponse, getApiErrorResponseWithBody, getApiErrorStatus, getBase64ByteLength, getCurrentContext, getFileUrlTool, getFileUrlToolInputSchema, getFileUrlToolOutputSchema, getGraphWebhookValidationResponse, getMetaWebhookVerificationResponse, getOAuthExpiresAtFromExpiresIn, getResponseHeaderValue, getServiceErrorData, graphWebhookHttp, inferSlateErrorFromAxios, isApiErrorRecord, isAxiosErrorLike, isServiceErrorData, isUrlEmbeddedCredential, looksLikeHtmlErrorBody, mapServiceErrorCode, mapServiceErrorToSlateErrorInput, mergeScopes, metaWebhookHttp, normalizeOAuthTokenResponse, pickDefined, publicTool, pushBoundedApiErrorDetail, readApiErrorText, redactUrlAttachmentSecrets, requestAxios, requestAxiosData, runWithContext, scopeClause, setIfDefined, skipWebhook, spec, statusLabelForApiError, tool, trigger, triggerGroup, truncateApiErrorMessage, uploadAttachmentDirect, validateScopes, verifyHmacSignature };
|
|
1207
|
+
export { API_ERROR_MAX_DETAILS, API_ERROR_MAX_MESSAGE_LENGTH, API_ERROR_TRUNCATED_PLACEHOLDER, AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX, type ApiErrorBuildHelpers, type ApiErrorDetailOptions, type ApiErrorResponse, type ApiErrorStatus, type ApiErrorTextOptions, type ApiServiceError, type AuthConfigSecretFilter, AuthConfigSecretRedactor, type BoundedApiErrorDetailOptions, type BuildApiServiceErrorOptions, type CreateHmacSignatureOptions, type DecodeApiErrorBodyOptions, GET_FILE_URL_TOOL_ID, type GetFileUrlHandler, type GetFileUrlToolInput, type GetFileUrlToolOutput, type NormalizeOAuthTokenResponseOptions, type OAuthExpiresAtOptions, type OAuthRefreshTokenFallbackMode, type OAuthTokenResponse, Slate, SlateAction, SlateActionBuilder, type SlateActionCreateParameters, type SlateActionDocsReference, type SlateActionParameters, type SlateActionParametersAny, type SlateActionParametersTool, type SlateActionParametersTrigger, type SlateActionScopeClause, type SlateActionScopeClauseInput, type SlateActionScopeValue, type SlateActionScopes, type SlateActionScopesInput, type SlateActionType, SlateAdapter, type SlateAdapterCapability, SlateAdapterSpec, type SlateAdapterSpecParameters, type SlateAddAttachmentContent, type SlateAddAttachmentInput, type SlateAttachment, type SlateAttachmentInlineContent, type SlateAttachmentUploadReferenceContent, type SlateAttachmentUrlContent, SlateAuth, type SlateAuthDocsReference, type SlateAuthType, type SlateAuthWithCustomData, type SlateAuthWithNone, type SlateAuthWithOauth, type SlateAuthWithServiceAccount, type SlateAuthWithToken, type SlateAuthenticatedAxiosDefaults, type SlateAxiosDefaults, type SlateAxiosErrorAdapter, type SlateAxiosErrorOptions, SlateConfig, type SlateConfigDocsReference, SlateContext, SlateDeclarationError, SlateDefaultPollingIntervalSeconds, type SlateDirectUploadInput, type SlateDocsReference, SlateError, type SlateErrorInput, type SlateErrorIssue, type SlateErrorKind, type SlateErrorProviderInfo, type SlateErrorResponse, type SlateErrorUpstreamInfo, type SlateGatewayEvent, type SlateLiveInvocationInfo, type SlateLogEntry, type SlateLogFields, type SlateLogListener, type SlateLogMessageInput, type SlateLogType, SlateLogger, type SlateProviderDocsReference, SlatePublicContext, SlatePublicTool, type SlatePublicToolInvocationHandler, type SlatePublicToolParameters, type SlateServiceErrorData, SlateSpecification, type SlateSpecificationCreateParameters, type SlateSpecificationParameters, SlateTool, SlateToolCategory, type SlateToolCategoryParameters, type SlateToolInvocationHandler, type SlateToolParameters, SlateTrigger, SlateTriggerGroup, SlateTriggerGroupBuilder, type SlateTriggerGroupCreateParameters, type SlateTriggerGroupGatewayConnectHandler, type SlateTriggerGroupGatewayParameters, type SlateTriggerGroupGatewayReceiveHandler, type SlateTriggerGroupParameters, type SlateTriggerGroupPollHandler, type SlateTriggerGroupPollingParameters, type SlateTriggerGroupRoutingMatchersHandler, type SlateTriggerGroupWebhookAutoRegistrationParameters, type SlateTriggerGroupWebhookManualRegistrationParameters, type SlateTriggerGroupWebhookParameters, type SlateTriggerMappingHandler, type SlateTriggerMatchesHandler, type SlateTriggerParameters, type SlateTriggerRoutingMatcher, type SlateTypedDocsReference, type SlateWebhookHttpResponseInit, type SlateWebhookManualFinishHandler, type SlateWebhookManualSetupHandler, type SlateWebhookProcessHandler, type SlateWebhookRegisterHandler, type SlateWebhookSkipped, type SlateWebhookTarget, type SlateWebhookTargetListHandler, type SlateWebhookTargetOwnership, type SlateWebhookUnregisterHandler, type VerifyHmacSignatureOptions, adapterSpec, allOf, anyOf, auth, axios, buildApiServiceError, collectApiErrorDetails, config, createApiServiceError, createAuthenticatedAxios, createAxios, createBase64Attachment, createHmacSignature, createSlateError, createTextAttachment, createUrlAttachment, decodeApiErrorBody, extractApiErrorMessage, getApiErrorResponse, getApiErrorResponseWithBody, getApiErrorStatus, getBase64ByteLength, getCurrentContext, getFileUrlTool, getFileUrlToolInputSchema, getFileUrlToolOutputSchema, getGraphWebhookValidationResponse, getMetaWebhookVerificationResponse, getOAuthExpiresAtFromExpiresIn, getResponseHeaderValue, getServiceErrorData, graphWebhookHttp, inferSlateErrorFromAxios, isApiErrorRecord, isAxiosErrorLike, isServiceErrorData, isUrlEmbeddedCredential, looksLikeHtmlErrorBody, mapServiceErrorCode, mapServiceErrorToSlateErrorInput, mergeScopes, metaWebhookHttp, normalizeOAuthTokenResponse, pickDefined, publicTool, pushBoundedApiErrorDetail, readApiErrorText, redactUrlAttachmentSecrets, requestAxios, requestAxiosData, runWithContext, scopeClause, setIfDefined, skipWebhook, spec, statusLabelForApiError, tool, toolCategory, trigger, triggerGroup, truncateApiErrorMessage, uploadAttachmentDirect, validateScopes, verifyHmacSignature };
|
package/dist/index.module.js
CHANGED
|
@@ -2055,6 +2055,33 @@ var SlatePublicTool = class {
|
|
|
2055
2055
|
};
|
|
2056
2056
|
var publicTool = (spec2, params) => SlatePublicTool.create(spec2, params);
|
|
2057
2057
|
|
|
2058
|
+
// src/action/toolCategory.ts
|
|
2059
|
+
var SlateToolCategory = class _SlateToolCategory {
|
|
2060
|
+
constructor(_params) {
|
|
2061
|
+
this._params = _params;
|
|
2062
|
+
}
|
|
2063
|
+
_params;
|
|
2064
|
+
static create(params) {
|
|
2065
|
+
return new _SlateToolCategory(params);
|
|
2066
|
+
}
|
|
2067
|
+
get key() {
|
|
2068
|
+
return this._params.key;
|
|
2069
|
+
}
|
|
2070
|
+
get name() {
|
|
2071
|
+
return this._params.name;
|
|
2072
|
+
}
|
|
2073
|
+
get description() {
|
|
2074
|
+
return this._params.description;
|
|
2075
|
+
}
|
|
2076
|
+
get imageUrl() {
|
|
2077
|
+
return this._params.imageUrl;
|
|
2078
|
+
}
|
|
2079
|
+
get tools() {
|
|
2080
|
+
return this._params.tools;
|
|
2081
|
+
}
|
|
2082
|
+
};
|
|
2083
|
+
var toolCategory = (params) => SlateToolCategory.create(params);
|
|
2084
|
+
|
|
2058
2085
|
// src/action/trigger.ts
|
|
2059
2086
|
var SlateTrigger = class _SlateTrigger extends SlateAction {
|
|
2060
2087
|
#triggerGroup;
|
|
@@ -3078,16 +3105,20 @@ var setIfDefined = (target, key, value) => {
|
|
|
3078
3105
|
|
|
3079
3106
|
// src/specification/slate.ts
|
|
3080
3107
|
var Slate = class _Slate {
|
|
3081
|
-
constructor(_spec, _actions, _adapters, _triggerGroups) {
|
|
3108
|
+
constructor(_spec, _actions, _adapters, _triggerGroups, _toolCategories, _toolCategoryKeysByActionKey) {
|
|
3082
3109
|
this._spec = _spec;
|
|
3083
3110
|
this._actions = _actions;
|
|
3084
3111
|
this._adapters = _adapters;
|
|
3085
3112
|
this._triggerGroups = _triggerGroups;
|
|
3113
|
+
this._toolCategories = _toolCategories;
|
|
3114
|
+
this._toolCategoryKeysByActionKey = _toolCategoryKeysByActionKey;
|
|
3086
3115
|
}
|
|
3087
3116
|
_spec;
|
|
3088
3117
|
_actions;
|
|
3089
3118
|
_adapters;
|
|
3090
3119
|
_triggerGroups;
|
|
3120
|
+
_toolCategories;
|
|
3121
|
+
_toolCategoryKeysByActionKey;
|
|
3091
3122
|
static create(params) {
|
|
3092
3123
|
let adapters = params.adapters ?? [];
|
|
3093
3124
|
let actions = [...params.triggers, ...params.tools];
|
|
@@ -3131,7 +3162,16 @@ var Slate = class _Slate {
|
|
|
3131
3162
|
`Only one trigger group may use manual webhook registration, but found: ${manualWebhookTriggerGroups.map((group) => group.key).join(", ")}`
|
|
3132
3163
|
);
|
|
3133
3164
|
}
|
|
3134
|
-
|
|
3165
|
+
let toolCategories = params.toolCategories ?? [];
|
|
3166
|
+
let toolCategoryKeysByActionKey = resolveToolCategoryMembership(toolCategories, actions);
|
|
3167
|
+
return new _Slate(
|
|
3168
|
+
params.spec,
|
|
3169
|
+
actions,
|
|
3170
|
+
adapters,
|
|
3171
|
+
triggerGroups,
|
|
3172
|
+
toolCategories,
|
|
3173
|
+
toolCategoryKeysByActionKey
|
|
3174
|
+
);
|
|
3135
3175
|
}
|
|
3136
3176
|
get spec() {
|
|
3137
3177
|
return this._spec;
|
|
@@ -3145,6 +3185,79 @@ var Slate = class _Slate {
|
|
|
3145
3185
|
get triggerGroups() {
|
|
3146
3186
|
return this._triggerGroups ?? [];
|
|
3147
3187
|
}
|
|
3188
|
+
get toolCategories() {
|
|
3189
|
+
return this._toolCategories ?? [];
|
|
3190
|
+
}
|
|
3191
|
+
// Keys of the tool categories an action belongs to, in declared category order.
|
|
3192
|
+
getToolCategoryKeys(actionKey) {
|
|
3193
|
+
return [...this._toolCategoryKeysByActionKey?.get(actionKey) ?? []];
|
|
3194
|
+
}
|
|
3195
|
+
};
|
|
3196
|
+
var TOOL_CATEGORY_KEY_PATTERN = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
3197
|
+
var isHttpUrl = (value) => {
|
|
3198
|
+
try {
|
|
3199
|
+
let url = new URL(value);
|
|
3200
|
+
return url.protocol === "https:" || url.protocol === "http:";
|
|
3201
|
+
} catch {
|
|
3202
|
+
return false;
|
|
3203
|
+
}
|
|
3204
|
+
};
|
|
3205
|
+
var resolveToolCategoryMembership = (toolCategories, actions) => {
|
|
3206
|
+
let effectiveActions = /* @__PURE__ */ new Map();
|
|
3207
|
+
for (let action of actions) {
|
|
3208
|
+
if (!effectiveActions.has(action.key)) effectiveActions.set(action.key, action);
|
|
3209
|
+
}
|
|
3210
|
+
let registeredActions = new Set(actions);
|
|
3211
|
+
let membersByCategoryKey = /* @__PURE__ */ new Map();
|
|
3212
|
+
for (let category of toolCategories) {
|
|
3213
|
+
if (!TOOL_CATEGORY_KEY_PATTERN.test(category.key)) {
|
|
3214
|
+
throw new SlateDeclarationError(
|
|
3215
|
+
`Tool category key "${category.key}" must match ${TOOL_CATEGORY_KEY_PATTERN}`
|
|
3216
|
+
);
|
|
3217
|
+
}
|
|
3218
|
+
if (membersByCategoryKey.has(category.key)) {
|
|
3219
|
+
throw new SlateDeclarationError(
|
|
3220
|
+
`Tool category "${category.key}" is registered more than once`
|
|
3221
|
+
);
|
|
3222
|
+
}
|
|
3223
|
+
if (!category.name?.trim()) {
|
|
3224
|
+
throw new SlateDeclarationError(`Tool category "${category.key}" must have a name`);
|
|
3225
|
+
}
|
|
3226
|
+
if (category.imageUrl !== void 0 && !isHttpUrl(category.imageUrl)) {
|
|
3227
|
+
throw new SlateDeclarationError(
|
|
3228
|
+
`Tool category "${category.key}" imageUrl must be an absolute http(s) URL`
|
|
3229
|
+
);
|
|
3230
|
+
}
|
|
3231
|
+
if (!category.tools?.length) {
|
|
3232
|
+
throw new SlateDeclarationError(
|
|
3233
|
+
`Tool category "${category.key}" must list at least one tool`
|
|
3234
|
+
);
|
|
3235
|
+
}
|
|
3236
|
+
let members = /* @__PURE__ */ new Set();
|
|
3237
|
+
for (let tool2 of category.tools) {
|
|
3238
|
+
if (!registeredActions.has(tool2)) {
|
|
3239
|
+
throw new SlateDeclarationError(
|
|
3240
|
+
`Tool category "${category.key}" lists tool "${tool2.key}", which is not registered in this slate`
|
|
3241
|
+
);
|
|
3242
|
+
}
|
|
3243
|
+
if (tool2.type !== "tool") {
|
|
3244
|
+
throw new SlateDeclarationError(
|
|
3245
|
+
`Tool category "${category.key}" lists trigger "${tool2.key}", but only tools can belong to a tool category`
|
|
3246
|
+
);
|
|
3247
|
+
}
|
|
3248
|
+
if (effectiveActions.get(tool2.key) === tool2) members.add(tool2.key);
|
|
3249
|
+
}
|
|
3250
|
+
membersByCategoryKey.set(category.key, members);
|
|
3251
|
+
}
|
|
3252
|
+
let keysByActionKey = /* @__PURE__ */ new Map();
|
|
3253
|
+
for (let category of toolCategories) {
|
|
3254
|
+
for (let actionKey of membersByCategoryKey.get(category.key) ?? []) {
|
|
3255
|
+
let keys = keysByActionKey.get(actionKey) ?? [];
|
|
3256
|
+
keys.push(category.key);
|
|
3257
|
+
keysByActionKey.set(actionKey, keys);
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
return keysByActionKey;
|
|
3148
3261
|
};
|
|
3149
3262
|
|
|
3150
3263
|
// src/specification/specification.ts
|
|
@@ -3273,6 +3386,7 @@ export {
|
|
|
3273
3386
|
SlatePublicTool,
|
|
3274
3387
|
SlateSpecification,
|
|
3275
3388
|
SlateTool,
|
|
3389
|
+
SlateToolCategory,
|
|
3276
3390
|
SlateTrigger,
|
|
3277
3391
|
SlateTriggerGroup,
|
|
3278
3392
|
SlateTriggerGroupBuilder,
|
|
@@ -3333,6 +3447,7 @@ export {
|
|
|
3333
3447
|
spec,
|
|
3334
3448
|
statusLabelForApiError,
|
|
3335
3449
|
tool,
|
|
3450
|
+
toolCategory,
|
|
3336
3451
|
trigger,
|
|
3337
3452
|
triggerGroup,
|
|
3338
3453
|
truncateApiErrorMessage,
|
package/package.json
CHANGED
package/src/action/index.ts
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { SlateTool } from './tool';
|
|
2
|
+
|
|
3
|
+
export interface SlateToolCategoryParameters {
|
|
4
|
+
key: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
imageUrl?: string;
|
|
8
|
+
tools: SlateTool<any, any, any, any>[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class SlateToolCategory {
|
|
12
|
+
private constructor(private readonly _params: SlateToolCategoryParameters) {}
|
|
13
|
+
|
|
14
|
+
static create(params: SlateToolCategoryParameters) {
|
|
15
|
+
return new SlateToolCategory(params);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get key() {
|
|
19
|
+
return this._params.key;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get name() {
|
|
23
|
+
return this._params.name;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get description() {
|
|
27
|
+
return this._params.description;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get imageUrl() {
|
|
31
|
+
return this._params.imageUrl;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get tools() {
|
|
35
|
+
return this._params.tools;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export let toolCategory = (params: SlateToolCategoryParameters) =>
|
|
40
|
+
SlateToolCategory.create(params);
|
package/src/auth/types.ts
CHANGED
|
@@ -3,6 +3,42 @@ import type { SlateAuthDocsReference } from '../docs';
|
|
|
3
3
|
|
|
4
4
|
type SlateAuthCallbackConfig = Record<string, any>;
|
|
5
5
|
|
|
6
|
+
type SlateOauthAuthorizationUrlContext<InputType> = {
|
|
7
|
+
redirectUri: string;
|
|
8
|
+
state: string;
|
|
9
|
+
input: InputType;
|
|
10
|
+
clientId: string;
|
|
11
|
+
clientSecret: string;
|
|
12
|
+
scopes: string[];
|
|
13
|
+
config?: SlateAuthCallbackConfig;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
type SlateOauthAuthorizationUrlResult<InputType> = {
|
|
17
|
+
url: string;
|
|
18
|
+
input?: InputType;
|
|
19
|
+
callbackState?: Record<string, any>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type SlateOauthCallbackContext<InputType> = {
|
|
23
|
+
code: string;
|
|
24
|
+
state: string;
|
|
25
|
+
redirectUri: string;
|
|
26
|
+
input: InputType;
|
|
27
|
+
clientId: string;
|
|
28
|
+
clientSecret: string;
|
|
29
|
+
scopes: string[];
|
|
30
|
+
callbackParams?: Record<string, string>;
|
|
31
|
+
callbackState: Record<string, any>;
|
|
32
|
+
config?: SlateAuthCallbackConfig;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
type SlateOauthAdminCallbackContext<InputType> = Omit<
|
|
36
|
+
SlateOauthCallbackContext<InputType>,
|
|
37
|
+
'code'
|
|
38
|
+
> & {
|
|
39
|
+
code?: string;
|
|
40
|
+
};
|
|
41
|
+
|
|
6
42
|
export type SlateAuthWithOauth<
|
|
7
43
|
InputType extends {},
|
|
8
44
|
OutputType extends {
|
|
@@ -28,6 +64,18 @@ export type SlateAuthWithOauth<
|
|
|
28
64
|
// connection of one installation, so a refresh must update all of them.
|
|
29
65
|
syncTokensAcrossConnections?: boolean;
|
|
30
66
|
|
|
67
|
+
// Missing hooks fall back to the regular flow (callback output discarded).
|
|
68
|
+
// Returned instructions are markdown shown to the admin.
|
|
69
|
+
adminSetup?: {
|
|
70
|
+
getAuthorizationUrl?: (
|
|
71
|
+
ctx: SlateOauthAuthorizationUrlContext<InputType>
|
|
72
|
+
) => Promise<SlateOauthAuthorizationUrlResult<InputType>>;
|
|
73
|
+
|
|
74
|
+
handleCallback?: (
|
|
75
|
+
ctx: SlateOauthAdminCallbackContext<InputType>
|
|
76
|
+
) => Promise<{ instructions?: string }>;
|
|
77
|
+
};
|
|
78
|
+
|
|
31
79
|
docs?: SlateAuthDocsReference[];
|
|
32
80
|
|
|
33
81
|
inputSchema?: z.ZodType<InputType>;
|
|
@@ -39,32 +87,11 @@ export type SlateAuthWithOauth<
|
|
|
39
87
|
|
|
40
88
|
getDefaultInput?: () => Promise<InputType>;
|
|
41
89
|
|
|
42
|
-
getAuthorizationUrl: (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
input: InputType;
|
|
46
|
-
clientId: string;
|
|
47
|
-
clientSecret: string;
|
|
48
|
-
scopes: string[];
|
|
49
|
-
config?: SlateAuthCallbackConfig;
|
|
50
|
-
}) => Promise<{
|
|
51
|
-
url: string;
|
|
52
|
-
input?: InputType;
|
|
53
|
-
callbackState?: Record<string, any>;
|
|
54
|
-
}>;
|
|
90
|
+
getAuthorizationUrl: (
|
|
91
|
+
ctx: SlateOauthAuthorizationUrlContext<InputType>
|
|
92
|
+
) => Promise<SlateOauthAuthorizationUrlResult<InputType>>;
|
|
55
93
|
|
|
56
|
-
handleCallback: (ctx: {
|
|
57
|
-
code: string;
|
|
58
|
-
state: string;
|
|
59
|
-
redirectUri: string;
|
|
60
|
-
input: InputType;
|
|
61
|
-
clientId: string;
|
|
62
|
-
clientSecret: string;
|
|
63
|
-
scopes: string[];
|
|
64
|
-
callbackParams?: Record<string, string>;
|
|
65
|
-
callbackState: Record<string, any>;
|
|
66
|
-
config?: SlateAuthCallbackConfig;
|
|
67
|
-
}) => Promise<{
|
|
94
|
+
handleCallback: (ctx: SlateOauthCallbackContext<InputType>) => Promise<{
|
|
68
95
|
output: OutputType;
|
|
69
96
|
input?: InputType;
|
|
70
97
|
scopes?: string[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { SlateTrigger, SlateTriggerGroup } from '../action';
|
|
3
|
+
import { SlateTool, SlateTrigger, SlateTriggerGroup, toolCategory } from '../action';
|
|
4
4
|
import { SlateAuth } from '../auth';
|
|
5
5
|
import { SlateConfig } from '../config';
|
|
6
6
|
import { Slate } from './slate';
|
|
@@ -117,3 +117,155 @@ describe('Slate.create', () => {
|
|
|
117
117
|
expect(slate.triggerGroups).toEqual([]);
|
|
118
118
|
});
|
|
119
119
|
});
|
|
120
|
+
|
|
121
|
+
let createTestTool = (spec: ReturnType<typeof createTestSpec>, key: string) =>
|
|
122
|
+
SlateTool.create(spec, { key, name: key })
|
|
123
|
+
.input(z.object({}))
|
|
124
|
+
.output(z.object({}))
|
|
125
|
+
.handleInvocation(async () => ({ output: {}, message: 'ok' }))
|
|
126
|
+
.build();
|
|
127
|
+
|
|
128
|
+
describe('Slate.create tool categories', () => {
|
|
129
|
+
it('resolves membership in declared category order', () => {
|
|
130
|
+
let spec = createTestSpec();
|
|
131
|
+
let records = createTestTool(spec, 'records');
|
|
132
|
+
let report = createTestTool(spec, 'report');
|
|
133
|
+
let other = createTestTool(spec, 'other');
|
|
134
|
+
|
|
135
|
+
let slate = Slate.create({
|
|
136
|
+
spec,
|
|
137
|
+
tools: [records, report, other],
|
|
138
|
+
triggers: [],
|
|
139
|
+
toolCategories: [
|
|
140
|
+
toolCategory({ key: 'crm', name: 'CRM', tools: [records, report] }),
|
|
141
|
+
toolCategory({ key: 'reporting', name: 'Reporting', tools: [report] })
|
|
142
|
+
]
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
expect(slate.toolCategories.map(category => category.key)).toEqual(['crm', 'reporting']);
|
|
146
|
+
expect(slate.getToolCategoryKeys('records')).toEqual(['crm']);
|
|
147
|
+
expect(slate.getToolCategoryKeys('report')).toEqual(['crm', 'reporting']);
|
|
148
|
+
expect(slate.getToolCategoryKeys('other')).toEqual([]);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('ignores a shadowed duplicate tool listed in a category', () => {
|
|
152
|
+
let spec = createTestSpec();
|
|
153
|
+
let writer = createTestTool(spec, 'dup');
|
|
154
|
+
let reader = createTestTool(spec, 'dup');
|
|
155
|
+
|
|
156
|
+
let slate = Slate.create({
|
|
157
|
+
spec,
|
|
158
|
+
tools: [writer, reader],
|
|
159
|
+
triggers: [],
|
|
160
|
+
toolCategories: [toolCategory({ key: 'read', name: 'Read', tools: [reader] })]
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
expect(slate.getToolCategoryKeys('dup')).toEqual([]);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('returns a copy of the membership list', () => {
|
|
167
|
+
let spec = createTestSpec();
|
|
168
|
+
let tool = createTestTool(spec, 'a');
|
|
169
|
+
let slate = Slate.create({
|
|
170
|
+
spec,
|
|
171
|
+
tools: [tool],
|
|
172
|
+
triggers: [],
|
|
173
|
+
toolCategories: [toolCategory({ key: 'crm', name: 'CRM', tools: [tool] })]
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
slate.getToolCategoryKeys('a').push('mutated');
|
|
177
|
+
expect(slate.getToolCategoryKeys('a')).toEqual(['crm']);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('defaults to no categories', () => {
|
|
181
|
+
let spec = createTestSpec();
|
|
182
|
+
let slate = Slate.create({ spec, tools: [createTestTool(spec, 'a')], triggers: [] });
|
|
183
|
+
|
|
184
|
+
expect(slate.toolCategories).toEqual([]);
|
|
185
|
+
expect(slate.getToolCategoryKeys('a')).toEqual([]);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('rejects duplicate and malformed category keys', () => {
|
|
189
|
+
let spec = createTestSpec();
|
|
190
|
+
let tool = createTestTool(spec, 'a');
|
|
191
|
+
|
|
192
|
+
expect(() =>
|
|
193
|
+
Slate.create({
|
|
194
|
+
spec,
|
|
195
|
+
tools: [tool],
|
|
196
|
+
triggers: [],
|
|
197
|
+
toolCategories: [
|
|
198
|
+
toolCategory({ key: 'crm', name: 'CRM', tools: [tool] }),
|
|
199
|
+
toolCategory({ key: 'crm', name: 'CRM again', tools: [tool] })
|
|
200
|
+
]
|
|
201
|
+
})
|
|
202
|
+
).toThrow('Tool category "crm" is registered more than once');
|
|
203
|
+
|
|
204
|
+
expect(() =>
|
|
205
|
+
Slate.create({
|
|
206
|
+
spec,
|
|
207
|
+
tools: [tool],
|
|
208
|
+
triggers: [],
|
|
209
|
+
toolCategories: [toolCategory({ key: 'Zoho CRM', name: 'CRM', tools: [tool] })]
|
|
210
|
+
})
|
|
211
|
+
).toThrow('Tool category key "Zoho CRM" must match');
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('accepts http(s) category images and rejects anything else', () => {
|
|
215
|
+
let spec = createTestSpec();
|
|
216
|
+
let tool = createTestTool(spec, 'a');
|
|
217
|
+
let slate = Slate.create({
|
|
218
|
+
spec,
|
|
219
|
+
tools: [tool],
|
|
220
|
+
triggers: [],
|
|
221
|
+
toolCategories: [
|
|
222
|
+
toolCategory({
|
|
223
|
+
key: 'crm',
|
|
224
|
+
name: 'CRM',
|
|
225
|
+
imageUrl: 'https://cdn.test/crm.svg',
|
|
226
|
+
tools: [tool]
|
|
227
|
+
})
|
|
228
|
+
]
|
|
229
|
+
});
|
|
230
|
+
expect(slate.toolCategories[0]?.imageUrl).toBe('https://cdn.test/crm.svg');
|
|
231
|
+
|
|
232
|
+
expect(() =>
|
|
233
|
+
Slate.create({
|
|
234
|
+
spec,
|
|
235
|
+
tools: [tool],
|
|
236
|
+
triggers: [],
|
|
237
|
+
toolCategories: [
|
|
238
|
+
toolCategory({ key: 'crm', name: 'CRM', imageUrl: 'crm.svg', tools: [tool] })
|
|
239
|
+
]
|
|
240
|
+
})
|
|
241
|
+
).toThrow('Tool category "crm" imageUrl must be an absolute http(s) URL');
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('rejects a category without tools', () => {
|
|
245
|
+
let spec = createTestSpec();
|
|
246
|
+
|
|
247
|
+
expect(() =>
|
|
248
|
+
Slate.create({
|
|
249
|
+
spec,
|
|
250
|
+
tools: [createTestTool(spec, 'a')],
|
|
251
|
+
triggers: [],
|
|
252
|
+
toolCategories: [toolCategory({ key: 'crm', name: 'CRM', tools: [] })]
|
|
253
|
+
})
|
|
254
|
+
).toThrow('Tool category "crm" must list at least one tool');
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('rejects unregistered member tools', () => {
|
|
258
|
+
let spec = createTestSpec();
|
|
259
|
+
|
|
260
|
+
expect(() =>
|
|
261
|
+
Slate.create({
|
|
262
|
+
spec,
|
|
263
|
+
tools: [],
|
|
264
|
+
triggers: [],
|
|
265
|
+
toolCategories: [
|
|
266
|
+
toolCategory({ key: 'crm', name: 'CRM', tools: [createTestTool(spec, 'stray')] })
|
|
267
|
+
]
|
|
268
|
+
})
|
|
269
|
+
).toThrow('Tool category "crm" lists tool "stray", which is not registered in this slate');
|
|
270
|
+
});
|
|
271
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SlateTool, SlateTrigger, SlateTriggerGroup } from '../action';
|
|
1
|
+
import type { SlateTool, SlateToolCategory, SlateTrigger, SlateTriggerGroup } from '../action';
|
|
2
2
|
import type { SlateAdapter } from '../adapter';
|
|
3
3
|
import { SlateDeclarationError } from '../error';
|
|
4
4
|
import type { SlateSpecification } from './specification';
|
|
@@ -11,7 +11,9 @@ export class Slate<ConfigType extends {}, AuthType extends {}> {
|
|
|
11
11
|
| SlateTool<ConfigType, AuthType, any, any>
|
|
12
12
|
)[],
|
|
13
13
|
private readonly _adapters: SlateAdapter<ConfigType, AuthType>[],
|
|
14
|
-
private readonly _triggerGroups: SlateTriggerGroup<ConfigType, AuthType>[]
|
|
14
|
+
private readonly _triggerGroups: SlateTriggerGroup<ConfigType, AuthType>[],
|
|
15
|
+
private readonly _toolCategories: SlateToolCategory[],
|
|
16
|
+
private readonly _toolCategoryKeysByActionKey: Map<string, string[]>
|
|
15
17
|
) {}
|
|
16
18
|
|
|
17
19
|
static create<ConfigType extends {}, AuthType extends {}>(params: {
|
|
@@ -20,6 +22,7 @@ export class Slate<ConfigType extends {}, AuthType extends {}> {
|
|
|
20
22
|
tools: SlateTool<ConfigType, AuthType, any, any>[];
|
|
21
23
|
adapters?: SlateAdapter<ConfigType, AuthType>[];
|
|
22
24
|
triggerGroups?: SlateTriggerGroup<ConfigType, AuthType>[];
|
|
25
|
+
toolCategories?: SlateToolCategory[];
|
|
23
26
|
}) {
|
|
24
27
|
let adapters = params.adapters ?? [];
|
|
25
28
|
let actions = [...params.triggers, ...params.tools];
|
|
@@ -71,7 +74,17 @@ export class Slate<ConfigType extends {}, AuthType extends {}> {
|
|
|
71
74
|
);
|
|
72
75
|
}
|
|
73
76
|
|
|
74
|
-
|
|
77
|
+
let toolCategories = params.toolCategories ?? [];
|
|
78
|
+
let toolCategoryKeysByActionKey = resolveToolCategoryMembership(toolCategories, actions);
|
|
79
|
+
|
|
80
|
+
return new Slate(
|
|
81
|
+
params.spec,
|
|
82
|
+
actions,
|
|
83
|
+
adapters,
|
|
84
|
+
triggerGroups,
|
|
85
|
+
toolCategories,
|
|
86
|
+
toolCategoryKeysByActionKey
|
|
87
|
+
);
|
|
75
88
|
}
|
|
76
89
|
|
|
77
90
|
get spec() {
|
|
@@ -89,4 +102,93 @@ export class Slate<ConfigType extends {}, AuthType extends {}> {
|
|
|
89
102
|
get triggerGroups() {
|
|
90
103
|
return this._triggerGroups ?? [];
|
|
91
104
|
}
|
|
105
|
+
|
|
106
|
+
get toolCategories() {
|
|
107
|
+
return this._toolCategories ?? [];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Keys of the tool categories an action belongs to, in declared category order.
|
|
111
|
+
getToolCategoryKeys(actionKey: string) {
|
|
112
|
+
return [...(this._toolCategoryKeysByActionKey?.get(actionKey) ?? [])];
|
|
113
|
+
}
|
|
92
114
|
}
|
|
115
|
+
|
|
116
|
+
let TOOL_CATEGORY_KEY_PATTERN = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
117
|
+
|
|
118
|
+
let isHttpUrl = (value: string) => {
|
|
119
|
+
try {
|
|
120
|
+
let url = new URL(value);
|
|
121
|
+
return url.protocol === 'https:' || url.protocol === 'http:';
|
|
122
|
+
} catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
type SlateActionAny = SlateTool<any, any, any, any> | SlateTrigger<any, any, any, any>;
|
|
128
|
+
|
|
129
|
+
let resolveToolCategoryMembership = (
|
|
130
|
+
toolCategories: SlateToolCategory[],
|
|
131
|
+
actions: SlateActionAny[]
|
|
132
|
+
) => {
|
|
133
|
+
// Actions resolve by key and the first registered one wins, so a shadowed duplicate must
|
|
134
|
+
// not lend its categories to the action that actually runs.
|
|
135
|
+
let effectiveActions = new Map<string, SlateActionAny>();
|
|
136
|
+
for (let action of actions) {
|
|
137
|
+
if (!effectiveActions.has(action.key)) effectiveActions.set(action.key, action);
|
|
138
|
+
}
|
|
139
|
+
let registeredActions = new Set(actions);
|
|
140
|
+
let membersByCategoryKey = new Map<string, Set<string>>();
|
|
141
|
+
|
|
142
|
+
for (let category of toolCategories) {
|
|
143
|
+
if (!TOOL_CATEGORY_KEY_PATTERN.test(category.key)) {
|
|
144
|
+
throw new SlateDeclarationError(
|
|
145
|
+
`Tool category key "${category.key}" must match ${TOOL_CATEGORY_KEY_PATTERN}`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
if (membersByCategoryKey.has(category.key)) {
|
|
149
|
+
throw new SlateDeclarationError(
|
|
150
|
+
`Tool category "${category.key}" is registered more than once`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
if (!category.name?.trim()) {
|
|
154
|
+
throw new SlateDeclarationError(`Tool category "${category.key}" must have a name`);
|
|
155
|
+
}
|
|
156
|
+
if (category.imageUrl !== undefined && !isHttpUrl(category.imageUrl)) {
|
|
157
|
+
throw new SlateDeclarationError(
|
|
158
|
+
`Tool category "${category.key}" imageUrl must be an absolute http(s) URL`
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
if (!category.tools?.length) {
|
|
162
|
+
throw new SlateDeclarationError(
|
|
163
|
+
`Tool category "${category.key}" must list at least one tool`
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
let members = new Set<string>();
|
|
168
|
+
for (let tool of category.tools) {
|
|
169
|
+
if (!registeredActions.has(tool)) {
|
|
170
|
+
throw new SlateDeclarationError(
|
|
171
|
+
`Tool category "${category.key}" lists tool "${tool.key}", which is not registered in this slate`
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
if (tool.type !== 'tool') {
|
|
175
|
+
throw new SlateDeclarationError(
|
|
176
|
+
`Tool category "${category.key}" lists trigger "${tool.key}", but only tools can belong to a tool category`
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
if (effectiveActions.get(tool.key) === tool) members.add(tool.key);
|
|
180
|
+
}
|
|
181
|
+
membersByCategoryKey.set(category.key, members);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
let keysByActionKey = new Map<string, string[]>();
|
|
185
|
+
for (let category of toolCategories) {
|
|
186
|
+
for (let actionKey of membersByCategoryKey.get(category.key) ?? []) {
|
|
187
|
+
let keys = keysByActionKey.get(actionKey) ?? [];
|
|
188
|
+
keys.push(category.key);
|
|
189
|
+
keysByActionKey.set(actionKey, keys);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return keysByActionKey;
|
|
194
|
+
};
|