feat: add plugin system for cortex and storage adapters

Simple plugin architecture with two use cases:
1. Native acceleration (@soulcraft/brainy-cortex) — auto-detected
2. Custom storage adapters (e.g., Redis, DynamoDB)

Plugins implement BrainyPlugin interface with activate/deactivate lifecycle.
Auto-detection tries dynamic import of known packages during init().
Manual registration via brain.use(plugin) before init().

Provider keys: metadataIndex, graphIndex, entityIdMapper, cache, hnsw,
roaring, embeddings, distance, msgpack, storage:<name>
This commit is contained in:
David Snelling 2026-01-31 09:22:32 -08:00
parent 35cb674157
commit cc50ac3776
3 changed files with 246 additions and 1 deletions

View file

@ -13,7 +13,8 @@ import { BaseStorage } from './storage/baseStorage.js'
import { StorageAdapter, Vector, DistanceFunction, EmbeddingFunction, GraphVerb } from './coreTypes.js'
import {
defaultEmbeddingFunction,
cosineDistance
cosineDistance,
getBrainyVersion
} from './utils/index.js'
import { embeddingManager } from './embeddings/EmbeddingManager.js'
import { matchesMetadataFilter } from './utils/metadataFilter.js'
@ -33,6 +34,8 @@ import { BlobStorage } from './storage/cow/BlobStorage.js'
import { NULL_HASH } from './storage/cow/constants.js'
import { createPipeline } from './streaming/pipeline.js'
import { configureLogger, LogLevel } from './utils/logger.js'
import { PluginRegistry } from './plugin.js'
import type { BrainyPlugin, BrainyPluginContext } from './plugin.js'
import { TransactionManager } from './transaction/TransactionManager.js'
import {
ValidationConfig,
@ -142,6 +145,9 @@ export class Brainy<T = any> implements BrainyInterface<T> {
error: typeof console.error
}
// Plugin system
private pluginRegistry = new PluginRegistry()
// Sub-APIs (lazy-loaded)
private _neural?: ImprovedNeuralAPI
private _nlp?: NaturalLanguageProcessor
@ -267,6 +273,9 @@ export class Brainy<T = any> implements BrainyInterface<T> {
(this.storage as any).enableCOWLightweight((this.config.storage as any)?.branch || 'main')
}
// Auto-detect and activate plugins (e.g., @soulcraft/brainy-cortex)
await this.loadPlugins()
// Setup index now that we have storage
this.index = this.setupIndex()
@ -6534,6 +6543,51 @@ export class Brainy<T = any> implements BrainyInterface<T> {
await this.metadataIndex.detectAndRepairCorruption()
}
/**
* Register a plugin manually.
*
* Must be called BEFORE init(). Plugins registered after init()
* will not be activated.
*/
use(plugin: BrainyPlugin): this {
this.pluginRegistry.register(plugin)
return this
}
/**
* Get list of active plugin names.
*/
getActivePlugins(): string[] {
return this.pluginRegistry.getActivePlugins()
}
/**
* Auto-detect and activate plugins.
* Called internally during init().
*/
private async loadPlugins(): Promise<void> {
// Auto-detect installed plugins (e.g., @soulcraft/brainy-cortex)
const pluginPackages = (this.config as any).plugins as string[] | undefined
await this.pluginRegistry.autoDetect(pluginPackages || [])
// Create plugin context
const context: BrainyPluginContext = {
registerProvider: (key, impl) => this.pluginRegistry.registerProvider(key, impl),
version: getBrainyVersion()
}
// Activate all registered plugins
const activated = await this.pluginRegistry.activateAll(context)
if (activated.length > 0) {
// Only log if not in silent mode
if (!this.config.silent) {
for (const name of activated) {
console.log(`[brainy] Plugin activated: ${name}`)
}
}
}
}
/**
* Close and cleanup
*
@ -6547,6 +6601,9 @@ export class Brainy<T = any> implements BrainyInterface<T> {
await this.index.flush()
}
// Deactivate plugins
await this.pluginRegistry.deactivateAll()
// Shutdown augmentations
const augs = this.augmentationRegistry.getAll()
for (const aug of augs) {