npm package: @kilwar/sentinel-client-sdk
Description: Official TypeScript SDK for Sentinel Platform - AI-powered operator orchestration
Author: Sentinel Platform Team
Latest version: 0.3.0

# Sentinel Client SDK

Official TypeScript SDK for the Sentinel Platform - AI-powered operator orchestration.

## Getting Access

The Sentinel Platform is an enterprise solution with controlled access. To obtain your API endpoint URL and credentials:

- Contact: **support@kilwar.com**
- Or visit our enterprise portal for onboarding

## Installation

```bash
npm install @kilwar/sentinel-client-sdk
# or
yarn add @kilwar/sentinel-client-sdk
# or
pnpm add @kilwar/sentinel-client-sdk
```

## Quick Start

```typescript
import { SentinelClient } from '@kilwar/sentinel-client-sdk';

// API URL is provided during onboarding
const client = new SentinelClient({
  apiUrl: process.env.SENTINEL_API_URL,  // From your .env file
});

// Login with your credentials
await client.auth.login(
  process.env.SENTINEL_EMAIL,
  process.env.SENTINEL_PASSWORD
);

// List tenants
const { data: tenants } = await client.tenants.list();
console.log(`Found ${tenants.length} tenants`);

// List projects in a tenant
const { data: projects } = await client.projects.list('your-tenant-slug');
console.log(`Found ${projects.length} projects`);

// Start a batch
const batch = await client.batches.start('tenant-slug', 'project-slug', {
  trigger: 'manual',
  context: { source: 'sdk' }
});
console.log('Batch started:', batch.id);
```

### Environment Variables

Create a `.env` file:

```bash
SENTINEL_API_URL=<your-api-url>
SENTINEL_EMAIL=<your-email>
SENTINEL_PASSWORD=<your-password>
```

## Authentication

### Basic Login

```typescript
const client = new SentinelClient({
  apiUrl: process.env.SENTINEL_API_URL
});

// Login with credentials
await client.auth.login('your-email@company.com', 'your-password');

// Check if authenticated
if (client.auth.isAuthenticated()) {
  console.log('Logged in!');
}

// Logout
await client.auth.logout();
```

### Token Persistence

#### Browser (localStorage)

```typescript
import { SentinelClient, BrowserTokenStorage } from '@kilwar/sentinel-client-sdk';

const client = new SentinelClient({
  apiUrl: process.env.SENTINEL_API_URL,
  tokenStorage: new BrowserTokenStorage()
});

// Tokens are automatically saved to localStorage
await client.auth.login('your-email@company.com', 'your-password');

// On page reload, tokens are automatically loaded
const client2 = new SentinelClient({
  apiUrl: process.env.SENTINEL_API_URL,
  tokenStorage: new BrowserTokenStorage()
});
// Already authenticated!
```

#### Node.js (File Storage)

```typescript
import { SentinelClient, FileTokenStorage } from '@kilwar/sentinel-client-sdk';

const client = new SentinelClient({
  apiUrl: process.env.SENTINEL_API_URL,
  tokenStorage: new FileTokenStorage('./.tokens.json')
});
```

#### React Native (AsyncStorage)

```typescript
import AsyncStorage from '@react-native-async-storage/async-storage';

const tokenStorage = {
  getAccessToken: () => AsyncStorage.getItem('access_token'),
  getRefreshToken: () => AsyncStorage.getItem('refresh_token'),
  setTokens: (access, refresh) => {
    AsyncStorage.setItem('access_token', access);
    AsyncStorage.setItem('refresh_token', refresh);
  },
  clear: () => {
    AsyncStorage.removeItem('access_token');
    AsyncStorage.removeItem('refresh_token');
  }
};

const client = new SentinelClient({
  tokenStorage
});
```

## Multi-Tenancy

```typescript
// Set default tenant for all requests
client.setTenantId('tenant-123');

// Or override per request
const projects = await client.projects.list({
  tenantId: 'different-tenant'
});

// Invite user to tenant
const invitation = await client.tenants.inviteUser('tenant-id', {
  email: 'user@example.com',
  roleName: 'Viewer'
});
```

## Projects

```typescript
// List all projects
const projects = await client.projects.list();

// Create a project
const project = await client.projects.create({
  name: 'My App',
  description: 'Application monitoring',
  region: 'us-east-1',
  settings: {
    notifications: {
      email: true,
      slack: true
    }
  }
});

// Update project
await client.projects.update(project.id, {
  status: 'paused',
  settings: {
    notifications: {
      email: false
    }
  }
});

// Archive project
await client.projects.archive(project.id);
```

## Operator Chains

```typescript
// Configure operator chain for a project
await client.chains.set(project.id, {
  operators: [
    {
      operatorId: 'op-newrelic',
      config: { apiKey: 'xxx', accountId: '123' }
    },
    {
      operatorId: 'op-datadog',
      config: { apiKey: 'yyy' }
    },
    {
      operatorId: 'op-sentinel-brain',
      config: { model: 'gpt-4' }
    }
  ]
});

// Get current chain
const chain = await client.chains.get(project.id);
console.log(`Chain has ${chain.operators.length} operators`);

// Add operator to chain
await client.chains.addOperator(project.id, {
  operatorId: 'op-slack',
  config: { webhookUrl: 'https://...' }
});
```

## Batch Execution

