@astermind/cybernetic-chatbot-client
Offline-capable AI chatbot client with local RAG fallback and agentic capabilities for AsterMind.

What is Cybernetic Chatbot Client?
Cybernetic Chatbot Client is the official JavaScript SDK for integrating AsterMind AI chatbot capabilities into your web applications. It provides a robust, offline-first architecture that ensures your users always get answers, even when disconnected from the server.
Key Features
- Dual Transport - WebSocket streaming for SaaS, REST+SSE for on-prem (auto-detected)
- Offline-First Architecture - IndexedDB caching with TF-IDF local search
- SSE Streaming - Real-time token-by-token responses (REST fallback)
- WebSocket Streaming - Low-latency streaming via persistent connection (SaaS)
- Session Management - Multi-turn conversation continuity
- Configurable Retry Logic - Exponential backoff with customizable settings
- Connection Status Monitoring - Real-time online/offline detection
- Maintenance Mode Support - Graceful degradation per ADR-200
- Agentic Capabilities - Intent classification and DOM automation (full bundle)
- Tree-Shakeable - Import only what you need
Table of Contents
Installation
npm / yarn / pnpm
npm install @astermind/cybernetic-chatbot-client
yarn add @astermind/cybernetic-chatbot-client
pnpm add @astermind/cybernetic-chatbot-client
Required import — add to your JavaScript/TypeScript file:
import { CyberneticClient } from '@astermind/cybernetic-chatbot-client';
Note: Most users should install @astermind/chatbot-template instead, which includes this package as a dependency along with pre-built UI components. Use this package directly only if you're building a custom chat UI.
CDN (Script Tag)
Include one of the following script tags in your HTML:
<script src="https://unpkg.com/@astermind/cybernetic-chatbot-client/dist/cybernetic-chatbot-client.umd.js"></script>
<script src="https://unpkg.com/@astermind/cybernetic-chatbot-client/dist/cybernetic-chatbot-client-full.umd.js"></script>
The client is available as window.AsterMindCybernetic (core) or window.AsterMindCyberneticFull (full bundle).
Quick Start
Note: No license key is required for development. See Licensing for production requirements.
Basic Usage
import { CyberneticClient } from '@astermind/cybernetic-chatbot-client';
const client = new CyberneticClient({
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
fallback: {
enabled: true,
cacheOnConnect: true
},
onStatusChange: (status) => {
console.log('Connection status:', status);
}
});
const response = await client.ask('What is AsterMind?');
console.log(response.reply);
await client.askStream('Tell me about RAG', {
onToken: (token) => process.stdout.write(token),
onSources: (sources) => console.log('Sources:', sources),
onComplete: (response) => console.log('\nDone:', response.sessionId)
});
Script Tag Integration
<script
src="https://unpkg.com/@astermind/cybernetic-chatbot-client/dist/cybernetic-chatbot-client.umd.js"
data-astermind-key="am_your_api_key"
data-astermind-url="https://api.astermind.ai"
></script>
Global Config Object
<script>
window.astermindConfig = {
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
fallback: { enabled: true }
};
</script>
<script src="https://unpkg.com/@astermind/cybernetic-chatbot-client/dist/cybernetic-chatbot-client.umd.js"></script>
Licensing
Free for Development — This package is free to use during development and testing. No license key is required for local development environments.
License Required for Production — A valid license key is required for production deployments. Without a license, chatbot responses in production will include a visible license notice. Licenses are available at https://astermind.ai.
License Products
| Cybernetic Chatbot Client | cybernetic-chatbot-client | Cybernetic Chatbot purchase |
| Agentic Add-On | agentic | Separate Agentic Add-On purchase |
- Cybernetic Chatbot: Includes the
cybernetic-chatbot-client feature, enabling all core client functionality (API communication, offline caching, streaming, session management).
- Agentic Add-On: Requires a separate purchase. Enables the
agentic feature for intent classification and DOM automation capabilities.
Applying Your License Key
Add your license key to the client configuration:
import { CyberneticClient } from '@astermind/cybernetic-chatbot-client';
const client = new CyberneticClient({
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
licenseKey: 'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...'
});
For script tag integration:
<script>
window.astermindConfig = {
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
licenseKey: 'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...'
};
</script>
<script src="https://unpkg.com/@astermind/cybernetic-chatbot-client/dist/cybernetic-chatbot-client.umd.js"></script>
Enforcement Behavior
The license system uses environment-aware enforcement:
| Development | localhost, 127.0.0.1, .local, .dev, dev ports (3000, 5173, 8080, etc.) | No | Free to use. Console warnings only. |
| Production | All other URLs | Yes | License warning appended to responses if missing/invalid. |
Development Mode (free, soft enforcement):
- No license key required — develop and test without any restrictions
- Console warnings are logged when license is missing, expired, or invalid (for awareness)
- Console warnings when using features not included in your license
- All functionality works normally — responses are returned unchanged
Production Mode (license required, hard enforcement):
-
A valid license key is required for production use
-
Without a valid license, chatbot responses include a visible notice:
"⚠️ License Notice: Your AsterMind license key needs to be updated. Please contact support@astermind.ai or visit https://astermind.ai/license to renew your license."
-
With a valid license, responses are returned normally without any modifications
Checking License Status
const status = client.getStatus();
console.log(status.license);
const license = client.getLicenseManager();
license.isValid();
license.hasFeature('cybernetic-chatbot-client');
license.hasFeature('agentic');
license.getStatusMessage();
Feature Validation
The client automatically validates features:
- Client feature (
cybernetic-chatbot-client): Checked on client initialization
- Agentic feature (
agentic): Checked only when agentic capabilities are used
If a required feature is missing, the console displays:
Obtaining a License
- Visit https://astermind.ai
- Purchase Cybernetic Chatbot for core client functionality
- Optionally purchase the Agentic Add-On for DOM automation features
- Your license key (JWT token) will be provided in your account dashboard
- Add the license key to your client configuration
For licensing questions, contact support@astermind.ai.
Configuration
All configuration is done in your own project—you never need to modify node_modules or the package source code.
Multi-Method Configuration
The client supports multiple configuration methods with a priority-based fallback chain. This allows you to use the most appropriate method for your hosting environment.
Priority Order (highest to lowest):
- Constructor config - Direct configuration passed to
CyberneticClient or createClient()
- Environment variables -
VITE_ASTERMIND_RAG_API_KEY, REACT_APP_ASTERMIND_RAG_API_KEY, etc.
- SSR-injected config -
window.__ASTERMIND_CONFIG__ (for server-side rendering)
- Global object -
window.astermindConfig
- Script data attributes -
data-astermind-key, data-astermind-url
Environment Variables
For bundled applications (Vite, Create React App, etc.), you can configure the client using environment variables:
Vite:
VITE_ASTERMIND_RAG_API_KEY=am_your_api_key
VITE_ASTERMIND_RAG_API_SERVER_URL=https://api.astermind.ai
Create React App:
REACT_APP_ASTERMIND_RAG_API_KEY=am_your_api_key
REACT_APP_ASTERMIND_RAG_API_SERVER_URL=https://api.astermind.ai
Node.js / Server:
ASTERMIND_RAG_API_KEY=am_your_api_key
ASTERMIND_RAG_API_SERVER_URL=https://api.astermind.ai
Auto-Loading Configuration
Use loadConfig() to automatically detect configuration from available sources:
import { loadConfig, createClient } from '@astermind/cybernetic-chatbot-client';
const config = loadConfig();
const client = createClient(config);
const config = loadConfig({ throwOnMissingKey: false });
if (config) {
const client = createClient(config);
} else {
console.log('Chatbot not configured');
}
SSR / Runtime Injection
For server-side rendered applications, inject configuration at runtime:
<script>
window.__ASTERMIND_CONFIG__ = {
apiKey: '<%= process.env.ASTERMIND_RAG_API_KEY %>',
apiUrl: '<%= process.env.ASTERMIND_RAG_API_SERVER_URL %>'
};
</script>
Configuration Source Debugging
The loaded configuration includes a _source field for debugging:
const config = loadConfig();
console.log(config._source);
Full Configuration Interface
interface CyberneticConfig {
apiUrl: string;
apiKey: string;
wsUrl?: string;
transport?: 'auto' | 'websocket' | 'rest';
websocket?: {
maxReconnectAttempts?: number;
reconnectDelay?: number;
connectionTimeout?: number;
};
licenseKey?: string;
fallback?: {
enabled?: boolean;
cacheMaxAge?: number;
cacheOnConnect?: boolean;
cacheStorage?: 'indexeddb' | 'localstorage';
};
retry?: {
maxRetries?: number;
initialDelay?: number;
exponentialBackoff?: boolean;
};
onStatusChange?: (status: ConnectionStatus) => void;
onError?: (error: CyberneticError) => void;
agentic?: AgenticConfig;
offline?: OfflineConfig;
sitemap?: SiteMapConfig;
}
type ConnectionStatus = 'online' | 'offline' | 'connecting' | 'error';
Agentic Configuration
interface AgenticConfig {
enabled: boolean;
confidenceThreshold?: number;
allowedActions?: ('click' | 'fill' | 'scroll' | 'navigate' | 'select')[];
requireConfirmation?: boolean;
maxActionsPerTurn?: number;
blockedSelectors?: string[];
allowedSelectors?: string[];
}
Features
WebSocket Transport (SaaS)
When connecting to AsterMind's SaaS infrastructure, the client automatically uses WebSocket transport for streaming chat. This provides lower latency and access to the full RAG pipeline (RSF temporal scoring, hybrid reranking, Omega embeddings, BYOLLM).
Auto-detection (zero config for SaaS users):
const client = new CyberneticClient({
apiUrl: 'https://chatapi.astermind.ai',
apiKey: 'am_your_api_key',
});
The client auto-derives WebSocket URLs for known SaaS domains:
chatapi.astermind.ai → wss://chatws.astermind.ai
chatapi-dev.astermind.ai → wss://chatws-dev.astermind.ai
api.astermind.ai → wss://chatws.astermind.ai
Explicit configuration:
const client = new CyberneticClient({
apiUrl: 'https://chatapi.astermind.ai',
apiKey: 'am_your_api_key',
wsUrl: 'wss://chatws.astermind.ai',
transport: 'websocket',
});
On-prem (unchanged, REST+SSE):
const client = new CyberneticClient({
apiUrl: 'http://localhost:3000',
apiKey: 'am_your_api_key',
});
Transport modes:
'auto' (default) — Uses WebSocket when available, falls back to REST+SSE on failure
'websocket' — Forces WebSocket only, no REST fallback
'rest' — Forces REST+SSE only, ignores WebSocket
Environment variable support:
# Vite
VITE_ASTERMIND_RAG_WS_URL=wss://chatws.astermind.ai
# Node.js / CRA
ASTERMIND_RAG_WS_URL=wss://chatws.astermind.ai
REACT_APP_ASTERMIND_RAG_WS_URL=wss://chatws.astermind.ai
Cleanup:
Call destroy() when disposing the client to close the WebSocket connection:
client.destroy();
Offline-First Architecture
The client includes built-in offline fallback with IndexedDB caching and TF-IDF local search—no additional setup required. When the server is unreachable, the client automatically serves cached responses:
const client = new CyberneticClient({
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
fallback: {
enabled: true,
cacheOnConnect: true,
cacheMaxAge: 86400000,
cacheStorage: 'indexeddb'
}
});
const status = client.getStatus();
console.log(status.connection);
console.log(status.cache);
const response = await client.ask('cached question');
if (response.offline) {
console.log('Response from local cache');
console.log('Confidence:', response.confidence);
}
await client.syncCache();
await client.clearCache();
Cache Validation: The server controls cache retention via cacheRetentionHours (default: 168 hours / 7 days). The client respects this setting and marks responses as stale when appropriate.
Pre-computed Vector Export (Advanced)
For enhanced offline performance, the client supports loading pre-computed TF-IDF vectors exported from the AsterMind admin panel. This eliminates client-side vector computation and provides faster, more consistent offline search results.
Exporting Vectors from Admin
- Navigate to your AsterMind admin panel
- Go to Settings > Vector Export (or Documents > Export)
- Click Export Vectors for Offline Use
- Download the JSON export file or note the export URL
The export file contains pre-computed TF-IDF vectors, document metadata, and optionally sitemap and category information for agentic navigation.
Configuring Offline Vectors
import { CyberneticClient } from '@astermind/cybernetic-chatbot-client';
const client = new CyberneticClient({
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
offline: {
enabled: true,
vectorFileUrl: 'https://your-cdn.com/vectors/export.json',
storageMode: 'indexeddb',
maxCacheAge: 604800000,
autoRefresh: true,
omega: {
enabled: true,
modelUrl: 'https://your-cdn.com/models/omega-model.json'
}
}
});
Inline Vector Data
You can also provide vector data directly in the configuration:
const client = new CyberneticClient({
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
offline: {
enabled: true,
vectorData: exportedVectorObject,
storageMode: 'memory'
}
});
Offline Configuration Options
interface OfflineConfig {
enabled: boolean;
vectorFileUrl?: string;
vectorData?: OfflineVectorExport;
storageMode?: 'memory' | 'indexeddb' | 'hybrid';
maxCacheAge?: number;
autoRefresh?: boolean;
omega?: {
enabled: boolean;
modelUrl?: string;
modelData?: SerializedModel;
config?: {
topK?: number;
rerankerTopK?: number;
minScore?: number;
};
};
}
Checking Offline Status
const ragStatus = client.getLocalRAGStatus();
console.log(ragStatus);
if (client.isOmegaOfflineEnabled()) {
const modelInfo = client.getOfflineModelInfo();
console.log('Omega model:', modelInfo);
}
await client.reloadOfflineVectors();
Console Warning
When offline.enabled is true but no vectors are loaded (missing URL, network error, or invalid data), the client logs a one-time console warning:
[CyberneticClient] Warning: Offline mode enabled but no vectors loaded.
Configure 'offline.vectorFileUrl' or provide 'offline.vectorData' for offline support.
Falling back to standard caching mode.
This helps identify configuration issues without disrupting functionality.
Streaming Responses
Real-time token streaming via WebSocket (SaaS) or Server-Sent Events (on-prem):
await client.askStream('Explain quantum computing', {
onToken: (token) => {
document.getElementById('output').textContent += token;
},
onSources: (sources) => {
console.log('Sources:', sources);
},
onComplete: (response) => {
console.log('Session ID:', response.sessionId);
},
onError: (error) => {
console.error('Error:', error.message);
}
});
Session Management
Maintain conversation context across multiple turns:
const response1 = await client.ask('Hello!');
const sessionId = response1.sessionId;
const response2 = await client.ask('Tell me more', { sessionId });
const response3 = await client.ask('Can you clarify?', { sessionId });
const response = await client.ask('Help me with this page', {
sessionId,
context: {
currentPage: '/products/widget',
pageTitle: 'Widget Product Page'
}
});
Agentic Capabilities
The full bundle includes intent classification and DOM automation:
import {
CyberneticClient,
CyberneticAgent,
CyberneticIntentClassifier
} from '@astermind/cybernetic-chatbot-client/full';
const client = new CyberneticClient({
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
agentic: {
enabled: true,
confidenceThreshold: 0.8,
requireConfirmation: true,
allowedActions: ['click', 'fill', 'navigate', 'scroll'],
blockedSelectors: ['.admin-panel', '#dangerous-button'],
maxActionsPerTurn: 5
}
});
const result = await client.smartAsk('Take me to the settings page');
if (result.action) {
console.log('Action:', result.action.type, result.action.target);
console.log('Confidence:', result.action.confidence);
if (userConfirmed) {
const actionResult = await client.executeAction(result.action);
console.log('Result:', actionResult.message);
}
} else if (result.response) {
console.log('Reply:', result.response.reply);
}
Supported Action Types
navigate | Navigate to URL/route | "go to settings", "take me to dashboard" |
fillForm | Fill form input fields | "search for products", "enter my email" |
clickElement | Click buttons/links | "click submit", "press the save button" |
scroll | Scroll to element/position | "scroll to top", "jump to pricing section" |
highlight | Highlight elements | "show me the login button" |
triggerModal | Open modal dialogs | "open help modal", "show settings dialog" |
custom | Custom action handlers | "export data", "refresh dashboard" |
Intent Classification
The classifier uses a hybrid approach with regex patterns and Jaccard similarity for fuzzy matching:
import { CyberneticIntentClassifier } from '@astermind/cybernetic-chatbot-client/full';
const classifier = new CyberneticIntentClassifier({
enabled: true,
confidenceThreshold: 0.8,
siteMap: [
{ path: '/settings', name: 'Settings', aliases: ['preferences', 'config'] },
{ path: '/dashboard', name: 'Dashboard', aliases: ['home', 'main'] }
]
});
const intent = classifier.classify('take me to the settings page');
Security Features
- Selector Sanitization: Removes potentially dangerous characters from CSS selectors
- URL Validation: Blocks
javascript: and data: URLs
- Blocked Selectors: Configure selectors that should never be interacted with
- Allowed Selectors: Optionally whitelist specific selectors
- Rate Limiting: Maximum actions per minute (default: 5)
- Confirmation Flow: Optional user approval before action execution
Sitemap Configuration
The sitemap enables intelligent navigation by mapping user intent to application routes. You can configure it statically or load it from the vector export:
Static Sitemap Configuration
const client = new CyberneticClient({
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
sitemap: {
enabled: true,
entries: [
{
path: '/dashboard',
name: 'Dashboard',
description: 'Main dashboard with analytics',
aliases: ['home', 'main', 'overview'],
keywords: ['stats', 'metrics', 'analytics']
},
{
path: '/settings',
name: 'Settings',
description: 'User and application settings',
aliases: ['preferences', 'config', 'options'],
keywords: ['account', 'profile', 'configuration']
},
{
path: '/products',
name: 'Products',
description: 'Product catalog and management',
aliases: ['catalog', 'inventory'],
keywords: ['items', 'shop', 'store']
}
]
}
});
Loading Sitemap from Vector Export
When using pre-computed vectors, the sitemap can be included in the export and loaded automatically:
const client = new CyberneticClient({
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
offline: {
enabled: true,
vectorFileUrl: 'https://your-cdn.com/vectors/export.json'
},
sitemap: {
enabled: true,
loadFromExport: true
}
});
Sitemap Configuration Options
interface SiteMapConfig {
enabled: boolean;
entries?: SiteMapEntry[];
loadFromExport?: boolean;
sitemapUrl?: string;
}
interface SiteMapEntry {
path: string;
name: string;
description?: string;
aliases?: string[];
keywords?: string[];
requiresAuth?: boolean;
roles?: string[];
children?: SiteMapEntry[];
}
Maintenance Mode Support
The client handles backend maintenance mode gracefully (per ADR-200):
if (client.isMaintenanceMode()) {
const message = client.getMaintenanceMessage();
console.log('Maintenance:', message);
}
const status = client.getStatus();
console.log(status.systemSettings);
When maintenance mode is active:
- The client automatically uses cached data
- New requests are served from local RAG
response.offline will be true
response.degradedReason will indicate maintenance mode
Bundle Options
| Core | @astermind/cybernetic-chatbot-client | Client, caching, local RAG | ~15KB |
| Full | @astermind/cybernetic-chatbot-client/full | Core + agentic capabilities | ~25KB |
Tree-Shakeable Imports
import { CyberneticClient } from '@astermind/cybernetic-chatbot-client';
import {
CyberneticClient,
CyberneticAgent,
CyberneticIntentClassifier
} from '@astermind/cybernetic-chatbot-client/full';
API Reference
CyberneticClient
class CyberneticClient {
constructor(config: CyberneticConfig);
ask(message: string, options?: AskOptions): Promise<CyberneticResponse>;
askStream(message: string, callbacks: StreamCallbacks, options?: AskOptions): Promise<void>;
smartAsk(message: string, options?: AskOptions): Promise<SmartAskResult>;
classifyIntent(message: string): IntentClassification | null;
executeAction(action: AgentAction): Promise<ActionResult>;
isAgenticEnabled(): boolean;
getStatus(): { connection: ConnectionStatus; cache: CacheStatus; lastError: CyberneticError | null; systemSettings: SystemSettings | null; license: LicenseState | null };
checkConnection(): Promise<boolean>;
checkSystemStatus(): Promise<SystemSettings>;
isMaintenanceMode(): boolean;
getMaintenanceMessage(): string | undefined;
isCacheValid(): boolean;
getLicenseManager(): LicenseManager;
syncCache(): Promise<void>;
clearCache(): Promise<void>;
destroy(): void;
}
Response Types
interface CyberneticResponse {
reply: string;
confidence: 'high' | 'medium' | 'low' | 'none';
sources: Source[];
offline: boolean;
sessionId?: string;
retryAfter?: number;
degradedReason?: string;
}
interface Source {
title: string;
snippet: string;
relevance: number;
documentId?: string;
}
interface StreamCallbacks {
onToken?: (token: string) => void;
onSources?: (sources: Source[]) => void;
onComplete?: (response: CyberneticResponse) => void;
onError?: (error: CyberneticError) => void;
}
interface CyberneticError {
code: 'NETWORK_ERROR' | 'AUTH_ERROR' | 'RATE_LIMIT' | 'SERVER_ERROR' | 'CACHE_ERROR' | 'LOCAL_RAG_ERROR' | 'WS_ERROR';
message: string;
retryAfter?: number;
}
interface LicenseState {
status: 'valid' | 'invalid' | 'expired' | 'missing' | 'eval';
payload: LicensePayload | null;
error?: string;
inGracePeriod: boolean;
daysRemaining: number | null;
}
interface LicensePayload {
iss: string;
sub: string;
aud: string;
iat: number;
exp: number;
plan: 'free' | 'pro' | 'business' | 'enterprise' | 'eval';
org?: string;
seats: number;
features: string[];
graceUntil?: number;
licenseVersion: number;
}
Browser Support
| Chrome | 80+ | Full support |
| Firefox | 75+ | Full support |
| Safari | 13.1+ | Full support |
| Edge | 80+ | Full support |
Requires IndexedDB support for offline caching.
Integration with Cybernetic Chatbot Backend
This client is designed to work with the AsterMind Cybernetic Chatbot backend. The client supports two transport modes:
REST API Endpoints (on-prem and supplementary):
/api/external/chat | POST | Send message, get complete response |
/api/external/chat/stream | POST | Send message, get SSE streaming response |
/api/external/docs | GET | Fetch documents for offline caching |
/api/external/status | GET | Check API status, quota, and system settings |
/api/external/health | GET | Health check (no auth required) |
/api/external/search | GET | Search documents |
/api/external/sitemap | GET | Get document sitemap for navigation |
/api/external/config | GET | Get chatbot configuration |
WebSocket Endpoint (SaaS streaming):
wss://chatws.astermind.ai | Production WebSocket streaming |
wss://chatws-dev.astermind.ai | Development WebSocket streaming |
WebSocket authentication uses an API key query parameter: ?apiKey=am_xxx
Authentication: REST endpoints require an X-API-Key header with a valid API key (prefixed with am_). WebSocket endpoints use a ?apiKey=am_xxx query parameter.
Rate Limiting: The backend enforces rate limits. The client handles 429 responses gracefully and includes retryAfter in responses when applicable.
Links
License
MIT License - see LICENSE for details.