fix: implement getVerbsWithPagination in FileSystemStorage adapter
- Add missing getVerbsWithPagination() method to FileSystemStorage - Fixes verb retrieval returning empty arrays - Add pagination method declarations to BaseStorageAdapter interface - Support filtering by sourceId, targetId, verbType, and service - Include metadata retrieval for each verb Resolves issue where brain.getVerbs() returned empty array even after successfully adding verbs with FileSystemStorage adapter.
This commit is contained in:
parent
f21031da88
commit
fa6c22ce4b
2 changed files with 175 additions and 0 deletions
|
|
@ -101,6 +101,64 @@ export abstract class BaseStorageAdapter implements StorageAdapter {
|
||||||
nextCursor?: string
|
nextCursor?: string
|
||||||
}>
|
}>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get nouns with pagination (internal implementation)
|
||||||
|
* This method should be implemented by storage adapters to support efficient pagination
|
||||||
|
* @param options Pagination options
|
||||||
|
* @returns Promise that resolves to a paginated result of nouns
|
||||||
|
*/
|
||||||
|
getNounsWithPagination?(options: {
|
||||||
|
limit?: number
|
||||||
|
cursor?: string
|
||||||
|
filter?: {
|
||||||
|
nounType?: string | string[]
|
||||||
|
service?: string | string[]
|
||||||
|
metadata?: Record<string, any>
|
||||||
|
}
|
||||||
|
}): Promise<{
|
||||||
|
items: any[]
|
||||||
|
totalCount?: number
|
||||||
|
hasMore: boolean
|
||||||
|
nextCursor?: string
|
||||||
|
}>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get verbs with pagination (internal implementation)
|
||||||
|
* This method should be implemented by storage adapters to support efficient pagination
|
||||||
|
* @param options Pagination options
|
||||||
|
* @returns Promise that resolves to a paginated result of verbs
|
||||||
|
*/
|
||||||
|
getVerbsWithPagination?(options: {
|
||||||
|
limit?: number
|
||||||
|
cursor?: string
|
||||||
|
filter?: {
|
||||||
|
verbType?: string | string[]
|
||||||
|
sourceId?: string | string[]
|
||||||
|
targetId?: string | string[]
|
||||||
|
service?: string | string[]
|
||||||
|
metadata?: Record<string, any>
|
||||||
|
}
|
||||||
|
}): Promise<{
|
||||||
|
items: any[]
|
||||||
|
totalCount?: number
|
||||||
|
hasMore: boolean
|
||||||
|
nextCursor?: string
|
||||||
|
}>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count total number of nouns (optional)
|
||||||
|
* @param filter Optional filter criteria
|
||||||
|
* @returns Promise that resolves to the count
|
||||||
|
*/
|
||||||
|
countNouns?(filter?: any): Promise<number>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count total number of verbs (optional)
|
||||||
|
* @param filter Optional filter criteria
|
||||||
|
* @returns Promise that resolves to the count
|
||||||
|
*/
|
||||||
|
countVerbs?(filter?: any): Promise<number>
|
||||||
|
|
||||||
// Statistics cache
|
// Statistics cache
|
||||||
protected statisticsCache: StatisticsData | null = null
|
protected statisticsCache: StatisticsData | null = null
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -970,6 +970,123 @@ export class FileSystemStorage extends BaseStorage {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get verbs with pagination
|
||||||
|
* This method reads verb files from the filesystem and returns them with pagination
|
||||||
|
*/
|
||||||
|
public async getVerbsWithPagination(options: {
|
||||||
|
limit?: number
|
||||||
|
cursor?: string
|
||||||
|
filter?: {
|
||||||
|
verbType?: string | string[]
|
||||||
|
sourceId?: string | string[]
|
||||||
|
targetId?: string | string[]
|
||||||
|
service?: string | string[]
|
||||||
|
metadata?: Record<string, any>
|
||||||
|
}
|
||||||
|
} = {}): Promise<{
|
||||||
|
items: GraphVerb[]
|
||||||
|
totalCount?: number
|
||||||
|
hasMore: boolean
|
||||||
|
nextCursor?: string
|
||||||
|
}> {
|
||||||
|
await this.ensureInitialized()
|
||||||
|
|
||||||
|
const limit = options.limit || 100
|
||||||
|
const startIndex = options.cursor ? parseInt(options.cursor, 10) : 0
|
||||||
|
|
||||||
|
try {
|
||||||
|
// List all verb files in the verbs directory
|
||||||
|
const files = await fs.promises.readdir(this.verbsDir)
|
||||||
|
const verbFiles = files.filter((f: string) => f.endsWith('.json'))
|
||||||
|
|
||||||
|
// Sort files for consistent ordering
|
||||||
|
verbFiles.sort()
|
||||||
|
|
||||||
|
// Calculate pagination
|
||||||
|
const totalCount = verbFiles.length
|
||||||
|
const endIndex = Math.min(startIndex + limit, totalCount)
|
||||||
|
const hasMore = endIndex < totalCount
|
||||||
|
|
||||||
|
// Load the requested page of verbs
|
||||||
|
const verbs: GraphVerb[] = []
|
||||||
|
|
||||||
|
for (let i = startIndex; i < endIndex; i++) {
|
||||||
|
const file = verbFiles[i]
|
||||||
|
const id = file.replace('.json', '')
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Read the verb data
|
||||||
|
const filePath = path.join(this.verbsDir, file)
|
||||||
|
const data = await fs.promises.readFile(filePath, 'utf-8')
|
||||||
|
const edge = JSON.parse(data)
|
||||||
|
|
||||||
|
// Also try to get metadata if it exists
|
||||||
|
const metadata = await this.getVerbMetadata(id)
|
||||||
|
|
||||||
|
// Convert to GraphVerb format
|
||||||
|
const verb: GraphVerb = {
|
||||||
|
id: edge.id,
|
||||||
|
source: metadata?.source || '',
|
||||||
|
target: metadata?.target || '',
|
||||||
|
type: metadata?.type || 'relationship',
|
||||||
|
...(metadata || {})
|
||||||
|
} as GraphVerb
|
||||||
|
|
||||||
|
// Apply filters if provided
|
||||||
|
if (options.filter) {
|
||||||
|
const filter = options.filter
|
||||||
|
|
||||||
|
// Check verbType filter
|
||||||
|
if (filter.verbType) {
|
||||||
|
const types = Array.isArray(filter.verbType) ? filter.verbType : [filter.verbType]
|
||||||
|
if (!types.includes(verb.type || '')) continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check sourceId filter
|
||||||
|
if (filter.sourceId) {
|
||||||
|
const sources = Array.isArray(filter.sourceId) ? filter.sourceId : [filter.sourceId]
|
||||||
|
if (!sources.includes(verb.source || '')) continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check targetId filter
|
||||||
|
if (filter.targetId) {
|
||||||
|
const targets = Array.isArray(filter.targetId) ? filter.targetId : [filter.targetId]
|
||||||
|
if (!targets.includes(verb.target || '')) continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check service filter
|
||||||
|
if (filter.service && metadata?.service) {
|
||||||
|
const services = Array.isArray(filter.service) ? filter.service : [filter.service]
|
||||||
|
if (!services.includes(metadata.service)) continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
verbs.push(verb)
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`Failed to read verb ${id}:`, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
items: verbs,
|
||||||
|
totalCount,
|
||||||
|
hasMore,
|
||||||
|
nextCursor: hasMore ? String(endIndex) : undefined
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error.code === 'ENOENT') {
|
||||||
|
// Verbs directory doesn't exist yet
|
||||||
|
return {
|
||||||
|
items: [],
|
||||||
|
totalCount: 0,
|
||||||
|
hasMore: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a verb from storage
|
* Delete a verb from storage
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue