@superatomai/sdk-node
v0.0.62
Published
Node.js TypeScript SDK for Superatom
Readme
@superatomai/sdk-node
A TypeScript/Node.js SDK for building AI-powered data applications with Superatom - a platform for creating data-driven, intelligent applications with real-time WebSocket communication, LLM integration, and comprehensive user management.
Features
- WebSocket Communication - Real-time bidirectional messaging with automatic reconnection
- AI-Powered Component Generation - Automatically generate dashboard components and visualizations from user questions
- Intelligent Text Responses - LLM-powered conversational responses with SQL query execution and retry logic
- Component Matching & Classification - Smart component selection based on question type and visualization needs
- Collection Handlers - Register custom data operation handlers (CRUD, queries, mutations)
- User Management - Built-in authentication and user storage with file-based persistence
- Dashboard & Report Management - Create and manage dashboards and reports with DSL-based rendering
- Multi-Provider LLM Integration - Unified interface for Anthropic Claude and Groq models with automatic fallback
- Thread & UI Block Management - Organize conversations and UI components with automatic cleanup
- Log Collection - Capture and send runtime logs to the UI with configurable log levels
- Prompt Loader - Load and cache custom prompts from the file system with template variable support
- Database Schema Management - Automatic schema documentation generation for LLM context
- Cleanup Service - Automatic memory management and old data removal
- TypeScript First - Full type safety with comprehensive type definitions
Installation
npm install @superatomai/sdk-nodeOr with pnpm:
pnpm add @superatomai/sdk-nodeQuick Start
import { SuperatomSDK } from '@superatomai/sdk-node';
// Initialize the SDK
const sdk = new SuperatomSDK({
apiKey: 'your-api-key',
projectId: 'your-project-id',
userId: 'user-123', // optional, defaults to 'anonymous'
type: 'data-agent', // optional, defaults to 'data-agent'
});
// The SDK automatically connects to the Superatom WebSocket service
// Wait for connection before using
await sdk.connect();
// Register a collection handler for data operations
sdk.addCollection('users', 'getMany', async (params) => {
return {
data: [
{ id: 1, name: 'John Doe', email: '[email protected]' },
{ id: 2, name: 'Jane Smith', email: '[email protected]' },
],
};
});
// Listen to messages
sdk.onMessage((message) => {
console.log('Received:', message.type);
});
// Cleanup when done
await sdk.destroy();Configuration
SuperatomSDKConfig
interface SuperatomSDKConfig {
apiKey: string; // Required: Your Superatom API key
projectId: string; // Required: Your project ID
userId?: string; // Optional: User identifier (default: 'anonymous')
type?: string; // Optional: Agent type (default: 'data-agent')
url?: string; // Optional: Custom WebSocket URL
bundleDir?: string; // Optional: Directory for bundle requests
promptsDir?: string; // Optional: Custom prompts directory (default: .prompts)
ANTHROPIC_API_KEY?: string; // Optional: Anthropic API key for LLM
GROQ_API_KEY?: string; // Optional: Groq API key for LLM
LLM_PROVIDERS?: LLMProvider[]; // Optional: Custom LLM providers
logLevel?: LogLevel; // Optional: Log level (errors, warnings, info, verbose) (default: 'info')
}Environment Variables
SA_WEBSOCKET_URL- WebSocket URL (default:wss://ws.superatom.ai/websocket)ANTHROPIC_API_KEY- Anthropic API key for Claude modelsGROQ_API_KEY- Groq API key for open-source modelsSUPERATOM_LOG_LEVEL- Log level for SDK logging (errors, warnings, info, verbose) (default: 'info')
Core Features
1. Collection Handlers
Register custom handlers for data operations. Supports standard CRUD operations and custom operations.
// Register a getMany handler
sdk.addCollection<ParamsType, ResultType>(
'products',
'getMany',
async (params) => {
// params includes filters, pagination, etc.
const products = await database.products.find(params);
return { data: products };
}
);
// Register a createOne handler
sdk.addCollection('products', 'createOne', async (params) => {
const newProduct = await database.products.create(params);
return { data: newProduct };
});
// Register a custom query handler
sdk.addCollection('analytics', 'query', async (params) => {
const results = await runAnalyticsQuery(params);
return { data: results };
});Supported Operations:
getMany- Fetch multiple recordsgetOne- Fetch single recordcreateOne- Create a recordupdateOne- Update a recorddeleteOne- Delete a recordquery- Custom queriesmutation- Custom mutations
2. Message Handling
Listen to all messages or specific message types:
// Listen to all messages
const unsubscribe = sdk.onMessage((message) => {
console.log('Message:', message.type, message.payload);
});
// Listen to specific message types
sdk.onMessageType('DATA_REQ', (message) => {
console.log('Data request received:', message.payload);
});
// Unsubscribe when needed
unsubscribe();
// Send messages
sdk.send({
type: 'CUSTOM_MESSAGE',
from: { id: 'sdk', type: 'agent' },
payload: { data: 'Hello' },
});Built-in Message Types:
DATA_REQ- Data request from runtimeBUNDLE_REQ- Bundle/asset requestAUTH_LOGIN_REQ- Authentication login requestAUTH_VERIFY_REQ- Token verification requestUSER_PROMPT_REQ- User prompt for LLM processingUSER_PROMPT_SUGGESTIONS_REQ- Request for prompt suggestionsACTIONS- Component actions requestCOMPONENT_LIST_RES- Available components listUSERS- User management operationsDASHBOARDS- Dashboard CRUD operationsREPORTS- Report CRUD operations
3. User Management
Built-in user authentication and management with file-based storage:
const userManager = sdk.getUserManager();
// Create a user
await userManager.createUser({
username: 'john_doe',
password: 'secure_password',
});
// Get a user
const user = await userManager.getUser('john_doe');
// Update a user
await userManager.updateUser('john_doe', {
password: 'new_password',
});
// Delete a user
await userManager.deleteUser('john_doe');
// Get all users
const users = await userManager.getAllUsers();Features:
- Automatic password hashing with bcrypt
- File-based storage (JSON)
- Token-based authentication
- Auto-save on changes
- Memory management with configurable limits
4. Dashboard Management
Create and manage dashboards with DSL-based rendering:
const dashboardManager = sdk.getDashboardManager();
// Create a dashboard
const dashboard = {
id: 'dashboard-1',
title: 'Sales Dashboard',
description: 'Overview of sales metrics',
dsl: {
type: 'container',
children: [
{ type: 'chart', props: { chartType: 'line', data: [...] } },
{ type: 'table', props: { columns: [...], data: [...] } },
],
},
};
await dashboardManager.createDashboard(dashboard);
// Get a dashboard
const retrieved = await dashboardManager.getDashboard('dashboard-1');
// Update a dashboard
await dashboardManager.updateDashboard('dashboard-1', {
title: 'Updated Sales Dashboard',
});
// Delete a dashboard
await dashboardManager.deleteDashboard('dashboard-1');
// Get all dashboards
const allDashboards = await dashboardManager.getAllDashboards();5. Report Management
Similar to dashboards, but for reports:
const reportManager = sdk.getReportManager();
// Create a report
const report = {
id: 'report-1',
title: 'Monthly Report',
description: 'Monthly performance report',
dsl: {
type: 'report',
sections: [
{ type: 'summary', content: '...' },
{ type: 'charts', data: [...] },
],
},
};
await reportManager.createReport(report);
// CRUD operations work the same as dashboards
const retrieved = await reportManager.getReport('report-1');
await reportManager.updateReport('report-1', { title: 'Q1 Report' });
await reportManager.deleteReport('report-1');
const allReports = await reportManager.getAllReports();6. LLM Integration
Unified interface for multiple LLM providers with streaming support:
import { LLM } from '@superatomai/sdk-node';
// Text generation
const response = await LLM.text(
{
sys: 'You are a helpful assistant.',
user: 'What is the meaning of life?',
},
{
model: 'anthropic/claude-sonnet-4-5', // or 'groq/llama3-70b'
apiKey: 'your-api-key',
maxTokens: 1000,
temperature: 0.7,
}
);
// Streaming responses
const result = await LLM.stream(
{
sys: 'You are a storyteller.',
user: 'Tell me a short story.',
},
{
model: 'anthropic/claude-sonnet-4-5',
apiKey: 'your-api-key',
partial: (chunk) => {
// Called for each chunk
process.stdout.write(chunk);
},
}
);
// JSON output
const jsonResult = await LLM.stream(
{
sys: 'Return a JSON object with user data.',
user: 'Create a user profile for John Doe.',
},
{
model: 'groq/llama3-70b',
apiKey: 'your-api-key',
},
true // Enable JSON parsing
);Supported Models:
- Anthropic:
claude-sonnet-4-5,claude-opus-4, etc. - Groq:
llama3-70b,mixtral-8x7b, etc.
Model Format:
- With provider:
anthropic/model-nameorgroq/model-name - Without provider: Defaults to Anthropic
7. AI-Powered User Response System
The SDK includes a powerful AI system for generating intelligent responses to user questions with two modes: component generation and text responses.
Component Generation Mode
Automatically match and generate dashboard components based on user questions:
import { get_user_response } from '@superatomai/sdk-node/userResponse';
const components = [
{ id: 'sales-chart', name: 'SalesChart', type: 'BarChart', /* ... */ },
{ id: 'kpi-card', name: 'RevenueKPI', type: 'KPICard', /* ... */ },
// ... more components
];
const result = await get_user_response(
'Show me sales by region',
components,
anthropicApiKey,
groqApiKey,
['anthropic', 'groq'], // Provider fallback order
logCollector,
conversationHistory,
'component' // Component generation mode
);
if (result.success) {
console.log('Generated component:', result.data.component);
console.log('Reasoning:', result.data.reasoning);
}Features:
- Question Classification - Automatically determines question type (analytical, data_modification, general)
- Visualization Type Detection - Identifies required visualization types (charts, tables, KPIs)
- Multi-Component Dashboards - Generates multiple components for comprehensive analysis
- Props Modification - Intelligently modifies component props including SQL queries
- SQL Query Validation - Ensures queries have proper LIMIT clauses and fixes scalar subqueries
Text Response Mode
Generate conversational text responses with SQL query execution:
const result = await get_user_response(
'What were the top 5 selling products last month?',
components,
anthropicApiKey,
groqApiKey,
['anthropic', 'groq'],
logCollector,
conversationHistory,
'text', // Text response mode
(chunk) => {
// Stream text chunks in real-time
process.stdout.write(chunk);
},
collections // Required for query execution
);
if (result.success) {
console.log('Text response:', result.data.text);
console.log('Matched components:', result.data.matchedComponents);
console.log('Container component:', result.data.component);
}Features:
- SQL Query Execution - Automatically generates and executes SQL queries via tool calling
- Automatic Retry Logic - Up to 6 retry attempts with query correction on errors
- Streaming Responses - Real-time text streaming with query execution status updates
- Component Suggestions - Parses component suggestions from text and matches with available components
- Layout Discovery - Automatically selects appropriate dashboard layouts based on component metadata
- Performance Tracking - Measures and logs total time taken for request processing
Using BaseLLM Classes Directly
For more control, use the BaseLLM implementations directly:
import { anthropicLLM, groqLLM } from '@superatomai/sdk-node/userResponse';
// Classify user question
const classification = await anthropicLLM.classifyUserQuestion(
'Show me sales trends',
apiKey,
logCollector,
conversationHistory
);
console.log('Question type:', classification.questionType);
console.log('Visualizations needed:', classification.visualizations);
// Generate analytical component
const result = await anthropicLLM.generateAnalyticalComponent(
'Show me sales by region',
components,
'BarChart', // Preferred visualization type
apiKey,
logCollector,
conversationHistory
);
// Match existing component
const matchResult = await anthropicLLM.matchComponent(
'Update the sales dashboard',
components,
apiKey,
logCollector,
conversationHistory
);
// Generate next questions
const nextQuestions = await anthropicLLM.generateNextQuestions(
originalPrompt,
generatedComponent,
componentData,
apiKey,
logCollector,
conversationHistory
);BaseLLM Methods:
handleUserRequest()- Main orchestration method (supports both component and text modes)classifyUserQuestion()- Classify question type and identify visualizationsgenerateAnalyticalComponent()- Generate single analytical componentgenerateMultipleAnalyticalComponents()- Generate multiple components in parallelmatchComponent()- Match and modify existing componentvalidateAndModifyProps()- Validate and modify component propsgenerateTextResponse()- Generate text with tool calling supportmatchComponentsFromTextResponse()- Match components from text suggestionsgenerateNextQuestions()- Generate follow-up question suggestions
8. Prompt Loader System
The SDK includes a sophisticated prompt loading system with caching and template variable support:
import { promptLoader } from '@superatomai/sdk-node/userResponse';
// Initialize with custom directory (default: .prompts)
const sdk = new SuperatomSDK({
apiKey: 'your-api-key',
projectId: 'your-project-id',
promptsDir: './my-custom-prompts',
});
// Prompts are automatically loaded and cached on initialization
// Access prompt cache size
const cacheSize = promptLoader.getCacheSize();
console.log(`Loaded ${cacheSize} prompts`);
// Load specific prompts with variables
const prompts = await promptLoader.loadPrompts('classify', {
USER_PROMPT: userQuestion,
CONVERSATION_HISTORY: history || 'No previous conversation'
});
console.log('System prompt:', prompts.system);
console.log('User prompt:', prompts.user);Prompt Directory Structure:
.prompts/
├── classify/
│ ├── system.md # System prompt for classification
│ └── user.md # User prompt template
├── match-component/
│ ├── system.md
│ └── user.md
├── modify-props/
│ ├── system.md
│ └── user.md
├── text-response/
│ ├── system.md
│ └── user.md
└── match-text-components/
├── system.md
└── user.mdTemplate Variables:
Variables in prompts are replaced using the {{VARIABLE_NAME}} syntax:
# system.md
You are analyzing this question: {{USER_PROMPT}}
Previous conversation:
{{CONVERSATION_HISTORY}}
Available components:
{{AVAILABLE_COMPONENTS}}Built-in Prompt Types:
classify- Question classification and visualization type detectionmatch-component- Component matching and selectionmodify-props- Props validation and modificationsingle-component- Single analytical component generationtext-response- Text response with tool callingmatch-text-components- Component matching from text suggestionscontainer-metadata- Container title and description generationactions- Next question generation
9. Thread & UI Block Management
Organize conversations and UI components:
import { Thread, UIBlock, ThreadManager } from '@superatomai/sdk-node';
const threadManager = ThreadManager.getInstance();
// Create a thread
const thread = threadManager.createThread({
userId: 'user-123',
metadata: { source: 'chat' },
});
// Add UI blocks
const block1 = new UIBlock(
'block-1',
'text',
{ content: 'Hello!' }
);
thread.addBlock(block1);
const block2 = new UIBlock(
'block-2',
'table',
{
columns: ['Name', 'Age'],
data: [['John', 30], ['Jane', 25]]
}
);
thread.addBlock(block2);
// Get thread
const retrieved = threadManager.getThread(thread.getId());
// Get all threads
const allThreads = threadManager.getAllThreads();
// Delete thread
threadManager.deleteThread(thread.getId());UI Block Types:
text- Text contenttable- Tabular datachart- Charts and visualizationsform- Interactive forms- Custom types as needed
10. Logging System
The SDK includes a comprehensive logging system with environment-based log levels for both terminal and UI log collection.
Log Levels
The SDK supports hierarchical log levels:
errors- Only error logs are shownwarnings- Warning and error logs are showninfo- Info, warning, and error logs are shown (default)verbose- All logs including debug messages are shown
Configuring Log Level
You can set the log level in three ways:
1. Via environment variable (recommended for deployment):
export SUPERATOM_LOG_LEVEL=verbose
node your-app.js2. Via SDK configuration (overrides environment variable):
import { SuperatomSDK } from '@superatomai/sdk-node';
const sdk = new SuperatomSDK({
apiKey: 'your-api-key',
projectId: 'your-project-id',
logLevel: 'verbose', // errors | warnings | info | verbose
});3. Programmatically at runtime:
import { logger } from '@superatomai/sdk-node';
// Change log level at runtime
logger.setLogLevel('verbose');
// Get current log level
const currentLevel = logger.getLogLevel(); // returns 'verbose'Using the Logger
import { logger } from '@superatomai/sdk-node';
// These will be filtered based on the configured log level
logger.error('Critical error occurred'); // Shown at all levels
logger.warn('Something might be wrong'); // Hidden when level is 'errors'
logger.info('Processing completed'); // Hidden when level is 'errors' or 'warnings'
logger.debug('Detailed debug information'); // Only shown when level is 'verbose'UI Log Collection
The UILogCollector also respects the log level configuration. Logs are sent to the frontend and displayed in the terminal based on the configured level.
import { UILogCollector } from '@superatomai/sdk-node';
const collector = new UILogCollector(
clientId,
(msg) => sdk.send(msg),
'uiblock-123'
);
// These logs are filtered based on log level before being sent to UI
collector.error('Error message'); // Always sent
collector.warn('Warning message'); // Sent unless level is 'errors'
collector.info('Info message'); // Sent unless level is 'errors' or 'warnings'
collector.debug('Debug message'); // Only sent when level is 'verbose'
// Get all collected logs
const logs = collector.getLogs();Note: The log level affects both terminal output and UI log collection, ensuring consistent logging behavior across your application.
11. Cleanup Service
Automatic memory management for threads and UI blocks:
import { CleanupService } from '@superatomai/sdk-node';
const cleanupService = CleanupService.getInstance();
// Start automatic cleanup (runs every 24 hours by default)
cleanupService.startAutoCleanup(24);
// Manual cleanup
const stats = cleanupService.runFullCleanup();
console.log('Cleanup stats:', stats);
// Output: { threadsDeleted: 5, uiblocksDeleted: {...}, dataCleared: 10 }
// Get memory statistics
const memStats = cleanupService.getMemoryStats();
console.log('Memory:', memStats);
// Output: { threadCount: 42, totalUIBlocks: 156, avgUIBlocksPerThread: 3.7 }
// Stop automatic cleanup
cleanupService.stopAutoCleanup();Configuration:
import { STORAGE_CONFIG } from '@superatomai/sdk-node';
// Thread retention (default: 30 days)
STORAGE_CONFIG.THREAD_RETENTION_DAYS = 60;
// UI block retention (default: 7 days)
STORAGE_CONFIG.UIBLOCK_RETENTION_DAYS = 14;
// Max component data size (default: 100KB)
STORAGE_CONFIG.MAX_COMPONENT_DATA_SIZE = 200 * 1024;API Reference
SuperatomSDK
Methods
connect(): Promise<void>- Connect to WebSocket servicedisconnect(): void- Disconnect from WebSocketdestroy(): Promise<void>- Cleanup and disconnect permanentlyisConnected(): boolean- Check connection statussend(message: Message): void- Send a messageonMessage(handler): () => void- Register message handler (returns unsubscribe function)onMessageType(type, handler): () => void- Register type-specific handleraddCollection(name, operation, handler): void- Register collection handlergetUserManager(): UserManager- Get user manager instancegetDashboardManager(): DashboardManager- Get dashboard manager instancegetReportManager(): ReportManager- Get report manager instance
UserManager
Methods
createUser(data): Promise<User>- Create a new usergetUser(username): Promise<User | null>- Get user by usernameupdateUser(username, data): Promise<User>- Update userdeleteUser(username): Promise<boolean>- Delete usergetAllUsers(): Promise<User[]>- Get all usersverifyPassword(username, password): Promise<boolean>- Verify passwordgenerateToken(username): Promise<string>- Generate auth tokenverifyToken(token): Promise<User | null>- Verify auth token
DashboardManager
Methods
createDashboard(dashboard): Promise<DSLRendererProps>- Create dashboardgetDashboard(id): Promise<DSLRendererProps | null>- Get dashboardupdateDashboard(id, updates): Promise<DSLRendererProps>- Update dashboarddeleteDashboard(id): Promise<boolean>- Delete dashboardgetAllDashboards(): Promise<DSLRendererProps[]>- Get all dashboards
ReportManager
Same methods as DashboardManager but for reports.
LLM (Static Class)
Methods
text(messages, options): Promise<string>- Generate text responsestream(messages, options, json?): Promise<string | object>- Stream response
ThreadManager
Methods
getInstance(): ThreadManager- Get singleton instancecreateThread(options): Thread- Create new threadgetThread(id): Thread | undefined- Get thread by IDgetAllThreads(): Thread[]- Get all threadsdeleteThread(id): boolean- Delete thread
CleanupService
Methods
getInstance(): CleanupService- Get singleton instancestartAutoCleanup(intervalHours?): void- Start automatic cleanupstopAutoCleanup(): void- Stop automatic cleanuprunFullCleanup(): CleanupStats- Run manual cleanupgetMemoryStats(): MemoryStats- Get current memory statistics
UILogCollector
Methods
start(): void- Start collecting logsstop(): void- Stop collectingclear(): void- Clear collected logsgetLogs(): CapturedLog[]- Get all logsaddLog(log): void- Add custom logcreateMessage(uiBlockId): UILogsMessage- Create message for SDK
Advanced Usage
Custom Message Handlers
// Handle custom message types
sdk.onMessageType('CUSTOM_EVENT', async (message) => {
console.log('Custom event:', message.payload);
// Process and respond
sdk.send({
type: 'CUSTOM_RESPONSE',
from: { id: 'sdk', type: 'agent' },
payload: { result: 'processed' },
});
});Error Handling
try {
await sdk.connect();
} catch (error) {
console.error('Connection failed:', error);
}
// Handle WebSocket errors
sdk.onMessageType('error', (message) => {
console.error('Error message:', message.payload);
});Reconnection
The SDK automatically handles reconnection with exponential backoff:
- Max attempts: 5
- Delay: 1s, 2s, 4s, 8s, 10s (capped at 10s)
Bundle Requests
Serve static files via bundle requests:
const sdk = new SuperatomSDK({
apiKey: 'your-api-key',
projectId: 'your-project-id',
bundleDir: './public', // Directory to serve files from
});
// Files in ./public will be served when requestedTypeScript Support
This SDK is written in TypeScript and includes full type definitions. All exports are fully typed for the best development experience.
import type {
Message,
IncomingMessage,
SuperatomSDKConfig,
CollectionHandler,
CollectionOperation,
User,
UsersData,
Component,
T_RESPONSE,
LLMProvider,
LogLevel,
CapturedLog,
Action,
} from '@superatomai/sdk-node';
// Import LLM and utility classes
import {
LLM,
UserManager,
UILogCollector,
Thread,
UIBlock,
ThreadManager,
CleanupService,
logger,
} from '@superatomai/sdk-node';
// Import user response utilities
import {
get_user_response,
anthropicLLM,
groqLLM,
} from '@superatomai/sdk-node/userResponse';Examples
Check out the examples directory for complete examples:
- Basic WebSocket communication
- Data collection handlers
- User authentication flow
- LLM integration with streaming
- AI-powered component generation
- Text response with query execution
- Component matching and classification
- Thread management
- Dashboard creation
- Prompt customization
Development
# Install dependencies
pnpm install
# Build the SDK
pnpm run build
# Watch mode
pnpm run dev
# Run tests
pnpm testLicense
MIT
Support
For issues and questions:
- GitHub Issues: Report an issue
- Email: [email protected]
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
