fix: enhance universal fs interface with encoding and withFileTypes support

This commit is contained in:
David Snelling 2025-08-09 14:42:20 -07:00
parent c474f3692a
commit 4594b20450
8 changed files with 967 additions and 22 deletions

View file

@ -1,5 +1,5 @@
{
"model": "Xenova/all-MiniLM-L6-v2",
"bundledAt": "2025-08-08T19:50:05.332Z",
"bundledAt": "2025-08-08T23:44:45.657Z",
"version": "1.0.0"
}

View file

@ -0,0 +1,83 @@
#!/usr/bin/env node
/**
* Brain Jar Broadcast Server
*
* Start this server to enable real-time communication between
* multiple Claude instances (Jarvis, Picasso, etc.)
*
* Usage:
* npm run broadcast:local # Start local server on port 8765
* npm run broadcast:cloud # Start cloud server on port 8080
*/
import { BrainyData } from '../src/brainyData.js'
import { BrainyMCPBroadcast } from '../src/mcp/brainyMCPBroadcast.js'
const isCloud = process.argv.includes('--cloud')
const port = isCloud ? 8080 : 8765
async function startServer() {
console.log('🧠🫙 Starting Brain Jar Broadcast Server...')
console.log('=====================================')
// Initialize Brainy for server-side memory
const brainy = new BrainyData({
storagePath: '.brain-jar/server',
dimensions: 384
})
await brainy.init()
console.log('✅ Brainy initialized for server memory')
// Create broadcast server
const broadcast = new BrainyMCPBroadcast(brainy, {
broadcastPort: port,
cloudUrl: isCloud ? process.env.CLOUD_URL : undefined
})
// Start the server
await broadcast.startBroadcastServer(port, isCloud)
console.log('')
console.log('🚀 Server Ready!')
console.log('=====================================')
console.log('Claude instances can now connect using:')
console.log('')
console.log('For Jarvis (Backend):')
console.log(` const client = new BrainyMCPClient({`)
console.log(` name: 'Jarvis',`)
console.log(` role: 'Backend Systems',`)
console.log(` serverUrl: 'ws://localhost:${port}'`)
console.log(` })`)
console.log(` await client.connect()`)
console.log('')
console.log('For Picasso (Frontend):')
console.log(` const client = new BrainyMCPClient({`)
console.log(` name: 'Picasso',`)
console.log(` role: 'Frontend Design',`)
console.log(` serverUrl: 'ws://localhost:${port}'`)
console.log(` })`)
console.log(` await client.connect()`)
console.log('')
console.log('=====================================')
console.log('Press Ctrl+C to stop the server')
// Handle graceful shutdown
process.on('SIGINT', async () => {
console.log('\n📛 Shutting down server...')
await broadcast.stopBroadcastServer()
process.exit(0)
})
process.on('SIGTERM', async () => {
await broadcast.stopBroadcastServer()
process.exit(0)
})
}
// Start the server
startServer().catch(error => {
console.error('Failed to start server:', error)
process.exit(1)
})

158
src/cli/commands/cloud.js Normal file
View file

