Initial commit: Brainy - Multi-Dimensional AI Database

Open source vector database with HNSW indexing, graph relationships,
and metadata facets. Features CLI with professional augmentation registry
integration for discovering extensions and capabilities.
This commit is contained in:
David Snelling 2025-08-18 17:35:06 -07:00
commit f8c45f2d8d
448 changed files with 103294 additions and 0 deletions

368
dist/chat/BrainyChat.js vendored Normal file
View file

@ -0,0 +1,368 @@
/**
* BrainyChat - Magical Chat Command Center
*
* A smart chat system that leverages Brainy's standard noun/verb types
* to create intelligent, persistent conversations with automatic context loading.
*
* Key Features:
* - Uses standard NounType.Message for all chat messages
* - Employs VerbType.Communicates and VerbType.Precedes for conversation flow
* - Auto-discovery of previous sessions using Brainy's search capabilities
* - Hybrid architecture: basic chat (open source) + premium memory sync
*/
import { NounType, VerbType } from '../types/graphTypes.js';
/**
* Enhanced BrainyChat with automatic context loading and intelligent memory
*
* This extends basic chat functionality with premium features when available
*/
export class BrainyChat {
constructor(brainy) {
this.currentSessionId = null;
this.sessionCache = new Map();
this.brainy = brainy;
}
/**
* Initialize chat system and auto-discover last session
* Uses Brainy's advanced search to find the most recent conversation
*/
async initialize() {
try {
// Search for the most recent chat message using Brainy's search
const recentMessages = await this.brainy.search('recent chat conversation', 1, {
nounTypes: [NounType.Message],
metadata: {
messageType: 'chat'
}
});
if (recentMessages.length > 0) {
const lastMessage = recentMessages[0];
const sessionId = lastMessage.metadata?.sessionId;
if (sessionId) {
this.currentSessionId = sessionId;
return await this.loadSession(sessionId);
}
}
}
catch (error) {
console.debug('No previous session found, starting fresh:', error?.message);
}
return null;
}
/**
* Start a new chat session
* Automatically generates a session ID and stores session metadata
*/
async startNewSession(title, participants = ['user', 'assistant']) {
const sessionId = `chat-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const session = {
id: sessionId,
title,
createdAt: new Date(),
lastMessageAt: new Date(),
messageCount: 0,
participants,
metadata: {
tags: ['active'],
premium: await this.isPremiumEnabled()
}
};
// Store session using BrainyData add() method
await this.brainy.add({
sessionType: 'chat',
title: title || `Chat Session ${new Date().toLocaleDateString()}`,
createdAt: session.createdAt.toISOString(),
lastMessageAt: session.lastMessageAt.toISOString(),
messageCount: session.messageCount,
participants: session.participants
}, {
id: sessionId,
nounType: NounType.Concept,
sessionType: 'chat'
});
this.currentSessionId = sessionId;
this.sessionCache.set(sessionId, session);
return session;
}
/**
* Add a message to the current session
* Stores using standard NounType.Message and creates conversation flow relationships
*/
async addMessage(content, speaker = 'user', metadata) {
if (!this.currentSessionId) {
await this.startNewSession();
}
const messageId = `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const timestamp = new Date();
const message = {
id: messageId,
content,
speaker,
sessionId: this.currentSessionId,
timestamp,
metadata
};
// Store message using BrainyData add() method
await this.brainy.add({
messageType: 'chat',
content,
speaker,
sessionId: this.currentSessionId,
timestamp: timestamp.toISOString(),
...metadata
}, {
id: messageId,
nounType: NounType.Message,
messageType: 'chat',
sessionId: this.currentSessionId,
speaker
});
// Create relationships using standard verb types
await this.createMessageRelationships(messageId);
// Update session metadata
await this.updateSessionMetadata();
return message;
}
/**
* Get conversation history for current session
* Uses Brainy's graph traversal to get messages in chronological order
*/
async getHistory(limit = 50) {
if (!this.currentSessionId)
return [];
try {
// Search for messages in this session using Brainy's search
const messageNouns = await this.brainy.search('', // Empty query to get all messages
limit, {
nounTypes: [NounType.Message],
metadata: {
sessionId: this.currentSessionId,
messageType: 'chat'
}
});
return messageNouns.map((noun) => this.nounToChatMessage(noun));
}
catch (error) {
console.error('Error retrieving chat history:', error);
return [];
}
}
/**
* Search across all chat sessions and messages
* Leverages Brainy's powerful vector and semantic search
*/
async searchMessages(query, options) {
const metadata = {
messageType: 'chat'
};
if (options?.sessionId) {
metadata.sessionId = options.sessionId;
}
if (options?.speaker) {
metadata.speaker = options.speaker;
}
try {
const results = await this.brainy.search(options?.semanticSearch !== false ? query : '', options?.limit || 20, {
nounTypes: [NounType.Message],
metadata
});
return results.map((noun) => this.nounToChatMessage(noun));
}
catch (error) {
console.error('Error searching messages:', error);
return [];
}
}
/**
* Get all chat sessions
* Uses Brainy's search to find all conversation sessions
*/
async getSessions(limit = 20) {
try {
const sessionNouns = await this.brainy.search('', limit, {
nounTypes: [NounType.Concept],
metadata: {
sessionType: 'chat'
}
});
return sessionNouns.map((noun) => this.nounToChatSession(noun));
}
catch (error) {
console.error('Error retrieving sessions:', error);
return [];
}
}
/**
* Switch to a different session
* Automatically loads context and history
*/
async switchToSession(sessionId) {
try {
const session = await this.loadSession(sessionId);
if (session) {
this.currentSessionId = sessionId;
this.sessionCache.set(sessionId, session);
}
return session;
}
catch (error) {
console.error('Error switching to session:', error);
return null;
}
}
/**
* Archive a session (premium feature)
* Maintains full searchability while organizing conversations
*/
async archiveSession(sessionId) {
if (!await this.isPremiumEnabled()) {
throw new Error('Session archiving requires premium Brain Cloud subscription');
}
try {
// Since BrainyData doesn't have update, add an archive marker
await this.brainy.add({
archivedSessionId: sessionId,
archivedAt: new Date().toISOString(),
action: 'archive'
}, {
nounType: NounType.State,
sessionId,
archived: true
});
return true;
}
catch (error) {
console.error('Error archiving session:', error);
}
return false;
}
/**
* Generate session summary using AI (premium feature)
* Intelligently summarizes long conversations
*/
async generateSessionSummary(sessionId) {
if (!await this.isPremiumEnabled()) {
throw new Error('AI session summaries require premium Brain Cloud subscription');
}
try {
const messages = await this.getHistoryForSession(sessionId, 100);
const content = messages
.map(msg => `${msg.speaker}: ${msg.content}`)
.join('\n');
// Use Brainy's AI to generate summary (placeholder - would need actual AI integration)
const summaryResponse = `Summary of ${messages.length} messages discussing various topics in ${sessionId}`;
return summaryResponse || null;
}
catch (error) {
console.error('Error generating session summary:', error);
return null;
}
}
// Private helper methods
async createMessageRelationships(messageId) {
// Link message to session using unified addVerb API
await this.brainy.addVerb(messageId, this.currentSessionId, VerbType.PartOf, {
relationship: 'message-in-session'
});
// Find previous message to create conversation flow using VerbType.Precedes
const previousMessages = await this.brainy.search('', 1, {
nounTypes: [NounType.Message],
metadata: {
sessionId: this.currentSessionId,
messageType: 'chat'
}
});
if (previousMessages.length > 0 && previousMessages[0].id !== messageId) {
await this.brainy.addVerb(previousMessages[0].id, messageId, VerbType.Precedes, {
relationship: 'message-sequence'
});
}
}
async loadSession(sessionId) {
try {
const sessionNouns = await this.brainy.search('', 1, {
nounTypes: [NounType.Concept],
metadata: {
sessionType: 'chat'
}
});
// Filter by session ID manually since BrainyData search may not support ID filtering
const matchingSession = sessionNouns.find(noun => noun.id === sessionId);
if (matchingSession) {
return this.nounToChatSession(matchingSession);
}
}
catch (error) {
console.error('Error loading session:', error);
}
return null;
}
async getHistoryForSession(sessionId, limit = 50) {
try {
const messageNouns = await this.brainy.search('', limit, {
nounTypes: [NounType.Message],
metadata: {
sessionId: sessionId,
messageType: 'chat'
}
});
return messageNouns.map((noun) => this.nounToChatMessage(noun));
}
catch (error) {
console.error('Error retrieving session history:', error);
return [];
}
}
async updateSessionMetadata() {
if (!this.currentSessionId)
return;
// Since BrainyData doesn't have update functionality, we'll skip this
// In a real implementation, you'd need update capabilities
console.debug('Session metadata update skipped - BrainyData lacks update API');
}
nounToChatMessage(noun) {
return {
id: noun.id,
content: noun.metadata?.content || noun.data?.content || '',
speaker: noun.metadata?.speaker || noun.data?.speaker || 'unknown',
sessionId: noun.metadata?.sessionId || noun.data?.sessionId || '',
timestamp: new Date(noun.metadata?.timestamp || noun.data?.timestamp || Date.now()),
metadata: noun.metadata
};
}
nounToChatSession(noun) {
return {
id: noun.id,
title: noun.metadata?.title || noun.data?.title || 'Untitled Session',
createdAt: new Date(noun.metadata?.createdAt || noun.data?.createdAt || Date.now()),
lastMessageAt: new Date(noun.metadata?.lastMessageAt || noun.data?.lastMessageAt || Date.now()),
messageCount: noun.metadata?.messageCount || noun.data?.messageCount || 0,
participants: noun.metadata?.participants || noun.data?.participants || ['user', 'assistant'],
metadata: noun.metadata
};
}
toTimestamp(date) {
const seconds = Math.floor(date.getTime() / 1000);
const nanoseconds = (date.getTime() % 1000) * 1000000;
return { seconds, nanoseconds };
}
async isPremiumEnabled() {
// Check if premium augmentations are available
// This would integrate with the license validation system
try {
const augmentations = await this.brainy.listAugmentations();
return augmentations.some((aug) => aug.premium === true && aug.enabled === true);
}
catch {
return false;
}
}
// Public API methods for CLI integration
getCurrentSessionId() {
return this.currentSessionId;
}
getCurrentSession() {
return this.currentSessionId ? this.sessionCache.get(this.currentSessionId) || null : null;
}
}
//# sourceMappingURL=BrainyChat.js.map