@soulcraft/brainy 3.20.4 → 3.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +96 -1
- package/README.md +72 -2
- package/dist/brainy.js +9 -0
- package/dist/neural/entityExtractionCache.d.ts +111 -0
- package/dist/neural/entityExtractionCache.js +208 -0
- package/dist/neural/entityExtractor.d.ts +33 -1
- package/dist/neural/entityExtractor.js +66 -2
- package/dist/neural/relationshipConfidence.d.ts +79 -0
- package/dist/neural/relationshipConfidence.js +204 -0
- package/dist/storage/baseStorage.js +11 -6
- package/dist/types/brainy.types.d.ts +18 -0
- package/dist/types/progress.types.d.ts +107 -0
- package/dist/types/progress.types.js +221 -0
- package/package.json +10 -6
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Neural Entity Extractor using Brainy's NounTypes
|
|
3
3
|
* Uses embeddings and similarity matching for accurate type detection
|
|
4
|
+
*
|
|
5
|
+
* PRODUCTION-READY with caching support
|
|
4
6
|
*/
|
|
5
7
|
import { NounType } from '../types/graphTypes.js';
|
|
8
|
+
import { EntityExtractionCache, generateFileCacheKey, generateContentCacheKey, computeContentHash } from './entityExtractionCache.js';
|
|
6
9
|
export class NeuralEntityExtractor {
|
|
7
|
-
constructor(brain) {
|
|
10
|
+
constructor(brain, cacheOptions) {
|
|
8
11
|
// Type embeddings for similarity matching
|
|
9
12
|
this.typeEmbeddings = new Map();
|
|
10
13
|
this.initialized = false;
|
|
11
14
|
this.brain = brain;
|
|
15
|
+
this.cache = new EntityExtractionCache(cacheOptions);
|
|
12
16
|
}
|
|
13
17
|
/**
|
|
14
18
|
* Initialize type embeddings for neural matching
|
|
@@ -60,9 +64,24 @@ export class NeuralEntityExtractor {
|
|
|
60
64
|
}
|
|
61
65
|
/**
|
|
62
66
|
* Extract entities from text using neural matching
|
|
67
|
+
* Now with caching support for performance
|
|
63
68
|
*/
|
|
64
69
|
async extract(text, options) {
|
|
65
70
|
await this.initializeTypeEmbeddings();
|
|
71
|
+
// Check cache if enabled
|
|
72
|
+
if (options?.cache?.enabled !== false && (options?.path || options?.cache?.invalidateOn === 'hash')) {
|
|
73
|
+
const cacheKey = options.path
|
|
74
|
+
? generateFileCacheKey(options.path)
|
|
75
|
+
: generateContentCacheKey(text);
|
|
76
|
+
const cacheOptions = {
|
|
77
|
+
mtime: options.cache?.mtime,
|
|
78
|
+
contentHash: !options.path ? computeContentHash(text) : undefined
|
|
79
|
+
};
|
|
80
|
+
const cached = this.cache.get(cacheKey, cacheOptions);
|
|
81
|
+
if (cached) {
|
|
82
|
+
return cached;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
66
85
|
const entities = [];
|
|
67
86
|
const minConfidence = options?.confidence || 0.6;
|
|
68
87
|
const targetTypes = options?.types || Object.values(NounType);
|
|
@@ -111,7 +130,19 @@ export class NeuralEntityExtractor {
|
|
|
111
130
|
}
|
|
112
131
|
}
|
|
113
132
|
// Remove duplicates and overlaps
|
|
114
|
-
|
|
133
|
+
const deduplicatedEntities = this.deduplicateEntities(entities);
|
|
134
|
+
// Store in cache if enabled
|
|
135
|
+
if (options?.cache?.enabled !== false && (options?.path || options?.cache?.invalidateOn === 'hash')) {
|
|
136
|
+
const cacheKey = options.path
|
|
137
|
+
? generateFileCacheKey(options.path)
|
|
138
|
+
: generateContentCacheKey(text);
|
|
139
|
+
this.cache.set(cacheKey, deduplicatedEntities, {
|
|
140
|
+
ttl: options.cache?.ttl,
|
|
141
|
+
mtime: options.cache?.mtime,
|
|
142
|
+
contentHash: !options.path ? computeContentHash(text) : undefined
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
return deduplicatedEntities;
|
|
115
146
|
}
|
|
116
147
|
/**
|
|
117
148
|
* Extract candidate entities using patterns
|
|
@@ -312,5 +343,38 @@ export class NeuralEntityExtractor {
|
|
|
312
343
|
}
|
|
313
344
|
return result;
|
|
314
345
|
}
|
|
346
|
+
/**
|
|
347
|
+
* Invalidate cache entry for a specific path or hash
|
|
348
|
+
*/
|
|
349
|
+
invalidateCache(pathOrHash) {
|
|
350
|
+
const cacheKey = pathOrHash.includes(':')
|
|
351
|
+
? pathOrHash
|
|
352
|
+
: generateFileCacheKey(pathOrHash);
|
|
353
|
+
return this.cache.invalidate(cacheKey);
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Invalidate all cache entries matching a prefix
|
|
357
|
+
*/
|
|
358
|
+
invalidateCachePrefix(prefix) {
|
|
359
|
+
return this.cache.invalidatePrefix(prefix);
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Clear all cached entities
|
|
363
|
+
*/
|
|
364
|
+
clearCache() {
|
|
365
|
+
this.cache.clear();
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Get cache statistics
|
|
369
|
+
*/
|
|
370
|
+
getCacheStats() {
|
|
371
|
+
return this.cache.getStats();
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Cleanup expired cache entries
|
|
375
|
+
*/
|
|
376
|
+
cleanupCache() {
|
|
377
|
+
return this.cache.cleanup();
|
|
378
|
+
}
|
|
315
379
|
}
|
|
316
380
|
//# sourceMappingURL=entityExtractor.js.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relationship Confidence Scoring
|
|
3
|
+
*
|
|
4
|
+
* Scores the confidence of detected relationships based on multiple factors:
|
|
5
|
+
* - Entity proximity in text
|
|
6
|
+
* - Entity confidence scores
|
|
7
|
+
* - Pattern matches
|
|
8
|
+
* - Structural analysis
|
|
9
|
+
*
|
|
10
|
+
* PRODUCTION-READY - NO MOCKS, NO STUBS, REAL IMPLEMENTATION
|
|
11
|
+
*/
|
|
12
|
+
import { ExtractedEntity } from './entityExtractor.js';
|
|
13
|
+
import { VerbType } from '../types/graphTypes.js';
|
|
14
|
+
import { RelationEvidence } from '../types/brainy.types.js';
|
|
15
|
+
/**
|
|
16
|
+
* Detected relationship with confidence
|
|
17
|
+
*/
|
|
18
|
+
export interface DetectedRelationship {
|
|
19
|
+
sourceEntity: ExtractedEntity;
|
|
20
|
+
targetEntity: ExtractedEntity;
|
|
21
|
+
verbType: VerbType;
|
|
22
|
+
confidence: number;
|
|
23
|
+
evidence: RelationEvidence;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Configuration for relationship detection
|
|
27
|
+
*/
|
|
28
|
+
export interface RelationshipDetectionConfig {
|
|
29
|
+
minConfidence?: number;
|
|
30
|
+
maxDistance?: number;
|
|
31
|
+
useProximityBoost?: boolean;
|
|
32
|
+
usePatternMatching?: boolean;
|
|
33
|
+
useStructuralAnalysis?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Relationship confidence scorer
|
|
37
|
+
*/
|
|
38
|
+
export declare class RelationshipConfidenceScorer {
|
|
39
|
+
private config;
|
|
40
|
+
constructor(config?: RelationshipDetectionConfig);
|
|
41
|
+
/**
|
|
42
|
+
* Score a potential relationship between two entities
|
|
43
|
+
*/
|
|
44
|
+
scoreRelationship(source: ExtractedEntity, target: ExtractedEntity, verbType: VerbType, context: string): {
|
|
45
|
+
confidence: number;
|
|
46
|
+
evidence: RelationEvidence;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Calculate proximity boost based on distance between entities
|
|
50
|
+
*/
|
|
51
|
+
private calculateProximityBoost;
|
|
52
|
+
/**
|
|
53
|
+
* Check if entities match a verb pattern
|
|
54
|
+
*/
|
|
55
|
+
private checkVerbPattern;
|
|
56
|
+
/**
|
|
57
|
+
* Analyze structural relationship
|
|
58
|
+
*/
|
|
59
|
+
private analyzeStructure;
|
|
60
|
+
/**
|
|
61
|
+
* Get context text between two entities
|
|
62
|
+
*/
|
|
63
|
+
private getContextBetween;
|
|
64
|
+
/**
|
|
65
|
+
* Detect relationships between a list of entities
|
|
66
|
+
*/
|
|
67
|
+
detectRelationships(entities: ExtractedEntity[], context: string, verbHints?: VerbType[]): DetectedRelationship[];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Convenience function to score a single relationship
|
|
71
|
+
*/
|
|
72
|
+
export declare function scoreRelationshipConfidence(source: ExtractedEntity, target: ExtractedEntity, verbType: VerbType, context: string, config?: RelationshipDetectionConfig): {
|
|
73
|
+
confidence: number;
|
|
74
|
+
evidence: RelationEvidence;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Convenience function to detect all relationships in text
|
|
78
|
+
*/
|
|
79
|
+
export declare function detectRelationshipsWithConfidence(entities: ExtractedEntity[], context: string, config?: RelationshipDetectionConfig): DetectedRelationship[];
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relationship Confidence Scoring
|
|
3
|
+
*
|
|
4
|
+
* Scores the confidence of detected relationships based on multiple factors:
|
|
5
|
+
* - Entity proximity in text
|
|
6
|
+
* - Entity confidence scores
|
|
7
|
+
* - Pattern matches
|
|
8
|
+
* - Structural analysis
|
|
9
|
+
*
|
|
10
|
+
* PRODUCTION-READY - NO MOCKS, NO STUBS, REAL IMPLEMENTATION
|
|
11
|
+
*/
|
|
12
|
+
import { VerbType } from '../types/graphTypes.js';
|
|
13
|
+
/**
|
|
14
|
+
* Relationship confidence scorer
|
|
15
|
+
*/
|
|
16
|
+
export class RelationshipConfidenceScorer {
|
|
17
|
+
constructor(config = {}) {
|
|
18
|
+
this.config = {
|
|
19
|
+
minConfidence: config.minConfidence || 0.5,
|
|
20
|
+
maxDistance: config.maxDistance || 50,
|
|
21
|
+
useProximityBoost: config.useProximityBoost !== false,
|
|
22
|
+
usePatternMatching: config.usePatternMatching !== false,
|
|
23
|
+
useStructuralAnalysis: config.useStructuralAnalysis !== false
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Score a potential relationship between two entities
|
|
28
|
+
*/
|
|
29
|
+
scoreRelationship(source, target, verbType, context) {
|
|
30
|
+
let confidence = 0.5; // Base confidence
|
|
31
|
+
// Evidence tracking
|
|
32
|
+
const reasoningParts = [];
|
|
33
|
+
// Factor 1: Proximity boost (closer entities = higher confidence)
|
|
34
|
+
if (this.config.useProximityBoost) {
|
|
35
|
+
const proximityBoost = this.calculateProximityBoost(source, target);
|
|
36
|
+
confidence += proximityBoost;
|
|
37
|
+
if (proximityBoost > 0) {
|
|
38
|
+
reasoningParts.push(`Entities are close together (boost: +${proximityBoost.toFixed(2)})`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Factor 2: Entity confidence boost
|
|
42
|
+
const entityConfidence = (source.confidence + target.confidence) / 2;
|
|
43
|
+
const entityBoost = (entityConfidence - 0.5) * 0.2; // Scale to 0-0.2
|
|
44
|
+
confidence *= (1 + entityBoost);
|
|
45
|
+
if (entityBoost > 0) {
|
|
46
|
+
reasoningParts.push(`High entity confidence (boost: ${entityBoost.toFixed(2)})`);
|
|
47
|
+
}
|
|
48
|
+
// Factor 3: Pattern match boost
|
|
49
|
+
if (this.config.usePatternMatching) {
|
|
50
|
+
const patternBoost = this.checkVerbPattern(source, target, verbType, context);
|
|
51
|
+
confidence += patternBoost;
|
|
52
|
+
if (patternBoost > 0) {
|
|
53
|
+
reasoningParts.push(`Matches relationship pattern (boost: +${patternBoost.toFixed(2)})`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Factor 4: Structural boost (same sentence, clause, etc.)
|
|
57
|
+
if (this.config.useStructuralAnalysis) {
|
|
58
|
+
const structuralBoost = this.analyzeStructure(source, target, context);
|
|
59
|
+
confidence += structuralBoost;
|
|
60
|
+
if (structuralBoost > 0) {
|
|
61
|
+
reasoningParts.push(`Structural relationship (boost: +${structuralBoost.toFixed(2)})`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Cap confidence at 1.0
|
|
65
|
+
confidence = Math.min(confidence, 1.0);
|
|
66
|
+
// Extract source text evidence
|
|
67
|
+
const start = Math.min(source.position.start, target.position.start);
|
|
68
|
+
const end = Math.max(source.position.end, target.position.end);
|
|
69
|
+
const evidence = {
|
|
70
|
+
sourceText: context.substring(start, end),
|
|
71
|
+
position: { start, end },
|
|
72
|
+
method: 'neural',
|
|
73
|
+
reasoning: reasoningParts.join('; ')
|
|
74
|
+
};
|
|
75
|
+
return { confidence, evidence };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Calculate proximity boost based on distance between entities
|
|
79
|
+
*/
|
|
80
|
+
calculateProximityBoost(source, target) {
|
|
81
|
+
const distance = Math.abs(source.position.start - target.position.start);
|
|
82
|
+
if (distance === 0)
|
|
83
|
+
return 0; // Same position, not meaningful
|
|
84
|
+
// Very close (< 20 chars): +0.2
|
|
85
|
+
if (distance < 20)
|
|
86
|
+
return 0.2;
|
|
87
|
+
// Close (< 50 chars): +0.1
|
|
88
|
+
if (distance < 50)
|
|
89
|
+
return 0.1;
|
|
90
|
+
// Medium (< 100 chars): +0.05
|
|
91
|
+
if (distance < 100)
|
|
92
|
+
return 0.05;
|
|
93
|
+
// Far (> 100 chars): no boost
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Check if entities match a verb pattern
|
|
98
|
+
*/
|
|
99
|
+
checkVerbPattern(source, target, verbType, context) {
|
|
100
|
+
const contextBetween = this.getContextBetween(source, target, context);
|
|
101
|
+
const contextLower = contextBetween.toLowerCase();
|
|
102
|
+
// Verb-specific patterns
|
|
103
|
+
const patterns = {
|
|
104
|
+
[VerbType.Creates]: ['creates', 'made', 'built', 'developed', 'produces'],
|
|
105
|
+
[VerbType.Owns]: ['owns', 'belongs to', 'possessed by', 'has'],
|
|
106
|
+
[VerbType.Contains]: ['contains', 'includes', 'has', 'holds'],
|
|
107
|
+
[VerbType.Requires]: ['requires', 'needs', 'depends on', 'relies on'],
|
|
108
|
+
[VerbType.Uses]: ['uses', 'utilizes', 'employs', 'applies'],
|
|
109
|
+
[VerbType.Supervises]: ['manages', 'oversees', 'supervises', 'controls'],
|
|
110
|
+
[VerbType.Causes]: ['influences', 'affects', 'impacts', 'shapes', 'causes'],
|
|
111
|
+
[VerbType.DependsOn]: ['depends on', 'relies on', 'based on'],
|
|
112
|
+
[VerbType.Modifies]: ['modifies', 'changes', 'alters', 'updates'],
|
|
113
|
+
[VerbType.References]: ['references', 'cites', 'mentions', 'refers to']
|
|
114
|
+
};
|
|
115
|
+
const verbPatterns = patterns[verbType] || [];
|
|
116
|
+
for (const pattern of verbPatterns) {
|
|
117
|
+
if (contextLower.includes(pattern)) {
|
|
118
|
+
return 0.2; // Strong pattern match
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return 0; // No pattern match
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Analyze structural relationship
|
|
125
|
+
*/
|
|
126
|
+
analyzeStructure(source, target, context) {
|
|
127
|
+
const contextBetween = this.getContextBetween(source, target, context);
|
|
128
|
+
// Same sentence (no sentence-ending punctuation between them)
|
|
129
|
+
if (!contextBetween.match(/[.!?]/)) {
|
|
130
|
+
return 0.1;
|
|
131
|
+
}
|
|
132
|
+
// Same paragraph (single newline between them)
|
|
133
|
+
if (!contextBetween.match(/\n\n/)) {
|
|
134
|
+
return 0.05;
|
|
135
|
+
}
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get context text between two entities
|
|
140
|
+
*/
|
|
141
|
+
getContextBetween(source, target, context) {
|
|
142
|
+
const start = Math.min(source.position.end, target.position.end);
|
|
143
|
+
const end = Math.max(source.position.start, target.position.start);
|
|
144
|
+
if (start >= end)
|
|
145
|
+
return '';
|
|
146
|
+
return context.substring(start, end);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Detect relationships between a list of entities
|
|
150
|
+
*/
|
|
151
|
+
detectRelationships(entities, context, verbHints) {
|
|
152
|
+
const relationships = [];
|
|
153
|
+
const verbs = verbHints || [
|
|
154
|
+
VerbType.Creates,
|
|
155
|
+
VerbType.Uses,
|
|
156
|
+
VerbType.Contains,
|
|
157
|
+
VerbType.Requires,
|
|
158
|
+
VerbType.RelatedTo
|
|
159
|
+
];
|
|
160
|
+
// Check all entity pairs
|
|
161
|
+
for (let i = 0; i < entities.length; i++) {
|
|
162
|
+
for (let j = i + 1; j < entities.length; j++) {
|
|
163
|
+
const source = entities[i];
|
|
164
|
+
const target = entities[j];
|
|
165
|
+
// Check distance
|
|
166
|
+
const distance = Math.abs(source.position.start - target.position.start);
|
|
167
|
+
if (distance > this.config.maxDistance) {
|
|
168
|
+
continue; // Too far apart
|
|
169
|
+
}
|
|
170
|
+
// Try each verb type
|
|
171
|
+
for (const verbType of verbs) {
|
|
172
|
+
const { confidence, evidence } = this.scoreRelationship(source, target, verbType, context);
|
|
173
|
+
if (confidence >= this.config.minConfidence) {
|
|
174
|
+
relationships.push({
|
|
175
|
+
sourceEntity: source,
|
|
176
|
+
targetEntity: target,
|
|
177
|
+
verbType,
|
|
178
|
+
confidence,
|
|
179
|
+
evidence
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Sort by confidence (highest first)
|
|
186
|
+
relationships.sort((a, b) => b.confidence - a.confidence);
|
|
187
|
+
return relationships;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Convenience function to score a single relationship
|
|
192
|
+
*/
|
|
193
|
+
export function scoreRelationshipConfidence(source, target, verbType, context, config) {
|
|
194
|
+
const scorer = new RelationshipConfidenceScorer(config);
|
|
195
|
+
return scorer.scoreRelationship(source, target, verbType, context);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Convenience function to detect all relationships in text
|
|
199
|
+
*/
|
|
200
|
+
export function detectRelationshipsWithConfidence(entities, context, config) {
|
|
201
|
+
const scorer = new RelationshipConfidenceScorer(config);
|
|
202
|
+
return scorer.detectRelationships(entities, context);
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=relationshipConfidence.js.map
|
|
@@ -240,9 +240,11 @@ export class BaseStorage extends BaseStorageAdapter {
|
|
|
240
240
|
*/
|
|
241
241
|
async getVerbsBySource(sourceId) {
|
|
242
242
|
await this.ensureInitialized();
|
|
243
|
-
//
|
|
243
|
+
// CRITICAL: Fetch ALL verbs for this source, not just first page
|
|
244
|
+
// This is needed for delete operations to clean up all relationships
|
|
244
245
|
const result = await this.getVerbs({
|
|
245
|
-
filter: { sourceId }
|
|
246
|
+
filter: { sourceId },
|
|
247
|
+
pagination: { limit: Number.MAX_SAFE_INTEGER }
|
|
246
248
|
});
|
|
247
249
|
return result.items;
|
|
248
250
|
}
|
|
@@ -251,9 +253,11 @@ export class BaseStorage extends BaseStorageAdapter {
|
|
|
251
253
|
*/
|
|
252
254
|
async getVerbsByTarget(targetId) {
|
|
253
255
|
await this.ensureInitialized();
|
|
254
|
-
//
|
|
256
|
+
// CRITICAL: Fetch ALL verbs for this target, not just first page
|
|
257
|
+
// This is needed for delete operations to clean up all relationships
|
|
255
258
|
const result = await this.getVerbs({
|
|
256
|
-
filter: { targetId }
|
|
259
|
+
filter: { targetId },
|
|
260
|
+
pagination: { limit: Number.MAX_SAFE_INTEGER }
|
|
257
261
|
});
|
|
258
262
|
return result.items;
|
|
259
263
|
}
|
|
@@ -262,9 +266,10 @@ export class BaseStorage extends BaseStorageAdapter {
|
|
|
262
266
|
*/
|
|
263
267
|
async getVerbsByType(type) {
|
|
264
268
|
await this.ensureInitialized();
|
|
265
|
-
//
|
|
269
|
+
// Fetch ALL verbs of this type (no pagination limit)
|
|
266
270
|
const result = await this.getVerbs({
|
|
267
|
-
filter: { verbType: type }
|
|
271
|
+
filter: { verbType: type },
|
|
272
|
+
pagination: { limit: Number.MAX_SAFE_INTEGER }
|
|
268
273
|
});
|
|
269
274
|
return result.items;
|
|
270
275
|
}
|
|
@@ -21,6 +21,7 @@ export interface Entity<T = any> {
|
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* Relation representation (replaces GraphVerb)
|
|
24
|
+
* Enhanced with confidence scoring and evidence tracking
|
|
24
25
|
*/
|
|
25
26
|
export interface Relation<T = any> {
|
|
26
27
|
id: string;
|
|
@@ -32,6 +33,20 @@ export interface Relation<T = any> {
|
|
|
32
33
|
service?: string;
|
|
33
34
|
createdAt: number;
|
|
34
35
|
updatedAt?: number;
|
|
36
|
+
confidence?: number;
|
|
37
|
+
evidence?: RelationEvidence;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Evidence for why a relationship was detected
|
|
41
|
+
*/
|
|
42
|
+
export interface RelationEvidence {
|
|
43
|
+
sourceText?: string;
|
|
44
|
+
position?: {
|
|
45
|
+
start: number;
|
|
46
|
+
end: number;
|
|
47
|
+
};
|
|
48
|
+
method: 'neural' | 'pattern' | 'structural' | 'explicit';
|
|
49
|
+
reasoning?: string;
|
|
35
50
|
}
|
|
36
51
|
/**
|
|
37
52
|
* Search result with similarity score
|
|
@@ -76,6 +91,7 @@ export interface UpdateParams<T = any> {
|
|
|
76
91
|
}
|
|
77
92
|
/**
|
|
78
93
|
* Parameters for creating relationships
|
|
94
|
+
* Enhanced with confidence scoring and evidence tracking
|
|
79
95
|
*/
|
|
80
96
|
export interface RelateParams<T = any> {
|
|
81
97
|
from: string;
|
|
@@ -85,6 +101,8 @@ export interface RelateParams<T = any> {
|
|
|
85
101
|
metadata?: T;
|
|
86
102
|
bidirectional?: boolean;
|
|
87
103
|
service?: string;
|
|
104
|
+
confidence?: number;
|
|
105
|
+
evidence?: RelationEvidence;
|
|
88
106
|
}
|
|
89
107
|
/**
|
|
90
108
|
* Parameters for updating relationships
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standardized Progress Reporting
|
|
3
|
+
*
|
|
4
|
+
* Provides unified progress tracking across all long-running operations
|
|
5
|
+
* in Brainy (imports, clustering, large searches, etc.)
|
|
6
|
+
*
|
|
7
|
+
* PRODUCTION-READY - NO MOCKS, NO STUBS, REAL IMPLEMENTATION
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Progress status states
|
|
11
|
+
*/
|
|
12
|
+
export type ProgressStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
|
13
|
+
/**
|
|
14
|
+
* Standardized progress report
|
|
15
|
+
*/
|
|
16
|
+
export interface BrainyProgress<T = any> {
|
|
17
|
+
status: ProgressStatus;
|
|
18
|
+
progress: number;
|
|
19
|
+
message: string;
|
|
20
|
+
metadata: {
|
|
21
|
+
itemsProcessed: number;
|
|
22
|
+
itemsTotal: number;
|
|
23
|
+
currentItem?: string;
|
|
24
|
+
estimatedTimeRemaining?: number;
|
|
25
|
+
startedAt: number;
|
|
26
|
+
completedAt?: number;
|
|
27
|
+
throughput?: number;
|
|
28
|
+
};
|
|
29
|
+
result?: T;
|
|
30
|
+
error?: Error;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Progress tracker with automatic time estimation
|
|
34
|
+
*/
|
|
35
|
+
export declare class ProgressTracker<T = any> {
|
|
36
|
+
private status;
|
|
37
|
+
private processed;
|
|
38
|
+
private total;
|
|
39
|
+
private startedAt?;
|
|
40
|
+
private completedAt?;
|
|
41
|
+
private currentItem?;
|
|
42
|
+
private result?;
|
|
43
|
+
private error?;
|
|
44
|
+
private processingTimes;
|
|
45
|
+
constructor(total: number);
|
|
46
|
+
/**
|
|
47
|
+
* Factory method for creating progress trackers
|
|
48
|
+
*/
|
|
49
|
+
static create<T>(total: number): ProgressTracker<T>;
|
|
50
|
+
/**
|
|
51
|
+
* Start tracking progress
|
|
52
|
+
*/
|
|
53
|
+
start(): BrainyProgress<T>;
|
|
54
|
+
/**
|
|
55
|
+
* Update progress
|
|
56
|
+
*/
|
|
57
|
+
update(processed: number, currentItem?: string): BrainyProgress<T>;
|
|
58
|
+
/**
|
|
59
|
+
* Increment progress by 1
|
|
60
|
+
*/
|
|
61
|
+
increment(currentItem?: string): BrainyProgress<T>;
|
|
62
|
+
/**
|
|
63
|
+
* Mark as completed
|
|
64
|
+
*/
|
|
65
|
+
complete(result: T): BrainyProgress<T>;
|
|
66
|
+
/**
|
|
67
|
+
* Mark as failed
|
|
68
|
+
*/
|
|
69
|
+
fail(error: Error): BrainyProgress<T>;
|
|
70
|
+
/**
|
|
71
|
+
* Mark as cancelled
|
|
72
|
+
*/
|
|
73
|
+
cancel(): BrainyProgress<T>;
|
|
74
|
+
/**
|
|
75
|
+
* Get current progress state
|
|
76
|
+
*/
|
|
77
|
+
current(): BrainyProgress<T>;
|
|
78
|
+
/**
|
|
79
|
+
* Estimate time remaining based on processing history
|
|
80
|
+
*/
|
|
81
|
+
private estimateTimeRemaining;
|
|
82
|
+
/**
|
|
83
|
+
* Calculate current throughput (items/second)
|
|
84
|
+
*/
|
|
85
|
+
private calculateThroughput;
|
|
86
|
+
/**
|
|
87
|
+
* Get progress statistics
|
|
88
|
+
*/
|
|
89
|
+
getStats(): {
|
|
90
|
+
status: ProgressStatus;
|
|
91
|
+
processed: number;
|
|
92
|
+
total: number;
|
|
93
|
+
remaining: number;
|
|
94
|
+
progress: number;
|
|
95
|
+
elapsed: number;
|
|
96
|
+
estimatedTotal: number | undefined;
|
|
97
|
+
throughput: number | undefined;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Helper to format time duration
|
|
102
|
+
*/
|
|
103
|
+
export declare function formatDuration(ms: number): string;
|
|
104
|
+
/**
|
|
105
|
+
* Helper to format progress percentage
|
|
106
|
+
*/
|
|
107
|
+
export declare function formatProgress(progress: BrainyProgress): string;
|