npm package: @linegon/terabrain-sdk
Description: Official TypeScript SDK for TeraBrain AI automation platform
Author: Linegon
Latest version: 0.2.1

# TeraBrain SDK

Official TypeScript SDK for [TeraBrain](https://terabrain.ai) AI automation platform.

## Installation

```bash
npm install @linegon/terabrain-sdk
```

## Quick Start

```typescript
import { TeraBrain } from '@linegon/terabrain-sdk';

// Initialize the client
const client = new TeraBrain({
  apiKey: 'your-api-key',
  domain: 'terabrain.ai', // optional, defaults to 'terabrain.ai'
});

// Create a worker
const worker = await client.workers.create({
  name: 'Customer Support Assistant',
  jobtitle: 'Support Agent',
  model: 'gpt-4o',
  duties: [
    'Answer customer questions professionally',
    'Help troubleshoot common issues',
    'Escalate complex problems to human agents',
  ],
  skills: [],
});

console.log('Worker created:', worker.workerId);

// Deploy the worker
await client.workers.deploy(worker.workerId);
console.log('Worker deployed successfully');
```

## Configuration

### API Key

You need an API key to use the SDK. Get one from your [TeraBrain dashboard](https://app.terabrain.ai):

1. Sign in to your account
2. Go to Settings → API Keys
3. Create a new API key

```typescript
const client = new TeraBrain({
  apiKey: 'your-api-key',
});
```

### Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `apiKey` | `string` | *required* | Your TeraBrain API key |
| `domain` | `string` | `'terabrain.ai'` | Base domain for the API |
| `timeout` | `number` | `30000` | Request timeout in milliseconds |
| `maxRetries` | `number` | `3` | Maximum retry attempts for failed requests |
| `retryDelay` | `number` | `1000` | Initial delay between retries in milliseconds |

## Features

### ✅ Workers Management
Create, update, delete, and deploy AI workers with various skills and capabilities.

### ✅ Chat & Messages
Manage conversations with workers, send messages, and retrieve chat history.

### ✅ Real-time WebSocket
Connect to workers via WebSocket for real-time bidirectional communication.

### ✅ Local Function Connector
Expose local functions to cloud AI agents - access databases, file systems, and internal APIs.

### ✅ Profile & API Keys
Manage your account profile and API keys programmatically.

### ✅ Automatic Retries
Built-in retry logic with exponential backoff for network errors and rate limits.

### ✅ Type-Safe
Full TypeScript support with comprehensive type definitions.

### ✅ Error Handling
Custom error classes for different error types (authentication, validation, network, etc.).

## Usage Examples

### Workers

#### Create a Worker

```typescript
const worker = await client.workers.create({
  name: 'Email Assistant',
  jobtitle: 'Email Manager',
  model: 'gpt-4o',
  temperature: 0.7,
  timezone: 'Europe/Rome',
  duties: [
    'Respond to emails professionally',
    'Categorize incoming emails',
    'Draft responses for approval',
  ],
  skills: [
    {
      type: 'email',
      id: 'email-skill-1',
      data: {
        processNewEmails: true,
        signature: 'Best regards,\nThe Team',
      },
    },
  ],
  enableFileOperations: true,
  enableFileSearch: true,
});
```

#### List Workers

```typescript
const workers = await client.workers.list();

workers.forEach(worker => {
  console.log(`${worker.name} (${worker.workerId})`);
  console.log(`Status: ${worker.status}`);
  console.log(`Skills: ${worker.skills.join(', ')}`);
});
```

#### Get Worker Details

```typescript
const worker = await client.workers.get('worker-123');
console.log(worker);
```

#### Update a Worker

```typescript
await client.workers.update('worker-123', {
  name: 'Updated Worker Name',
  duties: ['New duty 1', 'New duty 2'],
});
```

#### Deploy a Worker

```typescript
await client.workers.deploy('worker-123');
```

#### Check Worker Status

```typescript
const status = await client.workers.getStatus('worker-123');
console.log('Status:', status.status); // 'ok', 'deploying', or 'failed'
console.log('Skills:', status.skills);
```

#### Delete a Worker

```typescript
await client.workers.delete('worker-123');
```

#### Direct Function Execution

Execute worker functions directly without going through a chat interface:

```typescript
// Execute a simple function
const result = await client.workers.executeFunction(
  workerId,
  'internaldb-query',
  { query: 'SELECT * FROM users' }
);

console.log('Result:', result.result);
```

Execute with chat context to maintain conversation state:

```typescript
const result = await client.workers.executeFunction(
  workerId,
  'custom-function',
  { param1: 'value1' },
  {
    chatId: 'existing-chat-id',  // Associate with existing chat
    caller: 'my-application'      // Identify the caller
  }
);
```

**Parameters:**
- `workerId`: The ID of the worker to execute the function on
- `functionName`: Name of the function (e.g., 'internaldb-query', 'email-send')
- `args`: Object containing function arguments
- `options` (optional):
  - `chatId`: Associate execution with an existing chat
  - `caller`: Identify the calling application (defaults to 'sdk')

### Chats & Messages

#### List Chats for a Worker

```typescript
const chats = await client.chats.list('worker-123');

chats.forEach(chat => {
  console.log(`Chat ${chat.chatId}`);
  console.log(`Last message: ${chat.lastPrompt}`);
  console.log(`Updated: ${chat.lastChange}`);
});
```

#### Get Messages from a Chat

```typescript
const messages = await client.chats.messages('worker-123').list('chat-456');

messages.forEach(msg => {
  msg.messages.forEach(m => {
    console.log(`${m.role}: ${m.content}`);
  });
});
```

#### Send a Message to a Chat

```typescript
await client.chats.messages('worker-123').create('chat-456', 'Hello, can you help me?');
```

#### Create a New Chat and Send First Message

```typescript
await client.chats.create('worker-123', 'Hello! I need help with my account.');
```

#### Attach a File to a Chat

```typescript
const fileInfo = await client.chats.attachFile(
  'worker-123',
  'chat-456',
  'document.pdf',
  'application/pdf'
);

// Use the putUrl to upload the file
await fetch(fileInfo.putUrl, {
  method: 'PUT',
  body: fileBuffer,
  headers: { 'Content-Type': 'application/pdf' },
});

console.log('File uploaded:', fileInfo.fileId);
```

### WebSocket (Real-time Communication)

```typescript
// Connect to a worker via WebSocket
const ws = client.websocket.connect('worker-123', 'chat-456');

// Event handlers
ws.on('open', () => {
  console.log('WebSocket connected');
});

ws.on('message', (message) => {
  console.log('Received:', message);
});

ws.on('error', (error) => {
  console.error('WebSocket error:', error);
});

ws.on('close', () => {
  console.log('WebSocket closed');
});

ws.on('reconnect', ({ attempt }) => {
  console.log(`Reconnecting... attempt ${attempt}`);
});

// Connect
await ws.connect();

// Send a message
ws.send({
  type: 'chat',
  content: 'Hello via WebSocket!',
});

// Check connection status
console.log('Connected:', ws.isConnected);

// Close connection
ws.close();
```

#### WebSocket Options

```typescript
const ws = client.websocket.connect('worker-123', undefined, {
  autoReconnect: true,
  reconnectDelay: 5000,
  maxReconnectAttempts: 10,
  heartbeatInterval: 30000,
});
```

### Connector (Local Function Hosting)

The Connector allows you to expose local functions to TeraBrain AI agents running in the cloud. This is useful for:

- Accessing local databases or file systems
- Integrating with internal APIs or services
- Performing computations on local hardware
- Executing custom logic that needs to run on-premises

#### Basic Usage

```typescript
// Create a connector with a unique identifier
const connector = client.connector.create('my-local-functions');

// Register a function (must start with 'proxy-')
connector.registerFunction(
  'proxy-getUserData',
  'Retrieves user data from the local database',
  {
    type: 'object',
    properties: {
      userId: {
        type: 'string',
        description: 'The ID of the user to retrieve',
      },
    },
    required: ['userId'],
  },
  async (event) => {
    // Your function logic here
    const userData = await database.getUserById(event.args.userId);

    return {
      success: true,
      user: userData,
    };
  }
);

// Set up event listeners
connector.on('open', () => {
  console.log('✅ Connector connected');
});

connector.on('execution', (event) => {
  console.log(`🚀 Executing: ${event.functionName}`);
});

connector.on('error', (error) => {
  console.error('❌ Error:', error.message);
});

// Start the connector
await connector.start();

// Keep it running...
// Later, to stop:
// connector.stop();
```

#### Multiple Functions Example

```typescript
const connector = client.connector.create('internal-tools');

// Function 1: Database access
connector.registerFunction(
  'proxy-queryDatabase',
  'Executes a SQL query on the local database',
  {
    type: 'object',
    properties: {
      query: { type: 'string', description: 'SQL query to execute' },
    },
    required: ['query'],
  },
  async (event) => {
    const results = await db.query(event.args.query);
    return { data: results };
  }
);

// Function 2: File system access
connector.registerFunction(
  'proxy-readFile',
  'Reads a file from the local file system',
  {
    type: 'object',
    properties: {
      path: { type: 'string', description: 'File path to read' },
    },
    required: ['path'],
  },
  async (event) => {
    const fs = await import('fs/promises');
    const content = await fs.readFile(event.args.path, 'utf-8');
    return { content };
  }
);

// Function 3: Internal API call
connector.registerFunction(
  'proxy-callInternalApi',
  'Calls an internal API that is not accessible from the internet',
  {
    type: 'object',
    properties: {
      endpoint: { type: 'string', description: 'API endpoint' },
    },
    required: ['endpoint'],
  },
  async (event) => {
    const response = await fetch(`http://internal-api.local${event.args.endpoint}`);
    const data = await response.json();
    return { data };
  }
);

