TypeScript SDK¶
The @limacharlie/ai-sessions package provides a TypeScript SDK for interacting with the AI Sessions Platform.
Installation¶
npm install @limacharlie/ai-sessions
# or
yarn add @limacharlie/ai-sessions
# or
pnpm add @limacharlie/ai-sessions
For Node.js environments, you also need the ws package:
Quick Start¶
import { createClient, createSessionWebSocket } from '@limacharlie/ai-sessions';
// Create REST client
const client = createClient({
baseUrl: 'https://ai-sessions.limacharlie.io',
token: 'your-limacharlie-jwt-token',
});
// Register user (first time only)
await client.register();
// Store your Anthropic API key
await client.storeAPIKey('sk-ant-api03-xxxxx');
// Create a session
const { session } = await client.createSession({
allowed_tools: ['Bash', 'Read', 'Write'],
});
console.log('Session created:', session.id);
// Connect via WebSocket for real-time communication
const ws = createSessionWebSocket(
client.getWebSocketURL(session.id),
{
onAssistant: (msg) => {
console.log('Claude:', msg.content);
},
onToolUse: (msg) => {
console.log('Tool:', msg.data.tool_name, msg.data.input);
},
onError: (err) => {
console.error('Error:', err);
},
onSessionEnd: (msg) => {
console.log('Session ended:', msg.data.reason);
},
onConnectionChange: (state) => {
console.log('Connection:', state);
},
}
);
await ws.connect();
// Send a prompt
ws.sendPrompt('Hello! List the files in the current directory.');
// Later, disconnect
ws.disconnect();
Features¶
- REST API Client: Full coverage of the AI Sessions API
- WebSocket Client: Real-time communication with automatic reconnection
- File Transfer: Upload and download files to/from sessions
- TypeScript Support: Full type definitions included
- Node.js & Browser: Works in both environments
REST Client¶
Configuration¶
import { createClient } from '@limacharlie/ai-sessions';
const client = createClient({
baseUrl: 'https://ai-sessions.limacharlie.io',
token: 'your-jwt-token',
timeout: 30000, // optional, default 30s
retry: {
maxRetries: 3,
retryDelay: 1000,
retryOn: [429, 502, 503, 504],
},
});
Registration¶
// Register for AI Sessions
await client.register();
// Deregister (deletes all data)
await client.deregister();
Sessions¶
// List all sessions
const { sessions } = await client.listSessions();
// List running sessions only
const { sessions } = await client.listSessions({ status: 'running' });
// Create a session
const { session } = await client.createSession({
allowed_tools: ['Bash', 'Read', 'Write'],
denied_tools: ['WebFetch'],
});
// Get session details
const { session } = await client.getSession(sessionId);
// Terminate a session
await client.terminateSession(sessionId);
// Delete session record (after termination)
await client.deleteSessionRecord(sessionId);
Credentials¶
// Store Anthropic API key
await client.storeAPIKey('sk-ant-api03-xxxxx');
// Check credential status
const status = await client.getCredentialStatus();
console.log(status.has_credentials); // true/false
console.log(status.credential_type); // 'api_key' or 'oauth_token'
// Delete stored credentials
await client.deleteCredentials();
OAuth Flow¶
// Start OAuth flow
const { oauth_session_id } = await client.startOAuth();
// Poll for OAuth URL
const response = await client.pollOAuthURL(oauth_session_id);
if (response.status === 'url_ready') {
console.log('Visit:', response.url);
}
// After user authorizes, submit the code
await client.submitOAuthCode(oauth_session_id, authorizationCode);
Profiles¶
// List profiles
const { profiles } = await client.listProfiles();
// Create a profile
const { profile } = await client.createProfile({
name: 'Investigation',
description: 'Profile for security investigations',
allowed_tools: ['Bash', 'Read', 'Grep'],
denied_tools: ['Write', 'Edit'],
max_turns: 100,
max_budget_usd: 10.0,
});
// Get profile
const { profile } = await client.getProfile(profileId);
// Update profile
await client.updateProfile(profileId, {
name: 'Updated Investigation',
max_turns: 150,
});
// Delete profile
await client.deleteProfile(profileId);
// Set as default
await client.setDefaultProfile(profileId);
// Capture session settings as profile
await client.captureProfile(sessionId, {
name: 'My Session Config',
});
File Transfer (REST)¶
// Request upload URL
const { upload_url, upload_id, target_path } = await client.requestUploadURL(
sessionId,
{
filename: 'data.csv',
content_type: 'text/csv',
size: 1024,
}
);
// Upload using the URL (use fetch or your preferred HTTP client)
await fetch(upload_url, {
method: 'PUT',
body: fileContent,
headers: { 'Content-Type': 'text/csv' },
});
// Notify upload complete
await client.notifyUploadComplete(sessionId, upload_id);
// Request download URL
const { download_url } = await client.requestDownloadURL(sessionId, {
path: '/workspace/output.txt',
});
// Download using the URL
const response = await fetch(download_url);
const content = await response.text();
WebSocket Client¶
Configuration¶
import { createSessionWebSocket } from '@limacharlie/ai-sessions';
const ws = createSessionWebSocket(
client.getWebSocketURL(sessionId),
{
// Message handlers
onMessage: (msg) => { /* any message */ },
onAssistant: (msg) => { /* Claude response */ },
onToolUse: (msg) => { /* tool being used */ },
onToolResult: (msg) => { /* tool result */ },
onUser: (msg) => { /* user message echo */ },
onSystem: (msg) => { /* system message */ },
onResult: (msg) => { /* final result */ },
onError: (err) => { /* error */ },
onSessionEnd: (msg) => { /* session ended */ },
onConnectionChange: (state) => { /* connection state changed */ },
},
{
// Options
autoReconnect: true,
maxReconnectAttempts: 5,
reconnectDelay: 1000,
heartbeatInterval: 30000,
}
);
Connection¶
// Connect
await ws.connect();
// Check connection state
console.log(ws.getState()); // 'connecting', 'connected', 'disconnected'
// Disconnect
ws.disconnect();
Sending Messages¶
// Send a prompt
ws.sendPrompt('Write a hello world in Python');
// Interrupt current operation
ws.sendInterrupt();
// Send heartbeat (usually handled automatically)
ws.sendHeartbeat();
File Transfer (WebSocket)¶
// Request upload URL
ws.requestUpload({
request_id: 'req_123',
filename: 'data.csv',
content_type: 'text/csv',
size: 1024,
});
// Listen for upload_url response in onMessage handler
// Notify upload complete
ws.notifyUploadComplete({
request_id: 'req_123',
filename: 'data.csv',
path: '/workspace/uploads/data.csv',
});
// Request download URL
ws.requestDownload({
request_id: 'req_456',
path: '/workspace/output.txt',
});
File Transfer Helper¶
The SDK provides a convenience wrapper for file transfers:
import { createFileTransfer, createWebSocketFileTransfer } from '@limacharlie/ai-sessions';
// REST-based file transfer
const fileTransfer = createFileTransfer(client);
// Upload a file
const path = await fileTransfer.uploadFile(
sessionId,
file, // File or Blob
'document.pdf',
{
onProgress: (progress) => console.log(`${progress}%`),
}
);
// Download a file
const blob = await fileTransfer.downloadFromURL(downloadUrl);
// WebSocket-based file transfer
const wsFileTransfer = createWebSocketFileTransfer(ws);
await wsFileTransfer.uploadFile(file, 'data.csv');
const blob = await wsFileTransfer.downloadFile('/output/result.txt');
Node.js Usage¶
For Node.js, provide WebSocket implementation:
import { createClient, createSessionWebSocket } from '@limacharlie/ai-sessions';
import WebSocket from 'ws';
const client = createClient({
baseUrl: 'https://ai-sessions.limacharlie.io',
token: 'your-jwt-token',
fetch: globalThis.fetch, // Node 18+ has native fetch
});
const ws = createSessionWebSocket(
client.getWebSocketURL(sessionId),
handlers,
options,
WebSocket as unknown as typeof globalThis.WebSocket
);
Types¶
All types are exported from the main package:
import type {
// Client types
AISessionsClient,
AISessionsConfig,
// Session types
Session,
SessionStatus,
CreateSessionRequest,
LCCredentials,
// Profile types
Profile,
CreateProfileRequest,
MCPServerConfig,
// WebSocket types
WebSocketMessage,
AssistantMessage,
ToolUseMessage,
ToolResultMessage,
WebSocketOptions,
ConnectionState,
// File transfer types
UploadRequest,
UploadResponse,
DownloadRequest,
DownloadResponse,
} from '@limacharlie/ai-sessions';
Error Handling¶
import { APIError } from '@limacharlie/ai-sessions';
try {
await client.createSession({});
} catch (error) {
if ('error' in error && 'message' in error) {
const apiError = error as APIError;
console.error(`API Error: ${apiError.error} - ${apiError.message}`);
// Handle specific errors
switch (apiError.status) {
case 401:
console.error('Authentication failed');
break;
case 403:
console.error('Not registered or no credentials');
break;
case 409:
console.error('Max sessions reached');
break;
case 429:
console.error('Rate limited');
break;
}
}
}
Complete Example¶
Here's a complete example showing a typical workflow:
import { createClient, createSessionWebSocket } from '@limacharlie/ai-sessions';
import WebSocket from 'ws';
async function main() {
// Create client
const client = createClient({
baseUrl: 'https://ai-sessions.limacharlie.io',
token: process.env.LC_JWT!,
});
// Check if registered, register if not
try {
await client.getCredentialStatus();
} catch (e) {
console.log('Registering...');
await client.register();
await client.storeAPIKey(process.env.ANTHROPIC_KEY!);
}
// Create session
console.log('Creating session...');
const { session } = await client.createSession({
allowed_tools: ['Bash', 'Read', 'Grep', 'Glob'],
denied_tools: ['Write', 'Edit'],
});
console.log('Session ID:', session.id);
// Wait for session to be running
let status = session.status;
while (status === 'pending') {
await new Promise(r => setTimeout(r, 1000));
const resp = await client.getSession(session.id);
status = resp.session.status;
}
if (status !== 'running') {
throw new Error(`Session failed to start: ${status}`);
}
// Connect via WebSocket
console.log('Connecting...');
const ws = createSessionWebSocket(
client.getWebSocketURL(session.id),
{
onAssistant: (msg) => {
for (const content of msg.payload.content) {
if (content.type === 'text') {
process.stdout.write(content.text);
}
}
},
onToolUse: (msg) => {
console.log(`\n[Using ${msg.payload.name}]`);
},
onToolResult: (msg) => {
console.log(`[Result: ${msg.payload.content.substring(0, 100)}...]`);
},
onSessionEnd: (msg) => {
console.log(`\nSession ended: ${msg.payload.reason}`);
process.exit(0);
},
onError: (err) => {
console.error('Error:', err);
},
},
{ autoReconnect: true },
WebSocket as unknown as typeof globalThis.WebSocket
);
await ws.connect();
console.log('Connected!');
// Send prompt
ws.sendPrompt('Find all Python files in /workspace and show their first 10 lines');
// Keep alive
process.on('SIGINT', async () => {
console.log('\nTerminating session...');
ws.disconnect();
await client.terminateSession(session.id);
process.exit(0);
});
}
main().catch(console.error);
License¶
MIT