chore(8.0): final pre-RC1 sweep — API consistency, named errors, orphans, zero-cast codebase
This commit is contained in:
parent
970e08c466
commit
1f7e365a4e
237 changed files with 1951 additions and 49413 deletions
|
|
@ -123,7 +123,7 @@ export class BackgroundDeduplicator {
|
|||
try {
|
||||
// Get all entities from this import using brain.find()
|
||||
const results = await this.brain.find({
|
||||
where: { importId } as any,
|
||||
where: { importId },
|
||||
limit: 100000 // Large limit to get all entities from import
|
||||
})
|
||||
|
||||
|
|
@ -298,7 +298,7 @@ export class BackgroundDeduplicator {
|
|||
return this.brain.find({
|
||||
query,
|
||||
limit: 5,
|
||||
where: { type: entity.type } as any // Type-aware search
|
||||
where: { type: entity.type } // Type-aware search
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -318,8 +318,11 @@ export class BackgroundDeduplicator {
|
|||
// Check if not already merged
|
||||
const stillExists = await this.brain.get(entity.id)
|
||||
if (stillExists) {
|
||||
// Cast match.entity to HNSWNounWithMetadata (it comes from brain.find results)
|
||||
const matchEntity = match.entity as any as HNSWNounWithMetadata
|
||||
// Typed boundary: bridge the public Entity<T> result shape from
|
||||
// brain.find() to the storage-layer HNSWNounWithMetadata record
|
||||
// (same structural bridge as the results.map above). The merge
|
||||
// path only reads id/type/metadata, present in both shapes.
|
||||
const matchEntity = match.entity as unknown as HNSWNounWithMetadata
|
||||
await this.mergeEntities([entity, matchEntity], 'Similarity')
|
||||
merged++
|
||||
break // Only merge with first high-similarity match
|
||||
|
|
@ -388,7 +391,7 @@ export class BackgroundDeduplicator {
|
|||
for (const entity of entities) {
|
||||
if (entity.id !== primary.id) {
|
||||
try {
|
||||
await this.brain.delete(entity.id)
|
||||
await this.brain.remove(entity.id)
|
||||
} catch (error) {
|
||||
// Entity might already be deleted, continue
|
||||
prodLog.debug(`[BackgroundDedup] Could not delete ${entity.id}:`, error)
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ export class EntityDeduplicator {
|
|||
const results = await this.brain.find({
|
||||
query: searchText,
|
||||
limit: 5,
|
||||
where: opts.strictTypeMatching ? { type: candidate.type } as any : undefined
|
||||
where: opts.strictTypeMatching ? { type: candidate.type } : undefined
|
||||
})
|
||||
|
||||
// Check each result for potential duplicates
|
||||
|
|
@ -227,7 +227,9 @@ export class EntityDeduplicator {
|
|||
const entityId = await this.brain.add({
|
||||
data: candidate.description || candidate.name,
|
||||
type: candidate.type,
|
||||
subtype: (candidate as any).subtype ?? 'imported',
|
||||
subtype:
|
||||
(candidate as EntityCandidate & { subtype?: string }).subtype ??
|
||||
'imported',
|
||||
confidence: candidate.confidence,
|
||||
metadata: {
|
||||
...candidate.metadata,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
import { Brainy } from '../brainy.js'
|
||||
import { FormatDetector, SupportedFormat } from './FormatDetector.js'
|
||||
import { ImportHistory } from './ImportHistory.js'
|
||||
import { ImportHistory, type ImportHistoryEntry } from './ImportHistory.js'
|
||||
import { BackgroundDeduplicator } from './BackgroundDeduplicator.js'
|
||||
import { SmartExcelImporter } from '../importers/SmartExcelImporter.js'
|
||||
import { SmartPDFImporter } from '../importers/SmartPDFImporter.js'
|
||||
|
|
@ -489,7 +489,13 @@ export class ImportCoordinator {
|
|||
await this.history.recordImport(
|
||||
importId,
|
||||
{
|
||||
type: normalizedSource.type === 'path' ? 'file' : normalizedSource.type as any,
|
||||
// 'url' sources were already converted to 'buffer' by
|
||||
// normalizeSource() → fetchUrl(), so only history-recordable
|
||||
// source types remain here after the 'path' → 'file' mapping.
|
||||
type:
|
||||
normalizedSource.type === 'path'
|
||||
? 'file'
|
||||
: (normalizedSource.type as ImportHistoryEntry['source']['type']),
|
||||
filename: normalizedSource.filename,
|
||||
format: detection.format
|
||||
},
|
||||
|
|
@ -699,11 +705,25 @@ export class ImportCoordinator {
|
|||
format: SupportedFormat,
|
||||
options: ImportOptions
|
||||
): Promise<any> {
|
||||
// Check if IntelligentImportAugmentation already extracted data
|
||||
if ((options as any)._intelligentImport && (options as any)._extractedData) {
|
||||
const extractedData = (options as any)._extractedData
|
||||
// Check if IntelligentImportAugmentation already extracted data.
|
||||
// Typed boundary: the intelligent-import pre-processing path smuggles its
|
||||
// results onto ImportOptions via these underscore-prefixed private fields —
|
||||
// they are not part of the public ImportOptions contract.
|
||||
const intelligentOptions = options as ImportOptions & {
|
||||
_intelligentImport?: boolean
|
||||
_extractedData?: Array<{
|
||||
id?: string
|
||||
name?: string
|
||||
type?: string
|
||||
description?: string
|
||||
metadata?: Record<string, unknown>
|
||||
}>
|
||||
_metadata?: { intelligentImport?: Record<string, unknown> }
|
||||
}
|
||||
if (intelligentOptions._intelligentImport && intelligentOptions._extractedData) {
|
||||
const extractedData = intelligentOptions._extractedData
|
||||
// Convert extracted data to ExtractedRow format
|
||||
const rows = extractedData.map((item: any) => ({
|
||||
const rows = extractedData.map((item) => ({
|
||||
entity: {
|
||||
id: item.id || `entity-${Date.now()}-${Math.random()}`,
|
||||
name: item.name || item.type || 'Unnamed',
|
||||
|
|
@ -719,7 +739,7 @@ export class ImportCoordinator {
|
|||
rows,
|
||||
entities: extractedData,
|
||||
relationships: [],
|
||||
metadata: (options as any)._metadata?.intelligentImport || {},
|
||||
metadata: intelligentOptions._metadata?.intelligentImport || {},
|
||||
stats: {
|
||||
byType: {},
|
||||
byConfidence: {}
|
||||
|
|
@ -811,7 +831,7 @@ export class ImportCoordinator {
|
|||
entity: {
|
||||
id: imageId,
|
||||
name: imageName,
|
||||
type: 'media' as any,
|
||||
type: 'media',
|
||||
description: '',
|
||||
confidence: 1.0,
|
||||
metadata: { subtype: 'image' }
|
||||
|
|
@ -864,7 +884,18 @@ export class ImportCoordinator {
|
|||
provenanceCount?: number
|
||||
}> {
|
||||
const entities: Array<{ id: string; name: string; type: NounType; vfsPath?: string; metadata?: Record<string, any> }> = []
|
||||
const relationships: Array<{ id: string; from: string; to: string; type: VerbType }> = []
|
||||
// Wider than the declared return type: confidence/weight/metadata are
|
||||
// collected per relationship for the relateMany() batch below; callers of
|
||||
// createGraphEntities() only see the narrower {id, from, to, type} rows.
|
||||
const relationships: Array<{
|
||||
id: string
|
||||
from: string
|
||||
to: string
|
||||
type: VerbType
|
||||
confidence?: number
|
||||
weight?: number
|
||||
metadata?: { evidence?: string; [key: string]: unknown }
|
||||
}> = []
|
||||
let mergedCount = 0
|
||||
let newCount = 0
|
||||
|
||||
|
|
@ -1227,7 +1258,7 @@ export class ImportCoordinator {
|
|||
...trackingContext.customMetadata
|
||||
})
|
||||
}
|
||||
} as any)
|
||||
})
|
||||
} catch (error) {
|
||||
// Skip relationship collection errors (entity might not exist, etc.)
|
||||
continue
|
||||
|
|
@ -1314,7 +1345,7 @@ export class ImportCoordinator {
|
|||
verbType = this.inferRelationshipType(
|
||||
sourceEntity.type,
|
||||
targetEntity.type,
|
||||
(rel as any).metadata?.evidence
|
||||
rel.metadata?.evidence
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -1323,7 +1354,7 @@ export class ImportCoordinator {
|
|||
to: rel.to,
|
||||
type: verbType, // Enhanced type
|
||||
metadata: {
|
||||
...((rel as any).metadata || {}),
|
||||
...(rel.metadata || {}),
|
||||
relationshipType: 'semantic', // Distinguish from VFS/provenance
|
||||
inferredType: verbType !== rel.type, // Track if type was enhanced
|
||||
originalType: rel.type
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ export class ImportHistory {
|
|||
// Delete entities
|
||||
for (const entityId of entry.entities) {
|
||||
try {
|
||||
await this.brain.delete(entityId)
|
||||
await this.brain.remove(entityId)
|
||||
result.entitiesDeleted++
|
||||
} catch (error) {
|
||||
result.errors.push(`Failed to delete entity ${entityId}: ${error instanceof Error ? error.message : String(error)}`)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue