feat: harden plugin system wiring and add developer diagnostics
Fix critical wiring bugs that prevented plugin-provided implementations from being used at runtime. All CRUD operations, fork/checkout/clear, batch embedding, neural APIs, and VFS path resolution now properly dispatch through the plugin registry. Changes: - Wire graphIndex to storage for getVerbsBySource() fast path - Replace instanceof checks with duck-typing (indexIsTypeAware flag) so plugin HNSW indexes work in add/update/delete/search - Add createIndex() shared helper for plugin HNSW factory - Fix fork/checkout/clear to use plugin factories for metadataIndex, graphIndex, and HNSW instead of hardcoding JS constructors - Add three-tier embedBatch priority: embedBatch > embeddings > WASM - Skip WASM warmup/eagerEmbeddings when plugin provides embeddings - Fix PathResolver metadataIndex access (was looking on storage) - Use global UnifiedCache in SemanticPathResolver - Wire plugin distance function through neural APIs - Add diagnostics() method and CLI command for provider inspection - Add requireProviders() for production fail-fast assertions - Add init-time provider summary log - Add plugin developer documentation (docs/PLUGINS.md) - Export DiagnosticsResult type
This commit is contained in:
parent
3a21bf62b7
commit
401e300ff2
12 changed files with 705 additions and 77 deletions
|
|
@ -92,18 +92,20 @@ interface ItemWithMetadata {
|
|||
export class ImprovedNeuralAPI {
|
||||
private brain: any // Brainy instance
|
||||
private config: NeuralAPIConfig
|
||||
|
||||
private distanceFn: (a: Vector, b: Vector) => number
|
||||
|
||||
// Caching for performance
|
||||
private similarityCache = new Map<string, number | SimilarityResult>()
|
||||
private clusterCache = new Map<string, ClusteringResult>()
|
||||
private hierarchyCache = new Map<string, SemanticHierarchy>()
|
||||
private neighborsCache = new Map<string, NeighborsResult>()
|
||||
|
||||
|
||||
// Performance tracking
|
||||
private performanceMetrics = new Map<string, PerformanceMetrics[]>()
|
||||
|
||||
|
||||
constructor(brain: any, config: NeuralAPIConfig = {}) {
|
||||
this.brain = brain
|
||||
this.distanceFn = brain.distance || cosineDistance
|
||||
this.config = {
|
||||
cacheSize: 1000,
|
||||
defaultAlgorithm: 'auto',
|
||||
|
|
@ -114,7 +116,7 @@ export class ImprovedNeuralAPI {
|
|||
streamingBatchSize: 100,
|
||||
...config
|
||||
}
|
||||
|
||||
|
||||
this._initializeCleanupTimer()
|
||||
}
|
||||
|
||||
|
|
@ -1458,7 +1460,7 @@ export class ImprovedNeuralAPI {
|
|||
|
||||
switch (metric) {
|
||||
case 'cosine':
|
||||
score = 1 - cosineDistance(v1, v2)
|
||||
score = 1 - this.distanceFn(v1, v2)
|
||||
break
|
||||
case 'euclidean':
|
||||
score = 1 / (1 + euclideanDistance(v1, v2))
|
||||
|
|
@ -1467,7 +1469,7 @@ export class ImprovedNeuralAPI {
|
|||
score = 1 / (1 + this._manhattanDistance(v1, v2))
|
||||
break
|
||||
default:
|
||||
score = 1 - cosineDistance(v1, v2)
|
||||
score = 1 - this.distanceFn(v1, v2)
|
||||
}
|
||||
|
||||
if (options.detailed) {
|
||||
|
|
@ -3047,7 +3049,7 @@ export class ImprovedNeuralAPI {
|
|||
continue
|
||||
}
|
||||
|
||||
const similarity = 1 - cosineDistance(
|
||||
const similarity = 1 - this.distanceFn(
|
||||
Array.from(c1.centroid) as number[],
|
||||
Array.from(c2.centroid) as number[]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -132,12 +132,14 @@ export interface LODConfig {
|
|||
*/
|
||||
export class NeuralAPI {
|
||||
private brain: any // Brainy instance
|
||||
private distanceFn: (a: Vector, b: Vector) => number
|
||||
private similarityCache: Map<string, number> = new Map()
|
||||
private clusterCache: Map<string, any> = new Map() // Enhanced for enterprise
|
||||
private hierarchyCache: Map<string, SemanticHierarchy> = new Map()
|
||||
|
||||
|
||||
constructor(brain: any) {
|
||||
this.brain = brain
|
||||
this.distanceFn = brain.distance || cosineDistance
|
||||
}
|
||||
|
||||
// ===== SMART USER-FRIENDLY API =====
|
||||
|
|
@ -471,7 +473,7 @@ export class NeuralAPI {
|
|||
}
|
||||
|
||||
// Calculate similarity
|
||||
const score = cosineDistance(itemA.vector, itemB.vector)
|
||||
const score = this.distanceFn(itemA.vector, itemB.vector)
|
||||
|
||||
this.similarityCache.set(cacheKey, score)
|
||||
|
||||
|
|
@ -498,7 +500,7 @@ export class NeuralAPI {
|
|||
}
|
||||
|
||||
private async similarityByVector(vectorA: Vector, vectorB: Vector, options?: SimilarityOptions): Promise<number | SimilarityResult> {
|
||||
const score = cosineDistance(vectorA, vectorB)
|
||||
const score = this.distanceFn(vectorA, vectorB)
|
||||
|
||||
if (options?.explain) {
|
||||
return {
|
||||
|
|
@ -610,7 +612,7 @@ export class NeuralAPI {
|
|||
// Find minimum distance to existing sample
|
||||
let minDistance = Infinity
|
||||
for (const selected of sample) {
|
||||
const distance = cosineDistance(candidate.vector, selected.vector)
|
||||
const distance = this.distanceFn(candidate.vector, selected.vector)
|
||||
minDistance = Math.min(minDistance, distance)
|
||||
}
|
||||
|
||||
|
|
@ -652,7 +654,7 @@ export class NeuralAPI {
|
|||
let bestDistance = Infinity
|
||||
|
||||
for (let c = 0; c < k; c++) {
|
||||
const distance = cosineDistance(item.vector, centroids[c])
|
||||
const distance = this.distanceFn(item.vector, centroids[c])
|
||||
if (distance < bestDistance) {
|
||||
bestDistance = distance
|
||||
bestCluster = c
|
||||
|
|
@ -679,7 +681,7 @@ export class NeuralAPI {
|
|||
let bestDistance = Infinity
|
||||
|
||||
for (let cc = 0; cc < k; cc++) {
|
||||
const distance = cosineDistance(item.vector, centroids[cc])
|
||||
const distance = this.distanceFn(item.vector, centroids[cc])
|
||||
if (distance < bestDistance) {
|
||||
bestDistance = distance
|
||||
bestCluster = cc
|
||||
|
|
@ -750,7 +752,7 @@ export class NeuralAPI {
|
|||
let merged = false
|
||||
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
const similarity = cosineDistance(result[i].centroid, batchCluster.centroid)
|
||||
const similarity = this.distanceFn(result[i].centroid, batchCluster.centroid)
|
||||
|
||||
if (similarity > 0.8) {
|
||||
// Merge clusters
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ interface HistoricalEntry {
|
|||
*/
|
||||
export class VerbEmbeddingSignal {
|
||||
private brain: Brainy
|
||||
private distanceFn: (a: Vector, b: Vector) => number
|
||||
private options: Required<VerbEmbeddingSignalOptions>
|
||||
|
||||
// Pre-computed verb type embeddings (loaded once at startup)
|
||||
|
|
@ -88,6 +89,7 @@ export class VerbEmbeddingSignal {
|
|||
|
||||
constructor(brain: Brainy, options?: VerbEmbeddingSignalOptions) {
|
||||
this.brain = brain
|
||||
this.distanceFn = (brain as any).distance || cosineDistance
|
||||
this.options = {
|
||||
minConfidence: options?.minConfidence ?? 0.60,
|
||||
minSimilarity: options?.minSimilarity ?? 0.55,
|
||||
|
|
@ -142,7 +144,7 @@ export class VerbEmbeddingSignal {
|
|||
const similarities: Array<{ type: VerbType; similarity: number }> = []
|
||||
|
||||
for (const [verbType, typeEmbedding] of this.verbTypeEmbeddings) {
|
||||
const distance = cosineDistance(embedding, typeEmbedding)
|
||||
const distance = this.distanceFn(embedding, typeEmbedding)
|
||||
const similarity = 1 - distance // Convert distance to similarity
|
||||
similarities.push({ type: verbType, similarity })
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue