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

View file

@ -0,0 +1,172 @@
import { AugmentationType, IConduitAugmentation, IWebSocketSupport, AugmentationResponse, WebSocketConnection } from '../types/augmentations.js';
/**
* Base class for conduit augmentations that provide data synchronization between Brainy instances
*/
declare abstract class BaseConduitAugmentation implements IConduitAugmentation {
readonly name: string;
readonly description: string;
enabled: boolean;
protected isInitialized: boolean;
protected connections: Map<string, any>;
constructor(name: string);
initialize(): Promise<void>;
shutDown(): Promise<void>;
getStatus(): Promise<'active' | 'inactive' | 'error'>;
abstract establishConnection(targetSystemId: string, config: Record<string, unknown>): Promise<AugmentationResponse<WebSocketConnection>>;
abstract readData(query: Record<string, unknown>, options?: Record<string, unknown>): Promise<AugmentationResponse<unknown>>;
abstract writeData(data: Record<string, unknown>, options?: Record<string, unknown>): Promise<AugmentationResponse<unknown>>;
abstract monitorStream(streamId: string, callback: (data: unknown) => void): Promise<void>;
protected ensureInitialized(): Promise<void>;
}
/**
* WebSocket conduit augmentation for syncing Brainy instances using WebSockets
*
* This conduit is for syncing between browsers and servers, or between servers.
* WebSockets cannot be used for direct browser-to-browser communication without a server in the middle.
*/
export declare class WebSocketConduitAugmentation extends BaseConduitAugmentation implements IWebSocketSupport {
readonly description = "Conduit augmentation that syncs Brainy instances using WebSockets";
private webSocketConnections;
private messageCallbacks;
constructor(name?: string);
getType(): AugmentationType;
/**
* Establishes a connection to another Brainy instance
* @param targetSystemId The URL or identifier of the target system
* @param config Configuration options for the connection
*/
establishConnection(targetSystemId: string, config: Record<string, unknown>): Promise<AugmentationResponse<WebSocketConnection>>;
/**
* Reads data from a connected Brainy instance
* @param query Query parameters for reading data
* @param options Additional options
*/
readData(query: Record<string, unknown>, options?: Record<string, unknown>): Promise<AugmentationResponse<unknown>>;
/**
* Writes data to a connected Brainy instance
* @param data The data to write
* @param options Additional options
*/
writeData(data: Record<string, unknown>, options?: Record<string, unknown>): Promise<AugmentationResponse<unknown>>;
/**
* Monitors a data stream from a connected Brainy instance
* @param streamId The ID of the stream to monitor (usually a connection ID)
* @param callback Function to call when new data is received
*/
monitorStream(streamId: string, callback: (data: unknown) => void): Promise<void>;
/**
* Establishes a WebSocket connection
* @param url The WebSocket server URL to connect to
* @param protocols Optional subprotocols
*/
connectWebSocket(url: string, protocols?: string | string[]): Promise<WebSocketConnection>;
/**
* Sends data through an established WebSocket connection
* @param connectionId The identifier of the established connection
* @param data The data to send (will be serialized if not a string)
*/
sendWebSocketMessage(connectionId: string, data: unknown): Promise<void>;
/**
* Registers a callback for incoming WebSocket messages
* @param connectionId The identifier of the established connection
* @param callback The function to call when a message is received
*/
onWebSocketMessage(connectionId: string, callback: (data: unknown) => void): Promise<void>;
/**
* Removes a callback for incoming WebSocket messages
* @param connectionId The identifier of the established connection
* @param callback The function to remove from the callbacks
*/
offWebSocketMessage(connectionId: string, callback: (data: unknown) => void): Promise<void>;
/**
* Closes an established WebSocket connection
* @param connectionId The identifier of the established connection
* @param code Optional close code
* @param reason Optional close reason
*/
closeWebSocket(connectionId: string, code?: number, reason?: string): Promise<void>;
}
/**
* WebRTC conduit augmentation for syncing Brainy instances using WebRTC
*
* This conduit is for direct peer-to-peer syncing between browsers.
* It is the recommended approach for browser-to-browser communication.
*/
export declare class WebRTCConduitAugmentation extends BaseConduitAugmentation implements IWebSocketSupport {
readonly description = "Conduit augmentation that syncs Brainy instances using WebRTC";
private peerConnections;
private dataChannels;
private webSocketConnections;
private messageCallbacks;
private signalServer;
constructor(name?: string);
getType(): AugmentationType;
initialize(): Promise<void>;
/**
* Establishes a connection to another Brainy instance using WebRTC
* @param targetSystemId The peer ID or signal server URL
* @param config Configuration options for the connection
*/
establishConnection(targetSystemId: string, config: Record<string, unknown>): Promise<AugmentationResponse<WebSocketConnection>>;
/**
* Handles an incoming WebRTC offer
* @param peerId The ID of the peer sending the offer
* @param offer The SDP offer
* @param config Configuration options
*/
private handleOffer;
/**
* Reads data from a connected Brainy instance
* @param query Query parameters for reading data
* @param options Additional options
*/
readData(query: Record<string, unknown>, options?: Record<string, unknown>): Promise<AugmentationResponse<unknown>>;
/**
* Writes data to a connected Brainy instance
* @param data The data to write
* @param options Additional options
*/
writeData(data: Record<string, unknown>, options?: Record<string, unknown>): Promise<AugmentationResponse<unknown>>;
/**
* Monitors a data stream from a connected Brainy instance
* @param streamId The ID of the stream to monitor (usually a connection ID)
* @param callback Function to call when new data is received
*/
monitorStream(streamId: string, callback: (data: unknown) => void): Promise<void>;
/**
* Establishes a WebSocket connection (used for signaling in WebRTC)
* @param url The WebSocket server URL to connect to
* @param protocols Optional subprotocols
*/
connectWebSocket(url: string, protocols?: string | string[]): Promise<WebSocketConnection>;
/**
* Sends data through an established WebSocket or WebRTC connection
* @param connectionId The identifier of the established connection
* @param data The data to send (will be serialized if not a string)
*/
sendWebSocketMessage(connectionId: string, data: unknown): Promise<void>;
/**
* Registers a callback for incoming WebSocket or WebRTC messages
* @param connectionId The identifier of the established connection
* @param callback The function to call when a message is received
*/
onWebSocketMessage(connectionId: string, callback: (data: unknown) => void): Promise<void>;
/**
* Removes a callback for incoming WebSocket or WebRTC messages
* @param connectionId The identifier of the established connection
* @param callback The function to remove from the callbacks
*/
offWebSocketMessage(connectionId: string, callback: (data: unknown) => void): Promise<void>;
/**
* Closes an established WebSocket or WebRTC connection
* @param connectionId The identifier of the established connection
* @param code Optional close code
* @param reason Optional close reason
*/
closeWebSocket(connectionId: string, code?: number, reason?: string): Promise<void>;
}
/**
* Factory function to create the appropriate conduit augmentation based on the type
*/
export declare function createConduitAugmentation(type: 'websocket' | 'webrtc', name?: string, options?: Record<string, unknown>): Promise<IConduitAugmentation & IWebSocketSupport>;
export {};

1158
dist/augmentations/conduitAugmentations.js vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,158 @@
import { ICognitionAugmentation, AugmentationResponse } from '../types/augmentations.js';
/**
* Configuration options for the Intelligent Verb Scoring augmentation
*/
export interface IVerbScoringConfig {
/** Enable semantic proximity scoring based on entity embeddings */
enableSemanticScoring: boolean;
/** Enable frequency-based weight amplification */
enableFrequencyAmplification: boolean;
/** Enable temporal decay for weights */
enableTemporalDecay: boolean;
/** Decay rate per day for temporal scoring (0-1) */
temporalDecayRate: number;
/** Minimum weight threshold */
minWeight: number;
/** Maximum weight threshold */
maxWeight: number;
/** Base confidence score for new relationships */
baseConfidence: number;
/** Learning rate for adaptive scoring (0-1) */
learningRate: number;
}
/**
* Default configuration for the Intelligent Verb Scoring augmentation
*/
export declare const DEFAULT_VERB_SCORING_CONFIG: IVerbScoringConfig;
/**
* Relationship statistics for learning and adaptation
*/
interface RelationshipStats {
count: number;
totalWeight: number;
averageWeight: number;
lastSeen: Date;
firstSeen: Date;
semanticSimilarity?: number;
}
/**
* Intelligent Verb Scoring Cognition Augmentation
*
* Automatically generates intelligent weight and confidence scores for verb relationships
* using semantic analysis, frequency patterns, and temporal factors.
*/
export declare class IntelligentVerbScoring implements ICognitionAugmentation {
readonly name = "intelligent-verb-scoring";
readonly description = "Automatically generates intelligent weight and confidence scores for verb relationships";
enabled: boolean;
private config;
private relationshipStats;
private brainyInstance;
private isInitialized;
constructor(config?: Partial<IVerbScoringConfig>);
initialize(): Promise<void>;
shutDown(): Promise<void>;
getStatus(): Promise<'active' | 'inactive' | 'error'>;
/**
* Set reference to the BrainyData instance for accessing graph data
*/
setBrainyInstance(instance: any): void;
/**
* Main reasoning method for generating intelligent verb scores
*/
reason(query: string, context?: Record<string, unknown>): AugmentationResponse<{
inference: string;
confidence: number;
}>;
infer(dataSubset: Record<string, unknown>): AugmentationResponse<Record<string, unknown>>;
executeLogic(ruleId: string, input: Record<string, unknown>): AugmentationResponse<boolean>;
/**
* Generate intelligent weight and confidence scores for a verb relationship
*
* @param sourceId - ID of the source entity
* @param targetId - ID of the target entity
* @param verbType - Type of the relationship
* @param existingWeight - Existing weight if any
* @param metadata - Additional metadata about the relationship
* @returns Computed weight and confidence scores
*/
computeVerbScores(sourceId: string, targetId: string, verbType: string, existingWeight?: number, metadata?: any): Promise<{
weight: number;
confidence: number;
reasoning: string[];
}>;
/**
* Calculate semantic similarity between two entities using their embeddings
*/
private calculateSemanticScore;
/**
* Calculate frequency-based boost for repeated relationships
*/
private calculateFrequencyBoost;
/**
* Calculate temporal decay factor based on recency
*/
private calculateTemporalFactor;
/**
* Calculate learning-based adjustment using historical patterns
*/
private calculateLearningAdjustment;
/**
* Update relationship statistics for learning
*/
private updateRelationshipStats;
/**
* Blend two scores using a weighted average
*/
private blendScores;
/**
* Get current configuration
*/
getConfig(): IVerbScoringConfig;
/**
* Update configuration
*/
updateConfig(newConfig: Partial<IVerbScoringConfig>): void;
/**
* Get relationship statistics (for debugging/monitoring)
*/
getRelationshipStats(): Map<string, RelationshipStats>;
/**
* Clear relationship statistics
*/
clearStats(): void;
/**
* Provide feedback to improve future scoring
* This allows the system to learn from user corrections or validation
*
* @param sourceId - Source entity ID
* @param targetId - Target entity ID
* @param verbType - Relationship type
* @param feedbackWeight - The corrected/validated weight (0-1)
* @param feedbackConfidence - The corrected/validated confidence (0-1)
* @param feedbackType - Type of feedback ('correction', 'validation', 'enhancement')
*/
provideFeedback(sourceId: string, targetId: string, verbType: string, feedbackWeight: number, feedbackConfidence?: number, feedbackType?: 'correction' | 'validation' | 'enhancement'): Promise<void>;
/**
* Get learning statistics for monitoring and debugging
*/
getLearningStats(): {
totalRelationships: number;
averageConfidence: number;
feedbackCount: number;
topRelationships: Array<{
relationship: string;
count: number;
averageWeight: number;
}>;
};
/**
* Export learning data for backup or analysis
*/
exportLearningData(): string;
/**
* Import learning data from backup
*/
importLearningData(jsonData: string): void;
}
export {};

