# Cybernate AI SDK

[![npm version](https://img.shields.io/npm/v/cybernate-ai.svg)](https://www.npmjs.com/package/cybernate-ai)
[![License](https://img.shields.io/npm/l/cybernate-ai.svg)](https://github.com/cybernate-ai/cybernate-sdk/blob/main/LICENSE)

JavaScript SDK for the Cybernate AI platform — general-purpose AI inference, multi-turn conversations, embeddings, vision, and security monitoring.

## Installation

```bash
npm install cybernate-ai
```

## Quick Start

```javascript
import { CybernateAI } from 'cybernate-ai';

const cybernate = new CybernateAI('YOUR_API_KEY');
await cybernate.connect();

// One-shot chat
const { result } = await cybernate.chat([
  { role: 'user', content: 'Summarise this report in Swahili.' }
]);
console.log(result);

// Persistent conversation (history managed server-side)
const { conversation } = await cybernate.createConversation('My session');
const reply = await cybernate.sendMessage(conversation._id, 'Hello!');
console.log(reply.result);
```

## AI — Chat

```javascript
// Single request — you manage history
const { result, usage, model } = await cybernate.chat(
  [{ role: 'user', content: 'What is 2+2?' }],
  { model: 'default', maxTokens: 400, temperature: 0.7 }
);

// List available models
const { local, remote } = await cybernate.listModels();
```

## AI — Conversations (server-managed history)

```javascript
// Create
const { conversation } = await cybernate.createConversation('Support chat');

// Send a message — full history is fetched automatically
const { result, usage } = await cybernate.sendMessage(conversation._id, 'Hi there');

// List all conversations
const { conversations } = await cybernate.listConversations();

// Get a conversation with messages
const { conversation: conv, messages } = await cybernate.getConversation(id);

// Update title or pinned state
await cybernate.updateConversation(id, { title: 'New title', pinned: true });

// Rate an AI message
await cybernate.rateMessage(conversationId, messageId, 'up'); // 'up' | 'down' | null

// Delete
await cybernate.deleteConversation(id);
```

## AI — Embeddings

```javascript
const { embeddings } = await cybernate.embed(['Hello world', 'Another sentence']);
// embeddings: number[][] — one vector per input string
```

## AI — Vision / Object Detection

```javascript
const { detections } = await cybernate.detectObjects({
  imageUrl: 'https://example.com/frame.jpg',
  confidence: 0.5,
  classes: ['person', 'vehicle'],
});
// or use imageBase64 for local files
```

## Security Monitoring

```javascript
// Watch a camera stream for detections
const watcher = await cybernate.watch({
  streamUrl: 'rtsp://camera.example.com/stream1',
  detectionSettings: { sensitivityLevel: 0.7, objectTypes: ['person', 'vehicle'] },
  notificationSettings: { method: 'webhook', webhookUrl: 'https://your-server.com/hook' },
});

// Listen for real-time events via WebSocket
cybernate.on('detection', (event) => {
  console.log('Detected:', event.objects.map(o => o.name).join(', '));
});

// Query past events
const { events } = await cybernate.queryEvents({
  businessId: 'YOUR_BUSINESS_ID',
  startDate: '2026-01-01T00:00:00Z',
  eventType: 'intrusion',
});

// Acknowledge an event
await cybernate.acknowledgeEvent(events[0]._id, 'Reviewed and resolved');

// Stop watching
await cybernate.unwatch(watcher.watcherId);
```

## Authentication

Obtain your API key from the Cybernate dashboard. This key will be used to authenticate all SDK requests.

```javascript
const cybernate = new CybernateAI('YOUR_API_KEY');
await cybernate.connect();
```

## API Reference

### Core Methods

#### `new CybernateAI(apiKey, options)`

Creates a new Cybernate AI client instance.

Parameters:
- `apiKey` (string): Your Cybernate API key
- `options` (object, optional):
  - `baseUrl` (string): API base URL (defaults to Cybernate production API)
  - `timeout` (number): Request timeout in milliseconds (default: 30000)
  - `autoReconnect` (boolean): Auto reconnect on connection failure (default: true)

#### `connect()`

Establishes a connection to the Cybernate API and validates your API key.

Returns: Promise resolving to an object with connection information.

#### `disconnect()`

Disconnects from the Cybernate service and cleans up resources.

### Event Monitoring

#### `watch(options)`

Begins monitoring a video stream, device, or business for security events.

Parameters:
- `options` (object):
  - `streamUrl` (string, optional): URL of the stream to watch
  - `deviceId` (string, optional): ID of the device to watch
  - `businessId` (string, optional): ID of the business to watch
  - `detectionSettings` (object, optional):
    - `sensitivityLevel` (number): Detection sensitivity (0-1)
    - `objectTypes` (string[]): Object types to detect
  - `notificationSettings` (object, optional):
    - `method` (string): Notification method ('webhook', 'socket')
    - `webhookUrl` (string): Webhook URL (required if method is 'webhook')

Returns: Promise resolving to an object with watcher ID and configuration.

#### `unwatch(watcherId)`

Stops monitoring a stream, device, or business.

Parameters:
- `watcherId` (string): ID of the watcher to stop

Returns: Promise resolving to a response object.

#### `getActiveWatchers()`

Retrieves all currently active watchers.

Returns: Promise resolving to an array of watcher objects.

#### `on(event, callback)`

Registers an event listener for a specific event type.

Parameters:
- `event` (string): Event type to listen for (e.g., 'detection', 'alert', 'notification')
- `callback` (function): Callback function to be called when the event occurs

#### `off(event, callback)`

Removes an event listener.

Parameters:
- `event` (string): Event type
- `callback` (function, optional): Callback function (if omitted, removes all listeners for the event)

### Event Management

#### `queryEvents(query)`

Searches for events with filtering and pagination.

Parameters:
- `query` (object, optional):
  - `streamId` (string): Filter by stream ID
  - `deviceId` (string): Filter by device ID
  - `businessId` (string): Filter by business ID
  - `eventType` (string): Filter by event type
  - `objectType` (string): Filter by detected object type
  - `startDate` (string): Filter by start date (ISO string)
  - `endDate` (string): Filter by end date (ISO string)
  - `page` (number): Page number
  - `limit` (number): Results per page

Returns: Promise resolving to an object with events and pagination info.

#### `getEventStatistics(query)`

Retrieves statistics about events.

Parameters:
- `query` (object, optional): Same as queryEvents

Returns: Promise resolving to an object with event statistics.

#### `acknowledgeEvent(eventId, notes)`

Marks an event as acknowledged.

Parameters:
- `eventId` (string): Event ID
- `notes` (string, optional): Optional notes

Returns: Promise resolving to the updated event.

### Webhook Management

#### `setWebhook(config)`

Configures a webhook for event notifications.

Parameters:
- `config` (object):
  - `url` (string): Webhook URL
  - `events` (string[], optional): Event types to receive (defaults to all)

Returns: Promise resolving to a response object.

#### `getWebhooks()`

Retrieves all configured webhooks.

Returns: Promise resolving to an array of webhook objects.

#### `deleteWebhook(webhookId)`

Deletes a webhook configuration.

Parameters:
- `webhookId` (string): Webhook ID

Returns: Promise resolving to a response object.
 
#### `testWebhook(url, payload)`

Tests a webhook endpoint.

Parameters:
- `url` (string): Webhook URL to test
- `payload` (object, optional): Optional custom payload

Returns: Promise resolving to a test result object.

### Storage Management

#### `uploadFile(options)`

Uploads a file to Cybernate storage.

Parameters:
- `options` (object):
  - `file` (File|Blob|Buffer): File to upload
  - `fileName` (string): Original file name
  - `eventId` (string, optional): Associated event ID
  - `streamId` (string, optional): Associated stream ID
  - `deviceId` (string, optional): Associated device ID
  - `businessId` (string, optional): Associated business ID
  - `metadata` (object, optional): Additional metadata
  - `isPublic` (boolean, optional): Whether file is publicly accessible (default: false)

Returns: Promise resolving to an object with uploaded file info.

#### `getFileInfo(fileId)`

Retrieves information about a stored file.

Parameters:
- `fileId` (string): File ID

Returns: Promise resolving to a file info object.

#### `queryFiles(query)`

Searches for files with filtering.

Parameters:
- `query` (object, optional):
  - `eventId` (string): Filter by event ID
  - `streamId` (string): Filter by stream ID
  - `deviceId` (string): Filter by device ID
  - `businessId` (string): Filter by business ID
  - `startDate` (string): Filter by start date (ISO string)
  - `endDate` (string): Filter by end date (ISO string)
  - `mimeType` (string): Filter by MIME type
  - `page` (number): Page number
  - `limit` (number): Results per page

Returns: Promise resolving to an object with files and pagination info.

#### `deleteFile(fileId)`

Deletes a file from storage.

Parameters:
- `fileId` (string): File ID

Returns: Promise resolving to a response object.

#### `getFileUrl(fileId, expiresIn)`

Gets a signed URL for a file.

Parameters:
- `fileId` (string): File ID
- `expiresIn` (number, optional): Expiration time in seconds (default: 3600)

Returns: Promise resolving to an object with a signed URL.

#### `captureStreamFrame(streamId, options)`

Captures a frame from a video stream.

Parameters:
- `streamId` (string): Stream ID
- `options` (object, optional):
  - `isPublic` (boolean, optional): Whether captured frame is publicly accessible (default: false)
  - `metadata` (object, optional): Additional metadata

Returns: Promise resolving to an object with captured frame info.

### Analytics

#### `getAnalytics(businessId, options)`

Retrieves analytics data for a business.

Parameters:
- `businessId` (string): Business ID
- `options` (object, optional):
  - `type` (string): Analytics type ('daily', 'weekly', 'monthly', default: 'daily')
  - `period` (string): Specific period to get
  - `startDate` (string): Filter by start date (ISO string)
  - `endDate` (string): Filter by end date (ISO string)
  - `limit` (number): Maximum records to return (default: 30)

Returns: Promise resolving to an array of analytics objects.

#### `getInsights(businessId, options)`

Retrieves insights for a business.

Parameters:
- `businessId` (string): Business ID
- `options` (object, optional):
  - `type` (string): Insight type ('trend', 'anomaly', 'recommendation', 'alert')
  - `minSeverity` (number): Minimum severity level (1-5, default: 1)
  - `isAcknowledged` (boolean): Filter by acknowledgment status
  - `startDate` (string): Filter by start date (ISO string)
  - `endDate` (string): Filter by end date (ISO string)
  - `page` (number): Page number (default: 1)
  - `limit` (number): Results per page (default: 20)

Returns: Promise resolving to an object with insights and pagination info.

#### `acknowledgeInsight(insightId, actionTaken)`

Acknowledges an insight.

Parameters:
- `insightId` (string): Insight ID
- `actionTaken` (string, optional): Action taken in response to insight

Returns: Promise resolving to the updated insight.

#### `getDashboardAnalytics(businessId)`

Retrieves dashboard analytics for a business.

Parameters:
- `businessId` (string): Business ID

Returns: Promise resolving to a dashboard data object.

### Integrations

#### `getIntegrations(query)`

Retrieves all integrations with filtering.

Parameters:
- `query` (object, optional):
  - `type` (string): Filter by integration type
  - `provider` (string): Filter by provider
  - `isActive` (boolean): Filter by active status
  - `page` (number): Page number (default: 1)
  - `limit` (number): Results per page (default: 20)

Returns: Promise resolving to an object with integrations and pagination info.

#### `createIntegration(integrationData)`

Creates a new integration.

Parameters:
- `integrationData` (object):
  - `name` (string): Integration name
  - `type` (string): Integration type
  - `provider` (string): Provider name
  - `businessId` (string): Business ID
  - `config` (object, optional): Configuration
  - `credentials` (object, optional): Credentials
  - `endpoints` (object, optional): Endpoints

Returns: Promise resolving to the created integration.

#### `getIntegration(integrationId)`

Retrieves an integration by ID.

Parameters:
- `integrationId` (string): Integration ID

Returns: Promise resolving to an integration object.

#### `updateIntegration(integrationId, updateData)`

Updates an integration.

Parameters:
- `integrationId` (string): Integration ID
- `updateData` (object): Update data

Returns: Promise resolving to the updated integration.

#### `deleteIntegration(integrationId)`

Deletes an integration.

Parameters:
- `integrationId` (string): Integration ID

Returns: Promise resolving to a response object.

#### `testIntegration(integrationId)`

Tests an integration connection.

Parameters:
- `integrationId` (string): Integration ID

Returns: Promise resolving to a test result object.

#### `triggerIntegration(integrationId, action, data)`

Triggers an integration action manually.

Parameters:
- `integrationId` (string): Integration ID
- `action` (string): Action to trigger
- `data` (object, optional): Action data

Returns: Promise resolving to an action result object.

### Notifications

#### `getNotifications(options)`

Retrieves notifications for the current user.

Parameters:
- `options` (object, optional):
  - `isRead` (boolean): Filter by read status
  - `type` (string): Filter by notification type
  - `category` (string): Filter by category
  - `priority` (string): Filter by priority
  - `startDate` (string): Filter by start date (ISO string)
  - `endDate` (string): Filter by end date (ISO string)
  - `page` (number): Page number (default: 1)
  - `limit` (number): Results per page (default: 20)

Returns: Promise resolving to an object with notifications and pagination info.

#### `markNotificationAsRead(notificationId)`

Marks a notification as read.

Parameters:
- `notificationId` (string): Notification ID

Returns: Promise resolving to the updated notification.

#### `markAllNotificationsAsRead()`

Marks all notifications as read.

Returns: Promise resolving to a response object.

#### `getNotificationPreferences()`

Retrieves notification preferences for the current user.

Returns: Promise resolving to a preferences object.

#### `updateNotificationPreferences(preferences)`

Updates notification preferences.

Parameters:
- `preferences` (object): Updated preferences

Returns: Promise resolving to the updated preferences.

#### `addDeviceToken(token)`

Adds a device token for push notifications.

Parameters:
- `token` (string): Device token

Returns: Promise resolving to a response object.

#### `removeDeviceToken(token)`

Removes a device token.

Parameters:
- `token` (string): Device token

Returns: Promise resolving to a response object.

## Complete Example

```javascript
import { CybernateAI } from 'cybernate-ai';

async function main() {
  const cybernate = new CybernateAI('YOUR_API_KEY');
  await cybernate.connect();

  // ── Chat ────────────────────────────────────────────────────────────────────
  const { result } = await cybernate.chat([
    { role: 'user', content: 'Explain crop rotation in Yoruba.' }
  ], { maxTokens: 512 });
  console.log(result);

  // ── Persistent conversation ──────────────────────────────────────────────
  const { conversation } = await cybernate.createConversation('Support session');
  const reply1 = await cybernate.sendMessage(conversation._id, 'What symptoms indicate malaria?');
  const reply2 = await cybernate.sendMessage(conversation._id, 'What is the recommended treatment?');
  console.log(reply1.result, reply2.result);

  // Rate a message
  await cybernate.rateMessage(conversation._id, reply1.messageId, 'up');

  // ── Embeddings ───────────────────────────────────────────────────────────
  const { embeddings } = await cybernate.embed([
    'Patient has a fever of 39°C',
    'Mgonjwa ana homa ya 39°C',
  ]);
  console.log('Embedding dimensions:', embeddings[0].length);

  // ── Vision / Object detection ────────────────────────────────────────────
  const { detections } = await cybernate.detectObjects({
    imageUrl: 'https://example.com/farm.jpg',
    confidence: 0.6,
    classes: ['crop', 'pest', 'weed'],
  });
  console.log('Detected:', detections.map(d => d.label));

  // ── List available models ────────────────────────────────────────────────
  const { local, remote } = await cybernate.listModels();
  console.log('Local models:', local.map(m => m.id));

  cybernate.disconnect();
}

main().catch(console.error);
```

## Error Handling

The SDK throws errors when API requests fail. Always wrap calls in try/catch blocks:

```javascript
try {
  await cybernate.watch({
    streamUrl: 'rtsp://camera.example.com/stream1'
  });
} catch (error) {
  console.error('Failed to start watching stream:', error.message);
}
```

## Browser Support

The SDK works in modern browsers and Node.js environments. For older browsers, you may need to use a fetch polyfill.

## License

MIT