@soulcraft/brainy 4.3.2 → 4.5.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 +117 -0
- package/dist/augmentations/intelligentImport/handlers/csvHandler.js +33 -1
- package/dist/augmentations/intelligentImport/handlers/excelHandler.js +48 -2
- package/dist/augmentations/intelligentImport/handlers/pdfHandler.js +37 -0
- package/dist/augmentations/intelligentImport/types.d.ts +33 -0
- package/dist/brainy.d.ts +43 -3
- package/dist/brainy.js +83 -12
- package/dist/cli/commands/core.d.ts +3 -0
- package/dist/cli/commands/core.js +21 -3
- package/dist/cli/commands/import.js +69 -34
- package/dist/importers/SmartCSVImporter.js +35 -1
- package/dist/importers/SmartDOCXImporter.js +12 -0
- package/dist/importers/SmartExcelImporter.js +37 -1
- package/dist/importers/SmartJSONImporter.js +18 -0
- package/dist/importers/SmartMarkdownImporter.js +25 -2
- package/dist/importers/SmartPDFImporter.js +37 -1
- package/dist/importers/SmartYAMLImporter.js +12 -0
- package/dist/types/brainy.types.d.ts +98 -0
- package/dist/utils/import-progress-tracker.d.ts +140 -0
- package/dist/utils/import-progress-tracker.js +444 -0
- package/dist/vfs/PathResolver.js +2 -2
- package/dist/vfs/VirtualFileSystem.js +37 -9
- package/dist/vfs/semantic/projections/AuthorProjection.js +6 -3
- package/dist/vfs/semantic/projections/TagProjection.js +6 -3
- package/dist/vfs/semantic/projections/TemporalProjection.js +4 -2
- package/dist/vfs/types.d.ts +1 -0
- package/package.json +1 -1
|
@@ -109,23 +109,37 @@ export const coreCommands = {
|
|
|
109
109
|
spinner.text = `Using detected type: ${nounType}`;
|
|
110
110
|
}
|
|
111
111
|
// Add with explicit type
|
|
112
|
-
const
|
|
112
|
+
const addParams = {
|
|
113
113
|
data: text,
|
|
114
114
|
type: nounType,
|
|
115
115
|
metadata
|
|
116
|
-
}
|
|
116
|
+
};
|
|
117
|
+
// v4.3.x: Add confidence and weight if provided
|
|
118
|
+
if (options.confidence) {
|
|
119
|
+
addParams.confidence = parseFloat(options.confidence);
|
|
120
|
+
}
|
|
121
|
+
if (options.weight) {
|
|
122
|
+
addParams.weight = parseFloat(options.weight);
|
|
123
|
+
}
|
|
124
|
+
const result = await brain.add(addParams);
|
|
117
125
|
spinner.succeed('Added successfully');
|
|
118
126
|
if (!options.json) {
|
|
119
127
|
console.log(chalk.green(`✓ Added with ID: ${result}`));
|
|
120
128
|
if (options.type) {
|
|
121
129
|
console.log(chalk.dim(` Type: ${options.type}`));
|
|
122
130
|
}
|
|
131
|
+
if (options.confidence) {
|
|
132
|
+
console.log(chalk.dim(` Confidence: ${options.confidence}`));
|
|
133
|
+
}
|
|
134
|
+
if (options.weight) {
|
|
135
|
+
console.log(chalk.dim(` Weight: ${options.weight}`));
|
|
136
|
+
}
|
|
123
137
|
if (Object.keys(metadata).length > 0) {
|
|
124
138
|
console.log(chalk.dim(` Metadata: ${JSON.stringify(metadata)}`));
|
|
125
139
|
}
|
|
126
140
|
}
|
|
127
141
|
else {
|
|
128
|
-
formatOutput({ id: result, metadata }, options);
|
|
142
|
+
formatOutput({ id: result, metadata, confidence: addParams.confidence, weight: addParams.weight }, options);
|
|
129
143
|
}
|
|
130
144
|
}
|
|
131
145
|
catch (error) {
|
|
@@ -260,6 +274,10 @@ export const coreCommands = {
|
|
|
260
274
|
if (options.includeRelations) {
|
|
261
275
|
searchParams.includeRelations = true;
|
|
262
276
|
}
|
|
277
|
+
// Include VFS files (v4.4.0 - find excludes VFS by default)
|
|
278
|
+
if (options.includeVfs) {
|
|
279
|
+
searchParams.includeVFS = true;
|
|
280
|
+
}
|
|
263
281
|
// Triple Intelligence Fusion - custom weighting
|
|
264
282
|
if (options.fusion || options.vectorWeight || options.graphWeight || options.fieldWeight) {
|
|
265
283
|
searchParams.fusion = {
|
|
@@ -120,19 +120,25 @@ export const importCommands = {
|
|
|
120
120
|
}]);
|
|
121
121
|
options.recursive = answer.recursive;
|
|
122
122
|
}
|
|
123
|
-
spinner = ora('Initializing
|
|
123
|
+
spinner = ora('Initializing import...').start();
|
|
124
124
|
const brain = getBrainy();
|
|
125
|
-
// Load UniversalImportAPI
|
|
126
|
-
const { UniversalImportAPI } = await import('../../api/UniversalImportAPI.js');
|
|
127
|
-
const universalImport = new UniversalImportAPI(brain);
|
|
128
|
-
await universalImport.init();
|
|
129
|
-
spinner.text = 'Processing import...';
|
|
130
125
|
// Handle different source types
|
|
131
126
|
let result;
|
|
132
127
|
if (isURL) {
|
|
133
|
-
// URL import
|
|
128
|
+
// URL import - fetch first
|
|
134
129
|
spinner.text = `Fetching from ${source}...`;
|
|
135
|
-
|
|
130
|
+
const response = await fetch(source);
|
|
131
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
132
|
+
spinner.text = 'Importing...';
|
|
133
|
+
result = await brain.import(buffer, {
|
|
134
|
+
enableNeuralExtraction: options.extractEntities !== false,
|
|
135
|
+
enableRelationshipInference: options.detectRelationships !== false,
|
|
136
|
+
enableConceptExtraction: options.extractConcepts || false,
|
|
137
|
+
confidenceThreshold: options.confidence ? parseFloat(options.confidence) : 0.6,
|
|
138
|
+
onProgress: options.progress ? (p) => {
|
|
139
|
+
spinner.text = `${p.message}${p.entities ? ` (${p.entities} entities)` : ''}`;
|
|
140
|
+
} : undefined
|
|
141
|
+
});
|
|
136
142
|
}
|
|
137
143
|
else if (isDirectory) {
|
|
138
144
|
// Directory import - process each file
|
|
@@ -163,31 +169,42 @@ export const importCommands = {
|
|
|
163
169
|
};
|
|
164
170
|
await collectFiles(source);
|
|
165
171
|
spinner.succeed(`Found ${files.length} files`);
|
|
166
|
-
// Process files
|
|
167
|
-
const batchSize = options.batchSize ? parseInt(options.batchSize) : 100;
|
|
172
|
+
// Process files with progress
|
|
168
173
|
let totalEntities = 0;
|
|
169
174
|
let totalRelationships = 0;
|
|
170
175
|
let filesProcessed = 0;
|
|
171
|
-
for (
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
for (const file of batch) {
|
|
177
|
-
try {
|
|
178
|
-
const fileResult = await universalImport.importFromFile(file);
|
|
179
|
-
totalEntities += fileResult.stats.entitiesCreated;
|
|
180
|
-
totalRelationships += fileResult.stats.relationshipsCreated;
|
|
181
|
-
filesProcessed++;
|
|
176
|
+
for (const file of files) {
|
|
177
|
+
try {
|
|
178
|
+
if (options.progress) {
|
|
179
|
+
spinner = ora(`[${filesProcessed + 1}/${files.length}] Importing ${file}...`).start();
|
|
182
180
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
181
|
+
const fileResult = await brain.import(file, {
|
|
182
|
+
enableNeuralExtraction: options.extractEntities !== false,
|
|
183
|
+
enableRelationshipInference: options.detectRelationships !== false,
|
|
184
|
+
enableConceptExtraction: options.extractConcepts || false,
|
|
185
|
+
confidenceThreshold: options.confidence ? parseFloat(options.confidence) : 0.6,
|
|
186
|
+
onProgress: options.progress ? (p) => {
|
|
187
|
+
spinner.text = `[${filesProcessed + 1}/${files.length}] ${p.message}`;
|
|
188
|
+
} : undefined
|
|
189
|
+
});
|
|
190
|
+
totalEntities += fileResult.entities.length;
|
|
191
|
+
totalRelationships += fileResult.relationships.length;
|
|
192
|
+
filesProcessed++;
|
|
193
|
+
if (options.progress) {
|
|
194
|
+
spinner.succeed(`[${filesProcessed}/${files.length}] ${file}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
if (options.verbose) {
|
|
199
|
+
if (spinner)
|
|
200
|
+
spinner.fail(`Failed: ${file}`);
|
|
201
|
+
console.log(chalk.yellow(`⚠️ ${error.message}`));
|
|
187
202
|
}
|
|
188
203
|
}
|
|
189
204
|
}
|
|
190
205
|
result = {
|
|
206
|
+
entities: [],
|
|
207
|
+
relationships: [],
|
|
191
208
|
stats: {
|
|
192
209
|
filesProcessed,
|
|
193
210
|
entitiesCreated: totalEntities,
|
|
@@ -195,11 +212,23 @@ export const importCommands = {
|
|
|
195
212
|
totalProcessed: filesProcessed
|
|
196
213
|
}
|
|
197
214
|
};
|
|
198
|
-
spinner.succeed(
|
|
215
|
+
spinner = ora().succeed(`Directory import complete: ${filesProcessed} files`);
|
|
199
216
|
}
|
|
200
217
|
else {
|
|
201
|
-
// File import
|
|
202
|
-
result = await
|
|
218
|
+
// File import with progress
|
|
219
|
+
result = await brain.import(source, {
|
|
220
|
+
format: options.format,
|
|
221
|
+
enableNeuralExtraction: options.extractEntities !== false,
|
|
222
|
+
enableRelationshipInference: options.detectRelationships !== false,
|
|
223
|
+
enableConceptExtraction: options.extractConcepts || false,
|
|
224
|
+
confidenceThreshold: options.confidence ? parseFloat(options.confidence) : 0.6,
|
|
225
|
+
onProgress: options.progress ? (p) => {
|
|
226
|
+
spinner.text = `${p.message}${p.entities ? ` (${p.entities} entities, ${p.relationships || 0} relationships)` : ''}`;
|
|
227
|
+
if (p.throughput && p.eta) {
|
|
228
|
+
spinner.text += ` - ${p.throughput.toFixed(1)}/sec, ETA: ${Math.round(p.eta / 1000)}s`;
|
|
229
|
+
}
|
|
230
|
+
} : undefined
|
|
231
|
+
});
|
|
203
232
|
}
|
|
204
233
|
spinner.succeed('Import complete');
|
|
205
234
|
// Post-processing: extract concepts if requested
|
|
@@ -270,15 +299,21 @@ export const importCommands = {
|
|
|
270
299
|
if (!options.json && !options.quiet) {
|
|
271
300
|
console.log(chalk.cyan('\n📊 Import Results:\n'));
|
|
272
301
|
console.log(chalk.bold('Statistics:'));
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
302
|
+
const entitiesCount = result.stats?.entitiesCreated || result.entities?.length || 0;
|
|
303
|
+
const relationshipsCount = result.stats?.relationshipsCreated || result.relationships?.length || 0;
|
|
304
|
+
console.log(` Entities created: ${chalk.green(entitiesCount)}`);
|
|
305
|
+
if (relationshipsCount > 0) {
|
|
306
|
+
console.log(` Relationships created: ${chalk.green(relationshipsCount)}`);
|
|
276
307
|
}
|
|
277
|
-
if (result.stats
|
|
308
|
+
if (result.stats?.filesProcessed) {
|
|
278
309
|
console.log(` Files processed: ${chalk.green(result.stats.filesProcessed)}`);
|
|
279
310
|
}
|
|
280
|
-
|
|
281
|
-
|
|
311
|
+
if (result.stats?.averageConfidence) {
|
|
312
|
+
console.log(` Average confidence: ${chalk.yellow((result.stats.averageConfidence * 100).toFixed(1))}%`);
|
|
313
|
+
}
|
|
314
|
+
if (result.stats?.processingTimeMs) {
|
|
315
|
+
console.log(` Processing time: ${chalk.dim(result.stats.processingTimeMs)}ms`);
|
|
316
|
+
}
|
|
282
317
|
if (options.verbose && result.entities && result.entities.length > 0) {
|
|
283
318
|
console.log(chalk.bold('\n📦 Imported Entities (first 10):'));
|
|
284
319
|
result.entities.slice(0, 10).forEach((entity, i) => {
|
|
@@ -53,10 +53,44 @@ export class SmartCSVImporter {
|
|
|
53
53
|
...options
|
|
54
54
|
};
|
|
55
55
|
// Parse CSV using existing handler
|
|
56
|
+
// v4.5.0: Pass progress hooks to handler for file parsing progress
|
|
56
57
|
const processedData = await this.csvHandler.process(buffer, {
|
|
57
58
|
...options,
|
|
58
59
|
csvDelimiter: opts.csvDelimiter,
|
|
59
|
-
csvHeaders: opts.csvHeaders
|
|
60
|
+
csvHeaders: opts.csvHeaders,
|
|
61
|
+
totalBytes: buffer.length,
|
|
62
|
+
progressHooks: {
|
|
63
|
+
onBytesProcessed: (bytes) => {
|
|
64
|
+
// Handler reports bytes processed during parsing
|
|
65
|
+
opts.onProgress?.({
|
|
66
|
+
processed: 0,
|
|
67
|
+
total: 0,
|
|
68
|
+
entities: 0,
|
|
69
|
+
relationships: 0,
|
|
70
|
+
phase: `Parsing CSV (${Math.round((bytes / buffer.length) * 100)}%)`
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
onCurrentItem: (message) => {
|
|
74
|
+
// Handler reports current processing step
|
|
75
|
+
opts.onProgress?.({
|
|
76
|
+
processed: 0,
|
|
77
|
+
total: 0,
|
|
78
|
+
entities: 0,
|
|
79
|
+
relationships: 0,
|
|
80
|
+
phase: message
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
onDataExtracted: (count, total) => {
|
|
84
|
+
// Handler reports rows extracted
|
|
85
|
+
opts.onProgress?.({
|
|
86
|
+
processed: 0,
|
|
87
|
+
total: total || count,
|
|
88
|
+
entities: 0,
|
|
89
|
+
relationships: 0,
|
|
90
|
+
phase: `Extracted ${count} rows`
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
60
94
|
});
|
|
61
95
|
const rows = processedData.data;
|
|
62
96
|
if (rows.length === 0) {
|
|
@@ -54,10 +54,22 @@ export class SmartDOCXImporter {
|
|
|
54
54
|
if (!this.mammothLoaded) {
|
|
55
55
|
await this.init();
|
|
56
56
|
}
|
|
57
|
+
// v4.5.0: Report parsing start
|
|
58
|
+
options.onProgress?.({
|
|
59
|
+
processed: 0,
|
|
60
|
+
entities: 0,
|
|
61
|
+
relationships: 0
|
|
62
|
+
});
|
|
57
63
|
// Extract raw text for entity extraction
|
|
58
64
|
const textResult = await mammoth.extractRawText({ buffer });
|
|
59
65
|
// Extract HTML for structure analysis (headings, tables)
|
|
60
66
|
const htmlResult = await mammoth.convertToHtml({ buffer });
|
|
67
|
+
// v4.5.0: Report parsing complete
|
|
68
|
+
options.onProgress?.({
|
|
69
|
+
processed: 0,
|
|
70
|
+
entities: 0,
|
|
71
|
+
relationships: 0
|
|
72
|
+
});
|
|
61
73
|
// Process the document
|
|
62
74
|
const result = await this.extractFromContent(textResult.value, htmlResult.value, options);
|
|
63
75
|
result.processingTime = Date.now() - startTime;
|
|
@@ -61,7 +61,43 @@ export class SmartExcelImporter {
|
|
|
61
61
|
...options
|
|
62
62
|
};
|
|
63
63
|
// Parse Excel using existing handler
|
|
64
|
-
|
|
64
|
+
// v4.5.0: Pass progress hooks to handler for file parsing progress
|
|
65
|
+
const processedData = await this.excelHandler.process(buffer, {
|
|
66
|
+
...options,
|
|
67
|
+
totalBytes: buffer.length,
|
|
68
|
+
progressHooks: {
|
|
69
|
+
onBytesProcessed: (bytes) => {
|
|
70
|
+
// Handler reports bytes processed during parsing
|
|
71
|
+
opts.onProgress?.({
|
|
72
|
+
processed: 0,
|
|
73
|
+
total: 0,
|
|
74
|
+
entities: 0,
|
|
75
|
+
relationships: 0,
|
|
76
|
+
phase: `Parsing Excel (${Math.round((bytes / buffer.length) * 100)}%)`
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
onCurrentItem: (message) => {
|
|
80
|
+
// Handler reports current processing step (e.g., "Reading sheet: Sales (1/3)")
|
|
81
|
+
opts.onProgress?.({
|
|
82
|
+
processed: 0,
|
|
83
|
+
total: 0,
|
|
84
|
+
entities: 0,
|
|
85
|
+
relationships: 0,
|
|
86
|
+
phase: message
|
|
87
|
+
});
|
|
88
|
+
},
|
|
89
|
+
onDataExtracted: (count, total) => {
|
|
90
|
+
// Handler reports rows extracted
|
|
91
|
+
opts.onProgress?.({
|
|
92
|
+
processed: 0,
|
|
93
|
+
total: total || count,
|
|
94
|
+
entities: 0,
|
|
95
|
+
relationships: 0,
|
|
96
|
+
phase: `Extracted ${count} rows from Excel`
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
65
101
|
const rows = processedData.data;
|
|
66
102
|
if (rows.length === 0) {
|
|
67
103
|
return this.emptyResult(startTime);
|
|
@@ -48,6 +48,12 @@ export class SmartJSONImporter {
|
|
|
48
48
|
onProgress: () => { },
|
|
49
49
|
...options
|
|
50
50
|
};
|
|
51
|
+
// v4.5.0: Report parsing start
|
|
52
|
+
opts.onProgress({
|
|
53
|
+
processed: 0,
|
|
54
|
+
entities: 0,
|
|
55
|
+
relationships: 0
|
|
56
|
+
});
|
|
51
57
|
// Parse JSON if string
|
|
52
58
|
let jsonData;
|
|
53
59
|
if (typeof data === 'string') {
|
|
@@ -61,6 +67,12 @@ export class SmartJSONImporter {
|
|
|
61
67
|
else {
|
|
62
68
|
jsonData = data;
|
|
63
69
|
}
|
|
70
|
+
// v4.5.0: Report parsing complete, starting traversal
|
|
71
|
+
opts.onProgress({
|
|
72
|
+
processed: 0,
|
|
73
|
+
entities: 0,
|
|
74
|
+
relationships: 0
|
|
75
|
+
});
|
|
64
76
|
// Traverse and extract
|
|
65
77
|
const entities = [];
|
|
66
78
|
const relationships = [];
|
|
@@ -82,6 +94,12 @@ export class SmartJSONImporter {
|
|
|
82
94
|
});
|
|
83
95
|
}
|
|
84
96
|
});
|
|
97
|
+
// v4.5.0: Report completion
|
|
98
|
+
opts.onProgress({
|
|
99
|
+
processed: nodesProcessed,
|
|
100
|
+
entities: entities.length,
|
|
101
|
+
relationships: relationships.length
|
|
102
|
+
});
|
|
85
103
|
return {
|
|
86
104
|
nodesProcessed,
|
|
87
105
|
entitiesExtracted: entities.length,
|
|
@@ -46,8 +46,22 @@ export class SmartMarkdownImporter {
|
|
|
46
46
|
onProgress: () => { },
|
|
47
47
|
...options
|
|
48
48
|
};
|
|
49
|
+
// v4.5.0: Report parsing start
|
|
50
|
+
opts.onProgress({
|
|
51
|
+
processed: 0,
|
|
52
|
+
total: 0,
|
|
53
|
+
entities: 0,
|
|
54
|
+
relationships: 0
|
|
55
|
+
});
|
|
49
56
|
// Parse markdown into sections
|
|
50
57
|
const parsedSections = this.parseMarkdown(markdown, opts);
|
|
58
|
+
// v4.5.0: Report parsing complete
|
|
59
|
+
opts.onProgress({
|
|
60
|
+
processed: 0,
|
|
61
|
+
total: parsedSections.length,
|
|
62
|
+
entities: 0,
|
|
63
|
+
relationships: 0
|
|
64
|
+
});
|
|
51
65
|
// Process each section
|
|
52
66
|
const sections = [];
|
|
53
67
|
const entityMap = new Map();
|
|
@@ -69,10 +83,19 @@ export class SmartMarkdownImporter {
|
|
|
69
83
|
relationships: sections.reduce((sum, s) => sum + s.relationships.length, 0)
|
|
70
84
|
});
|
|
71
85
|
}
|
|
86
|
+
// v4.5.0: Report completion
|
|
87
|
+
const totalEntities = sections.reduce((sum, s) => sum + s.entities.length, 0);
|
|
88
|
+
const totalRelationships = sections.reduce((sum, s) => sum + s.relationships.length, 0);
|
|
89
|
+
opts.onProgress({
|
|
90
|
+
processed: sections.length,
|
|
91
|
+
total: sections.length,
|
|
92
|
+
entities: totalEntities,
|
|
93
|
+
relationships: totalRelationships
|
|
94
|
+
});
|
|
72
95
|
return {
|
|
73
96
|
sectionsProcessed: sections.length,
|
|
74
|
-
entitiesExtracted:
|
|
75
|
-
relationshipsInferred:
|
|
97
|
+
entitiesExtracted: totalEntities,
|
|
98
|
+
relationshipsInferred: totalRelationships,
|
|
76
99
|
sections,
|
|
77
100
|
entityMap,
|
|
78
101
|
processingTime: Date.now() - startTime,
|
|
@@ -49,7 +49,43 @@ export class SmartPDFImporter {
|
|
|
49
49
|
...options
|
|
50
50
|
};
|
|
51
51
|
// Parse PDF using existing handler
|
|
52
|
-
|
|
52
|
+
// v4.5.0: Pass progress hooks to handler for file parsing progress
|
|
53
|
+
const processedData = await this.pdfHandler.process(buffer, {
|
|
54
|
+
...options,
|
|
55
|
+
totalBytes: buffer.length,
|
|
56
|
+
progressHooks: {
|
|
57
|
+
onBytesProcessed: (bytes) => {
|
|
58
|
+
// Handler reports bytes processed during parsing
|
|
59
|
+
opts.onProgress?.({
|
|
60
|
+
processed: 0,
|
|
61
|
+
total: 0,
|
|
62
|
+
entities: 0,
|
|
63
|
+
relationships: 0,
|
|
64
|
+
phase: `Parsing PDF (${Math.round((bytes / buffer.length) * 100)}%)`
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
onCurrentItem: (message) => {
|
|
68
|
+
// Handler reports current processing step (e.g., "Processing page 5 of 23")
|
|
69
|
+
opts.onProgress?.({
|
|
70
|
+
processed: 0,
|
|
71
|
+
total: 0,
|
|
72
|
+
entities: 0,
|
|
73
|
+
relationships: 0,
|
|
74
|
+
phase: message
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
onDataExtracted: (count, total) => {
|
|
78
|
+
// Handler reports items extracted (paragraphs + tables)
|
|
79
|
+
opts.onProgress?.({
|
|
80
|
+
processed: 0,
|
|
81
|
+
total: total || count,
|
|
82
|
+
entities: 0,
|
|
83
|
+
relationships: 0,
|
|
84
|
+
phase: `Extracted ${count} items from PDF`
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
53
89
|
const data = processedData.data;
|
|
54
90
|
const pdfMetadata = processedData.metadata.additionalInfo?.pdfMetadata || {};
|
|
55
91
|
if (data.length === 0) {
|
|
@@ -37,6 +37,12 @@ export class SmartYAMLImporter {
|
|
|
37
37
|
*/
|
|
38
38
|
async extract(yamlContent, options = {}) {
|
|
39
39
|
const startTime = Date.now();
|
|
40
|
+
// v4.5.0: Report parsing start
|
|
41
|
+
options.onProgress?.({
|
|
42
|
+
processed: 0,
|
|
43
|
+
entities: 0,
|
|
44
|
+
relationships: 0
|
|
45
|
+
});
|
|
40
46
|
// Parse YAML to JavaScript object
|
|
41
47
|
const yamlString = typeof yamlContent === 'string'
|
|
42
48
|
? yamlContent
|
|
@@ -48,6 +54,12 @@ export class SmartYAMLImporter {
|
|
|
48
54
|
catch (error) {
|
|
49
55
|
throw new Error(`Failed to parse YAML: ${error.message}`);
|
|
50
56
|
}
|
|
57
|
+
// v4.5.0: Report parsing complete
|
|
58
|
+
options.onProgress?.({
|
|
59
|
+
processed: 0,
|
|
60
|
+
entities: 0,
|
|
61
|
+
relationships: 0
|
|
62
|
+
});
|
|
51
63
|
// Process as JSON-like structure
|
|
52
64
|
const result = await this.extractFromData(data, options);
|
|
53
65
|
result.processingTime = Date.now() - startTime;
|
|
@@ -146,6 +146,7 @@ export interface FindParams<T = any> {
|
|
|
146
146
|
mode?: SearchMode;
|
|
147
147
|
explain?: boolean;
|
|
148
148
|
includeRelations?: boolean;
|
|
149
|
+
includeVFS?: boolean;
|
|
149
150
|
service?: string;
|
|
150
151
|
fusion?: {
|
|
151
152
|
strategy?: 'adaptive' | 'weighted' | 'progressive';
|
|
@@ -183,6 +184,7 @@ export interface SimilarParams<T = any> {
|
|
|
183
184
|
type?: NounType | NounType[];
|
|
184
185
|
where?: Partial<T>;
|
|
185
186
|
service?: string;
|
|
187
|
+
includeVFS?: boolean;
|
|
186
188
|
}
|
|
187
189
|
/**
|
|
188
190
|
* Parameters for getting relationships
|
|
@@ -317,6 +319,102 @@ export interface BatchResult<T = any> {
|
|
|
317
319
|
total: number;
|
|
318
320
|
duration: number;
|
|
319
321
|
}
|
|
322
|
+
/**
|
|
323
|
+
* Import stage enumeration
|
|
324
|
+
*/
|
|
325
|
+
export type ImportStage = 'detecting' | 'reading' | 'parsing' | 'extracting' | 'indexing' | 'completing';
|
|
326
|
+
/**
|
|
327
|
+
* Overall import status
|
|
328
|
+
*/
|
|
329
|
+
export type ImportStatus = 'starting' | 'processing' | 'completing' | 'done';
|
|
330
|
+
/**
|
|
331
|
+
* Comprehensive import progress information
|
|
332
|
+
*
|
|
333
|
+
* Provides multi-dimensional progress tracking:
|
|
334
|
+
* - Bytes processed (always deterministic)
|
|
335
|
+
* - Entities extracted and indexed
|
|
336
|
+
* - Stage-specific progress
|
|
337
|
+
* - Time estimates
|
|
338
|
+
* - Performance metrics
|
|
339
|
+
*
|
|
340
|
+
* @since v4.5.0
|
|
341
|
+
*/
|
|
342
|
+
export interface ImportProgress {
|
|
343
|
+
overall_progress: number;
|
|
344
|
+
overall_status: ImportStatus;
|
|
345
|
+
stage: ImportStage;
|
|
346
|
+
stage_progress: number;
|
|
347
|
+
stage_message: string;
|
|
348
|
+
bytes_processed: number;
|
|
349
|
+
total_bytes: number;
|
|
350
|
+
bytes_percentage: number;
|
|
351
|
+
bytes_per_second?: number;
|
|
352
|
+
entities_extracted: number;
|
|
353
|
+
entities_indexed: number;
|
|
354
|
+
entities_per_second?: number;
|
|
355
|
+
estimated_total_entities?: number;
|
|
356
|
+
estimation_confidence?: number;
|
|
357
|
+
elapsed_ms: number;
|
|
358
|
+
estimated_remaining_ms?: number;
|
|
359
|
+
estimated_total_ms?: number;
|
|
360
|
+
current_item?: string;
|
|
361
|
+
current_file?: string;
|
|
362
|
+
file_number?: number;
|
|
363
|
+
total_files?: number;
|
|
364
|
+
metrics?: {
|
|
365
|
+
parsing_rate_mbps?: number;
|
|
366
|
+
extraction_rate_entities_per_sec?: number;
|
|
367
|
+
indexing_rate_entities_per_sec?: number;
|
|
368
|
+
memory_usage_mb?: number;
|
|
369
|
+
peak_memory_mb?: number;
|
|
370
|
+
};
|
|
371
|
+
current: number;
|
|
372
|
+
total: number;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Import progress callback - backwards compatible
|
|
376
|
+
*
|
|
377
|
+
* Supports both legacy (current, total) and new (ImportProgress object) signatures
|
|
378
|
+
*/
|
|
379
|
+
export type ImportProgressCallback = ((progress: ImportProgress) => void) | ((current: number, total: number) => void);
|
|
380
|
+
/**
|
|
381
|
+
* Stage weight configuration for overall progress calculation
|
|
382
|
+
*
|
|
383
|
+
* These weights reflect the typical time distribution across stages.
|
|
384
|
+
* Extraction is typically the slowest stage (60% of time).
|
|
385
|
+
*/
|
|
386
|
+
export interface StageWeights {
|
|
387
|
+
detecting: number;
|
|
388
|
+
reading: number;
|
|
389
|
+
parsing: number;
|
|
390
|
+
extracting: number;
|
|
391
|
+
indexing: number;
|
|
392
|
+
completing: number;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Import result statistics
|
|
396
|
+
*/
|
|
397
|
+
export interface ImportStats {
|
|
398
|
+
graphNodesCreated: number;
|
|
399
|
+
graphEdgesCreated: number;
|
|
400
|
+
vfsFilesCreated: number;
|
|
401
|
+
duration: number;
|
|
402
|
+
bytesProcessed: number;
|
|
403
|
+
averageRate: number;
|
|
404
|
+
peakMemoryMB?: number;
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Import operation result
|
|
408
|
+
*/
|
|
409
|
+
export interface ImportResult {
|
|
410
|
+
success: boolean;
|
|
411
|
+
stats: ImportStats;
|
|
412
|
+
errors?: Array<{
|
|
413
|
+
stage: ImportStage;
|
|
414
|
+
message: string;
|
|
415
|
+
error?: any;
|
|
416
|
+
}>;
|
|
417
|
+
}
|
|
320
418
|
/**
|
|
321
419
|
* Graph traversal parameters
|
|
322
420
|
*/
|