@slates/provider 1.0.0-rc.17 → 1.0.0-rc.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slates/provider",
3
- "version": "1.0.0-rc.17",
3
+ "version": "1.0.0-rc.19",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -34,6 +34,7 @@
34
34
  "@lowerdeck/error": "^1.1.0",
35
35
  "@toon-format/toon": "^2.1.0",
36
36
  "axios": "^1.13.2",
37
+ "p-queue": "^6.6.2",
37
38
  "zod": "^4.2.1"
38
39
  },
39
40
  "devDependencies": {
@@ -42,4 +43,4 @@
42
43
  "typescript": "5.8.2",
43
44
  "vitest": "^3.1.2"
44
45
  }
45
- }
46
+ }
@@ -1,5 +1,5 @@
1
1
  import type { z } from 'zod';
2
- import type { SlateContext } from '../context';
2
+ import type { SlateContext, SlatePublicContext } from '../context';
3
3
  import type { SlateActionDocsReference } from '../docs';
4
4
  import type { SlateSpecification } from '../specification/specification';
5
5
  import type { SlateAttachment } from './attachment';
@@ -29,6 +29,8 @@ export interface SlateActionParameters {
29
29
  scopes?: SlateActionScopes;
30
30
  authMethods?: string[];
31
31
  docs?: SlateActionDocsReference[];
32
+ adapter?: string | null;
33
+ isPublic?: boolean;
32
34
  }
33
35
 
34
36
  export type SlateToolInvocationHandler<
@@ -42,6 +44,14 @@ export type SlateToolInvocationHandler<
42
44
  attachments?: SlateAttachment[];
43
45
  }>;
44
46
 
47
+ export type SlatePublicToolInvocationHandler<InputType extends {}, OutputType extends {}> = (
48
+ context: SlatePublicContext<InputType>
49
+ ) => Promise<{
50
+ output: OutputType;
51
+ message: string;
52
+ attachments?: SlateAttachment[];
53
+ }>;
54
+
45
55
  export type SlateTriggerMappingHandler<
46
56
  ConfigType extends {},
47
57
  AuthType extends {},
@@ -258,4 +268,12 @@ export abstract class SlateAction<
258
268
  get docs() {
259
269
  return this._params.docs;
260
270
  }
271
+
272
+ get adapter() {
273
+ return this._params.adapter ?? null;
274
+ }
275
+
276
+ get isPublic() {
277
+ return this._params.isPublic === true;
278
+ }
261
279
  }
@@ -1,6 +1,10 @@
1
1
  export interface SlateAttachmentUrlContent {
2
2
  type: 'url';
3
3
  url: string;
4
+ headers?: Record<string, string>;
5
+ query?: Record<string, string>;
6
+ refreshReference?: unknown;
7
+ refreshAt?: string;
4
8
  }
5
9
 
