@optimizely-opal/opal-tools-sdk
Version:
SDK for creating Opal-compatible tools services
273 lines (219 loc) • 7.37 kB
Markdown
# Opal Tools SDK for TypeScript
This SDK simplifies the creation of tools services compatible with the Opal Tools Management Service.
## Features
- Easy definition of tool functions with decorators
- Automatic generation of discovery endpoints
- Parameter validation and type checking
- Authentication helpers
- Express integration
- Island components for interactive UI responses
## Installation
```bash
npm install @optimizely-opal/opal-tools-sdk
```
## Usage
```typescript
import { ToolsService, tool, IslandResponse, IslandConfig } from '@optimizely-opal/opal-tools-sdk';
import express from 'express';
const app = express();
const toolsService = new ToolsService(app);
interface WeatherParameters {
location: string;
units: string;
}
@tool({
name: 'get_weather',
description: 'Gets current weather for a location'
})
async function getWeather(parameters: WeatherParameters) {
// Implementation...
return { temperature: 22, condition: 'sunny' };
}
// Discovery endpoint is automatically created at /discovery
```
## Authentication
The SDK provides two ways to require authentication for your tools:
### 1. Using the `@requiresAuth` decorator
```typescript
import { ToolsService, tool } from '@optimizely-opal/opal-tools-sdk';
import { requiresAuth } from '@optimizely-opal/opal-tools-sdk/auth';
import express from 'express';
const app = express();
const toolsService = new ToolsService(app);
interface CalendarParameters {
date: string;
timezone?: string;
}
// Single authentication requirement
@requiresAuth({ provider: 'google', scopeBundle: 'calendar', required: true })
@tool({
name: 'get_calendar_events',
description: 'Gets calendar events for a date'
})
async function getCalendarEvents(parameters: CalendarParameters, authData?: any) {
// The authData parameter contains authentication information
const token = authData?.credentials?.token || '';
// Use the token to make authenticated requests
// ...
return { events: ['Meeting at 10:00', 'Lunch at 12:00'] };
}
// Multiple authentication requirements (tool can work with either provider)
@requiresAuth({ provider: 'google', scopeBundle: 'calendar', required: true })
@requiresAuth({ provider: 'microsoft', scopeBundle: 'outlook', required: true })
@tool({
name: 'get_calendar_availability',
description: 'Check calendar availability'
})
async function getCalendarAvailability(parameters: CalendarParameters, authData?: any) {
const provider = authData?.provider || '';
const token = authData?.credentials?.token || '';
if (provider === 'google') {
// Use Google Calendar API
} else if (provider === 'microsoft') {
// Use Microsoft Outlook API
}
return { available: true, provider_used: provider };
}
```
### 2. Specifying auth requirements in the `@tool` decorator
```typescript
interface EmailParameters {
limit?: number;
folder?: string;
}
@tool({
name: 'get_email',
description: 'Gets emails from the user\'s inbox',
authRequirements: {
provider: 'google',
scopeBundle: 'gmail',
required: true
}
})
async function getEmail(parameters: EmailParameters, authData?: any) {
// Implementation...
return { emails: ['Email 1', 'Email 2'] };
}
```
## Authentication
The SDK provides authentication support for tools that require user credentials:
```typescript
import { ToolsService, tool, requiresAuth, AuthData } from '@optimizely-opal/opal-tools-sdk';
import express from 'express';
interface CalendarParameters {
date: string;
timezone?: string;
}
const app = express();
const toolsService = new ToolsService(app);
@requiresAuth({ provider: 'google', scopeBundle: 'calendar', required: true })
@tool({
name: 'get_calendar_events',
description: 'Gets calendar events for a date'
})
async function getCalendarEvents(parameters: CalendarParameters, authData?: AuthData) {
// The authData parameter contains authentication information
if (authData) {
const token = authData.credentials.access_token;
// Use the token to make authenticated requests
}
return { events: ['Meeting at 10:00', 'Lunch at 12:00'] };
}
```
## Island Components
The SDK includes Island components for creating interactive UI responses:
```typescript
import {
ToolsService,
tool,
IslandResponse,
IslandConfig
} from '@optimizely-opal/opal-tools-sdk';
import express from 'express';
interface WeatherParameters {
location: string;
units?: string;
}
const app = express();
const toolsService = new ToolsService(app);
@tool({
name: 'get_weather',
description: 'Gets current weather for a location'
})
async function getWeather(parameters: WeatherParameters) {
// Get weather data (implementation details omitted)
const weatherData = { temperature: 22, condition: 'sunny', humidity: 65 };
// Create an interactive island for weather settings
const island = new IslandConfig(
[
new IslandConfig.Field(
'location',
'Location',
'string',
parameters.location
),
new IslandConfig.Field(
'units',
'Temperature Units',
'string',
parameters.units || 'metric',
false,
['metric', 'imperial', 'kelvin']
),
new IslandConfig.Field(
'current_temp',
'Current Temperature',
'string',
`${weatherData.temperature}°${parameters.units === 'metric' ? 'C' : 'F'}`
)
],
[
new IslandConfig.Action(
'refresh_weather',
'Refresh Weather',
'button',
'/tools/get_weather',
'update'
)
]
);
return IslandResponse.create([island]);
}
```
### Island Components
#### IslandConfig.Field
Fields represent data inputs in the UI:
- `name`: Programmatic field identifier
- `label`: Human-readable label
- `type`: Field type (`'string'`, `'boolean'`, `'json'`)
- `value`: Current field value (optional)
- `hidden`: Whether to hide from user (optional, default: false)
- `options`: Available options for selection (optional)
#### IslandConfig.Action
Actions represent buttons or operations:
- `name`: Programmatic action identifier
- `label`: Human-readable button label
- `type`: UI element type (typically `'button'`)
- `endpoint`: API endpoint to call
- `operation`: Operation type (default: `'create'`)
#### IslandConfig
Contains the complete island configuration:
- `fields`: Array of IslandConfig.Field objects
- `actions`: Array of IslandConfig.Action objects
#### IslandResponse
The response wrapper for islands:
- Use `IslandResponse.create([islands])` to create responses
- Supports multiple islands per response
## Type Definitions
The SDK provides comprehensive TypeScript type definitions:
### Authentication Types
- `AuthData`: Interface containing provider and credentials information
- `Credentials`: Interface with access_token, org_sso_id, customer_id, instance_id, and product_sku
- `Environment`: Interface specifying execution mode (`'headless'` or `'interactive'`)
### Parameter Types
- `ParameterType`: Enum for supported parameter types
- `Parameter`: Class for tool parameter definitions
- `Function`: Class for complete tool function definitions
These types provide full IDE support and compile-time type checking for better development experience.
## Documentation
See full documentation for more examples and configuration options.