npm package: @optimizely-opal/opal-tools-sdk
Description: SDK for creating Opal-compatible tools services
Author: Optimizely
Latest version: 0.1.17-dev

# 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'
      )
    ],
    'button',  // Optional island type
    'plus'     // Optional island icon
  );

  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
- `type`: Optional island type for custom rendering (optional)
- `icon`: Optional icon identifier for the island (optional)

#### 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.