6
10
  export interface SlateAttachmentInlineContent {
@@ -9,21 +13,58 @@ export interface SlateAttachmentInlineContent {
9
13
  content: string;
10
14
  }
11
15
 
16
+ export interface SlateAttachmentUploadReferenceContent {
17
+ type: 'upload_reference';
18
+ referenceId: string;
19
+ }
20
+
12
21
  export interface SlateAttachment {
13
22
  mimeType?: string;
14
- content: SlateAttachmentUrlContent | SlateAttachmentInlineContent;
23
+ attachmentHash?: string;
24
+ content:
25
+ | SlateAttachmentUrlContent
26
+ | SlateAttachmentInlineContent
27
+ | SlateAttachmentUploadReferenceContent;
15
28
  }
16
29
 
17
- export let createUrlAttachment = (url: string, mimeType?: string): SlateAttachment => ({
18
- mimeType,
19
- content: {
20
- type: 'url',
21
- url
30
+ export let createUrlAttachment = (
31
+ url: string,
32
+ opts: {
33
+ mimeType?: string;
34
+ attachmentHash?: string;
35
+ headers?: Record<string, string>;
36
+ query?: Record<string, string>;
37
+ refreshReference?: unknown;
38
+ refreshAt?: string;
39
+ } = {}
40
+ ): SlateAttachment => {
41
+ if (opts.refreshReference !== undefined && !opts.refreshAt) {
42
+ throw new Error('createUrlAttachment: refreshAt is required when refreshReference is set');
22
43
  }
23
- });
24
44
 
25
- export let createBase64Attachment = (content: string, mimeType?: string): SlateAttachment => ({
45
+ return {
46
+ mimeType: opts.mimeType,
47
+ attachmentHash: opts.attachmentHash,
48
+ content: {
49
+ type: 'url',
50
+ url,
51
+ ...(opts.headers ? { headers: opts.headers } : {}),
52
+ ...(opts.query ? { query: opts.query } : {}),
53
+ ...(opts.refreshReference !== undefined
54
+ ? { refreshReference: opts.refreshReference }
55
+ : {}),
56
+ ...(opts.refreshAt ? { refreshAt: opts.refreshAt } : {})
57
+ }
58
+ };
59
+ };
60
+
61
+ export let createBase64Attachment = (
62
+ content: string,
63
+ mimeType?: string,
64
+ attachmentHash?: string
65
+ ): SlateAttachment => ({
26
66
  mimeType,
67
+ attachmentHash,
27
68
  content: {
28
69
  type: 'content',
29
70
  encoding: 'base64',
@@ -31,8 +72,13 @@ export let createBase64Attachment = (content: string, mimeType?: string): SlateA
31
72
  }
32
73
  });
33
74
 
34
- export let createTextAttachment = (content: string, mimeType?: string): SlateAttachment => ({
75
+ export let createTextAttachment = (
76
+ content: string,
77
+ mimeType?: string,
78
+ attachmentHash?: string
79
+ ): SlateAttachment => ({
35
80
  mimeType,
81
+ attachmentHash,
36
82
  content: {
37
83
  type: 'content',
38
84
  encoding: 'utf-8',
@@ -0,0 +1,136 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { z } from 'zod';
3
+ import { SlateAuth } from '../auth';
4
+ import { SlateConfig } from '../config';
5
+ import { SlatePublicContext } from '../context';
6
+ import { SlateSpecification } from '../specification/specification';
7
+ import { SlatePublicTool } from './publicTool';
8
+ import { SlateTool } from './tool';
9
+
10
+ let createTestSpec = () => {
11
+ let config = SlateConfig.create(
12
+ z.object({
13
+ prefix: z.string()
14
+ })
15
+ );
16
+ let auth = SlateAuth.create<{ token: string }>().output(
17
+ z.object({
18
+ token: z.string()
19
+ })
20
+ );
21
+
22
+ return SlateSpecification.create({
23
+ key: 'demo',
24
+ name: 'Demo',
25
+ config,
26
+ auth
27
+ });
28
+ };
29
+
30
+ describe('SlateActionBuilder.lockInterface', () => {
31
+ it('prevents changing input and output schemas after the interface is locked', () => {
32
+ let spec = createTestSpec();
33
+ let builder = SlateTool.create(spec, {
34
+ key: 'send',
35
+ name: 'Send'
36
+ })
37
+ .input(z.object({ to: z.string() }))
38
+ .output(z.object({ id: z.string() }))
39
+ .lockInterface();
40
+
41
+ expect(() => builder.input(z.object({}))).toThrow(
42
+ 'Adapter contract input schema cannot be changed'
43
+ );
44
+ expect(() => builder.output(z.object({}))).toThrow(
45
+ 'Adapter contract output schema cannot be changed'
46
+ );
47
+ });
48
+ });
49
+
50
+ describe('SlatePublicTool', () => {
51
+ it('builds a public tool that omits config and auth from the handler context', async () => {
52
+ let spec = createTestSpec();
53
+ let tool = SlatePublicTool.create(spec, {
54
+ key: 'setup',
55
+ name: 'Setup'
56
+ })
57
+ .input(
58
+ z.object({
59
+ name: z.string()
60
+ })
61
+ )
62
+ .output(
63
+ z.object({
64
+ greeting: z.string()
65
+ })
66
+ )
67
+ .handleInvocation(async ctx => {
68
+ expect(ctx).not.toHaveProperty('config');
69
+ expect(ctx).not.toHaveProperty('auth');
70
+
71
+ return {
72
+ output: { greeting: `Hello ${ctx.input.name}` },
73
+ message: 'ok'
74
+ };
75
+ })
76
+ .build();
77
+
78
+ expect(tool.isPublic).toBe(true);
79
+ expect(tool.key).toBe('setup');
80
+
81
+ let result = await tool.handleInvocation(
82
+ new SlatePublicContext({ name: 'Ada' }, spec, {
83
+ debug: () => {},
84
+ error: () => {},
85
+ info: () => {},
86
+ progress: () => {},
87
+ warn: () => {}
88
+ } as any) as any
89
+ );
90
+
91
+ expect(result.output).toEqual({ greeting: 'Hello Ada' });
92
+ });
93
+
94
+ it('keeps regular tools private by default', () => {
95
+ let spec = createTestSpec();
96
+ let tool = SlateTool.create(spec, {
97
+ key: 'send',
98
+ name: 'Send'
99
+ })
100
+ .input(z.object({}))
101
+ .output(z.object({}))
102
+ .handleInvocation(async () => ({
103
+ output: {},
104
+ message: 'ok'
105
+ }))
106
+ .build();
107
+
108
+ expect(tool.isPublic).toBe(false);
109
+ });
110
+
111
+ it('rejects authentication methods on public tools', () => {
112
+ let spec = createTestSpec();
113
+
114
+ expect(() =>
115
+ SlatePublicTool.create(spec, {
116
+ key: 'setup',
117
+ name: 'Setup'
118
+ }).authMethods(['token_auth'])
119
+ ).toThrow('Public tools cannot require authentication methods');
120
+
121
+ expect(() =>
122
+ SlatePublicTool.create(spec, {
123
+ key: 'setup',
124
+ name: 'Setup',
125
+ authMethods: ['token_auth']
126
+ })
127
+ .input(z.object({}))
128
+ .output(z.object({}))
129
+ .handleInvocation(async () => ({
130
+ output: {},
131
+ message: 'ok'
132
+ }))
133
+ .build()
134
+ ).toThrow('Public tools cannot require authentication methods');
135
+ });
136
+ });
@@ -10,6 +10,7 @@ import type {
10
10
  SlateActionScopes,
11
11
  SlateActionType,
12
12
  SlatePollingOptions,
13
+ SlatePublicToolInvocationHandler,
13
14
  SlateToolInvocationHandler,
14
15
  SlateTriggerMappingHandler,
15
16
  SlateTriggerPollingHandler,
@@ -26,7 +27,8 @@ export class SlateActionBuilder<
26
27
  AuthType extends {},
27
28
  InputType extends {},
28
29
  OutputType extends {},
29
- Result extends SlateAction<Type, ConfigType, AuthType, any, any>
30
+ Result extends SlateAction<Type, ConfigType, AuthType, any, any>,
31
+ IsPublic extends boolean = false
30
32
  > {
31
33
  #configSchema: z.ZodType<ConfigType>;
32
34
  #authSchema: z.ZodType<AuthType>;
@@ -43,6 +45,7 @@ export class SlateActionBuilder<
43
45
  InputType,
44
46
  OutputType
45
47
  > | null = null;
48
+ #interfaceLocked = false;
46
49
 
47
50
  constructor(
48
51
  private readonly type: Type,
@@ -50,7 +53,8 @@ export class SlateActionBuilder<
50
53
  private readonly params: SlateActionParameters,
51
54
  private readonly factory: (
52
55
  params: SlateActionCreateParameters<any, any, any, any>
53
- ) => Result
56
+ ) => Result,
57
+ private readonly isPublicTool: IsPublic = false as IsPublic
54
58
  ) {
55
59
  this.#configSchema = spec.configSchema;
56
60
  this.#authSchema = spec.authSchema;
@@ -58,21 +62,58 @@ export class SlateActionBuilder<
58
62
 
59
63
  input<NewInputType extends {}>(
60
64
  schema: z.ZodType<NewInputType>
61
- ): SlateActionBuilder<Type, ConfigType, AuthType, NewInputType, OutputType, Result> {
65
+ ): SlateActionBuilder<
66
+ Type,
67
+ ConfigType,
68
+ AuthType,
69
+ NewInputType,
70
+ OutputType,
71
+ Result,
72
+ IsPublic
73
+ > {
74
+ if (this.#interfaceLocked) {
75
+ throw new SlateDeclarationError('Adapter contract input schema cannot be changed');
76
+ }
77
+
62
78
  this.#inputSchema = schema as any;
63
79
  return this as any;
64
80
  }
65
81
 
66
82
  output<NewOutputType extends {}>(
67
83
  schema: z.ZodType<NewOutputType>
68
- ): SlateActionBuilder<Type, ConfigType, AuthType, InputType, NewOutputType, Result> {
84
+ ): SlateActionBuilder<
85
+ Type,
86
+ ConfigType,
87
+ AuthType,
88
+ InputType,
89
+ NewOutputType,
90
+ Result,
91
+ IsPublic
92
+ > {
93
+ if (this.#interfaceLocked) {
94
+ throw new SlateDeclarationError('Adapter contract output schema cannot be changed');
95
+ }
96
+
69
97
  this.#outputSchema = schema as any;
70
98
  return this as any;
71
99
  }
72
100
 
101
+ lockInterface(): SlateActionBuilder<
102
+ Type,
103
+ ConfigType,
104
+ AuthType,
105
+ InputType,
106
+ OutputType,
107
+ Result,
108
+ IsPublic
109
+ > {
110
+ this.#interfaceLocked = true;
111
+ return this;
112
+ }
113
+
73
114
  scopes(
74
115
  scopes: SlateActionScopes
75
- ): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result> {
116
+ ): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result, IsPublic> {
76
117
  validateScopes(scopes);
77
118
  this.#scopes = scopes;
78
119
  return this;
@@ -80,7 +121,11 @@ export class SlateActionBuilder<
80
121
 
81
122
  authMethods(
82
123
  authMethods: string[]
83
- ): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result> {
124
+ ): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result, IsPublic> {
125
+ if (this.isPublicTool) {
126
+ throw new SlateDeclarationError('Public tools cannot require authentication methods');
127
+ }
128
+
84
129
  this.#authMethods = this.validateAuthMethods(authMethods);
85
130
  return this;
86
131
  }
@@ -97,15 +142,22 @@ export class SlateActionBuilder<
97
142
  }
98
143
 
99
144
  handleInvocation(
100
- handler: SlateToolInvocationHandler<ConfigType, AuthType, InputType, OutputType>
101
- ): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result> {
145
+ handler: IsPublic extends true
146
+ ? SlatePublicToolInvocationHandler<InputType, OutputType>
147
+ : SlateToolInvocationHandler<ConfigType, AuthType, InputType, OutputType>
148
+ ): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result, IsPublic> {
102
149
  if (this.type !== 'tool') {
103
150
  throw new SlateDeclarationError('handleInvocation can only be set for tool actions');
104
151
  }
105
152
 
106
153
  this.#toolParams = {
107
154
  type: 'tool',
108
- handleInvocation: handler
155
+ handleInvocation: handler as SlateToolInvocationHandler<
156
+ ConfigType,
157
+ AuthType,
158
+ InputType,
159
+ OutputType
160
+ >
109
161
  };
110
162
 
111
163
  return this;
@@ -117,7 +169,7 @@ export class SlateActionBuilder<
117
169
  autoRegisterWebhook?: SlateTriggerWebhookAutoRegistrationHandler<ConfigType, AuthType>;
118
170
  autoUnregisterWebhook?: SlateTriggerWebhookAutoUnregistrationHandler<ConfigType, AuthType>;
119
171
  http?: SlateWebhookHttpOptions;
120
- }): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result> {
172
+ }): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result, IsPublic> {
121
173
  if (this.type !== 'trigger') {
122
174
  throw new SlateDeclarationError('handleEvent can only be set for trigger actions');
123
175
  }
@@ -139,7 +191,7 @@ export class SlateActionBuilder<
139
191
  options?: SlatePollingOptions;
140
192
  pollEvents?: SlateTriggerPollingHandler<ConfigType, AuthType, InputType>;
141
193
  handleEvent: SlateTriggerMappingHandler<ConfigType, AuthType, InputType, OutputType>;
142
- }): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result> {
194
+ }): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result, IsPublic> {
143
195
  if (this.type !== 'trigger') {
144
196
  throw new SlateDeclarationError('handleEvent can only be set for trigger actions');
145
197
  }
@@ -162,6 +214,10 @@ export class SlateActionBuilder<
162
214
  }
163
215
  let authMethods = this.validateAuthMethods(this.#authMethods ?? this.params.authMethods);
164
216
 
217
+ if (this.isPublicTool && authMethods) {
218
+ throw new SlateDeclarationError('Public tools cannot require authentication methods');
219
+ }
220
+
165
221
  if (!this.#inputSchema) {
166
222
  throw new SlateDeclarationError('Input schema is not defined');
167
223
  }
@@ -179,6 +235,7 @@ export class SlateActionBuilder<
179
235
  ...this.params,
180
236
  scopes,
181
237
  authMethods,
238
+ isPublic: this.isPublicTool === true,
182
239
  configSchema: this.#configSchema,
183
240
  authSchema: this.#authSchema,
184
241
  inputSchema: this.#inputSchema,
@@ -0,0 +1,59 @@
1
+ import type { SlateAttachment } from './attachment';
2
+
3
+ export interface SlateLiveInvocationInfo {
4
+ token: string;
5
+ baseUrl: string;
6
+ maxAttachmentSizeBytes: number;
7
+ }
8
+
9
+ export interface SlateDirectUploadInput {
10
+ live: SlateLiveInvocationInfo;
11
+ mimeType?: string;
12
+ filename?: string;
13
+ body: ReadableStream<Uint8Array> | Uint8Array;
14
+ }
15
+
16
+ export let uploadAttachmentDirect = async (
17
+ d: SlateDirectUploadInput
18
+ ): Promise<SlateAttachment> => {
19
+ let baseUrl = d.live.baseUrl.replace(/\/$/, '');
20
+
21
+ let registerRes = await fetch(`${baseUrl}/slates-hub/live-invocation/attachments`, {
22
+ method: 'POST',
23
+ headers: {
24
+ 'content-type': 'application/json',
25
+ authorization: `Bearer ${d.live.token}`
26
+ },
27
+ body: JSON.stringify({
28
+ attachments: [{ mimeType: d.mimeType, filename: d.filename }]
29
+ })
30
+ });
31
+ if (!registerRes.ok) {
32
+ throw new Error(
33
+ `Failed to register attachment for direct upload (status ${registerRes.status})`
34
+ );
35
+ }
36
+
37
+ let { attachments } = (await registerRes.json()) as {
38
+ attachments: { referenceId: string; uploadUrl: string }[];
39
+ };
40
+ let registration = attachments[0];
41
+ if (!registration) {
42
+ throw new Error('Live invocation API returned no attachment registrations');
43
+ }
44
+
45
+ let putRes = await fetch(registration.uploadUrl, {
46
+ method: 'PUT',
47
+ ...(d.body instanceof Uint8Array ? {} : ({ duplex: 'half' } as any)),
48
+ headers: d.mimeType ? { 'content-type': d.mimeType } : undefined,
49
+ body: d.body
50
+ });
51
+ if (!putRes.ok) {
52
+ throw new Error(`Failed to upload attachment content (status ${putRes.status})`);
53
+ }
54
+
55
+ return {
56
+ mimeType: d.mimeType,
57
+ content: { type: 'upload_reference', referenceId: registration.referenceId }
58
+ };
59
+ };
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod';
2
+ import type { SlateContext } from '../context/context';
3
+ import type { SlateSpecification } from '../specification/specification';
4
+ import { tool } from './tool';
5
+
6
+ export let GET_FILE_URL_TOOL_ID = 'metorial$getFileUrl';
7
+
8
+ export let getFileUrlToolInputSchema = z.object({
9
+ url: z.string(),
10
+ reference: z.any().nullable()
11
+ });
12
+ export type GetFileUrlToolInput = z.infer<typeof getFileUrlToolInputSchema>;
13
+
14
+ export let getFileUrlToolOutputSchema = z.object({
15
+ url: z.string(),
16
+ expiresAt: z.string(),
17
+ headers: z.record(z.string(), z.string()).optional(),
18
+ query: z.record(z.string(), z.string()).optional()
19
+ });
20
+ export type GetFileUrlToolOutput = z.infer<typeof getFileUrlToolOutputSchema>;
21
+
22
+ export type GetFileUrlHandler<ConfigType extends {}, AuthType extends {}> = (
23
+ context: SlateContext<ConfigType, AuthType, GetFileUrlToolInput>
24
+ ) => Promise<GetFileUrlToolOutput>;
25
+
26
+ export let getFileUrlTool = <ConfigType extends {}, AuthType extends {}>(
27
+ spec: SlateSpecification<ConfigType, AuthType>,
28
+ handleGetFileUrl: GetFileUrlHandler<ConfigType, AuthType>
29
+ ) =>
30
+ tool(spec, {
31
+ key: GET_FILE_URL_TOOL_ID,
32
+ name: 'Get File URL',
33
+ description: 'Reserved: refreshes an expiring attachment download URL. Hub-internal only.'
34
+ })
35
+ .input(getFileUrlToolInputSchema)
36
+ .output(getFileUrlToolOutputSchema)
37
+ .handleInvocation(async ctx => ({
38
+ output: await handleGetFileUrl(ctx),
39
+ message: 'ok'
40
+ }))
41
+ .build();
@@ -1,5 +1,7 @@
1
1
  export * from './action';
2
- export type * from './builder';
2
+ export * from './builder';
3
+ export * from './getFileUrlTool';
4
+ export * from './publicTool';
3
5
  export * from './scopes';
4
6
  export * from './tool';
5
7
  export * from './trigger';
@@ -0,0 +1,36 @@
1
+ import type { SlateSpecification } from '../specification/specification';
2
+ import type { SlateActionParameters, SlatePublicToolInvocationHandler } from './action';
3
+ import { SlateActionBuilder } from './builder';
4
+ import { SlateTool } from './tool';
5
+
6
+ export interface SlatePublicToolParameters<InputType extends {}, OutputType extends {}>
7
+ extends SlateActionParameters {
8
+ handleInvocation: SlatePublicToolInvocationHandler<InputType, OutputType>;
9
+ }
10
+
11
+ export class SlatePublicTool {
12
+ private constructor() {}
13
+
14
+ static create<ConfigType extends {}, AuthType extends {}>(
15
+ spec: SlateSpecification<ConfigType, AuthType>,
16
+ params: SlateActionParameters
17
+ ) {
18
+ return new SlateActionBuilder(
19
+ 'tool',
20
+ spec,
21
+ params,
22
+ params => {
23
+ return SlateTool.fromCreateParameters(spec, {
24
+ ...params,
25
+ isPublic: true
26
+ });
27
+ },
28
+ true
29
+ );
30
+ }
31
+ }
32
+
33
+ export let publicTool = <ConfigType extends {}, AuthType extends {}>(
34
+ spec: SlateSpecification<ConfigType, AuthType>,
35
+ params: SlateActionParameters
36
+ ) => SlatePublicTool.create(spec, params);
@@ -24,7 +24,7 @@ export class SlateTool<
24
24
  > extends SlateAction<'tool', ConfigType, AuthType, InputType, OutputType> {
25
25
  #handleInvocation: SlateToolInvocationHandler<ConfigType, AuthType, InputType, OutputType>;
26
26
 
27
- private constructor(
27
+ protected constructor(
28
28
  spec: SlateSpecification<ConfigType, AuthType>,
29
29
  inputSchema: z.ZodType<InputType>,
30
30
  outputSchema: z.ZodType<OutputType>,
@@ -40,11 +40,23 @@ export class SlateTool<
40
40
  params: SlateActionParameters
41
41
  ) {
42
42
  return new SlateActionBuilder('tool', spec, params, params => {
43
- if (params.type !== 'tool') throw new Error('Invalid action type for tool');
44
- return new SlateTool(spec, params.inputSchema, params.outputSchema, params);
43
+ return SlateTool.fromCreateParameters(spec, params);
45
44
  });
46
45
  }
47
46
 
47
+ static fromCreateParameters<ConfigType extends {}, AuthType extends {}>(
48
+ spec: SlateSpecification<ConfigType, AuthType>,
49
+ params: {
50
+ type: string;
51
+ inputSchema: z.ZodType<any>;
52
+ outputSchema: z.ZodType<any>;
53
+ handleInvocation?: SlateToolInvocationHandler<ConfigType, AuthType, any, any>;
54
+ } & SlateActionParameters
55
+ ) {
56
+ if (params.type !== 'tool') throw new Error('Invalid action type for tool');
57
+ return new SlateTool(spec, params.inputSchema, params.outputSchema, params as any);
58
+ }
59
+
48
60
  get handleInvocation() {
49
61
  return this.#handleInvocation;
50
62
  }
@@ -0,0 +1,38 @@
1
+ import type { SlateTool, SlateTrigger } from '../action';
2
+ import type { SlateAdapterSpec } from './spec';
3
+
4
+ export class SlateAdapter<ConfigType extends {}, AuthType extends {}> {
5
+ constructor(
6
+ private readonly _spec: SlateAdapterSpec,
7
+ private readonly _tools: SlateTool<ConfigType, AuthType, any, any>[],
8
+ private readonly _triggers: SlateTrigger<ConfigType, AuthType, any, any>[]
9
+ ) {}
10
+
11
+ get spec() {
12
+ return this._spec;
13
+ }
14
+
15
+ get id() {
16
+ return this._spec.id;
17
+ }
18
+
19
+ get name() {
20
+ return this._spec.name;
21
+ }
22
+
23
+ get capabilities() {
24
+ return this._spec.capabilities;
25
+ }
26
+
27
+ get tools() {
28
+ return this._tools;
29
+ }
30
+
31
+ get triggers() {
32
+ return this._triggers;
33
+ }
34
+
35
+ get actions() {
36
+ return [...this._triggers, ...this._tools];
37
+ }
38
+ }