View file

@ -0,0 +1,377 @@
import { cosineDistance } from '../utils/distance.js';
/**
* Default configuration for the Intelligent Verb Scoring augmentation
*/
export const DEFAULT_VERB_SCORING_CONFIG = {
enableSemanticScoring: true,
enableFrequencyAmplification: true,
enableTemporalDecay: true,
temporalDecayRate: 0.01, // 1% decay per day
minWeight: 0.1,
maxWeight: 1.0,
baseConfidence: 0.5,
learningRate: 0.1
};
/**
* Intelligent Verb Scoring Cognition Augmentation
*
* Automatically generates intelligent weight and confidence scores for verb relationships
* using semantic analysis, frequency patterns, and temporal factors.
*/
export class IntelligentVerbScoring {
constructor(config = {}) {
this.name = 'intelligent-verb-scoring';
this.description = 'Automatically generates intelligent weight and confidence scores for verb relationships';
this.enabled = false; // Off by default as requested
this.relationshipStats = new Map();
this.isInitialized = false;
this.config = { ...DEFAULT_VERB_SCORING_CONFIG, ...config };
}
async initialize() {
if (this.isInitialized)
return;
this.isInitialized = true;
}
async shutDown() {
this.relationshipStats.clear();
this.isInitialized = false;
}
async getStatus() {
return this.enabled && this.isInitialized ? 'active' : 'inactive';
}
/**
* Set reference to the BrainyData instance for accessing graph data
*/
setBrainyInstance(instance) {
this.brainyInstance = instance;
}
/**
* Main reasoning method for generating intelligent verb scores
*/
reason(query, context) {
if (!this.enabled) {
return {
success: false,
data: { inference: 'Augmentation is disabled', confidence: 0 },
error: 'Intelligent verb scoring is disabled'
};
}
return {
success: true,
data: {
inference: 'Intelligent verb scoring active',
confidence: 1.0
}
};
}
infer(dataSubset) {
return {
success: true,
data: dataSubset
};
}
executeLogic(ruleId, input) {
return {
success: true,
data: true
};
}
/**
* Generate intelligent weight and confidence scores for a verb relationship
*
* @param sourceId - ID of the source entity
* @param targetId - ID of the target entity
* @param verbType - Type of the relationship
* @param existingWeight - Existing weight if any
* @param metadata - Additional metadata about the relationship
* @returns Computed weight and confidence scores
*/
async computeVerbScores(sourceId, targetId, verbType, existingWeight, metadata) {
if (!this.enabled || !this.brainyInstance) {
return {
weight: existingWeight ?? 0.5,
confidence: this.config.baseConfidence,
reasoning: ['Intelligent scoring disabled']
};
}
const reasoning = [];
let weight = existingWeight ?? 0.5;
let confidence = this.config.baseConfidence;
try {
// Get relationship key for statistics
const relationKey = `${sourceId}-${verbType}-${targetId}`;
// Update relationship statistics
this.updateRelationshipStats(relationKey, weight, metadata);
// Apply semantic scoring if enabled
if (this.config.enableSemanticScoring) {
const semanticScore = await this.calculateSemanticScore(sourceId, targetId);
if (semanticScore !== null) {
weight = this.blendScores(weight, semanticScore, 0.3);
confidence = Math.min(confidence + semanticScore * 0.2, 1.0);
reasoning.push(`Semantic similarity: ${semanticScore.toFixed(3)}`);
}
}
// Apply frequency amplification if enabled
if (this.config.enableFrequencyAmplification) {
const frequencyBoost = this.calculateFrequencyBoost(relationKey);
weight = this.blendScores(weight, frequencyBoost, 0.2);
if (frequencyBoost > 0.5) {
confidence = Math.min(confidence + 0.1, 1.0);
reasoning.push(`Frequency boost: ${frequencyBoost.toFixed(3)}`);
}
}
// Apply temporal decay if enabled
if (this.config.enableTemporalDecay) {
const temporalFactor = this.calculateTemporalFactor(relationKey);
weight *= temporalFactor;
reasoning.push(`Temporal factor: ${temporalFactor.toFixed(3)}`);
}
// Apply learning adjustments
const learningAdjustment = this.calculateLearningAdjustment(relationKey);
weight = this.blendScores(weight, learningAdjustment, this.config.learningRate);
// Clamp values to configured bounds
weight = Math.max(this.config.minWeight, Math.min(this.config.maxWeight, weight));
confidence = Math.max(0, Math.min(1, confidence));
reasoning.push(`Final weight: ${weight.toFixed(3)}, confidence: ${confidence.toFixed(3)}`);
return { weight, confidence, reasoning };
}
catch (error) {
console.warn('Error computing verb scores:', error);
return {
weight: existingWeight ?? 0.5,
confidence: this.config.baseConfidence,
reasoning: [`Error in scoring: ${error}`]
};
}
}
/**
* Calculate semantic similarity between two entities using their embeddings
*/
async calculateSemanticScore(sourceId, targetId) {
try {
if (!this.brainyInstance?.storage)
return null;
// Get noun embeddings from storage
const sourceNoun = await this.brainyInstance.storage.getNoun(sourceId);
const targetNoun = await this.brainyInstance.storage.getNoun(targetId);
if (!sourceNoun?.vector || !targetNoun?.vector)
return null;
// Calculate cosine similarity (1 - distance)
const distance = cosineDistance(sourceNoun.vector, targetNoun.vector);
return Math.max(0, 1 - distance);
}
catch (error) {
console.warn('Error calculating semantic score:', error);
return null;
}
}
/**
* Calculate frequency-based boost for repeated relationships
*/
calculateFrequencyBoost(relationKey) {
const stats = this.relationshipStats.get(relationKey);
if (!stats || stats.count <= 1)
return 0.5;
// Logarithmic scaling: more occurrences = higher weight, but with diminishing returns
const boost = Math.log(stats.count + 1) / Math.log(10); // Log base 10
return Math.min(boost, 1.0);
}
/**
* Calculate temporal decay factor based on recency
*/
calculateTemporalFactor(relationKey) {
const stats = this.relationshipStats.get(relationKey);
if (!stats)
return 1.0;
const daysSinceLastSeen = (Date.now() - stats.lastSeen.getTime()) / (1000 * 60 * 60 * 24);
const decayFactor = Math.exp(-this.config.temporalDecayRate * daysSinceLastSeen);
return Math.max(0.1, decayFactor); // Minimum 10% of original weight
}
/**
* Calculate learning-based adjustment using historical patterns
*/
calculateLearningAdjustment(relationKey) {
const stats = this.relationshipStats.get(relationKey);
if (!stats || stats.count <= 1)
return 0.5;
// Use moving average of weights as learned baseline
return Math.max(0, Math.min(1, stats.averageWeight));
}
/**
* Update relationship statistics for learning
*/
updateRelationshipStats(relationKey, weight, metadata) {
const now = new Date();
const existing = this.relationshipStats.get(relationKey);
if (existing) {
// Update existing stats
existing.count++;
existing.totalWeight += weight;
existing.averageWeight = existing.totalWeight / existing.count;
existing.lastSeen = now;
}
else {
// Create new stats entry
this.relationshipStats.set(relationKey, {
count: 1,
totalWeight: weight,
averageWeight: weight,
lastSeen: now,
firstSeen: now
});
}
}
/**
* Blend two scores using a weighted average
*/
blendScores(score1, score2, weight2) {
const weight1 = 1 - weight2;
return score1 * weight1 + score2 * weight2;
}
/**
* Get current configuration
*/
getConfig() {
return { ...this.config };
}
/**
* Update configuration
*/
updateConfig(newConfig) {
this.config = { ...this.config, ...newConfig };
}
/**
* Get relationship statistics (for debugging/monitoring)
*/
getRelationshipStats() {
return new Map(this.relationshipStats);
}
/**
* Clear relationship statistics
*/
clearStats() {
this.relationshipStats.clear();
}
/**
* Provide feedback to improve future scoring
* This allows the system to learn from user corrections or validation
*
* @param sourceId - Source entity ID
* @param targetId - Target entity ID
* @param verbType - Relationship type
* @param feedbackWeight - The corrected/validated weight (0-1)
* @param feedbackConfidence - The corrected/validated confidence (0-1)
* @param feedbackType - Type of feedback ('correction', 'validation', 'enhancement')
*/
async provideFeedback(sourceId, targetId, verbType, feedbackWeight, feedbackConfidence, feedbackType = 'correction') {
if (!this.enabled)
return;
const relationKey = `${sourceId}-${verbType}-${targetId}`;
const existing = this.relationshipStats.get(relationKey);
if (existing) {
// Apply feedback with learning rate
const newWeight = existing.averageWeight * (1 - this.config.learningRate) +
feedbackWeight * this.config.learningRate;
// Update the running average with feedback
existing.totalWeight = (existing.totalWeight * existing.count + feedbackWeight) / (existing.count + 1);
existing.averageWeight = existing.totalWeight / existing.count;
existing.count += 1;
existing.lastSeen = new Date();
if (this.brainyInstance?.loggingConfig?.verbose) {
console.log(`Feedback applied for ${relationKey}: ${feedbackType}, ` +
`old weight: ${existing.averageWeight.toFixed(3)}, ` +
`feedback: ${feedbackWeight.toFixed(3)}, ` +
`new weight: ${newWeight.toFixed(3)}`);
}
}
else {
// Create new entry with feedback as initial data
this.relationshipStats.set(relationKey, {
count: 1,
totalWeight: feedbackWeight,
averageWeight: feedbackWeight,
lastSeen: new Date(),
firstSeen: new Date()
});
}
}
/**
* Get learning statistics for monitoring and debugging
*/
getLearningStats() {
const relationships = Array.from(this.relationshipStats.entries());
const totalRelationships = relationships.length;
const feedbackCount = relationships.reduce((sum, [, stats]) => sum + stats.count, 0);
// Calculate average confidence (approximated from weight patterns)
const averageWeight = relationships.reduce((sum, [, stats]) => sum + stats.averageWeight, 0) / totalRelationships || 0;
const averageConfidence = Math.min(averageWeight + 0.2, 1.0); // Heuristic: confidence typically higher than weight
// Get top relationships by count
const topRelationships = relationships
.map(([key, stats]) => ({
relationship: key,
count: stats.count,
averageWeight: stats.averageWeight
}))
.sort((a, b) => b.count - a.count)
.slice(0, 10);
return {
totalRelationships,
averageConfidence,
feedbackCount,
topRelationships
};
}
/**
* Export learning data for backup or analysis
*/
exportLearningData() {
const data = {
config: this.config,
stats: Array.from(this.relationshipStats.entries()).map(([key, stats]) => ({
relationship: key,
...stats,
firstSeen: stats.firstSeen.toISOString(),
lastSeen: stats.lastSeen.toISOString()
})),
exportedAt: new Date().toISOString(),
version: '1.0'
};
return JSON.stringify(data, null, 2);
}
/**
* Import learning data from backup
*/
importLearningData(jsonData) {
try {
const data = JSON.parse(jsonData);
if (data.version !== '1.0') {
console.warn('Learning data version mismatch, importing anyway');
}
// Update configuration if provided
if (data.config) {
this.config = { ...this.config, ...data.config };
}
// Import relationship statistics
if (data.stats && Array.isArray(data.stats)) {
for (const stat of data.stats) {
if (stat.relationship) {
this.relationshipStats.set(stat.relationship, {
count: stat.count || 1,
totalWeight: stat.totalWeight || stat.averageWeight || 0.5,
averageWeight: stat.averageWeight || 0.5,
firstSeen: new Date(stat.firstSeen || Date.now()),
lastSeen: new Date(stat.lastSeen || Date.now()),
semanticSimilarity: stat.semanticSimilarity
});
}
}
}
console.log(`Imported learning data: ${this.relationshipStats.size} relationships`);
}
catch (error) {
console.error('Failed to import learning data:', error);
throw new Error(`Failed to import learning data: ${error}`);
}
}
}
//# sourceMappingURL=intelligentVerbScoring.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,72 @@
import { AugmentationType, IMemoryAugmentation, AugmentationResponse } from '../types/augmentations.js';
import { StorageAdapter } from '../coreTypes.js';
/**
* Base class for memory augmentations that wrap a StorageAdapter
*/
declare abstract class BaseMemoryAugmentation implements IMemoryAugmentation {
readonly name: string;
readonly description: string;
enabled: boolean;
protected storage: StorageAdapter;
protected isInitialized: boolean;
constructor(name: string, storage: StorageAdapter);
initialize(): Promise<void>;
shutDown(): Promise<void>;
getStatus(): Promise<'active' | 'inactive' | 'error'>;
storeData(key: string, data: unknown, options?: Record<string, unknown>): Promise<AugmentationResponse<boolean>>;
retrieveData(key: string, options?: Record<string, unknown>): Promise<AugmentationResponse<unknown>>;
updateData(key: string, data: unknown, options?: Record<string, unknown>): Promise<AugmentationResponse<boolean>>;
deleteData(key: string, options?: Record<string, unknown>): Promise<AugmentationResponse<boolean>>;
listDataKeys(pattern?: string, options?: Record<string, unknown>): Promise<AugmentationResponse<string[]>>;
/**
* Searches for data in the storage using vector similarity.
* Implements the findNearest functionality by calculating distances client-side.
* @param query The query vector or data to search for
* @param k Number of results to return (default: 10)
* @param options Optional search options
*/
search(query: unknown, k?: number, options?: Record<string, unknown>): Promise<AugmentationResponse<Array<{
id: string;
score: number;
data: unknown;
}>>>;
protected ensureInitialized(): Promise<void>;
}
/**
* Memory augmentation that uses in-memory storage
*/
export declare class MemoryStorageAugmentation extends BaseMemoryAugmentation {
readonly description = "Memory augmentation that stores data in memory";
enabled: boolean;
constructor(name: string);
getType(): AugmentationType;
}
/**
* Memory augmentation that uses file system storage
*/
export declare class FileSystemStorageAugmentation extends BaseMemoryAugmentation {
readonly description = "Memory augmentation that stores data in the file system";
enabled: boolean;
private rootDirectory;
constructor(name: string, rootDirectory?: string);
initialize(): Promise<void>;
getType(): AugmentationType;
}
/**
* Memory augmentation that uses OPFS (Origin Private File System) storage
*/
export declare class OPFSStorageAugmentation extends BaseMemoryAugmentation {
readonly description = "Memory augmentation that stores data in the Origin Private File System";
enabled: boolean;
constructor(name: string);
getType(): AugmentationType;
}
/**
* Factory function to create the appropriate memory augmentation based on the environment
*/
export declare function createMemoryAugmentation(name: string, options?: {
storageType?: 'memory' | 'filesystem' | 'opfs';
rootDirectory?: string;
requestPersistentStorage?: boolean;
}): Promise<IMemoryAugmentation>;
export {};

