feat: simplify chat CLI with unified command structure
- Replace `brainy chat-session` subcommands with `brainy chat` options - Add --list, --search, --history flags to main chat command - Implement beautiful terminal formatting without external dependencies - Improve user experience with helpful tips and upgrade hints
This commit is contained in:
parent
48e51204c3
commit
427f98cf6a
5 changed files with 1169 additions and 15 deletions
180
bin/brainy.js
180
bin/brainy.js
|
|
@ -76,9 +76,39 @@ program
|
|||
|
||||
program
|
||||
.command('add [data]')
|
||||
.description('Add data across multiple dimensions (vector, graph, facets)')
|
||||
.description('🔒 Add data literally (safe, no AI processing)')
|
||||
.option('-m, --metadata <json>', 'Metadata facets as JSON')
|
||||
.option('-i, --id <id>', 'Custom ID')
|
||||
.option('--smart', 'Enable AI processing (same as smart-add command)')
|
||||
.action(wrapAction(async (data, options) => {
|
||||
let metadata = {}
|
||||
if (options.metadata) {
|
||||
try {
|
||||
metadata = JSON.parse(options.metadata)
|
||||
} catch {
|
||||
console.error(chalk.red('Invalid JSON metadata'))
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
if (options.id) {
|
||||
metadata.id = options.id
|
||||
}
|
||||
|
||||
// Use smart processing if --smart flag is provided
|
||||
if (options.smart) {
|
||||
console.log(chalk.dim('🧠 AI processing enabled'))
|
||||
await cortex.addSmart(data, metadata)
|
||||
} else {
|
||||
console.log(chalk.dim('🔒 Literal storage (safe for secrets/API keys)'))
|
||||
await cortex.add(data, metadata)
|
||||
}
|
||||
}))
|
||||
|
||||
program
|
||||
.command('smart-add [data]')
|
||||
.description('🧠 Add data with AI processing (Neural Import, entity detection)')
|
||||
.option('-m, --metadata <json>', 'Metadata facets as JSON')
|
||||
.option('-i, --id <id>', 'Custom ID')
|
||||
.action(wrapAction(async (data, options) => {
|
||||
let metadata = {}
|
||||
if (options.metadata) {
|
||||
|
|
@ -92,7 +122,9 @@ program
|
|||
if (options.id) {
|
||||
metadata.id = options.id
|
||||
}
|
||||
await cortex.add(data, metadata)
|
||||
|
||||
console.log(chalk.dim('🧠 AI processing enabled (Neural Import + entity detection)'))
|
||||
await cortex.addSmart(data, metadata)
|
||||
}))
|
||||
|
||||
program
|
||||
|
|
@ -124,10 +156,44 @@ program
|
|||
|
||||
program
|
||||
.command('chat [question]')
|
||||
.description('AI-powered chat with multi-dimensional context')
|
||||
.option('-l, --llm <model>', 'LLM model to use')
|
||||
.description('🧠 Beautiful AI chat with local memory')
|
||||
.option('-l, --list', 'List all chat sessions')
|
||||
.option('-s, --search <query>', 'Search all conversations')
|
||||
.option('-h, --history [limit]', 'Show conversation history (default: 10)')
|
||||
.option('--session <id>', 'Use specific chat session')
|
||||
.option('--new', 'Start a new session')
|
||||
.option('--role <name>', 'Agent role (premium feature preview)', 'assistant')
|
||||
.action(wrapInteractive(async (question, options) => {
|
||||
await cortex.chat(question)
|
||||
const { BrainyData } = await import('../dist/brainyData.js')
|
||||
const { ChatCLI } = await import('../dist/chat/ChatCLI.js')
|
||||
|
||||
const brainy = new BrainyData()
|
||||
await brainy.init()
|
||||
|
||||
const chatCLI = new ChatCLI(brainy)
|
||||
|
||||
// Handle different modes
|
||||
if (options.list) {
|
||||
await chatCLI.listSessions()
|
||||
} else if (options.search) {
|
||||
await chatCLI.searchConversations(options.search)
|
||||
} else if (options.history) {
|
||||
const limit = typeof options.history === 'string' ? parseInt(options.history) : 10
|
||||
await chatCLI.showHistory(limit)
|
||||
} else if (question) {
|
||||
// Single message mode
|
||||
await chatCLI.sendMessage(question, {
|
||||
sessionId: options.session,
|
||||
speaker: options.role
|
||||
})
|
||||
} else {
|
||||
// Interactive chat mode
|
||||
await chatCLI.startInteractiveChat({
|
||||
sessionId: options.session,
|
||||
speaker: options.role,
|
||||
newSession: options.new
|
||||
})
|
||||
}
|
||||
}))
|
||||
|
||||
program
|
||||
|
|
@ -176,6 +242,8 @@ program
|
|||
await cortex.restore(file)
|
||||
}))
|
||||
|
||||
// Chat commands moved to main chat command above
|
||||
|
||||
// ========================================
|
||||
// BRAIN CLOUD INTEGRATION
|
||||
// ========================================
|
||||
|
|
@ -857,6 +925,99 @@ program
|
|||
await cortex.chat()
|
||||
}))
|
||||
|
||||
// ========================================
|
||||
// AUGMENTATION CONTROL COMMANDS
|
||||
// ========================================
|
||||
|
||||
program
|
||||
.command('augment')
|
||||
.description('List all augmentations with their status')
|
||||
.action(wrapAction(async () => {
|
||||
const { BrainyData } = await import('../dist/brainyData.js')
|
||||
const brainy = new BrainyData()
|
||||
await brainy.init()
|
||||
|
||||
const augmentations = brainy.listAugmentations()
|
||||
|
||||
if (augmentations.length === 0) {
|
||||
console.log(chalk.yellow('No augmentations registered'))
|
||||
return
|
||||
}
|
||||
|
||||
console.log(chalk.cyan('🔧 Augmentations Status\n'))
|
||||
|
||||
const grouped = augmentations.reduce((acc, aug) => {
|
||||
if (!acc[aug.type]) acc[aug.type] = []
|
||||
acc[aug.type].push(aug)
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
for (const [type, augs] of Object.entries(grouped)) {
|
||||
console.log(chalk.bold(`${type.toUpperCase()}:`))
|
||||
for (const aug of augs) {
|
||||
const status = aug.enabled ? chalk.green('✅ enabled') : chalk.red('❌ disabled')
|
||||
console.log(` ${aug.name} - ${status}`)
|
||||
console.log(chalk.dim(` ${aug.description}`))
|
||||
}
|
||||
console.log('')
|
||||
}
|
||||
}))
|
||||
|
||||
program
|
||||
.command('augment enable <name>')
|
||||
.description('Enable an augmentation by name')
|
||||
.action(wrapAction(async (name) => {
|
||||
const { BrainyData } = await import('../dist/brainyData.js')
|
||||
const brainy = new BrainyData()
|
||||
await brainy.init()
|
||||
|
||||
const success = brainy.enableAugmentation(name)
|
||||
|
||||
if (success) {
|
||||
console.log(chalk.green(`✅ Enabled augmentation: ${name}`))
|
||||
} else {
|
||||
console.log(chalk.red(`❌ Augmentation not found: ${name}`))
|
||||
console.log(chalk.dim('Use "brainy augment" to see available augmentations'))
|
||||
}
|
||||
}))
|
||||
|
||||
program
|
||||
.command('augment disable <name>')
|
||||
.description('Disable an augmentation by name')
|
||||
.action(wrapAction(async (name) => {
|
||||
const { BrainyData } = await import('../dist/brainyData.js')
|
||||
const brainy = new BrainyData()
|
||||
await brainy.init()
|
||||
|
||||
const success = brainy.disableAugmentation(name)
|
||||
|
||||
if (success) {
|
||||
console.log(chalk.green(`✅ Disabled augmentation: ${name}`))
|
||||
} else {
|
||||
console.log(chalk.red(`❌ Augmentation not found: ${name}`))
|
||||
console.log(chalk.dim('Use "brainy augment" to see available augmentations'))
|
||||
}
|
||||
}))
|
||||
|
||||
program
|
||||
.command('augment status <name>')
|
||||
.description('Check if an augmentation is enabled')
|
||||
.action(wrapAction(async (name) => {
|
||||
const { BrainyData } = await import('../dist/brainyData.js')
|
||||
const brainy = new BrainyData()
|
||||
await brainy.init()
|
||||
|
||||
const enabled = brainy.isAugmentationEnabled(name)
|
||||
|
||||
if (enabled !== undefined) {
|
||||
const status = enabled ? chalk.green('✅ enabled') : chalk.red('❌ disabled')
|
||||
console.log(`${name}: ${status}`)
|
||||
} else {
|
||||
console.log(chalk.red(`❌ Augmentation not found: ${name}`))
|
||||
console.log(chalk.dim('Use "brainy augment" to see available augmentations'))
|
||||
}
|
||||
}))
|
||||
|
||||
// ========================================
|
||||
// PARSE AND HANDLE
|
||||
// ========================================
|
||||
|
|
@ -872,7 +1033,14 @@ if (!process.argv.slice(2).length) {
|
|||
console.log(' brainy init # Initialize project')
|
||||
console.log(' brainy add "some data" # Add multi-dimensional data')
|
||||
console.log(' brainy search "query" # Search across all dimensions')
|
||||
console.log(' brainy chat # AI chat with full context')
|
||||
console.log(' brainy chat # 🧠 Magical AI chat with perfect memory')
|
||||
console.log('')
|
||||
console.log(chalk.bold('Chat & Memory:'))
|
||||
console.log(' brainy chat # Interactive chat with local memory')
|
||||
console.log(' brainy chat "question" # Single question with context')
|
||||
console.log(' brainy chat --list # List all chat sessions')
|
||||
console.log(' brainy chat --search "query" # Search all conversations')
|
||||
console.log(' brainy chat --history # Show conversation history')
|
||||
console.log('')
|
||||
console.log(chalk.bold('Brain Cloud (Premium):'))
|
||||
console.log(chalk.green(' brainy cloud setup # Auto-setup with provisioning'))
|
||||
|
|
|
|||
504
src/chat/BrainyChat.ts
Normal file
504
src/chat/BrainyChat.ts
Normal file
|
|
@ -0,0 +1,504 @@
|
|||
/**
|
||||
* 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 { BrainyData } from '../brainyData.js'
|
||||
import { NounType, VerbType, type Message, type GraphNoun, type GraphVerb } from '../types/graphTypes.js'
|
||||
|
||||
export interface ChatMessage {
|
||||
id: string
|
||||
content: string
|
||||
speaker: 'user' | 'assistant' | string // Allow custom speaker names for multi-agent
|
||||
sessionId: string
|
||||
timestamp: Date
|
||||
metadata?: {
|
||||
model?: string
|
||||
usage?: {
|
||||
prompt_tokens?: number
|
||||
completion_tokens?: number
|
||||
}
|
||||
context?: Record<string, any>
|
||||
}
|
||||
}
|
||||
|
||||
export interface ChatSession {
|
||||
id: string
|
||||
title?: string
|
||||
createdAt: Date
|
||||
lastMessageAt: Date
|
||||
messageCount: number
|
||||
participants: string[]
|
||||
metadata?: {
|
||||
tags?: string[]
|
||||
summary?: string
|
||||
archived?: boolean
|
||||
premium?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhanced BrainyChat with automatic context loading and intelligent memory
|
||||
*
|
||||
* This extends basic chat functionality with premium features when available
|
||||
*/
|
||||
export class BrainyChat {
|
||||
private brainy: BrainyData
|
||||
private currentSessionId: string | null = null
|
||||
private sessionCache = new Map<string, ChatSession>()
|
||||
|
||||
constructor(brainy: BrainyData) {
|
||||
this.brainy = brainy
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize chat system and auto-discover last session
|
||||
* Uses Brainy's advanced search to find the most recent conversation
|
||||
*/
|
||||
async initialize(): Promise<ChatSession | null> {
|
||||
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: any) {
|
||||
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?: string, participants: string[] = ['user', 'assistant']): Promise<ChatSession> {
|
||||
const sessionId = `chat-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
||||
const session: ChatSession = {
|
||||
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: string,
|
||||
speaker: string = 'user',
|
||||
metadata?: ChatMessage['metadata']
|
||||
): Promise<ChatMessage> {
|
||||
if (!this.currentSessionId) {
|
||||
await this.startNewSession()
|
||||
}
|
||||
|
||||
const messageId = `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
||||
const timestamp = new Date()
|
||||
|
||||
const message: ChatMessage = {
|
||||
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: number = 50): Promise<ChatMessage[]> {
|
||||
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: any) => 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: string,
|
||||
options?: {
|
||||
sessionId?: string
|
||||
speaker?: string
|
||||
limit?: number
|
||||
semanticSearch?: boolean
|
||||
}
|
||||
): Promise<ChatMessage[]> {
|
||||
const metadata: Record<string, any> = {
|
||||
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: any) => 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: number = 20): Promise<ChatSession[]> {
|
||||
try {
|
||||
const sessionNouns = await this.brainy.search(
|
||||
'',
|
||||
limit,
|
||||
{
|
||||
nounTypes: [NounType.Concept],
|
||||
metadata: {
|
||||
sessionType: 'chat'
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return sessionNouns.map((noun: any) => 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: string): Promise<ChatSession | null> {
|
||||
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: string): Promise<boolean> {
|
||||
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: string): Promise<string | null> {
|
||||
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
|
||||
|
||||
private async createMessageRelationships(messageId: string): Promise<void> {
|
||||
// Link message to session using BrainyData addVerb() method
|
||||
await this.brainy.addVerb(
|
||||
messageId,
|
||||
this.currentSessionId!,
|
||||
undefined,
|
||||
{
|
||||
type: VerbType.PartOf,
|
||||
metadata: {
|
||||
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,
|
||||
undefined,
|
||||
{
|
||||
type: VerbType.Precedes,
|
||||
metadata: {
|
||||
relationship: 'message-sequence'
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private async loadSession(sessionId: string): Promise<ChatSession | null> {
|
||||
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
|
||||
}
|
||||
|
||||
private async getHistoryForSession(sessionId: string, limit: number = 50): Promise<ChatMessage[]> {
|
||||
try {
|
||||
const messageNouns = await this.brainy.search(
|
||||
'',
|
||||
limit,
|
||||
{
|
||||
nounTypes: [NounType.Message],
|
||||
metadata: {
|
||||
sessionId: sessionId,
|
||||
messageType: 'chat'
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return messageNouns.map((noun: any) => this.nounToChatMessage(noun))
|
||||
} catch (error) {
|
||||
console.error('Error retrieving session history:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
private async updateSessionMetadata(): Promise<void> {
|
||||
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')
|
||||
}
|
||||
|
||||
private nounToChatMessage(noun: any): ChatMessage {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
private nounToChatSession(noun: any): ChatSession {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
private toTimestamp(date: Date): { seconds: number; nanoseconds: number } {
|
||||
const seconds = Math.floor(date.getTime() / 1000)
|
||||
const nanoseconds = (date.getTime() % 1000) * 1000000
|
||||
return { seconds, nanoseconds }
|
||||
}
|
||||
|
||||
private async isPremiumEnabled(): Promise<boolean> {
|
||||
// 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: any) => aug.premium === true && aug.enabled === true)
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Public API methods for CLI integration
|
||||
|
||||
getCurrentSessionId(): string | null {
|
||||
return this.currentSessionId
|
||||
}
|
||||
|
||||
getCurrentSession(): ChatSession | null {
|
||||
return this.currentSessionId ? this.sessionCache.get(this.currentSessionId) || null : null
|
||||
}
|
||||
}
|
||||
428
src/chat/ChatCLI.ts
Normal file
428
src/chat/ChatCLI.ts
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
/**
|
||||
* ChatCLI - Command Line Interface for BrainyChat
|
||||
*
|
||||
* Provides a magical chat experience through the Brainy CLI with:
|
||||
* - Auto-discovery of previous sessions
|
||||
* - Intelligent context loading
|
||||
* - Multi-agent coordination support
|
||||
* - Premium memory sync integration
|
||||
*/
|
||||
|
||||
import { BrainyChat, type ChatSession, type ChatMessage } from './BrainyChat.js'
|
||||
import { BrainyData } from '../brainyData.js'
|
||||
|
||||
// Simple color utility without external dependencies
|
||||
const colors = {
|
||||
cyan: (text: string) => `\x1b[36m${text}\x1b[0m`,
|
||||
green: (text: string) => `\x1b[32m${text}\x1b[0m`,
|
||||
yellow: (text: string) => `\x1b[33m${text}\x1b[0m`,
|
||||
blue: (text: string) => `\x1b[34m${text}\x1b[0m`,
|
||||
gray: (text: string) => `\x1b[90m${text}\x1b[0m`,
|
||||
red: (text: string) => `\x1b[31m${text}\x1b[0m`
|
||||
}
|
||||
|
||||
export class ChatCLI {
|
||||
private brainyChat: BrainyChat
|
||||
private brainy: BrainyData
|
||||
|
||||
constructor(brainy: BrainyData) {
|
||||
this.brainy = brainy
|
||||
this.brainyChat = new BrainyChat(brainy)
|
||||
}
|
||||
|
||||
/**
|
||||
* Start an interactive chat session
|
||||
* Automatically discovers and loads previous context
|
||||
*/
|
||||
async startInteractiveChat(options?: {
|
||||
sessionId?: string
|
||||
speaker?: string
|
||||
memory?: boolean
|
||||
newSession?: boolean
|
||||
}): Promise<void> {
|
||||
console.log(colors.cyan('🧠 Brainy Chat - Local Memory & Intelligence'))
|
||||
console.log()
|
||||
|
||||
let session: ChatSession | null = null
|
||||
|
||||
if (options?.sessionId) {
|
||||
// Load specific session
|
||||
session = await this.brainyChat.switchToSession(options.sessionId)
|
||||
if (session) {
|
||||
console.log(colors.green(`📂 Loaded session: ${session.title || session.id}`))
|
||||
console.log(colors.gray(` Created: ${session.createdAt.toLocaleDateString()}`))
|
||||
console.log(colors.gray(` Messages: ${session.messageCount}`))
|
||||
} else {
|
||||
console.log(colors.yellow(`⚠️ Session ${options.sessionId} not found, starting new session`))
|
||||
}
|
||||
} else if (!options?.newSession) {
|
||||
// Auto-discover last session
|
||||
console.log(colors.gray('🔍 Looking for your last conversation...'))
|
||||
session = await this.brainyChat.initialize()
|
||||
|
||||
if (session) {
|
||||
console.log(colors.green(`✨ Found your last session: ${session.title || 'Untitled'}`))
|
||||
console.log(colors.gray(` Last active: ${session.lastMessageAt.toLocaleString()}`))
|
||||
console.log(colors.gray(` Messages: ${session.messageCount}`))
|
||||
|
||||
// Show recent context if memory option is enabled
|
||||
if (options?.memory !== false) {
|
||||
await this.showRecentContext()
|
||||
}
|
||||
} else {
|
||||
console.log(colors.blue('🆕 No previous sessions found, starting fresh!'))
|
||||
}
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
session = await this.brainyChat.startNewSession(
|
||||
`Chat ${new Date().toLocaleDateString()}`,
|
||||
['user', options?.speaker || 'assistant']
|
||||
)
|
||||
console.log(colors.green(`🎉 Started new session: ${session.id}`))
|
||||
}
|
||||
|
||||
console.log()
|
||||
console.log(colors.gray('💡 Tips:'))
|
||||
console.log(colors.gray(' - Type /history to see conversation history'))
|
||||
console.log(colors.gray(' - Type /search <query> to search all conversations'))
|
||||
console.log(colors.gray(' - Type /sessions to list all sessions'))
|
||||
console.log(colors.gray(' - Type /help for more commands'))
|
||||
console.log(colors.gray(' - Type /quit to exit'))
|
||||
console.log()
|
||||
console.log(colors.blue('🚀 Want multi-agent coordination? Try: brainy cloud auth'))
|
||||
console.log()
|
||||
|
||||
// Start interactive loop
|
||||
await this.interactiveLoop(options?.speaker || 'assistant')
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a single message and get response
|
||||
*/
|
||||
async sendMessage(
|
||||
message: string,
|
||||
options?: {
|
||||
sessionId?: string
|
||||
speaker?: string
|
||||
noResponse?: boolean
|
||||
}
|
||||
): Promise<ChatMessage[]> {
|
||||
if (options?.sessionId) {
|
||||
await this.brainyChat.switchToSession(options.sessionId)
|
||||
}
|
||||
|
||||
// Add user message
|
||||
const userMessage = await this.brainyChat.addMessage(message, 'user')
|
||||
console.log(colors.blue(`👤 You: ${message}`))
|
||||
|
||||
if (options?.noResponse) {
|
||||
return [userMessage]
|
||||
}
|
||||
|
||||
// For CLI usage, we'd integrate with whatever AI service is configured
|
||||
// This is a placeholder showing the architecture
|
||||
const response = await this.generateResponse(message, options?.speaker || 'assistant')
|
||||
const assistantMessage = await this.brainyChat.addMessage(
|
||||
response,
|
||||
options?.speaker || 'assistant',
|
||||
{
|
||||
model: 'claude-3-sonnet',
|
||||
context: { userMessage: userMessage.id }
|
||||
}
|
||||
)
|
||||
|
||||
console.log(colors.green(`🤖 ${options?.speaker || 'Assistant'}: ${response}`))
|
||||
|
||||
return [userMessage, assistantMessage]
|
||||
}
|
||||
|
||||
/**
|
||||
* Show conversation history
|
||||
*/
|
||||
async showHistory(limit: number = 10): Promise<void> {
|
||||
const messages = await this.brainyChat.getHistory(limit)
|
||||
|
||||
if (messages.length === 0) {
|
||||
console.log(colors.yellow('📭 No messages in current session'))
|
||||
return
|
||||
}
|
||||
|
||||
console.log(colors.cyan(`📜 Last ${Math.min(limit, messages.length)} messages:`))
|
||||
console.log()
|
||||
|
||||
for (const message of messages.slice(-limit)) {
|
||||
const timestamp = message.timestamp.toLocaleTimeString()
|
||||
const speakerColor = message.speaker === 'user' ? colors.blue : colors.green
|
||||
const icon = message.speaker === 'user' ? '👤' : '🤖'
|
||||
|
||||
console.log(speakerColor(`${icon} ${message.speaker} (${timestamp}):`))
|
||||
console.log(colors.gray(` ${message.content}`))
|
||||
console.log()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search across all conversations
|
||||
*/
|
||||
async searchConversations(
|
||||
query: string,
|
||||
options?: {
|
||||
limit?: number
|
||||
sessionId?: string
|
||||
semantic?: boolean
|
||||
}
|
||||
): Promise<void> {
|
||||
console.log(colors.cyan(`🔍 Searching for: "${query}"`))
|
||||
|
||||
const results = await this.brainyChat.searchMessages(query, {
|
||||
limit: options?.limit || 10,
|
||||
sessionId: options?.sessionId,
|
||||
semanticSearch: options?.semantic !== false
|
||||
})
|
||||
|
||||
if (results.length === 0) {
|
||||
console.log(colors.yellow('🤷 No matching messages found'))
|
||||
return
|
||||
}
|
||||
|
||||
console.log(colors.green(`✨ Found ${results.length} matches:`))
|
||||
console.log()
|
||||
|
||||
for (const message of results) {
|
||||
const date = message.timestamp.toLocaleDateString()
|
||||
const time = message.timestamp.toLocaleTimeString()
|
||||
const speakerColor = message.speaker === 'user' ? colors.blue : colors.green
|
||||
const icon = message.speaker === 'user' ? '👤' : '🤖'
|
||||
|
||||
console.log(colors.gray(`📅 ${date} ${time} - Session: ${message.sessionId.substring(0, 8)}...`))
|
||||
console.log(speakerColor(`${icon} ${message.speaker}: ${message.content}`))
|
||||
console.log()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all chat sessions
|
||||
*/
|
||||
async listSessions(): Promise<void> {
|
||||
const sessions = await this.brainyChat.getSessions()
|
||||
|
||||
if (sessions.length === 0) {
|
||||
console.log(colors.yellow('📭 No chat sessions found'))
|
||||
return
|
||||
}
|
||||
|
||||
console.log(colors.cyan(`💬 Your chat sessions (${sessions.length}):`))
|
||||
console.log()
|
||||
|
||||
for (const session of sessions) {
|
||||
const isActive = session.id === this.brainyChat.getCurrentSessionId()
|
||||
const activeIndicator = isActive ? colors.green(' ● ACTIVE') : ''
|
||||
const archived = session.metadata?.archived ? colors.gray(' [ARCHIVED]') : ''
|
||||
|
||||
console.log(colors.blue(`📂 ${session.title || 'Untitled'}${activeIndicator}${archived}`))
|
||||
console.log(colors.gray(` ID: ${session.id}`))
|
||||
console.log(colors.gray(` Created: ${session.createdAt.toLocaleDateString()}`))
|
||||
console.log(colors.gray(` Last active: ${session.lastMessageAt.toLocaleDateString()}`))
|
||||
console.log(colors.gray(` Messages: ${session.messageCount}`))
|
||||
console.log(colors.gray(` Participants: ${session.participants.join(', ')}`))
|
||||
console.log()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to a different session
|
||||
*/
|
||||
async switchSession(sessionId: string): Promise<void> {
|
||||
const session = await this.brainyChat.switchToSession(sessionId)
|
||||
|
||||
if (session) {
|
||||
console.log(colors.green(`✅ Switched to session: ${session.title || session.id}`))
|
||||
console.log(colors.gray(` Messages: ${session.messageCount}`))
|
||||
console.log(colors.gray(` Last active: ${session.lastMessageAt.toLocaleString()}`))
|
||||
} else {
|
||||
console.log(colors.red(`❌ Session ${sessionId} not found`))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show help for chat commands
|
||||
*/
|
||||
showHelp(): void {
|
||||
console.log(colors.cyan('🧠 Brainy Chat Commands:'))
|
||||
console.log()
|
||||
console.log(colors.blue('Basic Commands:'))
|
||||
console.log(' /history [limit] - Show conversation history (default: 10 messages)')
|
||||
console.log(' /search <query> - Search all conversations')
|
||||
console.log(' /sessions - List all chat sessions')
|
||||
console.log(' /switch <id> - Switch to a specific session')
|
||||
console.log(' /new - Start a new session')
|
||||
console.log(' /help - Show this help')
|
||||
console.log(' /quit - Exit chat')
|
||||
console.log()
|
||||
|
||||
console.log(colors.yellow('Local Features:'))
|
||||
console.log(' ✨ Automatic session discovery')
|
||||
console.log(' 🧠 Local memory across all conversations')
|
||||
console.log(' 🔍 Semantic search using vector similarity')
|
||||
console.log(' 📊 Standard noun/verb graph relationships')
|
||||
console.log()
|
||||
|
||||
console.log(colors.green('Want More? Premium Features:'))
|
||||
console.log(' 🤝 Multi-agent coordination')
|
||||
console.log(' ☁️ Cross-device memory sync')
|
||||
console.log(' 🎨 Rich web coordination UI')
|
||||
console.log(' 🔄 Real-time team collaboration')
|
||||
console.log()
|
||||
console.log(colors.blue('Get premium: brainy cloud auth'))
|
||||
console.log()
|
||||
}
|
||||
|
||||
// Private methods
|
||||
|
||||
private async interactiveLoop(assistantSpeaker: string = 'assistant'): Promise<void> {
|
||||
const readline = require('readline')
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
})
|
||||
|
||||
const askQuestion = (): Promise<string> => {
|
||||
return new Promise((resolve) => {
|
||||
rl.question(colors.blue('💬 You: '), resolve)
|
||||
})
|
||||
}
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
const input = await askQuestion()
|
||||
|
||||
if (input.trim() === '') continue
|
||||
|
||||
// Handle commands
|
||||
if (input.startsWith('/')) {
|
||||
const [command, ...args] = input.slice(1).split(' ')
|
||||
|
||||
switch (command.toLowerCase()) {
|
||||
case 'quit':
|
||||
case 'exit':
|
||||
console.log(colors.cyan('👋 Thanks for chatting! Your conversation is saved.'))
|
||||
rl.close()
|
||||
return
|
||||
|
||||
case 'history':
|
||||
const limit = args[0] ? parseInt(args[0]) : 10
|
||||
await this.showHistory(limit)
|
||||
break
|
||||
|
||||
case 'search':
|
||||
if (args.length === 0) {
|
||||
console.log(colors.yellow('Usage: /search <query>'))
|
||||
} else {
|
||||
await this.searchConversations(args.join(' '))
|
||||
}
|
||||
break
|
||||
|
||||
case 'sessions':
|
||||
await this.listSessions()
|
||||
break
|
||||
|
||||
case 'switch':
|
||||
if (args.length === 0) {
|
||||
console.log(colors.yellow('Usage: /switch <session-id>'))
|
||||
} else {
|
||||
await this.switchSession(args[0])
|
||||
}
|
||||
break
|
||||
|
||||
case 'new':
|
||||
const newSession = await this.brainyChat.startNewSession(
|
||||
`Chat ${new Date().toLocaleDateString()}`
|
||||
)
|
||||
console.log(colors.green(`🆕 Started new session: ${newSession.id}`))
|
||||
break
|
||||
|
||||
case 'archive':
|
||||
const sessionToArchive = args[0] || this.brainyChat.getCurrentSessionId()
|
||||
if (sessionToArchive) {
|
||||
try {
|
||||
await this.brainyChat.archiveSession(sessionToArchive)
|
||||
console.log(colors.green(`📁 Session archived: ${sessionToArchive}`))
|
||||
} catch (error: any) {
|
||||
console.log(colors.red(`❌ ${error?.message}`))
|
||||
}
|
||||
} else {
|
||||
console.log(colors.yellow('No session to archive'))
|
||||
}
|
||||
break
|
||||
|
||||
case 'summary':
|
||||
const sessionToSummarize = args[0] || this.brainyChat.getCurrentSessionId()
|
||||
if (sessionToSummarize) {
|
||||
try {
|
||||
const summary = await this.brainyChat.generateSessionSummary(sessionToSummarize)
|
||||
if (summary) {
|
||||
console.log(colors.green('📋 Session Summary:'))
|
||||
console.log(colors.gray(summary))
|
||||
} else {
|
||||
console.log(colors.yellow('No summary could be generated'))
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.log(colors.red(`❌ ${error?.message}`))
|
||||
}
|
||||
} else {
|
||||
console.log(colors.yellow('No session to summarize'))
|
||||
}
|
||||
break
|
||||
|
||||
case 'help':
|
||||
this.showHelp()
|
||||
break
|
||||
|
||||
default:
|
||||
console.log(colors.yellow(`Unknown command: ${command}`))
|
||||
console.log(colors.gray('Type /help for available commands'))
|
||||
}
|
||||
} else {
|
||||
// Regular message
|
||||
await this.sendMessage(input, { speaker: assistantSpeaker })
|
||||
}
|
||||
|
||||
console.log()
|
||||
} catch (error: any) {
|
||||
console.error(colors.red(`Error: ${error?.message}`))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async showRecentContext(limit: number = 3): Promise<void> {
|
||||
const recentMessages = await this.brainyChat.getHistory(limit)
|
||||
|
||||
if (recentMessages.length > 0) {
|
||||
console.log(colors.gray('💭 Recent context:'))
|
||||
for (const msg of recentMessages.slice(-limit)) {
|
||||
const preview = msg.content.length > 60
|
||||
? msg.content.substring(0, 60) + '...'
|
||||
: msg.content
|
||||
console.log(colors.gray(` ${msg.speaker}: ${preview}`))
|
||||
}
|
||||
console.log()
|
||||
}
|
||||
}
|
||||
|
||||
private async generateResponse(message: string, speaker: string): Promise<string> {
|
||||
// This is a placeholder for AI integration
|
||||
// In a real implementation, this would call the configured AI service
|
||||
// and could include multi-agent coordination
|
||||
|
||||
// Example responses for demonstration
|
||||
const responses = [
|
||||
"I remember our conversation and can help with that!",
|
||||
"Based on our previous discussions, I think...",
|
||||
"Let me search through our chat history for relevant context.",
|
||||
"I can coordinate with other AI agents if needed for this task."
|
||||
]
|
||||
|
||||
return responses[Math.floor(Math.random() * responses.length)]
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { BrainyData } from '../brainyData.js'
|
||||
import { BrainyChat } from '../chat/brainyChat.js'
|
||||
import { BrainyChat } from '../chat/BrainyChat.js'
|
||||
import { PerformanceMonitor } from './performanceMonitor.js'
|
||||
import { HealthCheck } from './healthCheck.js'
|
||||
// Licensing system moved to quantum-vault
|
||||
|
|
@ -603,6 +603,61 @@ export class Cortex {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add data with AI processing enabled (Neural Import + entity detection)
|
||||
*/
|
||||
async addSmart(data?: string, metadata?: any): Promise<void> {
|
||||
await this.ensureInitialized()
|
||||
|
||||
// Interactive mode if no data provided
|
||||
if (!data) {
|
||||
const responses = await prompts([
|
||||
{
|
||||
type: 'text',
|
||||
name: 'data',
|
||||
message: `${emojis.brain} Enter data for AI processing:`
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'id',
|
||||
message: 'ID (optional, press enter to auto-generate):'
|
||||
},
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'hasMetadata',
|
||||
message: 'Add metadata?',
|
||||
initial: false
|
||||
},
|
||||
{
|
||||
type: (prev: any) => prev ? 'text' : null,
|
||||
name: 'metadata',
|
||||
message: 'Enter metadata (JSON format):'
|
||||
}
|
||||
])
|
||||
|
||||
data = responses.data
|
||||
if (responses.metadata) {
|
||||
try {
|
||||
metadata = JSON.parse(responses.metadata)
|
||||
} catch {
|
||||
console.log(colors.warning('Invalid JSON, skipping metadata'))
|
||||
}
|
||||
}
|
||||
if (responses.id) {
|
||||
metadata = { ...metadata, id: responses.id }
|
||||
}
|
||||
}
|
||||
|
||||
const spinner = ora('🧠 Processing with AI...').start()
|
||||
try {
|
||||
const id = await this.brainy!.addSmart(data, metadata)
|
||||
spinner.succeed(colors.success(`${emojis.check} Processed with AI and added with ID: ${id}`))
|
||||
} catch (error) {
|
||||
spinner.fail('Failed to add data with AI processing')
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search with beautiful results display and advanced options
|
||||
*/
|
||||
|
|
@ -1899,8 +1954,8 @@ export class Cortex {
|
|||
await this.ensureInitialized()
|
||||
|
||||
// Import and create the Cortex SENSE augmentation
|
||||
const { CortexSenseAugmentation } = await import('../augmentations/cortexSense.js')
|
||||
const neuralSense = new CortexSenseAugmentation(this.brainy!, options)
|
||||
const { NeuralImportAugmentation } = await import('../augmentations/neuralImport.js')
|
||||
const neuralSense = new NeuralImportAugmentation(this.brainy!, options)
|
||||
|
||||
// Initialize the augmentation
|
||||
await neuralSense.initialize()
|
||||
|
|
@ -1942,8 +1997,8 @@ export class Cortex {
|
|||
async neuralAnalyze(filePath: string): Promise<void> {
|
||||
await this.ensureInitialized()
|
||||
|
||||
const { CortexSenseAugmentation } = await import('../augmentations/cortexSense.js')
|
||||
const neuralSense = new CortexSenseAugmentation(this.brainy!)
|
||||
const { NeuralImportAugmentation } = await import('../augmentations/neuralImport.js')
|
||||
const neuralSense = new NeuralImportAugmentation(this.brainy!)
|
||||
|
||||
await neuralSense.initialize()
|
||||
|
||||
|
|
@ -1982,8 +2037,8 @@ export class Cortex {
|
|||
async neuralValidate(filePath: string): Promise<void> {
|
||||
await this.ensureInitialized()
|
||||
|
||||
const { CortexSenseAugmentation } = await import('../augmentations/cortexSense.js')
|
||||
const neuralSense = new CortexSenseAugmentation(this.brainy!)
|
||||
const { NeuralImportAugmentation } = await import('../augmentations/neuralImport.js')
|
||||
const neuralSense = new NeuralImportAugmentation(this.brainy!)
|
||||
|
||||
await neuralSense.initialize()
|
||||
|
||||
|
|
|
|||
|
|
@ -72,9 +72,8 @@ import {
|
|||
} from './utils/logger.js'
|
||||
|
||||
// Export BrainyChat for conversational AI
|
||||
import { BrainyChat, ChatOptions } from './chat/brainyChat.js'
|
||||
import { BrainyChat } from './chat/BrainyChat.js'
|
||||
export { BrainyChat }
|
||||
export type { ChatOptions }
|
||||
|
||||
// Export Cortex CLI functionality - commented out for core MIT build
|
||||
// export { Cortex } from './cortex/cortex.js'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue