
Security News
/Company News
Securing the Financial Frontier: How Capital One Uses Socket for Open Source Security
Capital One is partnering with Socket to proactively secure its open source supply chain.
@astermind/evo-virtual-assistant-client
Advanced tools
Offline-capable AI virtual assistant client with local RAG fallback and agentic capabilities for AsterMind
Offline-capable AI virtual assistant client with local RAG fallback and agentic capabilities for AsterMind.
EVO Virtual Assistant Client is the official JavaScript SDK for integrating AsterMind AI virtual assistant 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.
npm install @astermind/evo-virtual-assistant-client
yarn add @astermind/evo-virtual-assistant-client
pnpm add @astermind/evo-virtual-assistant-client
Required import — add to your JavaScript/TypeScript file:
import { CyberneticClient } from '@astermind/evo-virtual-assistant-client';
Note: Most users should install
@astermind/evo-virtual-assistant-templateinstead, 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.
Include one of the following script tags in your HTML:
<!-- Core bundle (API client, caching, offline fallback) -->
<script src="https://unpkg.com/@astermind/evo-virtual-assistant-client/dist/evo-virtual-assistant-client.umd.js"></script>
<!-- Or full bundle (core + agentic capabilities) -->
<script src="https://unpkg.com/@astermind/evo-virtual-assistant-client/dist/evo-virtual-assistant-client-full.umd.js"></script>
The client is available as window.AsterMindCybernetic (core) or window.AsterMindCyberneticFull (full bundle).
Note: No license key is required for development. See Licensing for production requirements.
import { CyberneticClient } from '@astermind/evo-virtual-assistant-client';
const client = new CyberneticClient({
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
// licenseKey: 'your-license-key', // Optional in development, required in production
fallback: {
enabled: true,
cacheOnConnect: true
},
onStatusChange: (status) => {
console.log('Connection status:', status);
}
});
// Simple question
const response = await client.ask('What is AsterMind?');
console.log(response.reply);
// With streaming
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
src="https://unpkg.com/@astermind/evo-virtual-assistant-client/dist/evo-virtual-assistant-client.umd.js"
data-astermind-key="am_your_api_key"
data-astermind-url="https://api.astermind.ai"
></script>
<script>
window.astermindConfig = {
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
fallback: { enabled: true }
};
</script>
<script src="https://unpkg.com/@astermind/evo-virtual-assistant-client/dist/evo-virtual-assistant-client.umd.js"></script>
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, virtual assistant responses in production will include a visible license notice. Licenses are available at https://astermind.ai.
| Product | Feature Flag | Included With |
|---|---|---|
| EVO Virtual Assistant Client | evo-virtual-assistant-client | EVO Virtual Assistant purchase |
| Agentic Add-On | agentic | Separate Agentic Add-On purchase |
evo-virtual-assistant-client feature, enabling all core client functionality (API communication, offline caching, streaming, session management).agentic feature for intent classification and DOM automation capabilities.Add your license key to the client configuration:
import { CyberneticClient } from '@astermind/evo-virtual-assistant-client';
const client = new CyberneticClient({
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
licenseKey: 'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...' // Your license key (JWT)
});
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/evo-virtual-assistant-client/dist/evo-virtual-assistant-client.umd.js"></script>
The license system uses environment-aware enforcement:
| Environment | Detection | License Required? | Behavior |
|---|---|---|---|
| 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):
Production Mode (license required, hard enforcement):
A valid license key is required for production use
Without a valid license, virtual assistant 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
// Get current status including license state
const status = client.getStatus();
console.log(status.license);
// {
// status: 'valid' | 'invalid' | 'expired' | 'missing' | 'eval',
// payload: { plan, features, exp, ... },
// daysRemaining: 30,
// inGracePeriod: false
// }
// Get license manager for advanced operations
const license = client.getLicenseManager();
// Check if license is valid
license.isValid();
// Check specific features
license.hasFeature('evo-virtual-assistant-client');
license.hasFeature('agentic');
// Get human-readable status
license.getStatusMessage();
// "License valid (30 days remaining)"
The client automatically validates features:
evo-virtual-assistant-client): Checked on client initializationagentic): Checked only when agentic capabilities are usedIf a required feature is missing, the console displays:
For licensing questions, contact support@astermind.ai.
All configuration is done in your own project—you never need to modify node_modules or the package source code.
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):
CyberneticClient or createClient()VITE_ASTERMIND_RAG_API_KEY, REACT_APP_ASTERMIND_RAG_API_KEY, etc.window.__ASTERMIND_CONFIG__ (for server-side rendering)window.astermindConfigdata-astermind-key, data-astermind-urlFor 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
Use loadConfig() to automatically detect configuration from available sources:
import { loadConfig, createClient } from '@astermind/evo-virtual-assistant-client';
// Auto-detect configuration (throws if no API key found)
const config = loadConfig();
const client = createClient(config);
// Or suppress errors and handle missing config gracefully
const config = loadConfig({ throwOnMissingKey: false });
if (config) {
const client = createClient(config);
} else {
console.log('Virtual assistant not configured');
}
For server-side rendered applications, inject configuration at runtime:
<!-- In your SSR template -->
<script>
window.__ASTERMIND_CONFIG__ = {
apiKey: '<%= process.env.ASTERMIND_RAG_API_KEY %>',
apiUrl: '<%= process.env.ASTERMIND_RAG_API_SERVER_URL %>'
};
</script>
The loaded configuration includes a _source field for debugging:
const config = loadConfig();
console.log(config._source);
// 'env' | 'vite' | 'window' | 'data-attr' | 'props'
interface CyberneticConfig {
/** Backend API URL (required) */
apiUrl: string;
/** API key for authentication - must start with 'am_' (required) */
apiKey: string;
/** WebSocket URL for SaaS streaming (auto-derived from apiUrl for known SaaS domains) */
wsUrl?: string;
/** Transport mode: 'auto' (default) tries WebSocket then REST, 'websocket' forces WS, 'rest' forces REST+SSE */
transport?: 'auto' | 'websocket' | 'rest';
/** WebSocket transport options */
websocket?: {
maxReconnectAttempts?: number; // Default: 3
reconnectDelay?: number; // Default: 1000ms (exponential backoff)
connectionTimeout?: number; // Default: 10000ms
};
/** License key (JWT token) from https://astermind.ai */
licenseKey?: string;
/** Fallback/offline configuration */
fallback?: {
/** Enable offline fallback (default: true) */
enabled?: boolean;
/** Cache max age in milliseconds (default: 86400000 = 24 hours) */
cacheMaxAge?: number;
/** Sync documents on connect (default: true) */
cacheOnConnect?: boolean;
/** Storage type (default: 'indexeddb') */
cacheStorage?: 'indexeddb' | 'localstorage';
};
/** Retry configuration */
retry?: {
/** Max retries before fallback (default: 2) */
maxRetries?: number;
/** Initial delay in ms (default: 1000) */
initialDelay?: number;
/** Use exponential backoff (default: true) */
exponentialBackoff?: boolean;
};
/** Event callbacks */
onStatusChange?: (status: ConnectionStatus) => void;
onError?: (error: CyberneticError) => void;
/** Agentic capabilities configuration (requires full bundle) */
agentic?: AgenticConfig;
/** Offline vector export configuration (see Pre-computed Vector Export section) */
offline?: OfflineConfig;
/** Sitemap configuration for agentic navigation (see Sitemap Configuration section) */
sitemap?: SiteMapConfig;
}
type ConnectionStatus = 'online' | 'offline' | 'connecting' | 'error';
interface AgenticConfig {
/** Enable agentic DOM interactions (default: false) */
enabled: boolean;
/** Confidence threshold for action execution (default: 0.8) */
confidenceThreshold?: number;
/** Allowed DOM actions */
allowedActions?: ('click' | 'fill' | 'scroll' | 'navigate' | 'select')[];
/** Require user confirmation before actions (default: true) */
requireConfirmation?: boolean;
/** Maximum actions per conversation turn (default: 5) */
maxActionsPerTurn?: number;
/** CSS selectors to never interact with */
blockedSelectors?: string[];
/** Only allow actions within these selectors */
allowedSelectors?: string[];
}
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',
// wsUrl auto-derived → wss://chatws.astermind.ai
});
The client auto-derives WebSocket URLs for known SaaS domains:
chatapi.astermind.ai → wss://chatws.astermind.aichatapi-dev.astermind.ai → wss://chatws-dev.astermind.aiapi.astermind.ai → wss://chatws.astermind.aiExplicit configuration:
const client = new CyberneticClient({
apiUrl: 'https://chatapi.astermind.ai',
apiKey: 'am_your_api_key',
wsUrl: 'wss://chatws.astermind.ai',
transport: 'websocket', // Force WebSocket only (no REST fallback)
});
On-prem (unchanged, REST+SSE):
const client = new CyberneticClient({
apiUrl: 'http://localhost:3000',
apiKey: 'am_your_api_key',
// No wsUrl → uses REST+SSE as before
});
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 WebSocketEnvironment 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();
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, // Cache responses for offline use
cacheMaxAge: 86400000, // 24 hours
cacheStorage: 'indexeddb'
}
});
// Check connection status
const status = client.getStatus();
console.log(status.connection); // 'online' | 'offline' | 'connecting'
console.log(status.cache); // { documentCount, lastSyncAt, cacheSize, isStale }
// Response includes offline indicator
const response = await client.ask('cached question');
if (response.offline) {
console.log('Response from local cache');
console.log('Confidence:', response.confidence); // 'medium' or 'low' when offline
}
// Manually sync cache
await client.syncCache();
// Clear cache
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.
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.
The export file contains pre-computed TF-IDF vectors, document metadata, and optionally sitemap and category information for agentic navigation.
import { CyberneticClient } from '@astermind/evo-virtual-assistant-client';
const client = new CyberneticClient({
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
// Offline vector configuration
offline: {
enabled: true,
vectorFileUrl: 'https://your-cdn.com/vectors/export.json', // URL to exported vectors
storageMode: 'indexeddb', // 'memory' | 'indexeddb' | 'hybrid'
maxCacheAge: 604800000, // 7 days in milliseconds
autoRefresh: true, // Auto-refresh when new export available
// Optional: Omega advanced RAG (requires @astermind/astermind-community)
omega: {
enabled: true,
modelUrl: 'https://your-cdn.com/models/omega-model.json'
}
}
});
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, // Loaded from file or bundled
storageMode: 'memory'
}
});
interface OfflineConfig {
/** Enable offline vector support */
enabled: boolean;
/** URL to fetch vector export JSON */
vectorFileUrl?: string;
/** Inline vector data (alternative to URL) */
vectorData?: OfflineVectorExport;
/** Storage mode for cached vectors */
storageMode?: 'memory' | 'indexeddb' | 'hybrid';
/** Maximum cache age in milliseconds (default: 7 days) */
maxCacheAge?: number;
/** Auto-refresh vectors when new export available */
autoRefresh?: boolean;
/** Omega advanced RAG configuration */
omega?: {
enabled: boolean;
modelUrl?: string;
modelData?: SerializedModel;
config?: {
topK?: number;
rerankerTopK?: number;
minScore?: number;
};
};
}
// Get local RAG status
const ragStatus = client.getLocalRAGStatus();
console.log(ragStatus);
// {
// loaded: true,
// loadedFromExport: true,
// documentCount: 150,
// chunkCount: 1200,
// exportVersion: '1.0.0',
// exportedAt: '2024-01-15T10:30:00Z'
// }
// Check if Omega is enabled and ready
if (client.isOmegaOfflineEnabled()) {
const modelInfo = client.getOfflineModelInfo();
console.log('Omega model:', modelInfo);
}
// Force reload vectors
await client.reloadOfflineVectors();
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.
Real-time token streaming via WebSocket (SaaS) or Server-Sent Events (on-prem):
await client.askStream('Explain quantum computing', {
onToken: (token) => {
// Called for each token as it arrives
document.getElementById('output').textContent += token;
},
onSources: (sources) => {
// Called when sources are available
console.log('Sources:', sources);
},
onComplete: (response) => {
// Called when streaming is complete
console.log('Session ID:', response.sessionId);
},
onError: (error) => {
// Called on error
console.error('Error:', error.message);
}
});
Maintain conversation context across multiple turns:
// First message establishes session
const response1 = await client.ask('Hello!');
const sessionId = response1.sessionId;
// Continue conversation with session ID
const response2 = await client.ask('Tell me more', { sessionId });
const response3 = await client.ask('Can you clarify?', { sessionId });
// Optionally pass page context
const response = await client.ask('Help me with this page', {
sessionId,
context: {
currentPage: '/products/widget',
pageTitle: 'Widget Product Page'
}
});
The full bundle includes intent classification and DOM automation:
import {
CyberneticClient,
CyberneticAgent,
CyberneticIntentClassifier
} from '@astermind/evo-virtual-assistant-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
}
});
// Smart ask - checks for action intent first, then falls back to RAG
const result = await client.smartAsk('Take me to the settings page');
if (result.action) {
// Action detected
console.log('Action:', result.action.type, result.action.target);
console.log('Confidence:', result.action.confidence);
// If requireConfirmation is true, action is returned but not executed
// Your UI can show a confirmation dialog, then execute:
if (userConfirmed) {
const actionResult = await client.executeAction(result.action);
console.log('Result:', actionResult.message);
}
} else if (result.response) {
// Standard RAG response
console.log('Reply:', result.response.reply);
}
| Action | Description | Example Phrases |
|---|---|---|
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" |
The classifier uses a hybrid approach with regex patterns and Jaccard similarity for fuzzy matching:
import { CyberneticIntentClassifier } from '@astermind/evo-virtual-assistant-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');
// { action: { type: 'navigate', target: '/settings', confidence: 0.92 }, ... }
javascript: and data: URLsThe sitemap enables intelligent navigation by mapping user intent to application routes. You can configure it statically or load it from the vector export:
const client = new CyberneticClient({
apiUrl: 'https://api.astermind.ai',
apiKey: 'am_your_api_key',
// Static sitemap configuration
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']
}
]
}
});
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 // Load sitemap from vector export
}
});
interface SiteMapConfig {
/** Enable sitemap-based navigation */
enabled: boolean;
/** Static sitemap entries */
entries?: SiteMapEntry[];
/** Load sitemap from vector export (requires offline.enabled) */
loadFromExport?: boolean;
/** URL to fetch sitemap JSON separately */
sitemapUrl?: string;
}
interface SiteMapEntry {
/** Route path (e.g., '/dashboard') */
path: string;
/** Display name */
name: string;
/** Description for context matching */
description?: string;
/** Alternative names/phrases */
aliases?: string[];
/** Related keywords for matching */
keywords?: string[];
/** Authentication required */
requiresAuth?: boolean;
/** Required user roles */
roles?: string[];
/** Child routes */
children?: SiteMapEntry[];
}
The client handles backend maintenance mode gracefully (per ADR-200):
// Check if maintenance mode is active
if (client.isMaintenanceMode()) {
const message = client.getMaintenanceMessage();
console.log('Maintenance:', message);
}
// Get full system status
const status = client.getStatus();
console.log(status.systemSettings);
// {
// maintenanceMode: boolean,
// maintenanceMessage?: string,
// cacheRetentionHours: number,
// forceOfflineClients: boolean
// }
When maintenance mode is active:
response.offline will be trueresponse.degradedReason will indicate maintenance mode| Entry Point | Import Path | Description | Size (minified) |
|---|---|---|---|
| Core | @astermind/evo-virtual-assistant-client | Client, caching, local RAG | ~15KB |
| Full | @astermind/evo-virtual-assistant-client/full | Core + agentic capabilities | ~25KB |
// Import only core client (smaller bundle)
import { CyberneticClient } from '@astermind/evo-virtual-assistant-client';
// Import agentic features when needed
import {
CyberneticClient,
CyberneticAgent,
CyberneticIntentClassifier
} from '@astermind/evo-virtual-assistant-client/full';
class CyberneticClient {
constructor(config: CyberneticConfig);
// Core methods
ask(message: string, options?: AskOptions): Promise<CyberneticResponse>;
askStream(message: string, callbacks: StreamCallbacks, options?: AskOptions): Promise<void>;
// Agentic methods (requires agentic config and license)
smartAsk(message: string, options?: AskOptions): Promise<SmartAskResult>;
classifyIntent(message: string): IntentClassification | null;
executeAction(action: AgentAction): Promise<ActionResult>;
isAgenticEnabled(): boolean;
// Status methods (includes license state)
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;
// License methods
getLicenseManager(): LicenseManager;
// Cache methods
syncCache(): Promise<void>;
clearCache(): Promise<void>;
// Cleanup
destroy(): void; // Close WebSocket connection and clean up resources
}
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; // Issuer
sub: string; // Subject (license ID)
aud: string; // Audience (product)
iat: number; // Issued at
exp: number; // Expiration
plan: 'free' | 'pro' | 'business' | 'enterprise' | 'eval';
org?: string; // Organization
seats: number; // Number of seats
features: string[]; // Enabled features
graceUntil?: number; // Grace period end
licenseVersion: number;
}
| Browser | Version | Notes |
|---|---|---|
| Chrome | 80+ | Full support |
| Firefox | 75+ | Full support |
| Safari | 13.1+ | Full support |
| Edge | 80+ | Full support |
Requires IndexedDB support for offline caching.
This client is designed to work with the AsterMind EVO Virtual Assistant backend. The client supports two transport modes:
REST API Endpoints (on-prem and supplementary):
| Endpoint | Method | Description |
|---|---|---|
/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 virtual assistant configuration |
WebSocket Endpoint (SaaS streaming):
| Endpoint | Description |
|---|---|
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.
MIT License - see LICENSE for details.
FAQs
Offline-capable AI virtual assistant client with local RAG fallback and agentic capabilities for AsterMind
The npm package @astermind/evo-virtual-assistant-client receives a total of 25 weekly downloads. As such, @astermind/evo-virtual-assistant-client popularity was classified as not popular.
We found that @astermind/evo-virtual-assistant-client demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.

Security News
/Company News
Capital One is partnering with Socket to proactively secure its open source supply chain.

Security News
Socket CTO Ahmad Nassri discusses how to keep AI agents from bypassing package blocks, limit credential access, and monitor their actions.

Security News
GPT-6 Astra tried to plant malicious code in simulated open source projects using fake GitHub accounts and deceptive PRs during an assigned CTF challenge.