Skip to main content
Glama
RecoveryEngine.ts32.7 kB
/** * Recovery Engine * * Implements memory recovery capabilities using multiple strategies including * associative recovery, schema-based reconstruction, and partial cue recovery. * Tracks recovery success and continuously improves recovery effectiveness. */ import { AssociativeRecoveryStrategy, EnhancedRecoveryResult, FailurePattern, IRecoveryEngine, PartialCueRecoveryStrategy, QualityIssue, RecoveryAttempt, RecoveryConfidenceAssessment, RecoveryCue, RecoveryMetadata, RecoveryQualityAssessment, RecoveryResult, RecoveryStatistics, RecoveryStrategy, RecoveryTrend, RecoveryValidation, ReliabilityFactor, SchemaBasedRecoveryStrategy, UncertaintySource, } from "../../interfaces/forgetting.js"; import { Concept, Episode } from "../../types/core.js"; export interface RecoveryEngineConfig { max_recovery_attempts: number; confidence_threshold: number; enable_strategy_learning: boolean; enable_quality_assessment: boolean; recovery_timeout_ms: number; statistics_retention_days: number; } export class RecoveryEngine implements IRecoveryEngine { private config: RecoveryEngineConfig; private recoveryStrategies: Map<string, RecoveryStrategy> = new Map(); private recoveryHistory: Map<string, RecoveryAttempt[]> = new Map(); private recoveryStatistics: RecoveryStatistics; private validationHistory: Map<string, RecoveryValidation[]> = new Map(); constructor(config?: Partial<RecoveryEngineConfig>) { this.config = { max_recovery_attempts: 5, confidence_threshold: 0.3, enable_strategy_learning: true, enable_quality_assessment: true, recovery_timeout_ms: 30000, statistics_retention_days: 90, ...config, }; this.recoveryStatistics = this.initializeStatistics(); this.initializeDefaultStrategies(); } private initializeStatistics(): RecoveryStatistics { return { total_recovery_attempts: 0, successful_recoveries: 0, partial_recoveries: 0, failed_recoveries: 0, average_recovery_confidence: 0, average_recovery_time_ms: 0, strategy_success_rates: new Map(), improvement_trends: [], common_failure_patterns: [], }; } private initializeDefaultStrategies(): void { // Add associative recovery strategy this.addRecoveryStrategy( new AssociativeRecoveryStrategyImpl({ name: "associative_recovery", description: "Recover memories using associative networks and spreading activation", confidence_threshold: 0.4, association_weight: 0.7, spreading_activation_depth: 3, similarity_threshold: 0.6, }) ); // Add schema-based recovery strategy this.addRecoveryStrategy( new SchemaBasedRecoveryStrategyImpl({ name: "schema_based_recovery", description: "Recover memories using schema matching and pattern completion", confidence_threshold: 0.5, schema_matching_threshold: 0.7, pattern_completion_enabled: true, contextual_inference_weight: 0.8, }) ); // Add partial cue recovery strategy this.addRecoveryStrategy( new PartialCueRecoveryStrategyImpl({ name: "partial_cue_recovery", description: "Recover memories using partial cues and reconstruction", confidence_threshold: 0.3, minimum_cue_strength: 0.4, cue_combination_method: "weighted_sum", temporal_decay_compensation: true, }) ); } async attemptRecovery( memory_id: string, recovery_cues: RecoveryCue[], recovery_metadata?: RecoveryMetadata ): Promise<EnhancedRecoveryResult> { const startTime = Date.now(); const attempts: RecoveryAttempt[] = []; let bestAttempt: RecoveryAttempt | null = null; let bestConfidence = 0; // Validate inputs if (!recovery_cues || recovery_cues.length === 0) { throw new Error("Recovery cues are required for memory recovery"); } if (!recovery_metadata) { console.warn( `No recovery metadata provided for memory ${memory_id}, using cues only` ); } // Sort strategies by their assessed recovery probability const strategiesWithProbability = await Promise.all( Array.from(this.recoveryStrategies.values()).map(async (strategy) => ({ strategy, probability: recovery_metadata ? await strategy.assessRecoveryProbability( recovery_cues, recovery_metadata ) : 0.5, // Default probability when no metadata })) ); strategiesWithProbability.sort((a, b) => b.probability - a.probability); // Attempt recovery with each strategy for (const { strategy } of strategiesWithProbability) { if (attempts.length >= this.config.max_recovery_attempts) { break; } try { const attempt = recovery_metadata ? await strategy.recover(memory_id, recovery_cues, recovery_metadata) : await this.recoverWithoutMetadata( strategy, memory_id, recovery_cues ); attempts.push(attempt); // Track the best attempt if (attempt.success && attempt.confidence > bestConfidence) { bestAttempt = attempt; bestConfidence = attempt.confidence; } // If we have a high-confidence recovery, we can stop if (attempt.confidence > 0.9) { break; } } catch (error) { console.error(`Recovery strategy ${strategy.name} failed:`, error); attempts.push({ strategy_name: strategy.name, success: false, confidence: 0, partial_recovery: false, recovered_elements: [], missing_elements: ["all"], recovery_method_details: `Strategy failed: ${error}`, processing_time_ms: Date.now() - startTime, }); } } // Determine overall recovery result const success = bestAttempt?.success ?? false; const recoveredMemory = bestAttempt?.recovered_content; const combinedConfidence = this.calculateCombinedConfidence(attempts); const partialRecovery = attempts.some((a) => a.partial_recovery); // Assess recovery quality if enabled const qualityAssessment = this.config.enable_quality_assessment && recoveredMemory ? await this.assessRecoveryQuality( recoveredMemory, recovery_metadata, recovery_cues ) : this.createDefaultQualityAssessment(); // Create enhanced recovery result const result: EnhancedRecoveryResult = { success, recovered_memory: recoveredMemory as Episode | Concept | undefined, recovery_confidence: combinedConfidence, recovery_method: bestAttempt?.strategy_name ?? "none", partial_recovery: partialRecovery, missing_elements: bestAttempt?.missing_elements ?? [], recovery_metadata_used: recovery_metadata ?? this.createEmptyRecoveryMetadata(memory_id), recovery_attempts: attempts, best_attempt: bestAttempt ?? attempts[0], combined_confidence: combinedConfidence, recovery_strategies_used: attempts.map((a) => a.strategy_name), recovery_time_ms: Date.now() - startTime, quality_assessment: qualityAssessment, }; // Update statistics await this.updateRecoveryStatistics(result); // Store recovery history this.recoveryHistory.set(memory_id, attempts); return result; } async assessRecoveryConfidence( recovered_content: any, original_metadata: RecoveryMetadata ): Promise<RecoveryConfidenceAssessment> { const reliabilityFactors: ReliabilityFactor[] = []; const uncertaintySources: UncertaintySource[] = []; const validationSuggestions: string[] = []; // Assess content accuracy based on available metadata let contentAccuracy = 0.5; // Default moderate confidence let completeness = 0.5; if (original_metadata) { // Check content hash if available if (original_metadata.original_content_hash) { const recoveredHash = this.generateContentHash(recovered_content); const hashMatch = recoveredHash === original_metadata.original_content_hash; contentAccuracy = hashMatch ? 0.95 : 0.3; reliabilityFactors.push({ factor_name: "content_hash_match", impact: hashMatch ? 0.4 : -0.3, description: hashMatch ? "Content hash matches original" : "Content hash differs from original", evidence: [`Hash comparison: ${hashMatch ? "match" : "mismatch"}`], }); } // Assess completeness based on recovery cues const cuesCovered = original_metadata.recovery_cues.length; const expectedCues = Math.max(cuesCovered, 3); // Minimum expected cues completeness = Math.min(cuesCovered / expectedCues, 1); reliabilityFactors.push({ factor_name: "recovery_cues_coverage", impact: (completeness - 0.5) * 0.4, description: `${cuesCovered} recovery cues available`, evidence: [`Cue coverage: ${(completeness * 100).toFixed(1)}%`], }); // Check degradation history impact const totalDegradation = original_metadata.degradation_history.reduce( (sum, record) => sum + record.degradation_factor, 0 ); if (totalDegradation > 0) { const degradationImpact = -totalDegradation * 0.3; reliabilityFactors.push({ factor_name: "degradation_impact", impact: degradationImpact, description: `Memory underwent ${(totalDegradation * 100).toFixed( 1 )}% degradation`, evidence: [ `Degradation stages: ${original_metadata.degradation_history.length}`, ], }); uncertaintySources.push({ source_name: "memory_degradation", uncertainty_level: totalDegradation * 0.5, description: "Memory content may be incomplete due to degradation", mitigation_strategies: [ "Cross-reference with related memories", "Validate with external sources", ], }); } } // Add general uncertainty sources uncertaintySources.push({ source_name: "reconstruction_artifacts", uncertainty_level: 0.2, description: "Recovery process may introduce reconstruction artifacts", mitigation_strategies: [ "Compare with similar memories", "Verify key facts independently", ], }); // Generate validation suggestions validationSuggestions.push( "Cross-reference recovered content with related memories" ); validationSuggestions.push("Verify key facts and dates independently"); if (original_metadata?.association_fingerprint) { validationSuggestions.push("Check consistency with associated memories"); } // Calculate overall confidence const baseConfidence = (contentAccuracy + completeness) / 2; const reliabilityAdjustment = reliabilityFactors.reduce( (sum, factor) => sum + factor.impact, 0 ); const overallConfidence = Math.max( 0.1, Math.min(1, baseConfidence + reliabilityAdjustment) ); return { overall_confidence: overallConfidence, content_accuracy_estimate: contentAccuracy, completeness_estimate: completeness, reliability_factors: reliabilityFactors, uncertainty_sources: uncertaintySources, validation_suggestions: validationSuggestions, }; } async trackRecoverySuccess( memory_id: string, recovery_result: RecoveryResult, user_validation?: RecoveryValidation ): Promise<void> { // Store user validation if provided if (user_validation) { const validations = this.validationHistory.get(memory_id) ?? []; validations.push(user_validation); this.validationHistory.set(memory_id, validations); // Update strategy success rates based on validation if (this.config.enable_strategy_learning) { await this.updateStrategyLearning(recovery_result, user_validation); } } // Update recovery statistics this.recoveryStatistics.total_recovery_attempts++; if (recovery_result.success) { if (recovery_result.partial_recovery) { this.recoveryStatistics.partial_recoveries++; } else { this.recoveryStatistics.successful_recoveries++; } } else { this.recoveryStatistics.failed_recoveries++; } // Update average confidence const totalAttempts = this.recoveryStatistics.total_recovery_attempts; const currentAvg = this.recoveryStatistics.average_recovery_confidence; this.recoveryStatistics.average_recovery_confidence = (currentAvg * (totalAttempts - 1) + recovery_result.recovery_confidence) / totalAttempts; } async getRecoveryStatistics(): Promise<RecoveryStatistics> { // Calculate improvement trends const trends = await this.calculateRecoveryTrends(); // Identify failure patterns const failurePatterns = await this.identifyFailurePatterns(); return { ...this.recoveryStatistics, improvement_trends: trends, common_failure_patterns: failurePatterns, }; } addRecoveryStrategy(strategy: RecoveryStrategy): void { this.recoveryStrategies.set(strategy.name, strategy); // Initialize success rate tracking if (!this.recoveryStatistics.strategy_success_rates.has(strategy.name)) { this.recoveryStatistics.strategy_success_rates.set(strategy.name, 0); } } removeRecoveryStrategy(strategyName: string): void { this.recoveryStrategies.delete(strategyName); this.recoveryStatistics.strategy_success_rates.delete(strategyName); } // Private helper methods private async recoverWithoutMetadata( strategy: RecoveryStrategy, memory_id: string, recovery_cues: RecoveryCue[] ): Promise<RecoveryAttempt> { // Create minimal recovery metadata from cues const minimalMetadata: RecoveryMetadata = this.createEmptyRecoveryMetadata(memory_id); minimalMetadata.recovery_cues = recovery_cues; return await strategy.recover(memory_id, recovery_cues, minimalMetadata); } private createEmptyRecoveryMetadata(memory_id: string): RecoveryMetadata { return { original_memory_id: memory_id, original_content_hash: "", original_importance: 0.5, original_timestamp: Date.now(), degradation_history: [], recovery_cues: [], association_fingerprint: { strong_associations: [], weak_associations: [], semantic_clusters: [], temporal_neighbors: [], contextual_tags: [], }, content_summary: "", recovery_difficulty_estimate: 0.5, preservation_timestamp: Date.now(), }; } private calculateCombinedConfidence(attempts: RecoveryAttempt[]): number { if (attempts.length === 0) return 0; const successfulAttempts = attempts.filter((a) => a.success); if (successfulAttempts.length === 0) return 0; // Use weighted average of successful attempts const totalWeight = successfulAttempts.reduce( (sum, a) => sum + a.confidence, 0 ); return totalWeight / successfulAttempts.length; } private async assessRecoveryQuality( recovered_content: any, recovery_metadata?: RecoveryMetadata, _recovery_cues?: RecoveryCue[] ): Promise<RecoveryQualityAssessment> { const qualityIssues: QualityIssue[] = []; // Assess content coherence const contentCoherence = this.assessContentCoherence(recovered_content); // Assess contextual consistency const contextualConsistency = recovery_metadata ? this.assessContextualConsistency(recovered_content, recovery_metadata) : 0.5; // Assess temporal accuracy const temporalAccuracy = recovery_metadata ? this.assessTemporalAccuracy(recovered_content, recovery_metadata) : 0.5; // Assess associative integrity const associativeIntegrity = recovery_metadata ? this.assessAssociativeIntegrity(recovered_content, recovery_metadata) : 0.5; // Calculate overall quality const overallQuality = (contentCoherence + contextualConsistency + temporalAccuracy + associativeIntegrity) / 4; // Identify quality issues if (contentCoherence < 0.6) { qualityIssues.push({ issue_type: "inconsistency", severity: "medium", description: "Recovered content shows internal inconsistencies", affected_content: ["content_structure"], suggested_resolution: "Review and validate content structure", }); } if (contextualConsistency < 0.5) { qualityIssues.push({ issue_type: "gap", severity: "medium", description: "Contextual information may be incomplete", affected_content: ["context_data"], suggested_resolution: "Cross-reference with related memories", }); } return { content_coherence: contentCoherence, contextual_consistency: contextualConsistency, temporal_accuracy: temporalAccuracy, associative_integrity: associativeIntegrity, overall_quality: overallQuality, quality_issues: qualityIssues, }; } private createDefaultQualityAssessment(): RecoveryQualityAssessment { return { content_coherence: 0.5, contextual_consistency: 0.5, temporal_accuracy: 0.5, associative_integrity: 0.5, overall_quality: 0.5, quality_issues: [], }; } private assessContentCoherence(content: any): number { // Simplified coherence assessment if (!content) return 0; if (typeof content === "string") { // Basic string coherence checks const hasRepeatedWords = /\b(\w+)\s+\1\b/i.test(content); const hasBasicStructure = content.length > 10 && content.includes(" "); return hasBasicStructure && !hasRepeatedWords ? 0.8 : 0.4; } return 0.6; // Default for non-string content } private assessContextualConsistency( content: any, metadata: RecoveryMetadata ): number { // Check if recovered content is consistent with metadata context let consistency = 0.5; // Check against content summary if (metadata.content_summary && typeof content === "string") { const summaryWords = metadata.content_summary.toLowerCase().split(" "); const contentWords = content.toLowerCase().split(" "); const overlap = summaryWords.filter((word) => contentWords.includes(word) ).length; consistency += (overlap / summaryWords.length) * 0.3; } // Check against contextual tags if (metadata.association_fingerprint.contextual_tags.length > 0) { // Simplified check - in real implementation, would use more sophisticated matching consistency += 0.2; } return Math.min(consistency, 1); } private assessTemporalAccuracy( _content: any, metadata: RecoveryMetadata ): number { // Assess if temporal aspects of recovered content are accurate const timeDiff = Date.now() - metadata.original_timestamp; const daysDiff = timeDiff / (1000 * 60 * 60 * 24); // Older memories are harder to verify temporally return Math.max(0.3, 1 - (daysDiff / 365) * 0.5); } private assessAssociativeIntegrity( _content: any, metadata: RecoveryMetadata ): number { // Assess if associative relationships are maintained const fingerprint = metadata.association_fingerprint; const totalAssociations = fingerprint.strong_associations.length + fingerprint.weak_associations.length; if (totalAssociations === 0) return 0.5; // Simplified assessment - in real implementation, would check actual associations return Math.min(0.8, 0.4 + (totalAssociations / 10) * 0.4); } private async updateRecoveryStatistics( result: EnhancedRecoveryResult ): Promise<void> { // Update strategy success rates for (const attempt of result.recovery_attempts) { const currentRate = this.recoveryStatistics.strategy_success_rates.get( attempt.strategy_name ) ?? 0; const newRate = attempt.success ? currentRate + 0.1 : Math.max(0, currentRate - 0.05); this.recoveryStatistics.strategy_success_rates.set( attempt.strategy_name, Math.min(1, newRate) ); } // Update average recovery time const totalAttempts = this.recoveryStatistics.total_recovery_attempts; const currentAvgTime = this.recoveryStatistics.average_recovery_time_ms; this.recoveryStatistics.average_recovery_time_ms = (currentAvgTime * totalAttempts + result.recovery_time_ms) / (totalAttempts + 1); } private async updateStrategyLearning( recovery_result: RecoveryResult, user_validation: RecoveryValidation ): Promise<void> { // Adjust strategy confidence based on user validation const strategyName = recovery_result.recovery_method; const strategy = this.recoveryStrategies.get(strategyName); if (strategy && user_validation.user_confirms_accuracy) { // Positive feedback - increase strategy success rate const currentRate = this.recoveryStatistics.strategy_success_rates.get(strategyName) ?? 0; const adjustment = user_validation.accuracy_rating * 0.1; this.recoveryStatistics.strategy_success_rates.set( strategyName, Math.min(1, currentRate + adjustment) ); } } private async calculateRecoveryTrends(): Promise<RecoveryTrend[]> { // Simplified trend calculation - in real implementation, would analyze historical data const trends: RecoveryTrend[] = []; const successRate = this.recoveryStatistics.successful_recoveries / Math.max(1, this.recoveryStatistics.total_recovery_attempts); trends.push({ metric_name: "success_rate", trend_direction: successRate > 0.6 ? "improving" : successRate < 0.4 ? "declining" : "stable", change_rate: 0.05, // Simplified time_period_days: 30, significance: 0.7, }); return trends; } private async identifyFailurePatterns(): Promise<FailurePattern[]> { // Simplified pattern identification const patterns: FailurePattern[] = []; const failureRate = this.recoveryStatistics.failed_recoveries / Math.max(1, this.recoveryStatistics.total_recovery_attempts); if (failureRate > 0.3) { patterns.push({ pattern_name: "high_failure_rate", frequency: failureRate, typical_causes: [ "Insufficient recovery cues", "Severe memory degradation", ], suggested_improvements: [ "Preserve more recovery metadata", "Implement additional recovery strategies", ], affected_memory_types: ["episodic", "semantic"], }); } return patterns; } private generateContentHash(content: any): string { // Simplified hash generation const contentStr = JSON.stringify(content); return `hash_${contentStr.length}_${Date.now()}`; } } // Implementation classes for recovery strategies class AssociativeRecoveryStrategyImpl implements AssociativeRecoveryStrategy { name!: string; description!: string; confidence_threshold!: number; association_weight!: number; spreading_activation_depth!: number; similarity_threshold!: number; constructor(config: { name: string; description: string; confidence_threshold: number; association_weight: number; spreading_activation_depth: number; similarity_threshold: number; }) { Object.assign(this, config); } async recover( _memory_id: string, recovery_cues: RecoveryCue[], recovery_metadata: RecoveryMetadata ): Promise<RecoveryAttempt> { const startTime = Date.now(); // Use associative fingerprint to guide recovery const fingerprint = recovery_metadata.association_fingerprint; const associativeCues = recovery_cues.filter( (cue) => cue.type === "associative" ); // Simulate associative recovery process const recoverySuccess = associativeCues.length > 0 && fingerprint.strong_associations.length > 0; const confidence = recoverySuccess ? Math.min( 0.9, 0.5 + associativeCues.length * 0.1 + fingerprint.strong_associations.length * 0.05 ) : 0.2; let recoveredContent = null; const recoveredElements: string[] = []; const missingElements: string[] = []; if (recoverySuccess) { // Simulate content recovery based on associations recoveredContent = { content: recovery_metadata.content_summary + " [recovered via associations]", associations: fingerprint.strong_associations.slice(0, 3), confidence: confidence, }; recoveredElements.push("content", "associations"); } else { missingElements.push("content", "associations"); } return { strategy_name: this.name, success: recoverySuccess, recovered_content: recoveredContent, confidence, partial_recovery: confidence > 0.3 && confidence < 0.7, recovered_elements: recoveredElements, missing_elements: missingElements, recovery_method_details: `Associative recovery using ${associativeCues.length} cues and ${fingerprint.strong_associations.length} associations`, processing_time_ms: Date.now() - startTime, }; } async assessRecoveryProbability( recovery_cues: RecoveryCue[], recovery_metadata: RecoveryMetadata ): Promise<number> { const associativeCues = recovery_cues.filter( (cue) => cue.type === "associative" ).length; const strongAssociations = recovery_metadata.association_fingerprint.strong_associations.length; return Math.min( 0.9, 0.3 + associativeCues * 0.1 + strongAssociations * 0.05 ); } } class SchemaBasedRecoveryStrategyImpl implements SchemaBasedRecoveryStrategy { name!: string; description!: string; confidence_threshold!: number; schema_matching_threshold!: number; pattern_completion_enabled!: boolean; contextual_inference_weight!: number; constructor(config: { name: string; description: string; confidence_threshold: number; schema_matching_threshold: number; pattern_completion_enabled: boolean; contextual_inference_weight: number; }) { Object.assign(this, config); } async recover( _memory_id: string, recovery_cues: RecoveryCue[], recovery_metadata: RecoveryMetadata ): Promise<RecoveryAttempt> { const startTime = Date.now(); // Use semantic and contextual cues for schema-based recovery const semanticCues = recovery_cues.filter((cue) => cue.type === "semantic"); const contextualCues = recovery_cues.filter( (cue) => cue.type === "contextual" ); const schemaMatch = semanticCues.length > 0 || contextualCues.length > 0; const confidence = schemaMatch ? Math.min( 0.85, 0.4 + semanticCues.length * 0.1 + contextualCues.length * 0.08 ) : 0.15; let recoveredContent = null; const recoveredElements: string[] = []; const missingElements: string[] = []; if (schemaMatch && confidence > this.confidence_threshold) { // Simulate schema-based content reconstruction recoveredContent = { content: recovery_metadata.content_summary + " [recovered via schema matching]", schema_elements: semanticCues.map((cue) => cue.value), context: contextualCues.map((cue) => cue.value), confidence: confidence, }; recoveredElements.push("content", "schema", "context"); } else { missingElements.push("content", "schema", "context"); } return { strategy_name: this.name, success: schemaMatch && confidence > this.confidence_threshold, recovered_content: recoveredContent, confidence, partial_recovery: confidence > 0.3 && confidence < 0.7, recovered_elements: recoveredElements, missing_elements: missingElements, recovery_method_details: `Schema-based recovery using ${semanticCues.length} semantic and ${contextualCues.length} contextual cues`, processing_time_ms: Date.now() - startTime, }; } async assessRecoveryProbability( recovery_cues: RecoveryCue[], _recovery_metadata: RecoveryMetadata ): Promise<number> { const semanticCues = recovery_cues.filter( (cue) => cue.type === "semantic" ).length; const contextualCues = recovery_cues.filter( (cue) => cue.type === "contextual" ).length; return Math.min(0.85, 0.2 + semanticCues * 0.12 + contextualCues * 0.1); } } class PartialCueRecoveryStrategyImpl implements PartialCueRecoveryStrategy { name!: string; description!: string; confidence_threshold!: number; minimum_cue_strength!: number; cue_combination_method!: "weighted_sum" | "max_activation" | "consensus"; temporal_decay_compensation!: boolean; constructor(config: { name: string; description: string; confidence_threshold: number; minimum_cue_strength: number; cue_combination_method: "weighted_sum" | "max_activation" | "consensus"; temporal_decay_compensation: boolean; }) { Object.assign(this, config); } async recover( _memory_id: string, recovery_cues: RecoveryCue[], recovery_metadata: RecoveryMetadata ): Promise<RecoveryAttempt> { const startTime = Date.now(); // Filter cues by minimum strength const strongCues = recovery_cues.filter( (cue) => cue.strength >= this.minimum_cue_strength ); // Combine cue strengths based on method let combinedStrength = 0; switch (this.cue_combination_method) { case "weighted_sum": combinedStrength = strongCues.reduce((sum, cue) => sum + cue.strength, 0) / strongCues.length; break; case "max_activation": combinedStrength = Math.max( ...strongCues.map((cue) => cue.strength), 0 ); break; case "consensus": combinedStrength = strongCues.length > 2 ? strongCues.reduce((sum, cue) => sum + cue.strength, 0) / strongCues.length : 0; break; } // Apply temporal decay compensation if enabled if (this.temporal_decay_compensation) { const age = Date.now() - recovery_metadata.original_timestamp; const daysSinceCreation = age / (1000 * 60 * 60 * 24); const decayFactor = Math.max(0.5, 1 - (daysSinceCreation / 365) * 0.3); combinedStrength *= decayFactor; } const recoverySuccess = combinedStrength > this.confidence_threshold; const confidence = Math.min(0.8, combinedStrength); let recoveredContent = null; const recoveredElements: string[] = []; const missingElements: string[] = []; if (recoverySuccess) { // Simulate partial content recovery recoveredContent = { content: recovery_metadata.content_summary + " [partial recovery from cues]", recovered_cues: strongCues.map((cue) => ({ type: cue.type, value: cue.value, })), confidence: confidence, }; recoveredElements.push("partial_content", "cues"); if (confidence < 0.6) { missingElements.push("detailed_content"); } } else { missingElements.push("content", "cues"); } return { strategy_name: this.name, success: recoverySuccess, recovered_content: recoveredContent, confidence, partial_recovery: confidence > 0.3 && confidence < 0.7, recovered_elements: recoveredElements, missing_elements: missingElements, recovery_method_details: `Partial cue recovery using ${strongCues.length} strong cues with ${this.cue_combination_method} combination`, processing_time_ms: Date.now() - startTime, }; } async assessRecoveryProbability( recovery_cues: RecoveryCue[], _recovery_metadata: RecoveryMetadata ): Promise<number> { const strongCues = recovery_cues.filter( (cue) => cue.strength >= this.minimum_cue_strength ); const avgStrength = strongCues.length > 0 ? strongCues.reduce((sum, cue) => sum + cue.strength, 0) / strongCues.length : 0; return Math.min(0.8, avgStrength * 0.8); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/keyurgolani/ThoughtMcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server