/** * Local SQLite Database Layer for VasperaMemory * * Provides offline-first storage for memories, decisions, error fixes, and preferences. * Uses FTS5 (Full-Text Search 5) for text search capabilities. */ import Database from 'better-sqlite3'; export interface Memory { id: string; projectId: string; type: 'pattern' | 'decision' | 'architectural'; content: string; reasoning?: string; confidence: number; createdAt: string; updatedAt: string; } export interface Decision { id: string; projectId: string; category: 'architectural' | 'pattern' | 'convention' | 'fix' | 'rejection' | 'preference'; title: string; content: string; reasoning?: string; relatedFiles?: string[]; confidence: number; createdAt: string; } export interface ErrorFix { id: string; projectId: string; errorMessage: string; errorFile?: string; rootCause: string; fixDescription: string; preventionRule?: string; createdAt: string; } export interface Preference { id: string; projectId?: string; category: 'code_style' | 'communication' | 'workflow' | 'tooling' | 'values'; key: string; value: string; confidence: number; createdAt: string; } export interface FileContext { id: string; projectId: string; filePath: string; purpose?: string; lastChangeSummary?: string; knownIssues?: string[]; patternsUsed?: string[]; riskLevel: 'low' | 'medium' | 'high'; riskFactors?: string[]; lastModifiedAt?: string; createdAt: string; updatedAt: string; } export interface SearchResult { item: T; score: number; } export type WorkflowType = 'feature' | 'bugfix' | 'refactor' | 'investigation' | 'documentation' | 'testing' | 'deployment' | 'general'; export type WorkflowStatus = 'active' | 'completed' | 'abandoned'; export interface Workflow { id: string; projectId: string; name?: string; description?: string; workflowType: WorkflowType; startedAt: string; endedAt?: string; durationMinutes?: number; status: WorkflowStatus; outcome?: string; filesTouched: string[]; operationCount: number; aiSummary?: string; } export interface ToolCallLog { id: string; projectId: string; workflowId?: string; toolName: string; toolCategory?: string; paramsSummary?: Record; success: boolean; resultType?: string; resultSummary?: string; durationMs?: number; createdAt: string; } export type AttributeCategory = 'code_style' | 'work_patterns' | 'tech_preferences' | 'error_handling' | 'architecture' | 'testing' | 'documentation' | 'general'; export interface LearnedAttribute { id: string; projectId: string; key: string; value: any; category: AttributeCategory; confidence: number; evidence: string[]; learnedAt: string; decayWeight: number; isOverridden?: boolean; overrideValue?: any; } export type EntityType = 'file' | 'function' | 'class' | 'api_endpoint' | 'service' | 'person' | 'package' | 'error_type' | 'concept'; export interface ExtractedEntity { id: string; projectId: string; entityType: EntityType; entityValue: string; normalizedValue: string; metadata?: Record; mentionCount: number; firstSeenAt: string; lastSeenAt: string; } export type CodePatternCategory = 'naming' | 'structure' | 'patterns' | 'imports' | 'error_handling' | 'testing' | 'styling'; export interface CodePattern { id: string; projectId: string; category: CodePatternCategory; pattern: string; description?: string; example?: string; confidence: number; createdAt: string; updatedAt: string; } export type DocCategory = 'product' | 'technical' | 'operations' | 'guides' | 'archive'; export type DocStatus = 'current' | 'needs_review' | 'outdated' | 'deprecated'; export interface IndexedDoc { id: string; projectId: string; filePath: string; category: DocCategory; title: string; description?: string; contentHash: string; status: DocStatus; keywords: string[]; relatedCodeFiles: string[]; lastModified: string; createdAt: string; updatedAt: string; } export type RelationshipType = 'imports' | 'imported_by' | 'co_changed' | 'test_for' | 'sibling' | 'parent'; export interface FileRelationship { id: string; projectId: string; sourceFile: string; targetFile: string; relationshipType: RelationshipType; strength: number; evidence?: string; createdAt: string; updatedAt: string; } export type EntityRegistryStatus = 'synced' | 'pending_sync' | 'error'; export interface EntityRegistry { id: string; projectId: string; filePath: string; contentHash: string; entityCount: number; relationshipCount: number; indexedAt: string; status: EntityRegistryStatus; } export declare class LocalDatabase { private db; /** Raw handle for the governance module (local gate + ledger). */ get rawDb(): Database.Database; private dataDir; constructor(dataDir?: string); private initSchema; private generateId; captureMemory(memory: Omit): Memory; searchMemories(projectId: string, query: string, limit?: number): SearchResult[]; private searchMemoriesLike; getMemories(projectId: string, type?: string, limit?: number): Memory[]; deleteMemory(id: string): boolean; private rowToMemory; captureDecision(decision: Omit): Decision; searchDecisions(projectId: string, query: string, limit?: number): SearchResult[]; private searchDecisionsLike; getRecentDecisions(projectId: string, limit?: number, category?: string): Decision[]; private rowToDecision; captureErrorFix(errorFix: Omit): ErrorFix; findErrorFix(projectId: string, errorMessage: string): SearchResult[]; private findErrorFixLike; getRecentErrorFixes(projectId: string, limit?: number): ErrorFix[]; private rowToErrorFix; setPreference(preference: Omit): Preference; getPreferences(projectId?: string, category?: string, limit?: number): Preference[]; private rowToPreference; createWorkflow(projectId: string): Workflow; getActiveWorkflow(projectId: string): Workflow | null; updateWorkflow(id: string, updates: Partial): boolean; getRecentWorkflows(projectId: string, limit?: number, status?: WorkflowStatus): Workflow[]; getWorkflow(id: string): Workflow | null; private rowToWorkflow; logToolCall(log: Omit): ToolCallLog; getToolCallLogs(projectId: string, limit?: number, workflowId?: string): ToolCallLog[]; getToolUsageStats(projectId: string, days?: number): { toolName: string; count: number; avgDuration: number; }[]; upsertLearnedAttribute(attr: Omit): LearnedAttribute; getLearnedAttributes(projectId: string, category?: AttributeCategory, minConfidence?: number): LearnedAttribute[]; validateLearnedAttribute(projectId: string, key: string, isCorrect: boolean, correctedValue?: any): boolean; upsertEntity(projectId: string, entity: { entityType: EntityType; entityValue: string; normalizedValue: string; metadata?: Record; }): ExtractedEntity; createEntityMention(entityId: string, sourceType: 'memory' | 'decision' | 'error_fix', sourceId: string, context?: string): boolean; searchEntities(projectId: string, query: string, entityType?: EntityType, limit?: number): ExtractedEntity[]; /** * Get all entities extracted from a specific file * Uses json_extract to query the metadata.file field */ getEntitiesByFile(projectId: string, filePath: string, limit?: number): ExtractedEntity[]; getMostMentionedEntities(projectId: string, entityType?: EntityType, limit?: number): ExtractedEntity[]; private rowToEntity; fuseContext(projectId: string, maxTokens?: number): string; getStats(projectId: string): { memories: number; decisions: number; errorFixes: number; preferences: number; }; learnCodePattern(pattern: Omit): CodePattern; getCodePatterns(projectId: string, category?: CodePatternCategory): CodePattern[]; private rowToCodePattern; getDecisionTimeline(projectId: string, limit?: number): Decision[]; getFileContext(projectId: string, filePath: string): FileContext | null; upsertFileContext(projectId: string, filePath: string, updates: Partial>): FileContext; getAllFileContexts(projectId: string): FileContext[]; getFileContextCount(projectId: string): number; private rowToFileContext; upsertIndexedDoc(projectId: string, doc: Omit): IndexedDoc; getIndexedDoc(projectId: string, filePath: string): IndexedDoc | null; getIndexedDocs(projectId: string, category?: DocCategory, status?: DocStatus): IndexedDoc[]; searchIndexedDocs(projectId: string, query: string, limit?: number): IndexedDoc[]; getIndexedDocsCount(projectId: string): number; private rowToIndexedDoc; upsertFileRelationship(projectId: string, rel: Omit): FileRelationship; getFileRelationship(projectId: string, sourceFile: string, targetFile: string, relationshipType: RelationshipType): FileRelationship | null; getRelatedFiles(projectId: string, filePath: string): FileRelationship[]; getAllFileRelationships(projectId: string, relationshipType?: RelationshipType): FileRelationship[]; private rowToFileRelationship; getEntityRegistry(projectId: string, filePath: string): EntityRegistry | null; upsertEntityRegistry(projectId: string, filePath: string, contentHash: string, entityCount: number, relationshipCount: number, status?: EntityRegistryStatus): EntityRegistry; getEntityRegistryByStatus(projectId: string, status: EntityRegistryStatus, limit?: number): EntityRegistry[]; markEntityRegistrySynced(projectId: string, filePaths: string[]): number; getEntityRegistryStats(projectId: string): { total: number; synced: number; pending: number; error: number; }; clearEntityRegistry(projectId: string): number; private rowToEntityRegistry; close(): void; } export declare function getLocalDatabase(dataDir?: string): LocalDatabase; export declare function closeLocalDatabase(): void; //# sourceMappingURL=local-db.d.ts.map