@optimizely-opal/opal-tools-sdk 0.1.0-dev → 0.1.3-dev
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/README.md +233 -9
- package/dist/models.d.ts +196 -1
- package/dist/models.js +149 -2
- package/package.json +1 -1
- package/src/decorators.ts +11 -11
- package/src/models.ts +179 -1
package/README.md
CHANGED
|
@@ -4,11 +4,12 @@ This SDK simplifies the creation of tools services compatible with the Opal Tool
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
- Parameter validation
|
|
7
|
+
- Easy definition of tool functions with decorators
|
|
8
|
+
- Automatic generation of discovery endpoints
|
|
9
|
+
- Parameter validation and type checking
|
|
11
10
|
- Authentication helpers
|
|
11
|
+
- Express integration
|
|
12
|
+
- Island components for interactive UI responses
|
|
12
13
|
|
|
13
14
|
## Installation
|
|
14
15
|
|
|
@@ -18,8 +19,152 @@ npm install @optimizely-opal/opal-tools-sdk
|
|
|
18
19
|
|
|
19
20
|
## Usage
|
|
20
21
|
|
|
22
|
+
```typescript
|
|
23
|
+
import { ToolsService, tool, IslandResponse, IslandConfig } from '@optimizely-opal/opal-tools-sdk';
|
|
24
|
+
import express from 'express';
|
|
25
|
+
|
|
26
|
+
const app = express();
|
|
27
|
+
const toolsService = new ToolsService(app);
|
|
28
|
+
|
|
29
|
+
interface WeatherParameters {
|
|
30
|
+
location: string;
|
|
31
|
+
units: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@tool({
|
|
35
|
+
name: 'get_weather',
|
|
36
|
+
description: 'Gets current weather for a location'
|
|
37
|
+
})
|
|
38
|
+
async function getWeather(parameters: WeatherParameters) {
|
|
39
|
+
// Implementation...
|
|
40
|
+
return { temperature: 22, condition: 'sunny' };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Discovery endpoint is automatically created at /discovery
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Authentication
|
|
47
|
+
|
|
48
|
+
The SDK provides two ways to require authentication for your tools:
|
|
49
|
+
|
|
50
|
+
### 1. Using the `@requiresAuth` decorator
|
|
51
|
+
|
|
21
52
|
```typescript
|
|
22
53
|
import { ToolsService, tool } from '@optimizely-opal/opal-tools-sdk';
|
|
54
|
+
import { requiresAuth } from '@optimizely-opal/opal-tools-sdk/auth';
|
|
55
|
+
import express from 'express';
|
|
56
|
+
|
|
57
|
+
const app = express();
|
|
58
|
+
const toolsService = new ToolsService(app);
|
|
59
|
+
|
|
60
|
+
interface CalendarParameters {
|
|
61
|
+
date: string;
|
|
62
|
+
timezone?: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Single authentication requirement
|
|
66
|
+
@requiresAuth({ provider: 'google', scopeBundle: 'calendar', required: true })
|
|
67
|
+
@tool({
|
|
68
|
+
name: 'get_calendar_events',
|
|
69
|
+
description: 'Gets calendar events for a date'
|
|
70
|
+
})
|
|
71
|
+
async function getCalendarEvents(parameters: CalendarParameters, authData?: any) {
|
|
72
|
+
// The authData parameter contains authentication information
|
|
73
|
+
const token = authData?.credentials?.token || '';
|
|
74
|
+
|
|
75
|
+
// Use the token to make authenticated requests
|
|
76
|
+
// ...
|
|
77
|
+
|
|
78
|
+
return { events: ['Meeting at 10:00', 'Lunch at 12:00'] };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Multiple authentication requirements (tool can work with either provider)
|
|
82
|
+
@requiresAuth({ provider: 'google', scopeBundle: 'calendar', required: true })
|
|
83
|
+
@requiresAuth({ provider: 'microsoft', scopeBundle: 'outlook', required: true })
|
|
84
|
+
@tool({
|
|
85
|
+
name: 'get_calendar_availability',
|
|
86
|
+
description: 'Check calendar availability'
|
|
87
|
+
})
|
|
88
|
+
async function getCalendarAvailability(parameters: CalendarParameters, authData?: any) {
|
|
89
|
+
const provider = authData?.provider || '';
|
|
90
|
+
const token = authData?.credentials?.token || '';
|
|
91
|
+
|
|
92
|
+
if (provider === 'google') {
|
|
93
|
+
// Use Google Calendar API
|
|
94
|
+
} else if (provider === 'microsoft') {
|
|
95
|
+
// Use Microsoft Outlook API
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return { available: true, provider_used: provider };
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 2. Specifying auth requirements in the `@tool` decorator
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
interface EmailParameters {
|
|
106
|
+
limit?: number;
|
|
107
|
+
folder?: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@tool({
|
|
111
|
+
name: 'get_email',
|
|
112
|
+
description: 'Gets emails from the user\'s inbox',
|
|
113
|
+
authRequirements: {
|
|
114
|
+
provider: 'google',
|
|
115
|
+
scopeBundle: 'gmail',
|
|
116
|
+
required: true
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
async function getEmail(parameters: EmailParameters, authData?: any) {
|
|
120
|
+
// Implementation...
|
|
121
|
+
return { emails: ['Email 1', 'Email 2'] };
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Authentication
|
|
126
|
+
|
|
127
|
+
The SDK provides authentication support for tools that require user credentials:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { ToolsService, tool, requiresAuth, AuthData } from '@optimizely-opal/opal-tools-sdk';
|
|
131
|
+
import express from 'express';
|
|
132
|
+
|
|
133
|
+
interface CalendarParameters {
|
|
134
|
+
date: string;
|
|
135
|
+
timezone?: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const app = express();
|
|
139
|
+
const toolsService = new ToolsService(app);
|
|
140
|
+
|
|
141
|
+
@requiresAuth({ provider: 'google', scopeBundle: 'calendar', required: true })
|
|
142
|
+
@tool({
|
|
143
|
+
name: 'get_calendar_events',
|
|
144
|
+
description: 'Gets calendar events for a date'
|
|
145
|
+
})
|
|
146
|
+
async function getCalendarEvents(parameters: CalendarParameters, authData?: AuthData) {
|
|
147
|
+
// The authData parameter contains authentication information
|
|
148
|
+
if (authData) {
|
|
149
|
+
const token = authData.credentials.access_token;
|
|
150
|
+
// Use the token to make authenticated requests
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return { events: ['Meeting at 10:00', 'Lunch at 12:00'] };
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Island Components
|
|
158
|
+
|
|
159
|
+
The SDK includes Island components for creating interactive UI responses:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import {
|
|
163
|
+
ToolsService,
|
|
164
|
+
tool,
|
|
165
|
+
IslandResponse,
|
|
166
|
+
IslandConfig
|
|
167
|
+
} from '@optimizely-opal/opal-tools-sdk';
|
|
23
168
|
import express from 'express';
|
|
24
169
|
|
|
25
170
|
interface WeatherParameters {
|
|
@@ -35,14 +180,93 @@ const toolsService = new ToolsService(app);
|
|
|
35
180
|
description: 'Gets current weather for a location'
|
|
36
181
|
})
|
|
37
182
|
async function getWeather(parameters: WeatherParameters) {
|
|
38
|
-
//
|
|
39
|
-
|
|
183
|
+
// Get weather data (implementation details omitted)
|
|
184
|
+
const weatherData = { temperature: 22, condition: 'sunny', humidity: 65 };
|
|
185
|
+
|
|
186
|
+
// Create an interactive island for weather settings
|
|
187
|
+
const island = new IslandConfig(
|
|
188
|
+
[
|
|
189
|
+
new IslandConfig.Field(
|
|
190
|
+
'location',
|
|
191
|
+
'Location',
|
|
192
|
+
'string',
|
|
193
|
+
parameters.location
|
|
194
|
+
),
|
|
195
|
+
new IslandConfig.Field(
|
|
196
|
+
'units',
|
|
197
|
+
'Temperature Units',
|
|
198
|
+
'string',
|
|
199
|
+
parameters.units || 'metric',
|
|
200
|
+
false,
|
|
201
|
+
['metric', 'imperial', 'kelvin']
|
|
202
|
+
),
|
|
203
|
+
new IslandConfig.Field(
|
|
204
|
+
'current_temp',
|
|
205
|
+
'Current Temperature',
|
|
206
|
+
'string',
|
|
207
|
+
`${weatherData.temperature}°${parameters.units === 'metric' ? 'C' : 'F'}`
|
|
208
|
+
)
|
|
209
|
+
],
|
|
210
|
+
[
|
|
211
|
+
new IslandConfig.Action(
|
|
212
|
+
'refresh_weather',
|
|
213
|
+
'Refresh Weather',
|
|
214
|
+
'button',
|
|
215
|
+
'/tools/get_weather',
|
|
216
|
+
'update'
|
|
217
|
+
)
|
|
218
|
+
]
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
return IslandResponse.create([island]);
|
|
40
222
|
}
|
|
41
|
-
|
|
42
|
-
// Discovery endpoint is automatically created at /discovery
|
|
43
|
-
app.listen(3000);
|
|
44
223
|
```
|
|
45
224
|
|
|
225
|
+
### Island Components
|
|
226
|
+
|
|
227
|
+
#### IslandConfig.Field
|
|
228
|
+
Fields represent data inputs in the UI:
|
|
229
|
+
- `name`: Programmatic field identifier
|
|
230
|
+
- `label`: Human-readable label
|
|
231
|
+
- `type`: Field type (`'string'`, `'boolean'`, `'json'`)
|
|
232
|
+
- `value`: Current field value (optional)
|
|
233
|
+
- `hidden`: Whether to hide from user (optional, default: false)
|
|
234
|
+
- `options`: Available options for selection (optional)
|
|
235
|
+
|
|
236
|
+
#### IslandConfig.Action
|
|
237
|
+
Actions represent buttons or operations:
|
|
238
|
+
- `name`: Programmatic action identifier
|
|
239
|
+
- `label`: Human-readable button label
|
|
240
|
+
- `type`: UI element type (typically `'button'`)
|
|
241
|
+
- `endpoint`: API endpoint to call
|
|
242
|
+
- `operation`: Operation type (default: `'create'`)
|
|
243
|
+
|
|
244
|
+
#### IslandConfig
|
|
245
|
+
Contains the complete island configuration:
|
|
246
|
+
- `fields`: Array of IslandConfig.Field objects
|
|
247
|
+
- `actions`: Array of IslandConfig.Action objects
|
|
248
|
+
|
|
249
|
+
#### IslandResponse
|
|
250
|
+
The response wrapper for islands:
|
|
251
|
+
- Use `IslandResponse.create([islands])` to create responses
|
|
252
|
+
- Supports multiple islands per response
|
|
253
|
+
|
|
254
|
+
## Type Definitions
|
|
255
|
+
|
|
256
|
+
The SDK provides comprehensive TypeScript type definitions:
|
|
257
|
+
|
|
258
|
+
### Authentication Types
|
|
259
|
+
- `AuthData`: Interface containing provider and credentials information
|
|
260
|
+
- `Credentials`: Interface with access_token, org_sso_id, customer_id, instance_id, and product_sku
|
|
261
|
+
- `Environment`: Interface specifying execution mode (`'headless'` or `'interactive'`)
|
|
262
|
+
|
|
263
|
+
### Parameter Types
|
|
264
|
+
- `ParameterType`: Enum for supported parameter types
|
|
265
|
+
- `Parameter`: Class for tool parameter definitions
|
|
266
|
+
- `Function`: Class for complete tool function definitions
|
|
267
|
+
|
|
268
|
+
These types provide full IDE support and compile-time type checking for better development experience.
|
|
269
|
+
|
|
46
270
|
## Documentation
|
|
47
271
|
|
|
48
272
|
See full documentation for more examples and configuration options.
|
package/dist/models.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export declare enum ParameterType {
|
|
|
6
6
|
Integer = "integer",
|
|
7
7
|
Number = "number",
|
|
8
8
|
Boolean = "boolean",
|
|
9
|
-
List = "
|
|
9
|
+
List = "array",
|
|
10
10
|
Dictionary = "object"
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
@@ -85,3 +85,198 @@ export declare class Function {
|
|
|
85
85
|
*/
|
|
86
86
|
toJSON(): any;
|
|
87
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Authentication credentials structure
|
|
90
|
+
*/
|
|
91
|
+
export type Credentials = {
|
|
92
|
+
access_token: string;
|
|
93
|
+
org_sso_id?: string;
|
|
94
|
+
customer_id: string;
|
|
95
|
+
instance_id: string;
|
|
96
|
+
product_sku: string;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Authentication data for an Opal tool
|
|
100
|
+
*/
|
|
101
|
+
export type AuthData = {
|
|
102
|
+
provider: string;
|
|
103
|
+
credentials: Credentials;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Execution environment for an Opal tool
|
|
107
|
+
*/
|
|
108
|
+
export type Environment = {
|
|
109
|
+
execution_mode: "headless" | "interactive";
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Island field definition for interactive UI components
|
|
113
|
+
*/
|
|
114
|
+
export declare class IslandField {
|
|
115
|
+
name: string;
|
|
116
|
+
label: string;
|
|
117
|
+
type: "string" | "boolean" | "json";
|
|
118
|
+
value: string;
|
|
119
|
+
hidden: boolean;
|
|
120
|
+
options: string[];
|
|
121
|
+
/**
|
|
122
|
+
* Create a new island field
|
|
123
|
+
* @param name Programmatic field identifier
|
|
124
|
+
* @param label Human-readable label
|
|
125
|
+
* @param type Field type
|
|
126
|
+
* @param value Current field value
|
|
127
|
+
* @param hidden Whether to hide from user
|
|
128
|
+
* @param options Available options for selection
|
|
129
|
+
*/
|
|
130
|
+
constructor(name: string, label: string, type: "string" | "boolean" | "json", value?: string, hidden?: boolean, options?: string[]);
|
|
131
|
+
/**
|
|
132
|
+
* Convert to JSON for the discovery endpoint
|
|
133
|
+
*/
|
|
134
|
+
toJSON(): {
|
|
135
|
+
name: string;
|
|
136
|
+
label: string;
|
|
137
|
+
type: "string" | "boolean" | "json";
|
|
138
|
+
value: string;
|
|
139
|
+
hidden: boolean;
|
|
140
|
+
options: string[];
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Island action definition for interactive UI components
|
|
145
|
+
*/
|
|
146
|
+
export declare class IslandAction {
|
|
147
|
+
name: string;
|
|
148
|
+
label: string;
|
|
149
|
+
type: string;
|
|
150
|
+
endpoint: string;
|
|
151
|
+
operation: string;
|
|
152
|
+
/**
|
|
153
|
+
* Create a new island action
|
|
154
|
+
* @param name Programmatic action identifier
|
|
155
|
+
* @param label Human-readable button label
|
|
156
|
+
* @param type UI element type
|
|
157
|
+
* @param endpoint API endpoint to call
|
|
158
|
+
* @param operation Operation type
|
|
159
|
+
*/
|
|
160
|
+
constructor(name: string, label: string, type: string, endpoint: string, operation?: string);
|
|
161
|
+
/**
|
|
162
|
+
* Convert to JSON for the discovery endpoint
|
|
163
|
+
*/
|
|
164
|
+
toJSON(): {
|
|
165
|
+
name: string;
|
|
166
|
+
label: string;
|
|
167
|
+
type: string;
|
|
168
|
+
endpoint: string;
|
|
169
|
+
operation: string;
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Island configuration for interactive UI components
|
|
174
|
+
*/
|
|
175
|
+
export declare class IslandConfig {
|
|
176
|
+
fields: IslandField[];
|
|
177
|
+
actions: IslandAction[];
|
|
178
|
+
static Field: typeof IslandField;
|
|
179
|
+
static Action: typeof IslandAction;
|
|
180
|
+
/**
|
|
181
|
+
* Create a new island configuration
|
|
182
|
+
* @param fields List of island fields
|
|
183
|
+
* @param actions List of island actions
|
|
184
|
+
*/
|
|
185
|
+
constructor(fields: IslandField[], actions: IslandAction[]);
|
|
186
|
+
/**
|
|
187
|
+
* Convert to JSON for the discovery endpoint
|
|
188
|
+
*/
|
|
189
|
+
toJSON(): {
|
|
190
|
+
fields: {
|
|
191
|
+
name: string;
|
|
192
|
+
label: string;
|
|
193
|
+
type: "string" | "boolean" | "json";
|
|
194
|
+
value: string;
|
|
195
|
+
hidden: boolean;
|
|
196
|
+
options: string[];
|
|
197
|
+
}[];
|
|
198
|
+
actions: {
|
|
199
|
+
name: string;
|
|
200
|
+
label: string;
|
|
201
|
+
type: string;
|
|
202
|
+
endpoint: string;
|
|
203
|
+
operation: string;
|
|
204
|
+
}[];
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Island response configuration
|
|
209
|
+
*/
|
|
210
|
+
export declare class IslandResponseConfig {
|
|
211
|
+
islands: IslandConfig[];
|
|
212
|
+
/**
|
|
213
|
+
* Create a new island response configuration
|
|
214
|
+
* @param islands List of island configurations
|
|
215
|
+
*/
|
|
216
|
+
constructor(islands: IslandConfig[]);
|
|
217
|
+
/**
|
|
218
|
+
* Convert to JSON for the discovery endpoint
|
|
219
|
+
*/
|
|
220
|
+
toJSON(): {
|
|
221
|
+
islands: {
|
|
222
|
+
fields: {
|
|
223
|
+
name: string;
|
|
224
|
+
label: string;
|
|
225
|
+
type: "string" | "boolean" | "json";
|
|
226
|
+
value: string;
|
|
227
|
+
hidden: boolean;
|
|
228
|
+
options: string[];
|
|
229
|
+
}[];
|
|
230
|
+
actions: {
|
|
231
|
+
name: string;
|
|
232
|
+
label: string;
|
|
233
|
+
type: string;
|
|
234
|
+
endpoint: string;
|
|
235
|
+
operation: string;
|
|
236
|
+
}[];
|
|
237
|
+
}[];
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Island response wrapper for interactive UI components
|
|
242
|
+
*/
|
|
243
|
+
export declare class IslandResponse {
|
|
244
|
+
config: IslandResponseConfig;
|
|
245
|
+
static ResponseConfig: typeof IslandResponseConfig;
|
|
246
|
+
type: "island";
|
|
247
|
+
/**
|
|
248
|
+
* Create a new island response
|
|
249
|
+
* @param config Response configuration
|
|
250
|
+
*/
|
|
251
|
+
constructor(config: IslandResponseConfig);
|
|
252
|
+
/**
|
|
253
|
+
* Create an island response with a list of islands
|
|
254
|
+
* @param islands List of island configurations
|
|
255
|
+
* @returns New IslandResponse instance
|
|
256
|
+
*/
|
|
257
|
+
static create(islands: IslandConfig[]): IslandResponse;
|
|
258
|
+
/**
|
|
259
|
+
* Convert to JSON for the discovery endpoint
|
|
260
|
+
*/
|
|
261
|
+
toJSON(): {
|
|
262
|
+
config: {
|
|
263
|
+
islands: {
|
|
264
|
+
fields: {
|
|
265
|
+
name: string;
|
|
266
|
+
label: string;
|
|
267
|
+
type: "string" | "boolean" | "json";
|
|
268
|
+
value: string;
|
|
269
|
+
hidden: boolean;
|
|
270
|
+
options: string[];
|
|
271
|
+
}[];
|
|
272
|
+
actions: {
|
|
273
|
+
name: string;
|
|
274
|
+
label: string;
|
|
275
|
+
type: string;
|
|
276
|
+
endpoint: string;
|
|
277
|
+
operation: string;
|
|
278
|
+
}[];
|
|
279
|
+
}[];
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
}
|
package/dist/models.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Function = exports.AuthRequirement = exports.Parameter = exports.ParameterType = void 0;
|
|
3
|
+
exports.IslandResponse = exports.IslandResponseConfig = exports.IslandConfig = exports.IslandAction = exports.IslandField = exports.Function = exports.AuthRequirement = exports.Parameter = exports.ParameterType = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Types of parameters supported by Opal tools
|
|
6
6
|
*/
|
|
@@ -10,7 +10,7 @@ var ParameterType;
|
|
|
10
10
|
ParameterType["Integer"] = "integer";
|
|
11
11
|
ParameterType["Number"] = "number";
|
|
12
12
|
ParameterType["Boolean"] = "boolean";
|
|
13
|
-
ParameterType["List"] = "
|
|
13
|
+
ParameterType["List"] = "array";
|
|
14
14
|
ParameterType["Dictionary"] = "object";
|
|
15
15
|
})(ParameterType || (exports.ParameterType = ParameterType = {}));
|
|
16
16
|
/**
|
|
@@ -111,3 +111,150 @@ class Function {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
exports.Function = Function;
|
|
114
|
+
/**
|
|
115
|
+
* Island field definition for interactive UI components
|
|
116
|
+
*/
|
|
117
|
+
class IslandField {
|
|
118
|
+
/**
|
|
119
|
+
* Create a new island field
|
|
120
|
+
* @param name Programmatic field identifier
|
|
121
|
+
* @param label Human-readable label
|
|
122
|
+
* @param type Field type
|
|
123
|
+
* @param value Current field value
|
|
124
|
+
* @param hidden Whether to hide from user
|
|
125
|
+
* @param options Available options for selection
|
|
126
|
+
*/
|
|
127
|
+
constructor(name, label, type, value = "", hidden = false, options = []) {
|
|
128
|
+
this.name = name;
|
|
129
|
+
this.label = label;
|
|
130
|
+
this.type = type;
|
|
131
|
+
this.value = value;
|
|
132
|
+
this.hidden = hidden;
|
|
133
|
+
this.options = options;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Convert to JSON for the discovery endpoint
|
|
137
|
+
*/
|
|
138
|
+
toJSON() {
|
|
139
|
+
return {
|
|
140
|
+
name: this.name,
|
|
141
|
+
label: this.label,
|
|
142
|
+
type: this.type,
|
|
143
|
+
value: this.value,
|
|
144
|
+
hidden: this.hidden,
|
|
145
|
+
options: this.options,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
exports.IslandField = IslandField;
|
|
150
|
+
/**
|
|
151
|
+
* Island action definition for interactive UI components
|
|
152
|
+
*/
|
|
153
|
+
class IslandAction {
|
|
154
|
+
/**
|
|
155
|
+
* Create a new island action
|
|
156
|
+
* @param name Programmatic action identifier
|
|
157
|
+
* @param label Human-readable button label
|
|
158
|
+
* @param type UI element type
|
|
159
|
+
* @param endpoint API endpoint to call
|
|
160
|
+
* @param operation Operation type
|
|
161
|
+
*/
|
|
162
|
+
constructor(name, label, type, endpoint, operation = "create") {
|
|
163
|
+
this.name = name;
|
|
164
|
+
this.label = label;
|
|
165
|
+
this.type = type;
|
|
166
|
+
this.endpoint = endpoint;
|
|
167
|
+
this.operation = operation;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Convert to JSON for the discovery endpoint
|
|
171
|
+
*/
|
|
172
|
+
toJSON() {
|
|
173
|
+
return {
|
|
174
|
+
name: this.name,
|
|
175
|
+
label: this.label,
|
|
176
|
+
type: this.type,
|
|
177
|
+
endpoint: this.endpoint,
|
|
178
|
+
operation: this.operation,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
exports.IslandAction = IslandAction;
|
|
183
|
+
/**
|
|
184
|
+
* Island configuration for interactive UI components
|
|
185
|
+
*/
|
|
186
|
+
class IslandConfig {
|
|
187
|
+
/**
|
|
188
|
+
* Create a new island configuration
|
|
189
|
+
* @param fields List of island fields
|
|
190
|
+
* @param actions List of island actions
|
|
191
|
+
*/
|
|
192
|
+
constructor(fields, actions) {
|
|
193
|
+
this.fields = fields;
|
|
194
|
+
this.actions = actions;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Convert to JSON for the discovery endpoint
|
|
198
|
+
*/
|
|
199
|
+
toJSON() {
|
|
200
|
+
return {
|
|
201
|
+
fields: this.fields.map((field) => field.toJSON()),
|
|
202
|
+
actions: this.actions.map((action) => action.toJSON()),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
exports.IslandConfig = IslandConfig;
|
|
207
|
+
IslandConfig.Field = IslandField;
|
|
208
|
+
IslandConfig.Action = IslandAction;
|
|
209
|
+
/**
|
|
210
|
+
* Island response configuration
|
|
211
|
+
*/
|
|
212
|
+
class IslandResponseConfig {
|
|
213
|
+
/**
|
|
214
|
+
* Create a new island response configuration
|
|
215
|
+
* @param islands List of island configurations
|
|
216
|
+
*/
|
|
217
|
+
constructor(islands) {
|
|
218
|
+
this.islands = islands;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Convert to JSON for the discovery endpoint
|
|
222
|
+
*/
|
|
223
|
+
toJSON() {
|
|
224
|
+
return {
|
|
225
|
+
islands: this.islands.map((island) => island.toJSON()),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
exports.IslandResponseConfig = IslandResponseConfig;
|
|
230
|
+
/**
|
|
231
|
+
* Island response wrapper for interactive UI components
|
|
232
|
+
*/
|
|
233
|
+
class IslandResponse {
|
|
234
|
+
/**
|
|
235
|
+
* Create a new island response
|
|
236
|
+
* @param config Response configuration
|
|
237
|
+
*/
|
|
238
|
+
constructor(config) {
|
|
239
|
+
this.config = config;
|
|
240
|
+
this.type = "island";
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Create an island response with a list of islands
|
|
244
|
+
* @param islands List of island configurations
|
|
245
|
+
* @returns New IslandResponse instance
|
|
246
|
+
*/
|
|
247
|
+
static create(islands) {
|
|
248
|
+
return new IslandResponse(new IslandResponseConfig(islands));
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Convert to JSON for the discovery endpoint
|
|
252
|
+
*/
|
|
253
|
+
toJSON() {
|
|
254
|
+
return {
|
|
255
|
+
config: this.config.toJSON(),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
exports.IslandResponse = IslandResponse;
|
|
260
|
+
IslandResponse.ResponseConfig = IslandResponseConfig;
|
package/package.json
CHANGED
package/src/decorators.ts
CHANGED
|
@@ -36,7 +36,7 @@ function mapTypeToParameterType(type: any): ParameterType {
|
|
|
36
36
|
} else if (type === Object || type.name === 'Object') {
|
|
37
37
|
return ParameterType.Dictionary;
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
// Default to string
|
|
41
41
|
return ParameterType.String;
|
|
42
42
|
}
|
|
@@ -47,14 +47,14 @@ function mapTypeToParameterType(type: any): ParameterType {
|
|
|
47
47
|
*/
|
|
48
48
|
function extractParameters(paramType: any): Parameter[] {
|
|
49
49
|
const parameters: Parameter[] = [];
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
// This is very basic and doesn't handle complex types
|
|
52
52
|
// For production use, this would need to be more sophisticated
|
|
53
53
|
for (const key in paramType) {
|
|
54
54
|
if (paramType.hasOwnProperty(key)) {
|
|
55
55
|
const type = typeof paramType[key] === 'undefined' ? String : paramType[key].constructor;
|
|
56
56
|
const required = true; // In a real implementation, we'd detect optional parameters
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
parameters.push(new Parameter(
|
|
59
59
|
key,
|
|
60
60
|
mapTypeToParameterType(type),
|
|
@@ -63,7 +63,7 @@ function extractParameters(paramType: any): Parameter[] {
|
|
|
63
63
|
));
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
return parameters;
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -72,10 +72,10 @@ function extractParameters(paramType: any): Parameter[] {
|
|
|
72
72
|
* @param options Tool options including:
|
|
73
73
|
* - name: Name of the tool
|
|
74
74
|
* - description: Description of the tool
|
|
75
|
-
* - authRequirements: (Optional) Authentication requirements
|
|
75
|
+
* - authRequirements: (Optional) Authentication requirements
|
|
76
76
|
* Format: { provider: "oauth_provider", scopeBundle: "permissions_scope", required: true }
|
|
77
77
|
* Example: { provider: "google", scopeBundle: "calendar", required: true }
|
|
78
|
-
*
|
|
78
|
+
*
|
|
79
79
|
* Note: If your tool requires authentication, define your handler function with two parameters:
|
|
80
80
|
* ```
|
|
81
81
|
* async function myTool(parameters: ParameterInterface, authData?: any): Promise<any> {
|
|
@@ -87,10 +87,10 @@ export function tool(options: ToolOptions) {
|
|
|
87
87
|
return function(target: any, propertyKey?: string, descriptor?: PropertyDescriptor) {
|
|
88
88
|
const isMethod = propertyKey && descriptor;
|
|
89
89
|
const handler = isMethod ? descriptor.value : target;
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
// Generate endpoint from name - ensure hyphens instead of underscores
|
|
92
92
|
const endpoint = `/tools/${options.name.replace(/_/g, '-')}`;
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
// Convert parameter definitions to Parameter objects
|
|
95
95
|
const parameters: Parameter[] = [];
|
|
96
96
|
if (options.parameters && options.parameters.length > 0) {
|
|
@@ -104,7 +104,7 @@ export function tool(options: ToolOptions) {
|
|
|
104
104
|
));
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
|
-
|
|
107
|
+
|
|
108
108
|
// Create auth requirements if specified
|
|
109
109
|
let authRequirements: AuthRequirement[] | undefined;
|
|
110
110
|
if (options.authRequirements) {
|
|
@@ -116,7 +116,7 @@ export function tool(options: ToolOptions) {
|
|
|
116
116
|
)
|
|
117
117
|
];
|
|
118
118
|
}
|
|
119
|
-
|
|
119
|
+
|
|
120
120
|
// Register the tool with all services
|
|
121
121
|
for (const service of registry.services) {
|
|
122
122
|
service.registerTool(
|
|
@@ -128,7 +128,7 @@ export function tool(options: ToolOptions) {
|
|
|
128
128
|
authRequirements
|
|
129
129
|
);
|
|
130
130
|
}
|
|
131
|
-
|
|
131
|
+
|
|
132
132
|
return isMethod ? descriptor : target;
|
|
133
133
|
};
|
|
134
134
|
}
|
package/src/models.ts
CHANGED
|
@@ -6,7 +6,7 @@ export enum ParameterType {
|
|
|
6
6
|
Integer = 'integer',
|
|
7
7
|
Number = 'number',
|
|
8
8
|
Boolean = 'boolean',
|
|
9
|
-
List = '
|
|
9
|
+
List = 'array',
|
|
10
10
|
Dictionary = 'object'
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -113,3 +113,181 @@ export class Function {
|
|
|
113
113
|
return result;
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Authentication credentials structure
|
|
119
|
+
*/
|
|
120
|
+
export type Credentials ={
|
|
121
|
+
access_token: string;
|
|
122
|
+
org_sso_id?: string;
|
|
123
|
+
customer_id: string;
|
|
124
|
+
instance_id: string;
|
|
125
|
+
product_sku: string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Authentication data for an Opal tool
|
|
130
|
+
*/
|
|
131
|
+
export type AuthData = {
|
|
132
|
+
provider: string;
|
|
133
|
+
credentials: Credentials;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Execution environment for an Opal tool
|
|
138
|
+
*/
|
|
139
|
+
export type Environment = {
|
|
140
|
+
execution_mode: "headless" | "interactive";
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Island field definition for interactive UI components
|
|
145
|
+
*/
|
|
146
|
+
export class IslandField {
|
|
147
|
+
/**
|
|
148
|
+
* Create a new island field
|
|
149
|
+
* @param name Programmatic field identifier
|
|
150
|
+
* @param label Human-readable label
|
|
151
|
+
* @param type Field type
|
|
152
|
+
* @param value Current field value
|
|
153
|
+
* @param hidden Whether to hide from user
|
|
154
|
+
* @param options Available options for selection
|
|
155
|
+
*/
|
|
156
|
+
constructor(
|
|
157
|
+
public name: string,
|
|
158
|
+
public label: string,
|
|
159
|
+
public type: "string" | "boolean" | "json",
|
|
160
|
+
public value: string = "",
|
|
161
|
+
public hidden: boolean = false,
|
|
162
|
+
public options: string[] = []
|
|
163
|
+
) {}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Convert to JSON for the discovery endpoint
|
|
167
|
+
*/
|
|
168
|
+
toJSON() {
|
|
169
|
+
return {
|
|
170
|
+
name: this.name,
|
|
171
|
+
label: this.label,
|
|
172
|
+
type: this.type,
|
|
173
|
+
value: this.value,
|
|
174
|
+
hidden: this.hidden,
|
|
175
|
+
options: this.options,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Island action definition for interactive UI components
|
|
182
|
+
*/
|
|
183
|
+
export class IslandAction {
|
|
184
|
+
/**
|
|
185
|
+
* Create a new island action
|
|
186
|
+
* @param name Programmatic action identifier
|
|
187
|
+
* @param label Human-readable button label
|
|
188
|
+
* @param type UI element type
|
|
189
|
+
* @param endpoint API endpoint to call
|
|
190
|
+
* @param operation Operation type
|
|
191
|
+
*/
|
|
192
|
+
constructor(
|
|
193
|
+
public name: string,
|
|
194
|
+
public label: string,
|
|
195
|
+
public type: string,
|
|
196
|
+
public endpoint: string,
|
|
197
|
+
public operation: string = "create"
|
|
198
|
+
) {}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Convert to JSON for the discovery endpoint
|
|
202
|
+
*/
|
|
203
|
+
toJSON() {
|
|
204
|
+
return {
|
|
205
|
+
name: this.name,
|
|
206
|
+
label: this.label,
|
|
207
|
+
type: this.type,
|
|
208
|
+
endpoint: this.endpoint,
|
|
209
|
+
operation: this.operation,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Island configuration for interactive UI components
|
|
216
|
+
*/
|
|
217
|
+
export class IslandConfig {
|
|
218
|
+
static Field = IslandField;
|
|
219
|
+
static Action = IslandAction;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Create a new island configuration
|
|
223
|
+
* @param fields List of island fields
|
|
224
|
+
* @param actions List of island actions
|
|
225
|
+
*/
|
|
226
|
+
constructor(
|
|
227
|
+
public fields: IslandField[],
|
|
228
|
+
public actions: IslandAction[]
|
|
229
|
+
) {}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Convert to JSON for the discovery endpoint
|
|
233
|
+
*/
|
|
234
|
+
toJSON() {
|
|
235
|
+
return {
|
|
236
|
+
fields: this.fields.map((field) => field.toJSON()),
|
|
237
|
+
actions: this.actions.map((action) => action.toJSON()),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Island response configuration
|
|
244
|
+
*/
|
|
245
|
+
export class IslandResponseConfig {
|
|
246
|
+
/**
|
|
247
|
+
* Create a new island response configuration
|
|
248
|
+
* @param islands List of island configurations
|
|
249
|
+
*/
|
|
250
|
+
constructor(public islands: IslandConfig[]) {}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Convert to JSON for the discovery endpoint
|
|
254
|
+
*/
|
|
255
|
+
toJSON() {
|
|
256
|
+
return {
|
|
257
|
+
islands: this.islands.map((island) => island.toJSON()),
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Island response wrapper for interactive UI components
|
|
264
|
+
*/
|
|
265
|
+
export class IslandResponse {
|
|
266
|
+
static ResponseConfig = IslandResponseConfig;
|
|
267
|
+
|
|
268
|
+
public type: "island" = "island";
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Create a new island response
|
|
272
|
+
* @param config Response configuration
|
|
273
|
+
*/
|
|
274
|
+
constructor(public config: IslandResponseConfig) {}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Create an island response with a list of islands
|
|
278
|
+
* @param islands List of island configurations
|
|
279
|
+
* @returns New IslandResponse instance
|
|
280
|
+
*/
|
|
281
|
+
static create(islands: IslandConfig[]): IslandResponse {
|
|
282
|
+
return new IslandResponse(new IslandResponseConfig(islands));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Convert to JSON for the discovery endpoint
|
|
287
|
+
*/
|
|
288
|
+
toJSON() {
|
|
289
|
+
return {
|
|
290
|
+
config: this.config.toJSON(),
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
}
|