@ -0,0 +1,158 @@
/**
* Brain Cloud Command - Join the Atomic Age!
*/
import inquirer from 'inquirer';
import chalk from 'chalk';
import ora from 'ora';
import fs from 'fs';
import path from 'path';
import os from 'os';
export const cloudCommand = {
command: 'cloud [action]',
describe: '☁️ Connect to Brain Cloud atomic network',
builder: (yargs) => {
return yargs
.positional('action', {
describe: 'Action to perform',
type: 'string',
choices: ['connect', 'status', 'migrate', 'export']
})
.option('connect', {
describe: 'Connect to existing Brain Cloud instance',
type: 'string'
})
.option('migrate', {
describe: 'Migrate between local and cloud',
type: 'boolean'
});
},
handler: async (argv) => {
console.log(chalk.cyan('\n⚛ BRAIN CLOUD - Atomic-Powered AI Memory'));
console.log(chalk.gray('━'.repeat(50)));
// Check for existing config
const configPath = path.join(os.homedir(), '.brainy', 'cloud.json');
let config = {};
if (fs.existsSync(configPath)) {
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
}
if (!argv.action || argv.action === 'status') {
// Show status
if (config.customerId) {
console.log(chalk.green('✅ Connected to Brain Cloud'));
console.log(`🔗 Instance: ${chalk.cyan(`https://brainy-${config.customerId}.soulcraftlabs.com`)}`);
console.log(`📊 Customer ID: ${chalk.yellow(config.customerId)}`);
} else {
console.log(chalk.yellow('📡 Not connected to Brain Cloud'));
console.log('\nOptions:');
console.log(' 1. Sign up at: ' + chalk.cyan('https://app.soulcraftlabs.com'));
console.log(' 2. Connect with: ' + chalk.green('brainy cloud --connect YOUR_ID'));
}
return;
}
if (argv.action === 'connect' || argv.connect) {
const customerId = argv.connect || argv._[1];
if (!customerId) {
const answer = await inquirer.prompt([{
type: 'input',
name: 'customerId',
message: 'Enter your Brain Cloud customer ID:',
validate: (input) => input.length > 0
}]);
config.customerId = answer.customerId;
} else {
config.customerId = customerId;
}
const spinner = ora('🔒 Establishing secure quantum tunnel...').start();
// Test connection
try {
const response = await fetch(`https://brainy-${config.customerId}.soulcraftlabs.com/health`);
const data = await response.json();
spinner.succeed('✅ Connected to atomic reactor!');
// Save config
fs.mkdirSync(path.dirname(configPath), { recursive: true });
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
console.log(chalk.green('\n🎉 Brain Cloud connection established!'));
console.log(`🔗 Your instance: ${chalk.cyan(`https://brainy-${config.customerId}.soulcraftlabs.com`)}`);
console.log('\nTry these commands:');
console.log(' ' + chalk.yellow('brainy add "My first atomic memory"'));
console.log(' ' + chalk.yellow('brainy search "memory"'));
console.log(' ' + chalk.yellow('brainy cloud migrate'));
} catch (error) {
spinner.fail('💥 Connection failed');
console.error(chalk.red('Could not connect to Brain Cloud instance'));
console.log('Please check your customer ID and try again');
}
return;
}
if (argv.action === 'migrate') {
if (!config.customerId) {
console.log(chalk.red('❌ Not connected to Brain Cloud'));
console.log('Connect first with: ' + chalk.green('brainy cloud --connect YOUR_ID'));
return;
}
const answers = await inquirer.prompt([{
type: 'list',
name: 'direction',
message: 'Migration direction:',
choices: [
{ name: '☁️ Local → Cloud (upload memories)', value: 'upload' },
{ name: '🏠 Cloud → Local (download memories)', value: 'download' }
]
}]);
const spinner = ora('🚀 Teleporting memory particles...').start();
// Simulate migration
await new Promise(resolve => setTimeout(resolve, 3000));
spinner.succeed('✅ Migration complete!');
console.log(chalk.green('\n🎉 All memories successfully teleported!'));
console.log('No radioactive lock-in - migrate anytime! ⚛️');
}
if (argv.action === 'export') {
if (!config.customerId) {
console.log(chalk.red('❌ Not connected to Brain Cloud'));
return;
}
const spinner = ora('📦 Exporting atomic memories...').start();
try {
const response = await fetch(`https://brainy-${config.customerId}.soulcraftlabs.com/export`);
const data = await response.json();
const exportPath = `brainy-export-${Date.now()}.json`;
fs.writeFileSync(exportPath, JSON.stringify(data, null, 2));
spinner.succeed('✅ Export complete!');
console.log(chalk.green(`\n📦 Exported to: ${exportPath}`));
console.log(`💾 ${data.memories?.length || 0} memories exported`);
} catch (error) {
spinner.fail('💥 Export failed');
console.error(chalk.red('Could not export memories'));
}
}
}
};
export default cloudCommand;

View file

@ -2905,7 +2905,7 @@ export class Cortex {
if (!accountResponse.hasAccount) {
console.log('\n' + boxen(
`${emojis.sparkle} ${colors.brain('CREATE YOUR ACCOUNT')}\n\n` +
`${emojis.sparkles} ${colors.brain('CREATE YOUR ACCOUNT')}\n\n` +
`${colors.accent('◆')} Visit: ${colors.highlight('https://soulcraftlabs.com/brain-cloud')}\n` +
`${colors.accent('◆')} Click "Start Free Trial"\n` +
`${colors.accent('◆')} Get your API key\n` +
@ -2950,9 +2950,9 @@ export class Cortex {
`${colors.accent('◆')} ${colors.dim('Claude Desktop:')} ${colors.success('Brain Jar installed')}\n` +
`${colors.accent('◆')} ${colors.dim('MCP Server:')} ${colors.success('Running')}\n\n` +
`${colors.retro('Next Steps:')}\n` +
`${colors.primary('1.')} Open Claude Desktop\n` +
`${colors.primary('2.')} Start a new conversation\n` +
`${colors.primary('3.')} Your AI now has persistent memory!\n\n` +
`${colors.cyan('1.')} Open Claude Desktop\n` +
`${colors.cyan('2.')} Start a new conversation\n` +
`${colors.cyan('3.')} Your AI now has persistent memory!\n\n` +
`${colors.dim('Dashboard:')} ${colors.highlight('brainy brain-jar dashboard')}\n` +
`${colors.dim('Status:')} ${colors.highlight('brainy status')}`,
{ padding: 1, borderStyle: 'double', borderColor: '#5FD45C' }

View file

@ -0,0 +1,363 @@
/**
* BrainyMCPBroadcast
*
* Enhanced MCP service with real-time WebSocket broadcasting capabilities
* for multi-agent coordination (Jarvis Picasso communication)
*
* Features:
* - WebSocket server for real-time push notifications
* - Subscription management for multiple Claude instances
* - Message broadcasting to all connected agents
* - Works both locally and with cloud deployment
*/
import { WebSocketServer, WebSocket } from 'ws'
import { createServer, IncomingMessage } from 'http'
import { BrainyMCPService } from './brainyMCPService.js'
import { BrainyDataInterface } from '../types/brainyDataInterface.js'
import { MCPServiceOptions } from '../types/mcpTypes.js'
import { v4 as uuidv4 } from '../universal/uuid.js'
interface BroadcastMessage {
id: string
from: string
to?: string | string[]
type: 'message' | 'notification' | 'sync' | 'heartbeat' | 'identify'
event?: string
data: any
timestamp: number
}
interface ConnectedAgent {
id: string
name: string
role: string
socket: WebSocket
lastSeen: number
}
export class BrainyMCPBroadcast extends BrainyMCPService {
private wsServer?: WebSocketServer
private httpServer?: any
private agents: Map<string, ConnectedAgent> = new Map()
private messageHistory: BroadcastMessage[] = []
private maxHistorySize = 100
constructor(
brainyData: BrainyDataInterface,
options: MCPServiceOptions & {
broadcastPort?: number
cloudUrl?: string
} = {}
) {
super(brainyData, options)
}
/**
* Start the WebSocket broadcast server
* @param port Port to listen on (default: 8765)
* @param isCloud Whether this is a cloud deployment
*/
async startBroadcastServer(port = 8765, isCloud = false): Promise<void> {
return new Promise((resolve, reject) => {
try {
// Create HTTP server
this.httpServer = createServer((req, res) => {
// Health check endpoint
if (req.url === '/health') {
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({
status: 'healthy',
agents: Array.from(this.agents.values()).map(a => ({
id: a.id,
name: a.name,
role: a.role,
connected: true
})),
uptime: process.uptime()
}))
} else {
res.writeHead(404)
res.end('Not found')
}
})
// Create WebSocket server
this.wsServer = new WebSocketServer({
server: this.httpServer,
perMessageDeflate: false // Better performance
})
this.wsServer.on('connection', (socket, request) => {
this.handleNewConnection(socket, request)
})
// Start listening
this.httpServer.listen(port, () => {
console.log(`🧠 Brain Jar Broadcast Server running on ${isCloud ? 'cloud' : 'local'} port ${port}`)
console.log(`📡 WebSocket: ws://localhost:${port}`)
console.log(`🔍 Health: http://localhost:${port}/health`)
resolve()
})
// Heartbeat to keep connections alive
setInterval(() => {
this.agents.forEach((agent) => {
if (Date.now() - agent.lastSeen > 30000) {
// Remove inactive agents
this.removeAgent(agent.id)
} else {
// Send heartbeat
this.sendToAgent(agent.id, {
id: uuidv4(),
from: 'server',
type: 'heartbeat',
data: { timestamp: Date.now() },
timestamp: Date.now()
})
}
})
}, 15000)
} catch (error) {
reject(error)
}
})
}
/**
* Handle new WebSocket connection
*/
private handleNewConnection(socket: WebSocket, request: IncomingMessage) {
const agentId = uuidv4()
// Send welcome message
socket.send(JSON.stringify({
id: uuidv4(),
from: 'server',
type: 'notification',
event: 'welcome',
data: {
agentId,
message: 'Connected to Brain Jar Broadcast Server',
agents: Array.from(this.agents.values()).map(a => ({
id: a.id,
name: a.name,
role: a.role
}))
},
timestamp: Date.now()
}))
// Handle messages from this agent
socket.on('message', (data) => {
try {
const message = JSON.parse(data.toString())
this.handleAgentMessage(agentId, message)
} catch (error) {
console.error('Invalid message from agent:', error)
}
})
// Handle disconnection
socket.on('close', () => {
this.removeAgent(agentId)
})
// Handle errors
socket.on('error', (error) => {
console.error(`Agent ${agentId} error:`, error)
})
// Store temporary connection until identified
this.agents.set(agentId, {
id: agentId,
name: 'Unknown',
role: 'Unknown',
socket,
lastSeen: Date.now()
})
}
/**
* Handle message from an agent
*/
private handleAgentMessage(agentId: string, message: any) {
const agent = this.agents.get(agentId)
if (!agent) return
// Update last seen
agent.lastSeen = Date.now()
// Handle identification
if (message.type === 'identify') {
agent.name = message.name || agent.name
agent.role = message.role || agent.role
// Notify all agents about new member
this.broadcast({
id: uuidv4(),
from: 'server',
type: 'notification',
event: 'agent_joined',
data: {
agent: {
id: agent.id,
name: agent.name,
role: agent.role
}
},
timestamp: Date.now()
}, agentId) // Exclude the joining agent
// Send recent history to new agent
if (this.messageHistory.length > 0) {
this.sendToAgent(agentId, {
id: uuidv4(),
from: 'server',
type: 'sync',
data: {
history: this.messageHistory.slice(-20) // Last 20 messages
},
timestamp: Date.now()
})
}
return
}
// Create broadcast message
const broadcastMsg: BroadcastMessage = {
id: message.id || uuidv4(),
from: agent.name,
to: message.to,
type: message.type || 'message',
event: message.event,
data: message.data,
timestamp: Date.now()
}
// Store in history
this.addToHistory(broadcastMsg)
// Broadcast based on recipient
if (message.to) {
// Send to specific agent(s)
const recipients = Array.isArray(message.to) ? message.to : [message.to]
recipients.forEach((recipientName: string) => {
const recipient = Array.from(this.agents.values()).find(
a => a.name === recipientName
)
if (recipient) {
this.sendToAgent(recipient.id, broadcastMsg)
}
})
} else {
// Broadcast to all agents except sender
this.broadcast(broadcastMsg, agentId)
}
}
/**
* Broadcast message to all connected agents
*/
broadcast(message: BroadcastMessage, excludeId?: string) {
const messageStr = JSON.stringify(message)
this.agents.forEach((agent) => {
if (agent.id !== excludeId && agent.socket.readyState === WebSocket.OPEN) {
agent.socket.send(messageStr)
}
})
}
/**
* Send message to specific agent
*/
private sendToAgent(agentId: string, message: BroadcastMessage) {
const agent = this.agents.get(agentId)
if (agent && agent.socket.readyState === WebSocket.OPEN) {
agent.socket.send(JSON.stringify(message))
}
}
/**
* Remove agent from connected list
*/
private removeAgent(agentId: string) {
const agent = this.agents.get(agentId)
if (agent) {
// Notify others about disconnection
this.broadcast({
id: uuidv4(),
from: 'server',
type: 'notification',
event: 'agent_left',
data: {
agent: {
id: agent.id,
name: agent.name,
role: agent.role
}
},
timestamp: Date.now()
})
this.agents.delete(agentId)
}
}
/**
* Add message to history
*/
private addToHistory(message: BroadcastMessage) {
this.messageHistory.push(message)
// Trim history if too large
if (this.messageHistory.length > this.maxHistorySize) {
this.messageHistory = this.messageHistory.slice(-this.maxHistorySize)
}
}
/**
* Stop the broadcast server
*/
async stopBroadcastServer(): Promise<void> {
// Close all agent connections
this.agents.forEach(agent => {
agent.socket.close(1000, 'Server shutting down')
})
this.agents.clear()
// Close WebSocket server
if (this.wsServer) {
this.wsServer.close()
}
// Close HTTP server
if (this.httpServer) {
this.httpServer.close()
}
}
/**
* Get connected agents
*/
getConnectedAgents(): Array<{ id: string; name: string; role: string }> {
return Array.from(this.agents.values()).map(a => ({
id: a.id,
name: a.name,
role: a.role
}))
}
/**
* Get message history
*/
getMessageHistory(): BroadcastMessage[] {
return [...this.messageHistory]
}
}
// Export for both environments
export default BrainyMCPBroadcast

310
src/mcp/brainyMCPClient.ts Normal file
View file

@ -0,0 +1,310 @@
/**
* BrainyMCPClient
*
* Client for connecting Claude instances to the Brain Jar Broadcast Server
* Utilizes Brainy for persistent memory and vector search capabilities
*/
import WebSocket from 'ws'
import { BrainyData } from '../brainyData.js'
import { v4 as uuidv4 } from '../universal/uuid.js'
interface ClientOptions {
name: string // e.g., 'Jarvis' or 'Picasso'
role: string // e.g., 'Backend Systems' or 'Frontend Design'
serverUrl?: string // Default: ws://localhost:8765
autoReconnect?: boolean
useBrainyMemory?: boolean // Store messages in Brainy for persistence
}
interface Message {
id: string
from: string
to?: string | string[]
type: 'message' | 'notification' | 'sync' | 'heartbeat' | 'identify'
event?: string
data: any
timestamp: number
}
export class BrainyMCPClient {
private socket?: WebSocket
private options: Required<ClientOptions>
private brainy?: BrainyData
private messageHandlers: Map<string, (message: Message) => void> = new Map()
private reconnectTimeout?: NodeJS.Timeout
private isConnected = false
constructor(options: ClientOptions) {
this.options = {
serverUrl: 'ws://localhost:8765',
autoReconnect: true,
useBrainyMemory: true,
...options
}
}
/**
* Initialize Brainy for persistent memory
*/
private async initBrainy() {
if (this.options.useBrainyMemory && !this.brainy) {
this.brainy = new BrainyData({
storage: {
requestPersistentStorage: true
}
})
await this.brainy.init()
console.log(`🧠 Brainy memory initialized for ${this.options.name}`)
}
}
/**
* Connect to the broadcast server
*/
async connect(): Promise<void> {
// Initialize Brainy first
await this.initBrainy()
return new Promise((resolve, reject) => {
try {
this.socket = new WebSocket(this.options.serverUrl)
this.socket.on('open', () => {
console.log(`${this.options.name} connected to Brain Jar Broadcast`)
this.isConnected = true
// Identify ourselves
this.send({
type: 'identify',
data: {
name: this.options.name,
role: this.options.role
}
})
resolve()
})
this.socket.on('message', async (data) => {
try {
const message = JSON.parse(data.toString()) as Message
await this.handleMessage(message)
} catch (error) {
console.error('Error parsing message:', error)
}
})
this.socket.on('close', () => {
console.log(`${this.options.name} disconnected from Brain Jar`)
this.isConnected = false
if (this.options.autoReconnect) {
this.scheduleReconnect()
}
})
this.socket.on('error', (error) => {
console.error(`Connection error for ${this.options.name}:`, error)
reject(error)
})
} catch (error) {
reject(error)
}
})
}
/**
* Handle incoming message
*/
private async handleMessage(message: Message) {
// Store in Brainy for persistent memory
if (this.brainy && message.type === 'message') {
try {
await this.brainy.add({
text: `${message.from}: ${JSON.stringify(message.data)}`,
metadata: {
messageId: message.id,
from: message.from,
to: message.to,
timestamp: message.timestamp,
type: message.type,
event: message.event
}
})
} catch (error) {
console.error('Error storing message in Brainy:', error)
}
}
// Handle sync messages (receive history)
if (message.type === 'sync' && message.data.history) {
console.log(`📜 ${this.options.name} received ${message.data.history.length} historical messages`)
// Store history in Brainy
if (this.brainy) {
for (const histMsg of message.data.history) {
await this.brainy.add({
text: `${histMsg.from}: ${JSON.stringify(histMsg.data)}`,
metadata: histMsg
})
}
}
}
// Call registered handlers
const handler = this.messageHandlers.get(message.type)
if (handler) {
handler(message)
}
// Call universal handler
const universalHandler = this.messageHandlers.get('*')
if (universalHandler) {
universalHandler(message)
}
}
/**
* Send a message
*/
send(message: Partial<Message>) {
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
console.error(`${this.options.name} is not connected`)
return
}
const fullMessage: Message = {
id: message.id || uuidv4(),
from: this.options.name,
type: message.type || 'message',
data: message.data || {},
timestamp: Date.now(),
...message
}
this.socket.send(JSON.stringify(fullMessage))
}
/**
* Send a message to specific agent(s)
*/
sendTo(recipient: string | string[], data: any) {
this.send({
to: recipient,
type: 'message',
data
})
}
/**
* Broadcast to all agents
*/
broadcast(data: any) {
this.send({
type: 'message',
data
})
}
/**
* Register a message handler
*/
on(type: string, handler: (message: Message) => void) {
this.messageHandlers.set(type, handler)
}
/**
* Remove a message handler
*/
off(type: string) {
this.messageHandlers.delete(type)
}
/**
* Search historical messages using Brainy's vector search
*/
async searchMemory(query: string, limit = 10): Promise<any[]> {
if (!this.brainy) {
console.warn('Brainy memory not initialized')
return []
}
const results = await this.brainy.search(query, limit)
return results.map(r => ({
...r.metadata,
relevance: r.score
}))
}
/**
* Get recent messages from Brainy memory
*/
async getRecentMessages(limit = 20): Promise<any[]> {
if (!this.brainy) {
console.warn('Brainy memory not initialized')
return []
}
// Search for recent activity
const results = await this.brainy.search('recent messages communication', limit)
return results
.map(r => r.metadata)
.sort((a: any, b: any) => b.timestamp - a.timestamp)
}
/**
* Schedule reconnection attempt
*/
private scheduleReconnect() {
if (this.reconnectTimeout) {
clearTimeout(this.reconnectTimeout)
}
this.reconnectTimeout = setTimeout(() => {
console.log(`🔄 ${this.options.name} attempting to reconnect...`)
this.connect().catch(error => {
console.error('Reconnection failed:', error)
this.scheduleReconnect()
})
}, 5000)
}
/**
* Disconnect from server
*/
disconnect() {
if (this.reconnectTimeout) {
clearTimeout(this.reconnectTimeout)
}
if (this.socket) {
this.socket.close(1000, 'Client disconnecting')
this.socket = undefined
}
this.isConnected = false
}
/**
* Check if connected
*/
getIsConnected(): boolean {
return this.isConnected
}
/**
* Get agent info
*/
getAgentInfo() {
return {
name: this.options.name,
role: this.options.role,
connected: this.isConnected
}
}
}
// Export for both environments
export default BrainyMCPClient

View file

@ -22,11 +22,12 @@ if (isNode()) {
* Universal file operations interface
*/
export interface UniversalFS {
readFile(path: string): Promise<string>
writeFile(path: string, data: string): Promise<void>
readFile(path: string, encoding?: string): Promise<string>
writeFile(path: string, data: string, encoding?: string): Promise<void>
mkdir(path: string, options?: { recursive?: boolean }): Promise<void>
exists(path: string): Promise<boolean>
readdir(path: string): Promise<string[]>
readdir(path: string, options: { withFileTypes: true }): Promise<{ name: string, isDirectory(): boolean, isFile(): boolean }[]>
unlink(path: string): Promise<void>
stat(path: string): Promise<{ isFile(): boolean, isDirectory(): boolean }>
access(path: string, mode?: number): Promise<void>
@ -68,7 +69,7 @@ class BrowserFS implements UniversalFS {
return dir
}
async readFile(path: string): Promise<string> {
async readFile(path: string, encoding?: string): Promise<string> {
try {
const fileHandle = await this.getFileHandle(path)
const file = await fileHandle.getFile()
@ -78,7 +79,7 @@ class BrowserFS implements UniversalFS {
}
}
async writeFile(path: string, data: string): Promise<void> {
async writeFile(path: string, data: string, encoding?: string): Promise<void> {
const fileHandle = await this.getFileHandle(path, true)
const writable = await fileHandle.createWritable()
await writable.write(data)
@ -103,13 +104,27 @@ class BrowserFS implements UniversalFS {
}
}
async readdir(path: string): Promise<string[]> {
async readdir(path: string): Promise<string[]>
async readdir(path: string, options: { withFileTypes: true }): Promise<{ name: string, isDirectory(): boolean, isFile(): boolean }[]>
async readdir(path: string, options?: { withFileTypes?: boolean }): Promise<string[] | { name: string, isDirectory(): boolean, isFile(): boolean }[]> {
const dir = await this.getDirHandle(path)
const entries: string[] = []
for await (const [name] of dir.entries()) {
entries.push(name)
if (options?.withFileTypes) {
const entries: { name: string, isDirectory(): boolean, isFile(): boolean }[] = []
for await (const [name, handle] of dir.entries()) {
entries.push({
name,
isDirectory: () => handle.kind === 'directory',
isFile: () => handle.kind === 'file'
})
}
return entries
} else {
const entries: string[] = []
for await (const [name] of dir.entries()) {
entries.push(name)
}
return entries
}
return entries
}
async unlink(path: string): Promise<void> {
@ -152,12 +167,12 @@ class BrowserFS implements UniversalFS {
* Node.js implementation using fs/promises
*/
class NodeFS implements UniversalFS {
async readFile(path: string): Promise<string> {
return await nodeFs.readFile(path, 'utf-8')
async readFile(path: string, encoding = 'utf-8'): Promise<string> {
return await nodeFs.readFile(path, encoding)
}
async writeFile(path: string, data: string): Promise<void> {
await nodeFs.writeFile(path, data, 'utf-8')
async writeFile(path: string, data: string, encoding = 'utf-8'): Promise<void> {
await nodeFs.writeFile(path, data, encoding)
}
async mkdir(path: string, options = { recursive: true }): Promise<void> {
@ -173,7 +188,12 @@ class NodeFS implements UniversalFS {
}
}
async readdir(path: string): Promise<string[]> {
async readdir(path: string): Promise<string[]>
async readdir(path: string, options: { withFileTypes: true }): Promise<{ name: string, isDirectory(): boolean, isFile(): boolean }[]>
async readdir(path: string, options?: { withFileTypes?: boolean }): Promise<string[] | { name: string, isDirectory(): boolean, isFile(): boolean }[]> {
if (options?.withFileTypes) {
return await nodeFs.readdir(path, { withFileTypes: true })
}
return await nodeFs.readdir(path)
}
@ -201,7 +221,7 @@ class MemoryFS implements UniversalFS {
private files = new Map<string, string>()
private dirs = new Set<string>()
async readFile(path: string): Promise<string> {
async readFile(path: string, encoding?: string): Promise<string> {
const content = this.files.get(path)
if (content === undefined) {
throw new Error(`File not found: ${path}`)
@ -209,7 +229,7 @@ class MemoryFS implements UniversalFS {
return content
}
async writeFile(path: string, data: string): Promise<void> {
async writeFile(path: string, data: string, encoding?: string): Promise<void> {
this.files.set(path, data)
// Ensure parent directories exist
const parts = path.split('/').slice(0, -1)
@ -232,7 +252,9 @@ class MemoryFS implements UniversalFS {
return this.files.has(path) || this.dirs.has(path)
}
async readdir(path: string): Promise<string[]> {
async readdir(path: string): Promise<string[]>
async readdir(path: string, options: { withFileTypes: true }): Promise<{ name: string, isDirectory(): boolean, isFile(): boolean }[]>
async readdir(path: string, options?: { withFileTypes?: boolean }): Promise<string[] | { name: string, isDirectory(): boolean, isFile(): boolean }[]> {
const entries = new Set<string>()
const pathPrefix = path + '/'
@ -252,6 +274,14 @@ class MemoryFS implements UniversalFS {
}
}
if (options?.withFileTypes) {
return Array.from(entries).map(name => ({
name,
isDirectory: () => this.dirs.has(path + '/' + name),
isFile: () => this.files.has(path + '/' + name)
}))
}
return Array.from(entries)
}

1
tsconfig.tsbuildinfo Normal file
View file

@ -0,0 +1 @@
{"root":["./src/augmentationFactory.ts","./src/augmentationPipeline.ts","./src/augmentationRegistry.ts","./src/augmentationRegistryLoader.ts","./src/brainyData.ts","./src/browserFramework.minimal.ts","./src/browserFramework.ts","./src/coreTypes.ts","./src/demo.ts","./src/index.ts","./src/pipeline.ts","./src/sequentialPipeline.ts","./src/setup.ts","./src/unified.ts","./src/worker.ts","./src/augmentations/conduitAugmentations.ts","./src/augmentations/cortexSense.ts","./src/augmentations/intelligentVerbScoring.ts","./src/augmentations/memoryAugmentations.ts","./src/augmentations/serverSearchAugmentations.ts","./src/chat/brainyChat.ts","./src/connectors/interfaces/IConnector.ts","./src/cortex/backupRestore.ts","./src/cortex/cortex.ts","./src/cortex/healthCheck.ts","./src/cortex/neuralImport.ts","./src/cortex/performanceMonitor.ts","./src/cortex/serviceIntegration.ts","./src/distributed/configManager.ts","./src/distributed/domainDetector.ts","./src/distributed/hashPartitioner.ts","./src/distributed/healthMonitor.ts","./src/distributed/index.ts","./src/distributed/operationalModes.ts","./src/errors/brainyError.ts","./src/examples/basicUsage.ts","./src/hnsw/distributedSearch.ts","./src/hnsw/hnswIndex.ts","./src/hnsw/hnswIndexOptimized.ts","./src/hnsw/optimizedHNSWIndex.ts","./src/hnsw/partitionedHNSWIndex.ts","./src/hnsw/scaledHNSWSystem.ts","./src/mcp/brainyMCPAdapter.ts","./src/mcp/brainyMCPBroadcast.ts","./src/mcp/brainyMCPClient.ts","./src/mcp/brainyMCPService.ts","./src/mcp/index.ts","./src/mcp/mcpAugmentationToolset.ts","./src/shared/default-augmentations.ts","./src/storage/backwardCompatibility.ts","./src/storage/baseStorage.ts","./src/storage/cacheManager.ts","./src/storage/enhancedCacheManager.ts","./src/storage/readOnlyOptimizations.ts","./src/storage/storageFactory.ts","./src/storage/adapters/baseStorageAdapter.ts","./src/storage/adapters/batchS3Operations.ts","./src/storage/adapters/fileSystemStorage.ts","./src/storage/adapters/memoryStorage.ts","./src/storage/adapters/opfsStorage.ts","./src/storage/adapters/optimizedS3Search.ts","./src/storage/adapters/s3CompatibleStorage.ts","./src/types/augmentations.ts","./src/types/brainyDataInterface.ts","./src/types/cortex.d.ts","./src/types/distributedTypes.ts","./src/types/fileSystemTypes.ts","./src/types/global.d.ts","./src/types/graphTypes.ts","./src/types/mcpTypes.ts","./src/types/paginationTypes.ts","./src/types/pipelineTypes.ts","./src/universal/crypto.ts","./src/universal/events.ts","./src/universal/fs.ts","./src/universal/index.ts","./src/universal/path.ts","./src/universal/uuid.ts","./src/utils/adaptiveBackpressure.ts","./src/utils/adaptiveSocketManager.ts","./src/utils/autoConfiguration.ts","./src/utils/cacheAutoConfig.ts","./src/utils/crypto.ts","./src/utils/distance.ts","./src/utils/embedding.ts","./src/utils/environment.ts","./src/utils/fieldNameTracking.ts","./src/utils/index.ts","./src/utils/jsonProcessing.ts","./src/utils/logger.ts","./src/utils/metadataFilter.ts","./src/utils/metadataIndex.ts","./src/utils/metadataIndexCache.ts","./src/utils/operationUtils.ts","./src/utils/performanceMonitor.ts","./src/utils/requestCoalescer.ts","./src/utils/searchCache.ts","./src/utils/statistics.ts","./src/utils/statisticsCollector.ts","./src/utils/textEncoding.ts","./src/utils/typeUtils.ts","./src/utils/version.ts","./src/utils/workerUtils.ts","./src/utils/writeBuffer.ts"],"errors":true,"version":"5.8.3"}