View file

@ -0,0 +1,280 @@
import { AugmentationType } from '../types/augmentations.js';
import { MemoryStorage, OPFSStorage } from '../storage/storageFactory.js';
// FileSystemStorage will be dynamically imported when needed to avoid fs imports in browser
import { cosineDistance } from '../utils/distance.js';
/**
* Base class for memory augmentations that wrap a StorageAdapter
*/
class BaseMemoryAugmentation {
constructor(name, storage) {
this.description = 'Base memory augmentation';
this.enabled = true;
this.isInitialized = false;
this.name = name;
this.storage = storage;
}
async initialize() {
if (this.isInitialized) {
return;
}
try {
await this.storage.init();
this.isInitialized = true;
}
catch (error) {
console.error(`Failed to initialize ${this.name}:`, error);
throw new Error(`Failed to initialize ${this.name}: ${error}`);
}
}
async shutDown() {
this.isInitialized = false;
}
async getStatus() {
return this.isInitialized ? 'active' : 'inactive';
}
async storeData(key, data, options) {
await this.ensureInitialized();
try {
await this.storage.saveMetadata(key, data);
return { success: true, data: true };
}
catch (error) {
console.error(`Failed to store data for key ${key}:`, error);
return {
success: false,
data: false,
error: `Failed to store data: ${error}`
};
}
}
async retrieveData(key, options) {
await this.ensureInitialized();
try {
const data = await this.storage.getMetadata(key);
return {
success: true,
data
};
}
catch (error) {
console.error(`Failed to retrieve data for key ${key}:`, error);
return {
success: false,
data: null,
error: `Failed to retrieve data: ${error}`
};
}
}
async updateData(key, data, options) {
await this.ensureInitialized();
try {
await this.storage.saveMetadata(key, data);
return { success: true, data: true };
}
catch (error) {
console.error(`Failed to update data for key ${key}:`, error);
return {
success: false,
data: false,
error: `Failed to update data: ${error}`
};
}
}
async deleteData(key, options) {
await this.ensureInitialized();
try {
// There's no direct deleteMetadata method, so we save null
await this.storage.saveMetadata(key, null);
return { success: true, data: true };
}
catch (error) {
console.error(`Failed to delete data for key ${key}:`, error);
return {
success: false,
data: false,
error: `Failed to delete data: ${error}`
};
}
}
async listDataKeys(pattern, options) {
// This is a limitation of the current StorageAdapter interface
// It doesn't provide a way to list all metadata keys
// We could implement this in the future by extending the StorageAdapter interface
return {
success: false,
data: [],
error: 'listDataKeys is not supported by this storage adapter'
};
}
/**
* Searches for data in the storage using vector similarity.
* Implements the findNearest functionality by calculating distances client-side.
* @param query The query vector or data to search for
* @param k Number of results to return (default: 10)
* @param options Optional search options
*/
async search(query, k = 10, options) {
await this.ensureInitialized();
try {
// Check if query is a vector
let queryVector;
if (Array.isArray(query) && query.every(item => typeof item === 'number')) {
queryVector = query;
}
else {
// If query is not a vector, we can't perform vector search
return {
success: false,
data: [],
error: 'Query must be a vector (array of numbers) for vector search'
};
}
// Process nodes in batches to avoid loading everything into memory
const allResults = [];
let hasMore = true;
let cursor;
while (hasMore) {
// Get a batch of nodes
const batchResult = await this.storage.getNouns({
pagination: { limit: 100, cursor }
});
// Process this batch
for (const noun of batchResult.items) {
// Skip nodes that don't have a vector
if (!noun.vector || !Array.isArray(noun.vector)) {
continue;
}
// Get metadata for the node
const metadata = await this.storage.getMetadata(noun.id);
// Calculate distance between query vector and node vector
const distance = cosineDistance(queryVector, noun.vector);
// Convert distance to similarity score (1 - distance for cosine)
// This way higher scores are better (more similar)
const score = 1 - distance;
allResults.push({
id: noun.id,
score,
data: metadata
});
}
// Update pagination state
hasMore = batchResult.hasMore;
cursor = batchResult.nextCursor;
}
// Sort results by score (descending) and take top k
allResults.sort((a, b) => b.score - a.score);
const topResults = allResults.slice(0, k);
return {
success: true,
data: topResults
};
}
catch (error) {
console.error(`Failed to search in storage:`, error);
return {
success: false,
data: [],
error: `Failed to search in storage: ${error}`
};
}
}
async ensureInitialized() {
if (!this.isInitialized) {
await this.initialize();
}
}
}
/**
* Memory augmentation that uses in-memory storage
*/
export class MemoryStorageAugmentation extends BaseMemoryAugmentation {
constructor(name) {
super(name, new MemoryStorage());
this.description = 'Memory augmentation that stores data in memory';
this.enabled = true;
}
getType() {
return AugmentationType.MEMORY;
}
}
/**
* Memory augmentation that uses file system storage
*/
export class FileSystemStorageAugmentation extends BaseMemoryAugmentation {
constructor(name, rootDirectory) {
// Temporarily use MemoryStorage, will be replaced in initialize()
super(name, new MemoryStorage());
this.description = 'Memory augmentation that stores data in the file system';
this.enabled = true;
this.rootDirectory = rootDirectory || '.';
}
async initialize() {
try {
// Dynamically import FileSystemStorage
const { FileSystemStorage } = await import('../storage/adapters/fileSystemStorage.js');
this.storage = new FileSystemStorage(this.rootDirectory);
await super.initialize();
}
catch (error) {
console.error('Failed to load FileSystemStorage:', error);
throw new Error(`Failed to initialize FileSystemStorage: ${error}`);
}
}
getType() {
return AugmentationType.MEMORY;
}
}
/**
* Memory augmentation that uses OPFS (Origin Private File System) storage
*/
export class OPFSStorageAugmentation extends BaseMemoryAugmentation {
constructor(name) {
super(name, new OPFSStorage());
this.description = 'Memory augmentation that stores data in the Origin Private File System';
this.enabled = true;
}
getType() {
return AugmentationType.MEMORY;
}
}
/**
* Factory function to create the appropriate memory augmentation based on the environment
*/
export async function createMemoryAugmentation(name, options = {}) {
// If a specific storage type is requested, use that
if (options.storageType) {
switch (options.storageType) {
case 'memory':
return new MemoryStorageAugmentation(name);
case 'filesystem':
return new FileSystemStorageAugmentation(name, options.rootDirectory);
case 'opfs':
return new OPFSStorageAugmentation(name);
}
}
// Otherwise, select based on environment
// Use the global isNode variable from the environment detection
const isNodeEnv = globalThis.__ENV__?.isNode || (typeof process !== 'undefined' &&
process.versions != null &&
process.versions.node != null);
if (isNodeEnv) {
// In Node.js, use FileSystemStorage
return new FileSystemStorageAugmentation(name, options.rootDirectory);
}
else {
// In browser, try OPFS first
const opfsStorage = new OPFSStorage();
if (opfsStorage.isOPFSAvailable()) {
// Request persistent storage if specified
if (options.requestPersistentStorage) {
await opfsStorage.requestPersistentStorage();
}
return new OPFSStorageAugmentation(name);
}
else {
// Fall back to memory storage
return new MemoryStorageAugmentation(name);
}
}
}
//# sourceMappingURL=memoryAugmentations.js.map

