@kilwar/sentinel-client-sdk
v0.2.0
Published
Official TypeScript SDK for Sentinel Platform - AI-powered operator orchestration
Maintainers
Readme
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: [email protected]
- Or visit our enterprise portal for onboarding
Installation
npm install @kilwar/sentinel-client-sdk
# or
yarn add @kilwar/sentinel-client-sdk
# or
pnpm add @kilwar/sentinel-client-sdkQuick Start
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:
SENTINEL_API_URL=<your-api-url>
SENTINEL_EMAIL=<your-email>
SENTINEL_PASSWORD=<your-password>Authentication
Basic Login
const client = new SentinelClient({
apiUrl: process.env.SENTINEL_API_URL
});
// Login with credentials
await client.auth.login('[email protected]', 'your-password');
// Check if authenticated
if (client.auth.isAuthenticated()) {
console.log('Logged in!');
}
// Logout
await client.auth.logout();Token Persistence
Browser (localStorage)
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('[email protected]', '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)
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)
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
// 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: '[email protected]',
roleName: 'Viewer'
});Projects
// 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
// 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
// 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
// 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
import {
SentinelClient,
AuthenticationError,
ValidationError,
NotFoundError
} from '@kilwar/sentinel-client-sdk';
try {
await client.auth.login('[email protected]', '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:
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
const client = new SentinelClient({
headers: {
'X-Custom-Header': 'value'
}
});
// Or per request
await client.projects.list({
headers: {
'X-Request-ID': 'abc123'
}
});Debug Mode
const client = new SentinelClient({
debug: true // Logs all HTTP requests/responses
});Custom Timeout
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
// Use the underlying HTTP client for custom endpoints
const httpClient = client.getHttpClient();
const customData = await httpClient.get('/v1/custom-endpoint');Framework Examples
React
// 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
// 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
// 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: [email protected]
License
MIT