```typescript
// Start a batch
const batch = await client.batches.create({
  projectId: project.id,
  name: 'Hourly check',
  metadata: {
    triggeredBy: 'scheduler'
  }
});

// Monitor batch status
const status = await client.batches.get(batch.id);
console.log('State:', status.state);

// Control batch execution
await client.batches.pause(batch.id, 'Manual pause');
await client.batches.resume(batch.id);
await client.batches.cancel(batch.id, 'No longer needed');

// Wait for completion
const completed = await client.batches.waitForCompletion(batch.id, {
  pollInterval: 5000, // Check every 5 seconds
  maxWaitTime: 300000 // Max 5 minutes
});
```

## Reports & Results

```typescript
// Get batch report
const report = await client.reports.getForBatch(batch.id);
console.log('Report:', report.status);

// Get operator runs
const runs = await client.reports.getOperatorRuns(batch.id);
runs.data.forEach(run => {
  console.log(`${run.operatorId}: ${run.state} (${run.duration}ms)`);
});

// Get batch statistics
const stats = await client.reports.getBatchStats(batch.id);
console.log('Success rate:', (stats.successful / stats.totalOperators) * 100);

// Check if all succeeded
if (await client.reports.allOperatorsSucceeded(batch.id)) {
  console.log('All operators completed successfully!');
}
```

## Error Handling

```typescript
import {
  SentinelClient,
  AuthenticationError,
  ValidationError,
  NotFoundError
} from '@kilwar/sentinel-client-sdk';

try {
  await client.auth.login('wrong@email.com', 'badpass');
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid credentials');
  }
}

try {
  await client.projects.get('non-existent');
} catch (error) {
  if (error instanceof NotFoundError) {
    console.error('Project not found');
  }
}

try {
  await client.projects.create({
    name: '', // Invalid
    region: 'invalid-region'
  });
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Validation failed:', error.details);
  }
}
```

## TypeScript Support

Full TypeScript support with all types exported:

```typescript
import type {
  Project,
  Batch,
  Operator,
  Chain,
  User,
  Tenant
} from '@kilwar/sentinel-client-sdk';

function processProject(project: Project): void {
  console.log(project.name);
  console.log(project.region);
  console.log(project.settings?.notifications?.email);
}
```

## Advanced Usage

### Custom Headers

```typescript
const client = new SentinelClient({
  headers: {
    'X-Custom-Header': 'value'
  }
});

// Or per request
await client.projects.list({
  headers: {
    'X-Request-ID': 'abc123'
  }
});
```

### Debug Mode

```typescript
const client = new SentinelClient({
  debug: true // Logs all HTTP requests/responses
});
```

### Custom Timeout

```typescript
const client = new SentinelClient({
  timeout: 60000 // 60 seconds
});

// Or per request
await client.batches.create(data, {
  timeout: 120000 // 2 minutes for this request
});
```

### Direct API Access

```typescript
// Use the underlying HTTP client for custom endpoints
const httpClient = client.getHttpClient();
const customData = await httpClient.get('/v1/custom-endpoint');
```

## Framework Examples

### React

```typescript
// hooks/useSentinel.ts
import { useState, useEffect } from 'react';
import { SentinelClient, BrowserTokenStorage } from '@kilwar/sentinel-client-sdk';

export function useSentinel() {
  const [client] = useState(() => new SentinelClient({
    apiUrl: process.env.REACT_APP_SENTINEL_API,
    tokenStorage: new BrowserTokenStorage()
  }));

  const [isAuthenticated, setIsAuthenticated] = useState(false);

  useEffect(() => {
    setIsAuthenticated(client.isAuthenticated());
  }, [client]);

  return { client, isAuthenticated };
}

// components/ProjectList.tsx
function ProjectList() {
  const { client } = useSentinel();
  const [projects, setProjects] = useState([]);

  useEffect(() => {
    client.projects.list().then(result => {
      setProjects(result.data);
    });
  }, [client]);

  return (
    <ul>
      {projects.map(p => <li key={p.id}>{p.name}</li>)}
    </ul>
  );
}
```

### Vue 3

```typescript
// composables/useSentinel.ts
import { ref, readonly } from 'vue';
import { SentinelClient, BrowserTokenStorage } from '@kilwar/sentinel-client-sdk';

const client = new SentinelClient({
  apiUrl: import.meta.env.VITE_SENTINEL_API,
  tokenStorage: new BrowserTokenStorage()
});

const isAuthenticated = ref(client.isAuthenticated());

export function useSentinel() {
  const login = async (email: string, password: string) => {
    await client.auth.login(email, password);
    isAuthenticated.value = true;
  };

  const logout = async () => {
    await client.auth.logout();
    isAuthenticated.value = false;
  };

  return {
    client,
    isAuthenticated: readonly(isAuthenticated),
    login,
    logout
  };
}
```

### Next.js

```typescript
// lib/sentinel.ts
import { SentinelClient } from '@kilwar/sentinel-client-sdk';

export function getSentinelClient(accessToken?: string) {
  return new SentinelClient({
    apiUrl: process.env.SENTINEL_API_URL,
    accessToken
  });
}

// pages/api/projects.ts
export default async function handler(req, res) {
  const client = getSentinelClient(req.cookies.token);

  try {
    const projects = await client.projects.list();
    res.json(projects);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
}
```

## API Reference

Full API documentation available at: https://docs.sentinel.dev/sdk

## Support

- GitHub Issues: https://github.com/KilwarCom/sentinel-platform/issues
- Documentation: https://docs.sentinel.dev
- Email: support@sentinel.dev

## License

MIT