File diff suppressed because one or more lines are too long

199
dist/augmentations/neuralImport.d.ts vendored Normal file
View file

@ -0,0 +1,199 @@
/**
* Neural Import Augmentation - AI-Powered Data Understanding
*
* 🧠 Built-in AI augmentation for intelligent data processing
* Always free, always included, always enabled
*
* This is the default AI-powered augmentation that comes with every Brainy installation.
* It provides intelligent data understanding, entity detection, and relationship analysis.
*/
import { ISenseAugmentation, AugmentationResponse } from '../types/augmentations.js';
import { BrainyData } from '../brainyData.js';
export interface NeuralAnalysisResult {
detectedEntities: DetectedEntity[];
detectedRelationships: DetectedRelationship[];
confidence: number;
insights: NeuralInsight[];
}
export interface DetectedEntity {
originalData: any;
nounType: string;
confidence: number;
suggestedId: string;
reasoning: string;
alternativeTypes: Array<{
type: string;
confidence: number;
}>;
}
export interface DetectedRelationship {
sourceId: string;
targetId: string;
verbType: string;
confidence: number;
weight: number;
reasoning: string;
context: string;
metadata?: Record<string, any>;
}
export interface NeuralInsight {
type: 'hierarchy' | 'cluster' | 'pattern' | 'anomaly' | 'opportunity';
description: string;
confidence: number;
affectedEntities: string[];
recommendation?: string;
}
export interface NeuralImportConfig {
confidenceThreshold: number;
enableWeights: boolean;
skipDuplicates: boolean;
categoryFilter?: string[];
}
/**
* Neural Import SENSE Augmentation - The Brain's Perceptual System
*/
export declare class NeuralImportAugmentation implements ISenseAugmentation {
readonly name: string;
readonly description: string;
enabled: boolean;
private brainy;
private config;
constructor(brainy: BrainyData, config?: Partial<NeuralImportConfig>);
initialize(): Promise<void>;
shutDown(): Promise<void>;
getStatus(): Promise<'active' | 'inactive' | 'error'>;
/**
* Process raw data into structured nouns and verbs using neural analysis
*/
processRawData(rawData: Buffer | string, dataType: string, options?: Record<string, unknown>): Promise<AugmentationResponse<{
nouns: string[];
verbs: string[];
confidence?: number;
insights?: Array<{
type: string;
description: string;
confidence: number;
}>;
metadata?: Record<string, unknown>;
}>>;
/**
* Listen to real-time data feeds and process them
*/
listenToFeed(feedUrl: string, callback: (data: {
nouns: string[];
verbs: string[];
confidence?: number;
}) => void): Promise<void>;
/**
* Analyze data structure without processing (preview mode)
*/
analyzeStructure(rawData: Buffer | string, dataType: string, options?: Record<string, unknown>): Promise<AugmentationResponse<{
entityTypes: Array<{
type: string;
count: number;
confidence: number;
}>;
relationshipTypes: Array<{
type: string;
count: number;
confidence: number;
}>;
dataQuality: {
completeness: number;
consistency: number;
accuracy: number;
};
recommendations: string[];
}>>;
/**
* Validate data compatibility with current knowledge base
*/
validateCompatibility(rawData: Buffer | string, dataType: string): Promise<AugmentationResponse<{
compatible: boolean;
issues: Array<{
type: string;
description: string;
severity: 'low' | 'medium' | 'high';
}>;
suggestions: string[];
}>>;
/**
* Get the full neural analysis result (custom method for Cortex integration)
*/
getNeuralAnalysis(rawData: Buffer | string, dataType: string): Promise<NeuralAnalysisResult>;
/**
* Parse raw data based on type
*/
private parseRawData;
/**
* Basic CSV parser
*/
private parseCSV;
/**
* Perform neural analysis on parsed data
*/
private performNeuralAnalysis;
/**
* Neural Entity Detection - The Core AI Engine
*/
private detectEntitiesWithNeuralAnalysis;
/**
* Calculate entity type confidence using AI
*/
private calculateEntityTypeConfidence;
/**
* Field-based confidence calculation
*/
private calculateFieldBasedConfidence;
/**
* Pattern-based confidence calculation
*/
private calculatePatternBasedConfidence;
/**
* Generate reasoning for entity type selection
*/
private generateEntityReasoning;
/**
* Neural Relationship Detection
*/
private detectRelationshipsWithNeuralAnalysis;
/**
* Calculate relationship confidence
*/
private calculateRelationshipConfidence;
/**
* Calculate relationship weight/strength
*/
private calculateRelationshipWeight;
/**
* Generate Neural Insights - The Intelligence Layer
*/
private generateNeuralInsights;
/**
* Helper methods for the neural system
*/
private extractMainText;
private generateSmartId;
private extractRelationshipContext;
private calculateTypeCompatibility;
private getVerbSpecificity;
private getRelevantFields;
private getMatchedPatterns;
private pruneRelationships;
private detectHierarchies;
private detectClusters;
private detectPatterns;
private calculateOverallConfidence;
private storeNeuralAnalysis;
private getDataTypeFromPath;
private generateRelationshipReasoning;
private extractRelationshipMetadata;
/**
* Assess data quality metrics
*/
private assessDataQuality;
/**
* Generate recommendations based on analysis
*/
private generateRecommendations;
}

750
dist/augmentations/neuralImport.js vendored Normal file
View file