await connector.start();
```

#### Connector Events

```typescript
// Connection opened
connector.on('open', () => {
  console.log('Connected');
});

// Connection closed
connector.on('close', (code, reason) => {
  console.log(`Closed: ${code} - ${reason}`);
});

// Error occurred
connector.on('error', (error) => {
  console.error('Error:', error);
});

// Function execution started
connector.on('execution', (event) => {
  console.log(`Executing: ${event.functionName}`);
  console.log(`Chat ID: ${event.chatId}`);
  console.log(`Arguments:`, event.args);
});

// Reconnection attempt
connector.on('reconnect', () => {
  console.log('Reconnecting...');
});

// WebSocket message received (for debugging)
connector.on('message', (data) => {
  console.log('Message:', data);
});
```

#### Connector Options

```typescript
const connector = client.connector.create('my-functions', {
  reconnectDelayMs: 5000,          // Delay between reconnection attempts (default: 5000)
  websocketTimeoutMs: 6000000,     // WebSocket timeout (default: 6000000 - 100 minutes)
  keepaliveIntervalMs: 570000,     // Keepalive interval (default: 570000 - 9.5 minutes)
});
```

#### Connector Properties

```typescript
// Check if connected
console.log('Connected:', connector.isConnected);

// Get number of registered functions
console.log('Functions:', connector.functionsCount);
```

#### Using Connector Functions in Workers

Once your connector is running, add the proxy skill to your worker with the same identifier:

```typescript
const worker = await client.workers.create({
  name: 'Assistant with Local Functions',
  jobtitle: 'Assistant',
  model: 'gpt-4o',
  duties: ['Help users with local data'],
  skills: [
    {
      type: 'proxy',
      id: 'proxy-1',
      data: {
        identifier: 'my-local-functions', // Same as connector identifier
      },
    },
  ],
});

await client.workers.deploy(worker.workerId);
```

Now your AI agent can call your local functions!

### Profile

#### Get User Profile

```typescript
const profile = await client.profile.get();

console.log('Email:', profile.email);
console.log('Plan:', profile.plan);
console.log('Workers:', profile.currentWorkers, '/', profile.maxWorkers);
console.log('Enabled skills:', profile.enabledSkills);
console.log('Credits:', profile.currentMonthUsedCredits, '/', profile.monthlyCredits);
```

### API Keys

#### Create an API Key

```typescript
const apikey = await client.apikeys.create('my-app-key');

// IMPORTANT: Save this key securely! It won't be shown again
console.log('API Key:', apikey.apiKey);
console.log('Identifier:', apikey.identifier);
```

#### List API Keys

```typescript
const apikeys = await client.apikeys.list();

apikeys.forEach(key => {
  console.log(`${key.identifier}: ${key.maskedApiKey}`);
  console.log(`Created: ${key.createdAt}`);
});
```

#### Delete an API Key

```typescript
await client.apikeys.delete('my-app-key');
```

### OAuth Consent URLs (for Skills)

Some skills (like O365, Google) require OAuth authentication:

```typescript
const profile = await client.profile.get();

const consentUrl = client.buildConsentUrl(
  'worker-123',
  'o365', // or 'google'
  profile.customerId
);

console.log('Authorize at:', consentUrl);
// Redirect user to this URL to complete OAuth flow
```

## Error Handling

The SDK provides custom error classes for different error scenarios:

```typescript
import {
  TeraBrainError,
  AuthenticationError,
  NotFoundError,
  ValidationError,
  RateLimitError,
  NetworkError,
  ServerError,
  TimeoutError,
} from '@linegon/terabrain-sdk';

try {
  await client.workers.get('invalid-id');
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key');
  } else if (error instanceof NotFoundError) {
    console.error('Worker not found');
  } else if (error instanceof ValidationError) {
    console.error('Invalid request:', error.message);
  } else if (error instanceof RateLimitError) {
    console.error('Rate limit exceeded, retry after:', error.retryAfter);
  } else if (error instanceof NetworkError) {
    console.error('Network error:', error.cause);
  } else if (error instanceof ServerError) {
    console.error('Server error:', error.statusCode);
  } else if (error instanceof TimeoutError) {
    console.error('Request timed out');
  } else if (error instanceof TeraBrainError) {
    console.error('TeraBrain error:', error.message);
  }
}
```

## TypeScript Support

The SDK is written in TypeScript and provides full type definitions:

```typescript
import type {
  workerI,
  workerStatus,
  skillI,
  Chat,
  Message,
  Profile,
} from '@linegon/terabrain-sdk';

const worker: workerI = {
  name: 'My Worker',
  jobtitle: 'Assistant',
  model: 'gpt-4o',
  duties: ['Help users'],
  skills: [],
};
```

## Support

- Documentation: [https://docs.terabrain.ai](https://docs.terabrain.ai)
- Email: support@terabrain.ai
- Issues: [GitHub Issues](https://github.com/linegon/terabrain-sdk/issues)

## License

MIT