@ -0,0 +1,750 @@
/**
* Neural Import Augmentation - AI-Powered Data Understanding
*
* 🧠 Built-in AI augmentation for intelligent data processing
* Always free, always included, always enabled
*
* This is the default AI-powered augmentation that comes with every Brainy installation.
* It provides intelligent data understanding, entity detection, and relationship analysis.
*/
import { NounType, VerbType } from '../types/graphTypes.js';
import * as fs from '../universal/fs.js';
import * as path from '../universal/path.js';
/**
* Neural Import SENSE Augmentation - The Brain's Perceptual System
*/
export class NeuralImportAugmentation {
constructor(brainy, config = {}) {
this.name = 'neural-import';
this.description = 'Built-in AI-powered data understanding and entity detection';
this.enabled = true;
this.brainy = brainy;
this.config = {
confidenceThreshold: 0.7,
enableWeights: true,
skipDuplicates: true,
...config
};
}
async initialize() {
// Initialize the cortex analysis system
console.log('🧠 Neural Import augmentation initialized');
}
async shutDown() {
console.log('🧠 Neural Import SENSE augmentation shut down');
}
async getStatus() {
return this.enabled ? 'active' : 'inactive';
}
/**
* Process raw data into structured nouns and verbs using neural analysis
*/
async processRawData(rawData, dataType, options) {
try {
// Merge options with config
const mergedConfig = { ...this.config, ...options };
// Parse the raw data based on type
const parsedData = await this.parseRawData(rawData, dataType);
// Perform neural analysis
const analysis = await this.performNeuralAnalysis(parsedData, mergedConfig);
// Extract nouns and verbs for the ISenseAugmentation interface
const nouns = analysis.detectedEntities.map(entity => entity.suggestedId);
const verbs = analysis.detectedRelationships.map(rel => `${rel.sourceId}->${rel.verbType}->${rel.targetId}`);
// Store the full analysis for later retrieval
await this.storeNeuralAnalysis(analysis);
return {
success: true,
data: {
nouns,
verbs,
confidence: analysis.confidence,
insights: analysis.insights.map((insight) => ({
type: insight.type,
description: insight.description,
confidence: insight.confidence
})),
metadata: {
detectedEntities: analysis.detectedEntities.length,
detectedRelationships: analysis.detectedRelationships.length,
timestamp: new Date().toISOString(),
augmentation: 'neural-import-sense'
}
}
};
}
catch (error) {
return {
success: false,
data: { nouns: [], verbs: [] },
error: error instanceof Error ? error.message : 'Neural analysis failed'
};
}
}
/**
* Listen to real-time data feeds and process them
*/
async listenToFeed(feedUrl, callback) {
// For file-based feeds, watch for changes
if (feedUrl.startsWith('file://')) {
const filePath = feedUrl.replace('file://', '');
// Watch file for changes using Node.js fs.watch
const fsWatch = require('fs');
const watcher = fsWatch.watch(filePath, async (eventType) => {
if (eventType === 'change') {
try {
const fileContent = await fs.readFile(filePath);
const result = await this.processRawData(fileContent, this.getDataTypeFromPath(filePath));
if (result.success) {
callback({
nouns: result.data.nouns,
verbs: result.data.verbs,
confidence: result.data.confidence
});
}
}
catch (error) {
console.error('Neural Import feed error:', error);
}
}
});
return;
}
// For other feed types, implement appropriate listeners
console.log(`🧠 Neural Import listening to feed: ${feedUrl}`);
}
/**
* Analyze data structure without processing (preview mode)
*/
async analyzeStructure(rawData, dataType, options) {
try {
// Parse the raw data
const parsedData = await this.parseRawData(rawData, dataType);
// Perform lightweight analysis for structure detection
const analysis = await this.performNeuralAnalysis(parsedData, { ...this.config, ...options });
// Summarize entity types
const entityTypeCounts = new Map();
analysis.detectedEntities.forEach(entity => {
const existing = entityTypeCounts.get(entity.nounType) || { count: 0, totalConfidence: 0 };
entityTypeCounts.set(entity.nounType, {
count: existing.count + 1,
totalConfidence: existing.totalConfidence + entity.confidence
});
});
const entityTypes = Array.from(entityTypeCounts.entries()).map(([type, stats]) => ({
type,
count: stats.count,
confidence: stats.totalConfidence / stats.count
}));
// Summarize relationship types
const relationshipTypeCounts = new Map();
analysis.detectedRelationships.forEach(rel => {
const existing = relationshipTypeCounts.get(rel.verbType) || { count: 0, totalConfidence: 0 };
relationshipTypeCounts.set(rel.verbType, {
count: existing.count + 1,
totalConfidence: existing.totalConfidence + rel.confidence
});
});
const relationshipTypes = Array.from(relationshipTypeCounts.entries()).map(([type, stats]) => ({
type,
count: stats.count,
confidence: stats.totalConfidence / stats.count
}));
// Assess data quality
const dataQuality = this.assessDataQuality(parsedData, analysis);
// Generate recommendations
const recommendations = this.generateRecommendations(parsedData, analysis, entityTypes, relationshipTypes);
return {
success: true,
data: {
entityTypes,
relationshipTypes,
dataQuality,
recommendations
}
};
}
catch (error) {
return {
success: false,
data: {
entityTypes: [],
relationshipTypes: [],
dataQuality: { completeness: 0, consistency: 0, accuracy: 0 },
recommendations: []
},
error: error instanceof Error ? error.message : 'Structure analysis failed'
};
}
}
/**
* Validate data compatibility with current knowledge base
*/
async validateCompatibility(rawData, dataType) {
try {
// Parse the raw data
const parsedData = await this.parseRawData(rawData, dataType);
// Perform neural analysis
const analysis = await this.performNeuralAnalysis(parsedData);
const issues = [];
const suggestions = [];
// Check for low confidence entities
const lowConfidenceEntities = analysis.detectedEntities.filter((e) => e.confidence < 0.5);
if (lowConfidenceEntities.length > 0) {
issues.push({
type: 'confidence',
description: `${lowConfidenceEntities.length} entities have low confidence scores`,
severity: 'medium'
});
suggestions.push('Consider reviewing field names and data structure for better entity detection');
}
// Check for missing relationships
if (analysis.detectedRelationships.length === 0 && analysis.detectedEntities.length > 1) {
issues.push({
type: 'relationships',
description: 'No relationships detected between entities',
severity: 'low'
});
suggestions.push('Consider adding contextual fields that describe entity relationships');
}
// Check for data type compatibility
const supportedTypes = ['json', 'csv', 'yaml', 'text'];
if (!supportedTypes.includes(dataType.toLowerCase())) {
issues.push({
type: 'format',
description: `Data type '${dataType}' may not be fully supported`,
severity: 'high'
});
suggestions.push(`Convert data to one of: ${supportedTypes.join(', ')}`);
}
// Check for data completeness
const incompleteEntities = analysis.detectedEntities.filter((e) => !e.originalData || Object.keys(e.originalData).length < 2);
if (incompleteEntities.length > 0) {
issues.push({
type: 'completeness',
description: `${incompleteEntities.length} entities have insufficient data`,
severity: 'medium'
});
suggestions.push('Ensure each entity has multiple descriptive fields');
}
const compatible = issues.filter(i => i.severity === 'high').length === 0;
return {
success: true,
data: {
compatible,
issues,
suggestions
}
};
}
catch (error) {
return {
success: false,
data: {
compatible: false,
issues: [{
type: 'error',
description: error instanceof Error ? error.message : 'Validation failed',
severity: 'high'
}],
suggestions: []
},
error: error instanceof Error ? error.message : 'Compatibility validation failed'
};
}
}
/**
* Get the full neural analysis result (custom method for Cortex integration)
*/
async getNeuralAnalysis(rawData, dataType) {
const parsedData = await this.parseRawData(rawData, dataType);
return await this.performNeuralAnalysis(parsedData);
}
/**
* Parse raw data based on type
*/
async parseRawData(rawData, dataType) {
const content = typeof rawData === 'string' ? rawData : rawData.toString('utf8');
switch (dataType.toLowerCase()) {
case 'json':
const jsonData = JSON.parse(content);
return Array.isArray(jsonData) ? jsonData : [jsonData];
case 'csv':
return this.parseCSV(content);
case 'yaml':
case 'yml':
// For now, basic YAML support - in full implementation would use yaml parser
return JSON.parse(content); // Placeholder
case 'txt':
case 'text':
// Split text into sentences/paragraphs for analysis
return content.split(/\n+/).filter(line => line.trim()).map(line => ({ text: line }));
default:
throw new Error(`Unsupported data type: ${dataType}`);
}
}
/**
* Basic CSV parser
*/
parseCSV(content) {
const lines = content.split('\n').filter(line => line.trim());
if (lines.length < 2)
return [];
const headers = lines[0].split(',').map(h => h.trim().replace(/"/g, ''));
const data = [];
for (let i = 1; i < lines.length; i++) {
const values = lines[i].split(',').map(v => v.trim().replace(/"/g, ''));
const row = {};
headers.forEach((header, index) => {
row[header] = values[index] || '';
});
data.push(row);
}
return data;
}
/**
* Perform neural analysis on parsed data
*/
async performNeuralAnalysis(parsedData, config = this.config) {
// Phase 1: Neural Entity Detection
const detectedEntities = await this.detectEntitiesWithNeuralAnalysis(parsedData, config);
// Phase 2: Neural Relationship Detection
const detectedRelationships = await this.detectRelationshipsWithNeuralAnalysis(detectedEntities, parsedData, config);
// Phase 3: Neural Insights Generation
const insights = await this.generateNeuralInsights(detectedEntities, detectedRelationships);
// Phase 4: Confidence Scoring
const overallConfidence = this.calculateOverallConfidence(detectedEntities, detectedRelationships);
return {
detectedEntities,
detectedRelationships,
confidence: overallConfidence,
insights
};
}
/**
* Neural Entity Detection - The Core AI Engine
*/
async detectEntitiesWithNeuralAnalysis(rawData, config = this.config) {
const entities = [];
const nounTypes = Object.values(NounType);
for (const [index, dataItem] of rawData.entries()) {
const mainText = this.extractMainText(dataItem);
const detections = [];
// Test against all noun types using semantic similarity
for (const nounType of nounTypes) {
const confidence = await this.calculateEntityTypeConfidence(mainText, dataItem, nounType);
if (confidence >= config.confidenceThreshold - 0.2) { // Allow slightly lower for alternatives
const reasoning = await this.generateEntityReasoning(mainText, dataItem, nounType);
detections.push({ type: nounType, confidence, reasoning });
}
}
if (detections.length > 0) {
// Sort by confidence
detections.sort((a, b) => b.confidence - a.confidence);
const primaryType = detections[0];
const alternatives = detections.slice(1, 3); // Top 2 alternatives
entities.push({
originalData: dataItem,
nounType: primaryType.type,
confidence: primaryType.confidence,
suggestedId: this.generateSmartId(dataItem, primaryType.type, index),
reasoning: primaryType.reasoning,
alternativeTypes: alternatives
});
}
}
return entities;
}
/**
* Calculate entity type confidence using AI
*/
async calculateEntityTypeConfidence(text, data, nounType) {
// Base semantic similarity using search
const searchResults = await this.brainy.search(text + ' ' + nounType, 1);
const textSimilarity = searchResults.length > 0 ? searchResults[0].score : 0.5;
// Field-based confidence boost
const fieldBoost = this.calculateFieldBasedConfidence(data, nounType);
// Pattern-based confidence boost
const patternBoost = this.calculatePatternBasedConfidence(text, data, nounType);
// Combine confidences with weights
const combined = (textSimilarity * 0.5) + (fieldBoost * 0.3) + (patternBoost * 0.2);
return Math.min(combined, 1.0);
}
/**
* Field-based confidence calculation
*/
calculateFieldBasedConfidence(data, nounType) {
const fields = Object.keys(data);
let boost = 0;
// Field patterns that boost confidence for specific noun types
const fieldPatterns = {
[NounType.Person]: ['name', 'email', 'phone', 'age', 'firstname', 'lastname', 'employee'],
[NounType.Organization]: ['company', 'organization', 'corp', 'inc', 'ltd', 'department', 'team'],
[NounType.Project]: ['project', 'task', 'deadline', 'status', 'milestone', 'deliverable'],
[NounType.Location]: ['address', 'city', 'country', 'state', 'zip', 'location', 'coordinates'],
[NounType.Product]: ['product', 'price', 'sku', 'inventory', 'category', 'brand'],
[NounType.Event]: ['date', 'time', 'venue', 'event', 'meeting', 'conference', 'schedule']
};
const relevantPatterns = fieldPatterns[nounType] || [];
for (const field of fields) {
for (const pattern of relevantPatterns) {
if (field.toLowerCase().includes(pattern)) {
boost += 0.1;
}
}
}
return Math.min(boost, 0.5);
}
/**
* Pattern-based confidence calculation
*/
calculatePatternBasedConfidence(text, data, nounType) {
let boost = 0;
// Content patterns that indicate entity types
const patterns = {
[NounType.Person]: [
/@.*\.com/i, // Email pattern
/\b[A-Z][a-z]+ [A-Z][a-z]+\b/, // Name pattern
/Mr\.|Mrs\.|Dr\.|Prof\./i // Title pattern
],
[NounType.Organization]: [
/\bInc\.|Corp\.|LLC\.|Ltd\./i, // Corporate suffixes
/Company|Corporation|Enterprise/i
],
[NounType.Location]: [
/\b\d{5}(-\d{4})?\b/, // ZIP code
/Street|Ave|Road|Blvd/i
]
};
const relevantPatterns = patterns[nounType] || [];
for (const pattern of relevantPatterns) {
if (pattern.test(text)) {
boost += 0.15;
}
}
return Math.min(boost, 0.3);
}
/**
* Generate reasoning for entity type selection
*/
async generateEntityReasoning(text, data, nounType) {
const reasons = [];
// Semantic similarity reason
const searchResults = await this.brainy.search(text + ' ' + nounType, 1);
const similarity = searchResults.length > 0 ? searchResults[0].score : 0.5;
if (similarity > 0.7) {
reasons.push(`High semantic similarity (${(similarity * 100).toFixed(1)}%)`);
}
// Field-based reasons
const relevantFields = this.getRelevantFields(data, nounType);
if (relevantFields.length > 0) {
reasons.push(`Contains ${nounType}-specific fields: ${relevantFields.join(', ')}`);
}
// Pattern-based reasons
const matchedPatterns = this.getMatchedPatterns(text, data, nounType);
if (matchedPatterns.length > 0) {
reasons.push(`Matches ${nounType} patterns: ${matchedPatterns.join(', ')}`);
}
return reasons.length > 0 ? reasons.join('; ') : 'General semantic match';
}
/**
* Neural Relationship Detection
*/
async detectRelationshipsWithNeuralAnalysis(entities, rawData, config = this.config) {
const relationships = [];
const verbTypes = Object.values(VerbType);
// For each pair of entities, test relationship possibilities
for (let i = 0; i < entities.length; i++) {
for (let j = i + 1; j < entities.length; j++) {
const sourceEntity = entities[i];
const targetEntity = entities[j];
// Extract context for relationship detection
const context = this.extractRelationshipContext(sourceEntity.originalData, targetEntity.originalData, rawData);
// Test all verb types
for (const verbType of verbTypes) {
const confidence = await this.calculateRelationshipConfidence(sourceEntity, targetEntity, verbType, context);
if (confidence >= config.confidenceThreshold - 0.1) { // Slightly lower threshold for relationships
const weight = config.enableWeights ?
this.calculateRelationshipWeight(sourceEntity, targetEntity, verbType, context) :
0.5;
const reasoning = await this.generateRelationshipReasoning(sourceEntity, targetEntity, verbType, context);
relationships.push({
sourceId: sourceEntity.suggestedId,
targetId: targetEntity.suggestedId,
verbType,
confidence,
weight,
reasoning,
context,
metadata: this.extractRelationshipMetadata(sourceEntity.originalData, targetEntity.originalData, verbType)
});
}
}
}
}
// Sort by confidence and remove duplicates/conflicts
return this.pruneRelationships(relationships);
}
/**
* Calculate relationship confidence
*/
async calculateRelationshipConfidence(source, target, verbType, context) {
// Semantic similarity between entities and verb type
const relationshipText = `${this.extractMainText(source.originalData)} ${verbType} ${this.extractMainText(target.originalData)}`;
const directResults = await this.brainy.search(relationshipText, 1);
const directSimilarity = directResults.length > 0 ? directResults[0].score : 0.5;
// Context-based similarity
const contextResults = await this.brainy.search(context + ' ' + verbType, 1);
const contextSimilarity = contextResults.length > 0 ? contextResults[0].score : 0.5;
// Entity type compatibility
const typeCompatibility = this.calculateTypeCompatibility(source.nounType, target.nounType, verbType);
// Combine with weights
return (directSimilarity * 0.4) + (contextSimilarity * 0.4) + (typeCompatibility * 0.2);
}
/**
* Calculate relationship weight/strength
*/
calculateRelationshipWeight(source, target, verbType, context) {
let weight = 0.5; // Base weight
// Context richness (more descriptive = stronger)
const contextWords = context.split(' ').length;
weight += Math.min(contextWords / 20, 0.2);
// Entity importance (higher confidence entities = stronger relationships)
const avgEntityConfidence = (source.confidence + target.confidence) / 2;
weight += avgEntityConfidence * 0.2;
// Verb type specificity (more specific verbs = stronger)
const verbSpecificity = this.getVerbSpecificity(verbType);
weight += verbSpecificity * 0.1;
return Math.min(weight, 1.0);
}
/**
* Generate Neural Insights - The Intelligence Layer
*/
async generateNeuralInsights(entities, relationships) {
const insights = [];
// Detect hierarchies
const hierarchies = this.detectHierarchies(relationships);
hierarchies.forEach(hierarchy => {
insights.push({
type: 'hierarchy',
description: `Detected ${hierarchy.type} hierarchy with ${hierarchy.levels} levels`,
confidence: hierarchy.confidence,
affectedEntities: hierarchy.entities,
recommendation: `Consider visualizing the ${hierarchy.type} structure`
});
});
// Detect clusters
const clusters = this.detectClusters(entities, relationships);
clusters.forEach(cluster => {
insights.push({
type: 'cluster',
description: `Found cluster of ${cluster.size} ${cluster.primaryType} entities`,
confidence: cluster.confidence,
affectedEntities: cluster.entities,
recommendation: `These ${cluster.primaryType}s might form a natural grouping`
});
});
// Detect patterns
const patterns = this.detectPatterns(relationships);
patterns.forEach(pattern => {
insights.push({
type: 'pattern',
description: `Common relationship pattern: ${pattern.description}`,
confidence: pattern.confidence,
affectedEntities: pattern.entities,
recommendation: pattern.recommendation
});
});
return insights;
}
/**
* Helper methods for the neural system
*/
extractMainText(data) {
// Extract the most relevant text from a data object
const textFields = ['name', 'title', 'description', 'content', 'text', 'label'];
for (const field of textFields) {
if (data[field] && typeof data[field] === 'string') {
return data[field];
}
}
// Fallback: concatenate all string values
return Object.values(data)
.filter(v => typeof v === 'string')
.join(' ')
.substring(0, 200); // Limit length
}
generateSmartId(data, nounType, index) {
const mainText = this.extractMainText(data);
const cleanText = mainText.toLowerCase().replace(/[^a-z0-9]/g, '_').substring(0, 20);
return `${nounType}_${cleanText}_${index}`;
}
extractRelationshipContext(source, target, allData) {
// Extract context for relationship detection
return [
this.extractMainText(source),
this.extractMainText(target),
// Add more contextual information
].join(' ');
}
calculateTypeCompatibility(sourceType, targetType, verbType) {
// Define type compatibility matrix for relationships
const compatibilityMatrix = {
[NounType.Person]: {
[NounType.Organization]: [VerbType.MemberOf, VerbType.WorksWith],
[NounType.Project]: [VerbType.WorksWith, VerbType.Creates],
[NounType.Person]: [VerbType.WorksWith, VerbType.Mentors, VerbType.ReportsTo]
}
// Add more compatibility rules
};
const sourceCompatibility = compatibilityMatrix[sourceType];
if (sourceCompatibility && sourceCompatibility[targetType]) {
return sourceCompatibility[targetType].includes(verbType) ? 1.0 : 0.3;
}
return 0.5; // Default compatibility
}
getVerbSpecificity(verbType) {
// More specific verbs get higher scores
const specificityScores = {
[VerbType.RelatedTo]: 0.1, // Very generic
[VerbType.WorksWith]: 0.7, // Specific
[VerbType.Mentors]: 0.9, // Very specific
[VerbType.ReportsTo]: 0.9, // Very specific
[VerbType.Supervises]: 0.9 // Very specific
};
return specificityScores[verbType] || 0.5;
}
getRelevantFields(data, nounType) {
// Implementation for finding relevant fields
return [];
}
getMatchedPatterns(text, data, nounType) {
// Implementation for finding matched patterns
return [];
}
pruneRelationships(relationships) {
// Remove duplicates and low-confidence relationships
return relationships
.sort((a, b) => b.confidence - a.confidence)
.slice(0, 1000); // Limit to top 1000 relationships
}
detectHierarchies(relationships) {
// Detect hierarchical structures
return [];
}
detectClusters(entities, relationships) {
// Detect entity clusters
return [];
}
detectPatterns(relationships) {
// Detect relationship patterns
return [];
}
calculateOverallConfidence(entities, relationships) {
if (entities.length === 0)
return 0;
const entityConfidence = entities.reduce((sum, e) => sum + e.confidence, 0) / entities.length;
if (relationships.length === 0)
return entityConfidence;
const relationshipConfidence = relationships.reduce((sum, r) => sum + r.confidence, 0) / relationships.length;
return (entityConfidence + relationshipConfidence) / 2;
}
async storeNeuralAnalysis(analysis) {
// Store the full analysis result for later retrieval by Neural Import or other systems
// This could be stored in the brainy instance metadata or a separate analysis store
}
getDataTypeFromPath(filePath) {
const ext = path.extname(filePath).toLowerCase();
switch (ext) {
case '.json': return 'json';
case '.csv': return 'csv';
case '.yaml':
case '.yml': return 'yaml';
case '.txt': return 'text';
default: return 'text';
}
}
async generateRelationshipReasoning(source, target, verbType, context) {
return `Neural analysis detected ${verbType} relationship based on semantic context`;
}
extractRelationshipMetadata(sourceData, targetData, verbType) {
return {
sourceType: typeof sourceData,
targetType: typeof targetData,
detectedBy: 'neural-import-sense',
timestamp: new Date().toISOString()
};
}
/**
* Assess data quality metrics
*/
assessDataQuality(parsedData, analysis) {
// Completeness: ratio of fields with data
let totalFields = 0;
let filledFields = 0;
parsedData.forEach(item => {
const fields = Object.keys(item);
totalFields += fields.length;
filledFields += fields.filter(field => item[field] !== null &&
item[field] !== undefined &&
item[field] !== '').length;
});
const completeness = totalFields > 0 ? filledFields / totalFields : 0;
// Consistency: variance in field structure
const fieldSets = parsedData.map(item => new Set(Object.keys(item)));
const allFields = new Set(fieldSets.flatMap(set => Array.from(set)));
let consistencyScore = 0;
if (fieldSets.length > 0) {
consistencyScore = Array.from(allFields).reduce((score, field) => {
const hasField = fieldSets.filter(set => set.has(field)).length;
return score + (hasField / fieldSets.length);
}, 0) / allFields.size;
}
// Accuracy: average confidence of detected entities
const accuracy = analysis.detectedEntities.length > 0 ?
analysis.detectedEntities.reduce((sum, e) => sum + e.confidence, 0) / analysis.detectedEntities.length :
0;
return {
completeness,
consistency: consistencyScore,
accuracy
};
}
/**
* Generate recommendations based on analysis
*/
generateRecommendations(parsedData, analysis, entityTypes, relationshipTypes) {
const recommendations = [];
// Low entity confidence recommendations
const lowConfidenceEntities = entityTypes.filter(et => et.confidence < 0.7);
if (lowConfidenceEntities.length > 0) {
recommendations.push(`Consider improving field names for ${lowConfidenceEntities.map(e => e.type).join(', ')} entities`);
}
// Missing relationships recommendations
if (relationshipTypes.length === 0 && entityTypes.length > 1) {
recommendations.push('Add fields that describe how entities relate to each other');
}
// Data structure recommendations
if (parsedData.length > 0) {
const firstItem = parsedData[0];
const fieldCount = Object.keys(firstItem).length;
if (fieldCount < 3) {
recommendations.push('Consider adding more descriptive fields to each entity');
}
if (fieldCount > 20) {
recommendations.push('Consider grouping related fields or splitting complex entities');
}
}
// Entity distribution recommendations
const dominantEntityType = entityTypes.reduce((max, current) => current.count > max.count ? current : max, entityTypes[0] || { count: 0 });
if (dominantEntityType && dominantEntityType.count > parsedData.length * 0.8) {
recommendations.push(`Consider diversifying entity types - ${dominantEntityType.type} dominates the dataset`);
}
// Relationship quality recommendations
const lowWeightRelationships = relationshipTypes.filter(rt => rt.confidence < 0.6);
if (lowWeightRelationships.length > 0) {
recommendations.push('Consider adding more contextual information to strengthen relationship detection');
}
return recommendations;
}
}
//# sourceMappingURL=neuralImport.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,167 @@
/**
* Server Search Augmentations
*
* This file implements conduit and activation augmentations for browser-server search functionality.
* It allows Brainy to search a server-hosted instance and store results locally.
*/
import { AugmentationType, IActivationAugmentation, AugmentationResponse, WebSocketConnection } from '../types/augmentations.js';
import { WebSocketConduitAugmentation } from './conduitAugmentations.js';
import { BrainyDataInterface } from '../types/brainyDataInterface.js';
/**
* ServerSearchConduitAugmentation
*
* A specialized conduit augmentation that provides functionality for searching
* a server-hosted Brainy instance and storing results locally.
*/
export declare class ServerSearchConduitAugmentation extends WebSocketConduitAugmentation {
private localDb;
constructor(name?: string);
/**
* Initialize the augmentation
*/
initialize(): Promise<void>;
/**
* Set the local Brainy instance
* @param db The Brainy instance to use for local storage
*/
setLocalDb(db: BrainyDataInterface): void;
/**
* Get the local Brainy instance
* @returns The local Brainy instance
*/
getLocalDb(): BrainyDataInterface | null;
/**
* Search the server-hosted Brainy instance and store results locally
* @param connectionId The ID of the established connection
* @param query The search query
* @param limit Maximum number of results to return
* @returns Search results
*/
searchServer(connectionId: string, query: string, limit?: number): Promise<AugmentationResponse<unknown>>;
/**
* Search the local Brainy instance
* @param query The search query
* @param limit Maximum number of results to return
* @returns Search results
*/
searchLocal(query: string, limit?: number): Promise<AugmentationResponse<unknown>>;
/**
* Search both server and local instances, combine results, and store server results locally
* @param connectionId The ID of the established connection
* @param query The search query
* @param limit Maximum number of results to return
* @returns Combined search results
*/
searchCombined(connectionId: string, query: string, limit?: number): Promise<AugmentationResponse<unknown>>;
/**
* Add data to both local and server instances
* @param connectionId The ID of the established connection
* @param data Text or vector to add
* @param metadata Metadata for the data
* @returns ID of the added data
*/
addToBoth(connectionId: string, data: string | any[], metadata?: any): Promise<AugmentationResponse<string>>;
}
/**
* ServerSearchActivationAugmentation
*
* An activation augmentation that provides actions for server search functionality.
*/
export declare class ServerSearchActivationAugmentation implements IActivationAugmentation {
readonly name: string;
readonly description: string;
enabled: boolean;
private isInitialized;
private conduitAugmentation;
private connections;
constructor(name?: string);
getType(): AugmentationType;
/**
* Initialize the augmentation
*/
initialize(): Promise<void>;
/**
* Shut down the augmentation
*/
shutDown(): Promise<void>;
/**
* Get the status of the augmentation
*/
getStatus(): Promise<'active' | 'inactive' | 'error'>;
/**
* Set the conduit augmentation to use for server search
* @param conduit The ServerSearchConduitAugmentation to use
*/
setConduitAugmentation(conduit: ServerSearchConduitAugmentation): void;
/**
* Store a connection for later use
* @param connectionId The ID to use for the connection
* @param connection The WebSocket connection
*/
storeConnection(connectionId: string, connection: WebSocketConnection): void;
/**
* Get a stored connection
* @param connectionId The ID of the connection to retrieve
* @returns The WebSocket connection
*/
getConnection(connectionId: string): WebSocketConnection | undefined;
/**
* Trigger an action based on a processed command or internal state
* @param actionName The name of the action to trigger
* @param parameters Optional parameters for the action
*/
triggerAction(actionName: string, parameters?: Record<string, unknown>): AugmentationResponse<unknown>;
/**
* Handle the connectToServer action
* @param parameters Action parameters
*/
private handleConnectToServer;
/**
* Handle the searchServer action
* @param parameters Action parameters
*/
private handleSearchServer;
/**
* Handle the searchLocal action
* @param parameters Action parameters
*/
private handleSearchLocal;
/**
* Handle the searchCombined action
* @param parameters Action parameters
*/
private handleSearchCombined;
/**
* Handle the addToBoth action
* @param parameters Action parameters
*/
private handleAddToBoth;
/**
* Generates an expressive output or response from Brainy
* @param knowledgeId The identifier of the knowledge to express
* @param format The desired output format (e.g., 'text', 'json')
*/
generateOutput(knowledgeId: string, format: string): AugmentationResponse<string | Record<string, unknown>>;
/**
* Interacts with an external system or API
* @param systemId The identifier of the external system
* @param payload The data to send to the external system
*/
interactExternal(systemId: string, payload: Record<string, unknown>): AugmentationResponse<unknown>;
}
/**
* Factory function to create server search augmentations
* @param serverUrl The URL of the server to connect to
* @param options Additional options
* @returns An object containing the created augmentations
*/
export declare function createServerSearchAugmentations(serverUrl: string, options?: {
conduitName?: string;
activationName?: string;
protocols?: string | string[];
localDb?: BrainyDataInterface;
}): Promise<{
conduit: ServerSearchConduitAugmentation;
activation: ServerSearchActivationAugmentation;
connection: WebSocketConnection;
}>;

View file

@ -0,0 +1,531 @@
/**
* Server Search Augmentations
*
* This file implements conduit and activation augmentations for browser-server search functionality.
* It allows Brainy to search a server-hosted instance and store results locally.
*/
import { AugmentationType } from '../types/augmentations.js';
import { WebSocketConduitAugmentation } from './conduitAugmentations.js';
/**
* ServerSearchConduitAugmentation
*
* A specialized conduit augmentation that provides functionality for searching
* a server-hosted Brainy instance and storing results locally.
*/
export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentation {
constructor(name = 'server-search-conduit') {
super(name);
this.localDb = null;
// this.description = 'Conduit augmentation for server-hosted Brainy search'
}
/**
* Initialize the augmentation
*/
async initialize() {
if (this.isInitialized) {
return;
}
try {
// Initialize the base conduit
await super.initialize();
// Local DB must be set before initialization
if (!this.localDb) {
throw new Error('Local database not set. Call setLocalDb before initializing.');
}
this.isInitialized = true;
}
catch (error) {
console.error(`Failed to initialize ${this.name}:`, error);
throw new Error(`Failed to initialize ${this.name}: ${error}`);
}
}
/**
* Set the local Brainy instance
* @param db The Brainy instance to use for local storage
*/
setLocalDb(db) {
this.localDb = db;
}
/**
* Get the local Brainy instance
* @returns The local Brainy instance
*/
getLocalDb() {
return this.localDb;
}
/**
* Search the server-hosted Brainy instance and store results locally
* @param connectionId The ID of the established connection
* @param query The search query
* @param limit Maximum number of results to return
* @returns Search results
*/
async searchServer(connectionId, query, limit = 10) {
await this.ensureInitialized();
try {
// Create a search request
const readResult = await this.readData({
connectionId,
query: {
type: 'search',
query,
limit
}
});
if (readResult.success && readResult.data) {
const searchResults = readResult.data;
// Store the results in the local Brainy instance
if (this.localDb) {
for (const result of searchResults) {
// Check if the noun already exists in the local database
const existingNoun = await this.localDb.get(result.id);
if (!existingNoun) {
// Add the noun to the local database
await this.localDb.add(result.vector, result.metadata);
}
}
}
return {
success: true,
data: searchResults
};
}
else {
return {
success: false,
data: null,
error: readResult.error || 'Unknown error searching server'
};
}
}
catch (error) {
console.error('Error searching server:', error);
return {
success: false,
data: null,
error: `Error searching server: ${error}`
};
}
}
/**
* Search the local Brainy instance
* @param query The search query
* @param limit Maximum number of results to return
* @returns Search results
*/
async searchLocal(query, limit = 10) {
await this.ensureInitialized();
try {
if (!this.localDb) {
return {
success: false,
data: null,
error: 'Local database not initialized'
};
}
const results = await this.localDb.searchText(query, limit);
return {
success: true,
data: results
};
}
catch (error) {
console.error('Error searching local database:', error);
return {
success: false,
data: null,
error: `Error searching local database: ${error}`
};
}
}
/**
* Search both server and local instances, combine results, and store server results locally
* @param connectionId The ID of the established connection
* @param query The search query
* @param limit Maximum number of results to return
* @returns Combined search results
*/
async searchCombined(connectionId, query, limit = 10) {
await this.ensureInitialized();
try {
// Search local first
const localSearchResult = await this.searchLocal(query, limit);
if (!localSearchResult.success) {
return localSearchResult;
}
const localResults = localSearchResult.data;
// If we have enough local results, return them
if (localResults.length >= limit) {
return localSearchResult;
}
// Otherwise, search server for additional results
const serverSearchResult = await this.searchServer(connectionId, query, limit - localResults.length);
if (!serverSearchResult.success) {
// If server search fails, return local results
return localSearchResult;
}
const serverResults = serverSearchResult.data;
// Combine results, removing duplicates
const combinedResults = [...localResults];
const localIds = new Set(localResults.map((r) => r.id));
for (const result of serverResults) {
if (!localIds.has(result.id)) {
combinedResults.push(result);
}
}
return {
success: true,
data: combinedResults
};
}
catch (error) {
console.error('Error performing combined search:', error);
return {
success: false,
data: null,
error: `Error performing combined search: ${error}`
};
}
}
/**
* Add data to both local and server instances
* @param connectionId The ID of the established connection
* @param data Text or vector to add
* @param metadata Metadata for the data
* @returns ID of the added data
*/
async addToBoth(connectionId, data, metadata = {}) {
await this.ensureInitialized();
try {
if (!this.localDb) {
return {
success: false,
data: '',
error: 'Local database not initialized'
};
}
// Add to local first
const id = await this.localDb.add(data, metadata);
// Get the vector and metadata
const noun = (await this.localDb.get(id));
if (!noun) {
return {
success: false,
data: '',
error: 'Failed to retrieve newly created noun'
};
}
// Add to server
const writeResult = await this.writeData({
connectionId,
data: {
type: 'addNoun',
vector: noun.vector,
metadata: noun.metadata
}
});
if (!writeResult.success) {
return {
success: true,
data: id,
error: `Added locally but failed to add to server: ${writeResult.error}`
};
}
return {
success: true,
data: id
};
}
catch (error) {
console.error('Error adding data to both:', error);
return {
success: false,
data: '',
error: `Error adding data to both: ${error}`
};
}
}
}
/**
* ServerSearchActivationAugmentation
*
* An activation augmentation that provides actions for server search functionality.
*/
export class ServerSearchActivationAugmentation {
constructor(name = 'server-search-activation') {
this.enabled = true;
this.isInitialized = false;
this.conduitAugmentation = null;
this.connections = new Map();
this.name = name;
this.description = 'Activation augmentation for server-hosted Brainy search';
}
getType() {
return AugmentationType.ACTIVATION;
}
/**
* Initialize the augmentation
*/
async initialize() {
if (this.isInitialized) {
return;
}
this.isInitialized = true;
}
/**
* Shut down the augmentation
*/
async shutDown() {
this.isInitialized = false;
}
/**
* Get the status of the augmentation
*/
async getStatus() {
return this.isInitialized ? 'active' : 'inactive';
}
/**
* Set the conduit augmentation to use for server search
* @param conduit The ServerSearchConduitAugmentation to use
*/
setConduitAugmentation(conduit) {
this.conduitAugmentation = conduit;
}
/**
* Store a connection for later use
* @param connectionId The ID to use for the connection
* @param connection The WebSocket connection
*/
storeConnection(connectionId, connection) {
this.connections.set(connectionId, connection);
}
/**
* Get a stored connection
* @param connectionId The ID of the connection to retrieve
* @returns The WebSocket connection
*/
getConnection(connectionId) {
return this.connections.get(connectionId);
}
/**
* Trigger an action based on a processed command or internal state
* @param actionName The name of the action to trigger
* @param parameters Optional parameters for the action
*/
triggerAction(actionName, parameters) {
if (!this.conduitAugmentation) {
return {
success: false,
data: null,
error: 'Conduit augmentation not set'
};
}
// Handle different actions
switch (actionName) {
case 'connectToServer':
return this.handleConnectToServer(parameters || {});
case 'searchServer':
return this.handleSearchServer(parameters || {});
case 'searchLocal':
return this.handleSearchLocal(parameters || {});
case 'searchCombined':
return this.handleSearchCombined(parameters || {});
case 'addToBoth':
return this.handleAddToBoth(parameters || {});
default:
return {
success: false,
data: null,
error: `Unknown action: ${actionName}`
};
}
}
/**
* Handle the connectToServer action
* @param parameters Action parameters
*/
handleConnectToServer(parameters) {
const serverUrl = parameters.serverUrl;
const protocols = parameters.protocols;
if (!serverUrl) {
return {
success: false,
data: null,
error: 'serverUrl parameter is required'
};
}
// Return a promise that will be resolved when the connection is established
return {
success: true,
data: this.conduitAugmentation.establishConnection(serverUrl, {
protocols
})
};
}
/**
* Handle the searchServer action
* @param parameters Action parameters
*/
handleSearchServer(parameters) {
const connectionId = parameters.connectionId;
const query = parameters.query;
const limit = parameters.limit || 10;
if (!connectionId) {
return {
success: false,
data: null,
error: 'connectionId parameter is required'
};
}
if (!query) {
return {
success: false,
data: null,
error: 'query parameter is required'
};
}
// Return a promise that will be resolved when the search is complete
return {
success: true,
data: this.conduitAugmentation.searchServer(connectionId, query, limit)
};
}
/**
* Handle the searchLocal action
* @param parameters Action parameters
*/
handleSearchLocal(parameters) {
const query = parameters.query;
const limit = parameters.limit || 10;
if (!query) {
return {
success: false,
data: null,
error: 'query parameter is required'
};
}
// Return a promise that will be resolved when the search is complete
return {
success: true,
data: this.conduitAugmentation.searchLocal(query, limit)
};
}
/**
* Handle the searchCombined action
* @param parameters Action parameters
*/
handleSearchCombined(parameters) {
const connectionId = parameters.connectionId;
const query = parameters.query;
const limit = parameters.limit || 10;
if (!connectionId) {
return {
success: false,
data: null,
error: 'connectionId parameter is required'
};
}
if (!query) {
return {
success: false,
data: null,
error: 'query parameter is required'
};
}
// Return a promise that will be resolved when the search is complete
return {
success: true,
data: this.conduitAugmentation.searchCombined(connectionId, query, limit)
};
}
/**
* Handle the addToBoth action
* @param parameters Action parameters
*/
handleAddToBoth(parameters) {
const connectionId = parameters.connectionId;
const data = parameters.data;
const metadata = parameters.metadata || {};
if (!connectionId) {
return {
success: false,
data: null,
error: 'connectionId parameter is required'
};
}
if (!data) {
return {
success: false,
data: null,
error: 'data parameter is required'
};
}
// Return a promise that will be resolved when the add is complete
return {
success: true,
data: this.conduitAugmentation.addToBoth(connectionId, data, metadata)
};
}
/**
* Generates an expressive output or response from Brainy
* @param knowledgeId The identifier of the knowledge to express
* @param format The desired output format (e.g., 'text', 'json')
*/
generateOutput(knowledgeId, format) {
// This method is not used for server search functionality
return {
success: false,
data: '',
error: 'generateOutput is not implemented for ServerSearchActivationAugmentation'
};
}
/**
* Interacts with an external system or API
* @param systemId The identifier of the external system
* @param payload The data to send to the external system
*/
interactExternal(systemId, payload) {
// This method is not used for server search functionality
return {
success: false,
data: null,
error: 'interactExternal is not implemented for ServerSearchActivationAugmentation'
};
}
}
/**
* Factory function to create server search augmentations
* @param serverUrl The URL of the server to connect to
* @param options Additional options
* @returns An object containing the created augmentations
*/
export async function createServerSearchAugmentations(serverUrl, options = {}) {
// Create the conduit augmentation
const conduit = new ServerSearchConduitAugmentation(options.conduitName);
await conduit.initialize();
// Set the local database if provided
if (options.localDb) {
conduit.setLocalDb(options.localDb);
}
// Create the activation augmentation
const activation = new ServerSearchActivationAugmentation(options.activationName);
await activation.initialize();
// Link the augmentations
activation.setConduitAugmentation(conduit);
// Connect to the server
const connectionResult = await conduit.establishConnection(serverUrl, {
protocols: options.protocols
});
if (!connectionResult.success || !connectionResult.data) {
throw new Error(`Failed to connect to server: ${connectionResult.error}`);
}
const connection = connectionResult.data;
// Store the connection in the activation augmentation
activation.storeConnection(connection.connectionId, connection);
return {
conduit,
activation,
connection
};
}
//# sourceMappingURL=serverSearchAugmentations.js.map

File diff suppressed because one or more lines are too long