empathy-framework 3.7.0__py3-none-any.whl → 3.7.1__py3-none-any.whl
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.
- coach_wizards/code_reviewer_README.md +60 -0
- coach_wizards/code_reviewer_wizard.py +180 -0
- {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/METADATA +20 -2
- empathy_framework-3.7.1.dist-info/RECORD +327 -0
- {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/top_level.txt +5 -1
- empathy_healthcare_plugin/monitors/__init__.py +9 -0
- empathy_healthcare_plugin/monitors/clinical_protocol_monitor.py +315 -0
- empathy_healthcare_plugin/monitors/monitoring/__init__.py +44 -0
- empathy_healthcare_plugin/monitors/monitoring/protocol_checker.py +300 -0
- empathy_healthcare_plugin/monitors/monitoring/protocol_loader.py +214 -0
- empathy_healthcare_plugin/monitors/monitoring/sensor_parsers.py +306 -0
- empathy_healthcare_plugin/monitors/monitoring/trajectory_analyzer.py +389 -0
- empathy_llm_toolkit/agent_factory/__init__.py +53 -0
- empathy_llm_toolkit/agent_factory/adapters/__init__.py +85 -0
- empathy_llm_toolkit/agent_factory/adapters/autogen_adapter.py +312 -0
- empathy_llm_toolkit/agent_factory/adapters/crewai_adapter.py +454 -0
- empathy_llm_toolkit/agent_factory/adapters/haystack_adapter.py +298 -0
- empathy_llm_toolkit/agent_factory/adapters/langchain_adapter.py +362 -0
- empathy_llm_toolkit/agent_factory/adapters/langgraph_adapter.py +333 -0
- empathy_llm_toolkit/agent_factory/adapters/native.py +228 -0
- empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +426 -0
- empathy_llm_toolkit/agent_factory/base.py +305 -0
- empathy_llm_toolkit/agent_factory/crews/__init__.py +67 -0
- empathy_llm_toolkit/agent_factory/crews/code_review.py +1113 -0
- empathy_llm_toolkit/agent_factory/crews/health_check.py +1246 -0
- empathy_llm_toolkit/agent_factory/crews/refactoring.py +1128 -0
- empathy_llm_toolkit/agent_factory/crews/security_audit.py +1018 -0
- empathy_llm_toolkit/agent_factory/decorators.py +286 -0
- empathy_llm_toolkit/agent_factory/factory.py +558 -0
- empathy_llm_toolkit/agent_factory/framework.py +192 -0
- empathy_llm_toolkit/agent_factory/memory_integration.py +324 -0
- empathy_llm_toolkit/agent_factory/resilient.py +320 -0
- empathy_llm_toolkit/cli/__init__.py +8 -0
- empathy_llm_toolkit/cli/sync_claude.py +487 -0
- empathy_llm_toolkit/code_health.py +150 -3
- empathy_llm_toolkit/config/__init__.py +29 -0
- empathy_llm_toolkit/config/unified.py +295 -0
- empathy_llm_toolkit/routing/__init__.py +32 -0
- empathy_llm_toolkit/routing/model_router.py +362 -0
- empathy_llm_toolkit/security/IMPLEMENTATION_SUMMARY.md +413 -0
- empathy_llm_toolkit/security/PHASE2_COMPLETE.md +384 -0
- empathy_llm_toolkit/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
- empathy_llm_toolkit/security/QUICK_REFERENCE.md +316 -0
- empathy_llm_toolkit/security/README.md +262 -0
- empathy_llm_toolkit/security/__init__.py +62 -0
- empathy_llm_toolkit/security/audit_logger.py +929 -0
- empathy_llm_toolkit/security/audit_logger_example.py +152 -0
- empathy_llm_toolkit/security/pii_scrubber.py +640 -0
- empathy_llm_toolkit/security/secrets_detector.py +678 -0
- empathy_llm_toolkit/security/secrets_detector_example.py +304 -0
- empathy_llm_toolkit/security/secure_memdocs.py +1192 -0
- empathy_llm_toolkit/security/secure_memdocs_example.py +278 -0
- empathy_llm_toolkit/wizards/__init__.py +38 -0
- empathy_llm_toolkit/wizards/base_wizard.py +364 -0
- empathy_llm_toolkit/wizards/customer_support_wizard.py +190 -0
- empathy_llm_toolkit/wizards/healthcare_wizard.py +362 -0
- empathy_llm_toolkit/wizards/patient_assessment_README.md +64 -0
- empathy_llm_toolkit/wizards/patient_assessment_wizard.py +193 -0
- empathy_llm_toolkit/wizards/technology_wizard.py +194 -0
- empathy_os/__init__.py +52 -52
- empathy_os/adaptive/__init__.py +13 -0
- empathy_os/adaptive/task_complexity.py +127 -0
- empathy_os/cli.py +118 -8
- empathy_os/cli_unified.py +121 -1
- empathy_os/config/__init__.py +63 -0
- empathy_os/config/xml_config.py +239 -0
- empathy_os/dashboard/__init__.py +15 -0
- empathy_os/dashboard/server.py +743 -0
- empathy_os/memory/__init__.py +195 -0
- empathy_os/memory/claude_memory.py +466 -0
- empathy_os/memory/config.py +224 -0
- empathy_os/memory/control_panel.py +1298 -0
- empathy_os/memory/edges.py +179 -0
- empathy_os/memory/graph.py +567 -0
- empathy_os/memory/long_term.py +1193 -0
- empathy_os/memory/nodes.py +179 -0
- empathy_os/memory/redis_bootstrap.py +540 -0
- empathy_os/memory/security/__init__.py +31 -0
- empathy_os/memory/security/audit_logger.py +930 -0
- empathy_os/memory/security/pii_scrubber.py +640 -0
- empathy_os/memory/security/secrets_detector.py +678 -0
- empathy_os/memory/short_term.py +2119 -0
- empathy_os/memory/storage/__init__.py +15 -0
- empathy_os/memory/summary_index.py +583 -0
- empathy_os/memory/unified.py +619 -0
- empathy_os/metrics/__init__.py +12 -0
- empathy_os/metrics/prompt_metrics.py +190 -0
- empathy_os/models/__init__.py +136 -0
- empathy_os/models/__main__.py +13 -0
- empathy_os/models/cli.py +655 -0
- empathy_os/models/empathy_executor.py +354 -0
- empathy_os/models/executor.py +252 -0
- empathy_os/models/fallback.py +671 -0
- empathy_os/models/provider_config.py +563 -0
- empathy_os/models/registry.py +382 -0
- empathy_os/models/tasks.py +302 -0
- empathy_os/models/telemetry.py +548 -0
- empathy_os/models/token_estimator.py +378 -0
- empathy_os/models/validation.py +274 -0
- empathy_os/monitoring/__init__.py +52 -0
- empathy_os/monitoring/alerts.py +23 -0
- empathy_os/monitoring/alerts_cli.py +268 -0
- empathy_os/monitoring/multi_backend.py +271 -0
- empathy_os/monitoring/otel_backend.py +363 -0
- empathy_os/optimization/__init__.py +19 -0
- empathy_os/optimization/context_optimizer.py +272 -0
- empathy_os/plugins/__init__.py +28 -0
- empathy_os/plugins/base.py +361 -0
- empathy_os/plugins/registry.py +268 -0
- empathy_os/project_index/__init__.py +30 -0
- empathy_os/project_index/cli.py +335 -0
- empathy_os/project_index/crew_integration.py +430 -0
- empathy_os/project_index/index.py +425 -0
- empathy_os/project_index/models.py +501 -0
- empathy_os/project_index/reports.py +473 -0
- empathy_os/project_index/scanner.py +538 -0
- empathy_os/prompts/__init__.py +61 -0
- empathy_os/prompts/config.py +77 -0
- empathy_os/prompts/context.py +177 -0
- empathy_os/prompts/parser.py +285 -0
- empathy_os/prompts/registry.py +313 -0
- empathy_os/prompts/templates.py +208 -0
- empathy_os/resilience/__init__.py +56 -0
- empathy_os/resilience/circuit_breaker.py +256 -0
- empathy_os/resilience/fallback.py +179 -0
- empathy_os/resilience/health.py +300 -0
- empathy_os/resilience/retry.py +209 -0
- empathy_os/resilience/timeout.py +135 -0
- empathy_os/routing/__init__.py +43 -0
- empathy_os/routing/chain_executor.py +433 -0
- empathy_os/routing/classifier.py +217 -0
- empathy_os/routing/smart_router.py +234 -0
- empathy_os/routing/wizard_registry.py +307 -0
- empathy_os/trust/__init__.py +28 -0
- empathy_os/trust/circuit_breaker.py +579 -0
- empathy_os/validation/__init__.py +19 -0
- empathy_os/validation/xml_validator.py +281 -0
- empathy_os/wizard_factory_cli.py +170 -0
- empathy_os/workflows/__init__.py +360 -0
- empathy_os/workflows/base.py +1530 -0
- empathy_os/workflows/bug_predict.py +962 -0
- empathy_os/workflows/code_review.py +960 -0
- empathy_os/workflows/code_review_adapters.py +310 -0
- empathy_os/workflows/code_review_pipeline.py +720 -0
- empathy_os/workflows/config.py +600 -0
- empathy_os/workflows/dependency_check.py +648 -0
- empathy_os/workflows/document_gen.py +1069 -0
- empathy_os/workflows/documentation_orchestrator.py +1205 -0
- empathy_os/workflows/health_check.py +679 -0
- empathy_os/workflows/keyboard_shortcuts/__init__.py +39 -0
- empathy_os/workflows/keyboard_shortcuts/generators.py +386 -0
- empathy_os/workflows/keyboard_shortcuts/parsers.py +414 -0
- empathy_os/workflows/keyboard_shortcuts/prompts.py +295 -0
- empathy_os/workflows/keyboard_shortcuts/schema.py +193 -0
- empathy_os/workflows/keyboard_shortcuts/workflow.py +505 -0
- empathy_os/workflows/manage_documentation.py +804 -0
- empathy_os/workflows/new_sample_workflow1.py +146 -0
- empathy_os/workflows/new_sample_workflow1_README.md +150 -0
- empathy_os/workflows/perf_audit.py +687 -0
- empathy_os/workflows/pr_review.py +748 -0
- empathy_os/workflows/progress.py +445 -0
- empathy_os/workflows/progress_server.py +322 -0
- empathy_os/workflows/refactor_plan.py +691 -0
- empathy_os/workflows/release_prep.py +808 -0
- empathy_os/workflows/research_synthesis.py +404 -0
- empathy_os/workflows/secure_release.py +585 -0
- empathy_os/workflows/security_adapters.py +297 -0
- empathy_os/workflows/security_audit.py +1050 -0
- empathy_os/workflows/step_config.py +234 -0
- empathy_os/workflows/test5.py +125 -0
- empathy_os/workflows/test5_README.md +158 -0
- empathy_os/workflows/test_gen.py +1855 -0
- empathy_os/workflows/test_lifecycle.py +526 -0
- empathy_os/workflows/test_maintenance.py +626 -0
- empathy_os/workflows/test_maintenance_cli.py +590 -0
- empathy_os/workflows/test_maintenance_crew.py +821 -0
- empathy_os/workflows/xml_enhanced_crew.py +285 -0
- empathy_software_plugin/cli/__init__.py +120 -0
- empathy_software_plugin/cli/inspect.py +362 -0
- empathy_software_plugin/cli.py +3 -1
- empathy_software_plugin/wizards/__init__.py +42 -0
- empathy_software_plugin/wizards/advanced_debugging_wizard.py +392 -0
- empathy_software_plugin/wizards/agent_orchestration_wizard.py +511 -0
- empathy_software_plugin/wizards/ai_collaboration_wizard.py +503 -0
- empathy_software_plugin/wizards/ai_context_wizard.py +441 -0
- empathy_software_plugin/wizards/ai_documentation_wizard.py +503 -0
- empathy_software_plugin/wizards/base_wizard.py +288 -0
- empathy_software_plugin/wizards/book_chapter_wizard.py +519 -0
- empathy_software_plugin/wizards/code_review_wizard.py +606 -0
- empathy_software_plugin/wizards/debugging/__init__.py +50 -0
- empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +414 -0
- empathy_software_plugin/wizards/debugging/config_loaders.py +442 -0
- empathy_software_plugin/wizards/debugging/fix_applier.py +469 -0
- empathy_software_plugin/wizards/debugging/language_patterns.py +383 -0
- empathy_software_plugin/wizards/debugging/linter_parsers.py +470 -0
- empathy_software_plugin/wizards/debugging/verification.py +369 -0
- empathy_software_plugin/wizards/enhanced_testing_wizard.py +537 -0
- empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +816 -0
- empathy_software_plugin/wizards/multi_model_wizard.py +501 -0
- empathy_software_plugin/wizards/pattern_extraction_wizard.py +422 -0
- empathy_software_plugin/wizards/pattern_retriever_wizard.py +400 -0
- empathy_software_plugin/wizards/performance/__init__.py +9 -0
- empathy_software_plugin/wizards/performance/bottleneck_detector.py +221 -0
- empathy_software_plugin/wizards/performance/profiler_parsers.py +278 -0
- empathy_software_plugin/wizards/performance/trajectory_analyzer.py +429 -0
- empathy_software_plugin/wizards/performance_profiling_wizard.py +305 -0
- empathy_software_plugin/wizards/prompt_engineering_wizard.py +425 -0
- empathy_software_plugin/wizards/rag_pattern_wizard.py +461 -0
- empathy_software_plugin/wizards/security/__init__.py +32 -0
- empathy_software_plugin/wizards/security/exploit_analyzer.py +290 -0
- empathy_software_plugin/wizards/security/owasp_patterns.py +241 -0
- empathy_software_plugin/wizards/security/vulnerability_scanner.py +604 -0
- empathy_software_plugin/wizards/security_analysis_wizard.py +322 -0
- empathy_software_plugin/wizards/security_learning_wizard.py +740 -0
- empathy_software_plugin/wizards/tech_debt_wizard.py +726 -0
- empathy_software_plugin/wizards/testing/__init__.py +27 -0
- empathy_software_plugin/wizards/testing/coverage_analyzer.py +459 -0
- empathy_software_plugin/wizards/testing/quality_analyzer.py +531 -0
- empathy_software_plugin/wizards/testing/test_suggester.py +533 -0
- empathy_software_plugin/wizards/testing_wizard.py +274 -0
- hot_reload/README.md +473 -0
- hot_reload/__init__.py +62 -0
- hot_reload/config.py +84 -0
- hot_reload/integration.py +228 -0
- hot_reload/reloader.py +298 -0
- hot_reload/watcher.py +179 -0
- hot_reload/websocket.py +176 -0
- scaffolding/README.md +589 -0
- scaffolding/__init__.py +35 -0
- scaffolding/__main__.py +14 -0
- scaffolding/cli.py +240 -0
- test_generator/__init__.py +38 -0
- test_generator/__main__.py +14 -0
- test_generator/cli.py +226 -0
- test_generator/generator.py +325 -0
- test_generator/risk_analyzer.py +216 -0
- workflow_patterns/__init__.py +33 -0
- workflow_patterns/behavior.py +249 -0
- workflow_patterns/core.py +76 -0
- workflow_patterns/output.py +99 -0
- workflow_patterns/registry.py +255 -0
- workflow_patterns/structural.py +288 -0
- workflow_scaffolding/__init__.py +11 -0
- workflow_scaffolding/__main__.py +12 -0
- workflow_scaffolding/cli.py +206 -0
- workflow_scaffolding/generator.py +265 -0
- agents/code_inspection/patterns/inspection/recurring_B112.json +0 -18
- agents/code_inspection/patterns/inspection/recurring_F541.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_FORMAT.json +0 -25
- agents/code_inspection/patterns/inspection/recurring_bug_20250822_def456.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20250915_abc123.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_3c5b9951.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_97c0f72f.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_a0871d53.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_20251212_a9b6ec41.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_bug_null_001.json +0 -16
- agents/code_inspection/patterns/inspection/recurring_builtin.json +0 -16
- agents/compliance_anticipation_agent.py +0 -1422
- agents/compliance_db.py +0 -339
- agents/epic_integration_wizard.py +0 -530
- agents/notifications.py +0 -291
- agents/trust_building_behaviors.py +0 -872
- empathy_framework-3.7.0.dist-info/RECORD +0 -105
- {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/WHEEL +0 -0
- {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/entry_points.txt +0 -0
- {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/licenses/LICENSE +0 -0
- /empathy_os/{monitoring.py → agent_monitoring.py} +0 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
"""Empathy Framework - Plugin System Base Classes
|
|
2
|
+
|
|
3
|
+
This module provides the core abstractions for creating domain-specific plugins
|
|
4
|
+
that extend the Empathy Framework.
|
|
5
|
+
|
|
6
|
+
Copyright 2025 Smart AI Memory, LLC
|
|
7
|
+
Licensed under Fair Source 0.9
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class PluginMetadata:
|
|
21
|
+
"""Metadata about a plugin"""
|
|
22
|
+
|
|
23
|
+
name: str
|
|
24
|
+
version: str
|
|
25
|
+
domain: str
|
|
26
|
+
description: str
|
|
27
|
+
author: str
|
|
28
|
+
license: str
|
|
29
|
+
requires_core_version: str # Minimum core framework version
|
|
30
|
+
dependencies: list[str] | None = None # Additional package dependencies
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class BaseWizard(ABC):
|
|
34
|
+
"""Universal base class for all wizards across all domains.
|
|
35
|
+
|
|
36
|
+
This replaces domain-specific base classes (BaseCoachWizard, etc.)
|
|
37
|
+
to provide a unified interface.
|
|
38
|
+
|
|
39
|
+
Design Philosophy:
|
|
40
|
+
- Domain-agnostic: Works for software, healthcare, finance, etc.
|
|
41
|
+
- Level-aware: Each wizard declares its empathy level
|
|
42
|
+
- Pattern-contributing: Wizards share learnings via pattern library
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self, name: str, domain: str, empathy_level: int, category: str | None = None):
|
|
46
|
+
"""Initialize a wizard
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
name: Human-readable wizard name
|
|
50
|
+
domain: Domain this wizard belongs to (e.g., 'software', 'healthcare')
|
|
51
|
+
empathy_level: Which empathy level this wizard operates at (1-5)
|
|
52
|
+
category: Optional category within domain
|
|
53
|
+
|
|
54
|
+
"""
|
|
55
|
+
self.name = name
|
|
56
|
+
self.domain = domain
|
|
57
|
+
self.empathy_level = empathy_level
|
|
58
|
+
self.category = category
|
|
59
|
+
self.logger = logging.getLogger(f"wizard.{domain}.{name}")
|
|
60
|
+
|
|
61
|
+
@abstractmethod
|
|
62
|
+
async def analyze(self, context: dict[str, Any]) -> dict[str, Any]:
|
|
63
|
+
"""Analyze the given context and return results.
|
|
64
|
+
|
|
65
|
+
This is the main entry point for all wizards. The context structure
|
|
66
|
+
is domain-specific but the return format should follow a standard pattern.
|
|
67
|
+
Subclasses must implement domain-specific analysis logic that aligns with
|
|
68
|
+
the wizard's empathy level.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
context: dict[str, Any]
|
|
72
|
+
Domain-specific context dictionary. Must contain all fields returned
|
|
73
|
+
by get_required_context(). Examples:
|
|
74
|
+
- Software: {'code': str, 'file_path': str, 'language': str}
|
|
75
|
+
- Healthcare: {'patient_id': str, 'vitals': dict, 'medications': list}
|
|
76
|
+
- Finance: {'transactions': list, 'account': dict, 'period': str}
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
dict[str, Any]
|
|
80
|
+
Analysis results dictionary containing:
|
|
81
|
+
- 'issues': list[dict] - Current issues found (Levels 1-3 analysis)
|
|
82
|
+
- 'predictions': list[dict] - Future issues predicted (Level 4 analysis)
|
|
83
|
+
- 'recommendations': list[dict] - Actionable next steps
|
|
84
|
+
- 'patterns': list[str] - Patterns detected for the pattern library
|
|
85
|
+
- 'confidence': float - Confidence score between 0.0 and 1.0
|
|
86
|
+
- 'wizard': str - Name of the wizard that performed analysis
|
|
87
|
+
- 'empathy_level': int - Empathy level of this analysis (1-5)
|
|
88
|
+
- 'timestamp': str - ISO format timestamp of analysis
|
|
89
|
+
|
|
90
|
+
Raises:
|
|
91
|
+
ValueError: If context is invalid or missing required fields
|
|
92
|
+
RuntimeError: If analysis fails due to domain-specific errors
|
|
93
|
+
TimeoutError: If analysis takes too long to complete
|
|
94
|
+
|
|
95
|
+
Note:
|
|
96
|
+
- Validate context using self.validate_context() at the beginning
|
|
97
|
+
- Each issue/prediction should include 'severity', 'description', 'affected_component'
|
|
98
|
+
- Use self.contribute_patterns() to extract learnings for the pattern library
|
|
99
|
+
- Confidence scores should reflect uncertainty in the analysis
|
|
100
|
+
- This method is async to support long-running analyses
|
|
101
|
+
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
@abstractmethod
|
|
105
|
+
def get_required_context(self) -> list[str]:
|
|
106
|
+
"""Declare what context fields this wizard needs.
|
|
107
|
+
|
|
108
|
+
This method defines the contract between the caller and the wizard.
|
|
109
|
+
The caller must provide all declared fields before calling analyze().
|
|
110
|
+
This enables validation via validate_context() and helps with introspection.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
list[str]
|
|
114
|
+
List of required context field names (keys). Each string should be
|
|
115
|
+
a simple identifier that matches the keys in context dictionaries
|
|
116
|
+
passed to analyze().
|
|
117
|
+
|
|
118
|
+
Examples:
|
|
119
|
+
Software wizard returns: ['code', 'file_path', 'language']
|
|
120
|
+
Healthcare wizard returns: ['patient_id', 'vitals', 'medications']
|
|
121
|
+
Finance wizard returns: ['transactions', 'account_id', 'period']
|
|
122
|
+
|
|
123
|
+
Note:
|
|
124
|
+
- Must return at least one field (even if minimal)
|
|
125
|
+
- Field names should match exactly what analyze() expects in context
|
|
126
|
+
- Order is not significant but consistency helps with documentation
|
|
127
|
+
- Consider validation requirements when declaring fields
|
|
128
|
+
- Used by validate_context() to check required fields before analyze()
|
|
129
|
+
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
def validate_context(self, context: dict[str, Any]) -> bool:
|
|
133
|
+
"""Validate that context contains required fields.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
context: Context to validate
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
True if valid, raises ValueError if invalid
|
|
140
|
+
|
|
141
|
+
"""
|
|
142
|
+
required = self.get_required_context()
|
|
143
|
+
missing = [key for key in required if key not in context]
|
|
144
|
+
|
|
145
|
+
if missing:
|
|
146
|
+
raise ValueError(f"Wizard '{self.name}' missing required context: {missing}")
|
|
147
|
+
|
|
148
|
+
return True
|
|
149
|
+
|
|
150
|
+
def get_empathy_level(self) -> int:
|
|
151
|
+
"""Get the empathy level this wizard operates at"""
|
|
152
|
+
return self.empathy_level
|
|
153
|
+
|
|
154
|
+
def contribute_patterns(self, analysis_result: dict[str, Any]) -> dict[str, Any]:
|
|
155
|
+
"""Extract patterns from analysis for the shared pattern library.
|
|
156
|
+
|
|
157
|
+
This enables cross-domain learning (Level 5 Systems Empathy).
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
analysis_result: Result from analyze()
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
Dictionary of patterns in standard format
|
|
164
|
+
|
|
165
|
+
"""
|
|
166
|
+
# Default implementation - override for custom pattern extraction
|
|
167
|
+
return {
|
|
168
|
+
"wizard": self.name,
|
|
169
|
+
"domain": self.domain,
|
|
170
|
+
"timestamp": datetime.now().isoformat(),
|
|
171
|
+
"patterns": analysis_result.get("patterns", []),
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class BasePlugin(ABC):
|
|
176
|
+
"""Base class for domain plugins.
|
|
177
|
+
|
|
178
|
+
A plugin is a collection of wizards and patterns for a specific domain.
|
|
179
|
+
|
|
180
|
+
Example:
|
|
181
|
+
- SoftwarePlugin: 16+ coach wizards for code analysis
|
|
182
|
+
- HealthcarePlugin: Clinical and compliance wizards
|
|
183
|
+
- FinancePlugin: Fraud detection, compliance wizards
|
|
184
|
+
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
def __init__(self):
|
|
188
|
+
self.logger = logging.getLogger(f"plugin.{self.get_metadata().domain}")
|
|
189
|
+
self._wizards: dict[str, type[BaseWizard]] = {}
|
|
190
|
+
self._initialized = False
|
|
191
|
+
|
|
192
|
+
@abstractmethod
|
|
193
|
+
def get_metadata(self) -> PluginMetadata:
|
|
194
|
+
"""Return metadata about this plugin.
|
|
195
|
+
|
|
196
|
+
This method provides essential information about the plugin that the
|
|
197
|
+
framework uses for loading, validation, and discovery. It must return
|
|
198
|
+
consistent metadata across multiple calls.
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
PluginMetadata
|
|
202
|
+
A PluginMetadata instance containing:
|
|
203
|
+
- name: str - Human-readable plugin name (e.g., 'Software Plugin')
|
|
204
|
+
- version: str - Semantic version string (e.g., '1.0.0')
|
|
205
|
+
- domain: str - Domain this plugin serves (e.g., 'software', 'healthcare')
|
|
206
|
+
- description: str - Brief description of plugin functionality
|
|
207
|
+
- author: str - Plugin author or organization name
|
|
208
|
+
- license: str - License identifier (e.g., 'Apache-2.0', 'MIT')
|
|
209
|
+
- requires_core_version: str - Minimum core framework version (e.g., '1.0.0')
|
|
210
|
+
- dependencies: list[str] - Optional list of required packages
|
|
211
|
+
|
|
212
|
+
Note:
|
|
213
|
+
- Called during plugin initialization to validate compatibility
|
|
214
|
+
- Used for plugin discovery and listing
|
|
215
|
+
- Should be immutable (return same values each call)
|
|
216
|
+
- Version should follow semantic versioning
|
|
217
|
+
- Domain names should be lowercase and consistent across plugins
|
|
218
|
+
- Core version requirement ensures framework compatibility
|
|
219
|
+
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
@abstractmethod
|
|
223
|
+
def register_wizards(self) -> dict[str, type[BaseWizard]]:
|
|
224
|
+
"""Register all wizards provided by this plugin.
|
|
225
|
+
|
|
226
|
+
This method defines all analysis wizards available in this plugin.
|
|
227
|
+
Wizards are lazy-instantiated by get_wizard() when first requested.
|
|
228
|
+
This method is called during plugin initialization.
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
dict[str, type[BaseWizard]]
|
|
232
|
+
Dictionary mapping wizard identifiers to Wizard classes (not instances).
|
|
233
|
+
Keys should be lowercase, snake_case identifiers. Values should be
|
|
234
|
+
uninstantiated class references.
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
dict[str, type[BaseWizard]]
|
|
238
|
+
Mapping structure:
|
|
239
|
+
{
|
|
240
|
+
'wizard_id': WizardClass,
|
|
241
|
+
'another_wizard': AnotherWizardClass,
|
|
242
|
+
...
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
Example:
|
|
246
|
+
Software plugin might return:
|
|
247
|
+
{
|
|
248
|
+
'security': SecurityWizard,
|
|
249
|
+
'performance': PerformanceWizard,
|
|
250
|
+
'maintainability': MaintainabilityWizard,
|
|
251
|
+
'accessibility': AccessibilityWizard,
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
Note:
|
|
255
|
+
- Return only the class, not instances (instantiation is lazy)
|
|
256
|
+
- Use consistent, descriptive wizard IDs
|
|
257
|
+
- All returned classes must be subclasses of BaseWizard
|
|
258
|
+
- Can return empty dict {} if plugin provides no wizards initially
|
|
259
|
+
- Called once during initialization via initialize()
|
|
260
|
+
- Framework caches results in self._wizards
|
|
261
|
+
|
|
262
|
+
"""
|
|
263
|
+
|
|
264
|
+
def register_patterns(self) -> dict[str, Any]:
|
|
265
|
+
"""Register domain-specific patterns for the pattern library.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
Dictionary of patterns in standard format
|
|
269
|
+
|
|
270
|
+
"""
|
|
271
|
+
# Optional - override if plugin provides pre-built patterns
|
|
272
|
+
return {}
|
|
273
|
+
|
|
274
|
+
def initialize(self) -> None:
|
|
275
|
+
"""Initialize the plugin (lazy initialization).
|
|
276
|
+
|
|
277
|
+
Called once before first use. Override to perform setup:
|
|
278
|
+
- Load configuration
|
|
279
|
+
- Initialize domain-specific services
|
|
280
|
+
- Validate dependencies
|
|
281
|
+
"""
|
|
282
|
+
if self._initialized:
|
|
283
|
+
return
|
|
284
|
+
|
|
285
|
+
self.logger.info(f"Initializing plugin: {self.get_metadata().name}")
|
|
286
|
+
|
|
287
|
+
# Register wizards
|
|
288
|
+
self._wizards = self.register_wizards()
|
|
289
|
+
|
|
290
|
+
self.logger.info(
|
|
291
|
+
f"Plugin '{self.get_metadata().name}' initialized with {len(self._wizards)} wizards",
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
self._initialized = True
|
|
295
|
+
|
|
296
|
+
def get_wizard(self, wizard_id: str) -> type[BaseWizard] | None:
|
|
297
|
+
"""Get a wizard by ID.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
wizard_id: Wizard identifier
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
Wizard class or None if not found
|
|
304
|
+
|
|
305
|
+
"""
|
|
306
|
+
if not self._initialized:
|
|
307
|
+
self.initialize()
|
|
308
|
+
|
|
309
|
+
return self._wizards.get(wizard_id)
|
|
310
|
+
|
|
311
|
+
def list_wizards(self) -> list[str]:
|
|
312
|
+
"""List all wizard IDs provided by this plugin.
|
|
313
|
+
|
|
314
|
+
Returns:
|
|
315
|
+
List of wizard identifiers
|
|
316
|
+
|
|
317
|
+
"""
|
|
318
|
+
if not self._initialized:
|
|
319
|
+
self.initialize()
|
|
320
|
+
|
|
321
|
+
return list(self._wizards.keys())
|
|
322
|
+
|
|
323
|
+
def get_wizard_info(self, wizard_id: str) -> dict[str, Any] | None:
|
|
324
|
+
"""Get information about a wizard without instantiating it.
|
|
325
|
+
|
|
326
|
+
Args:
|
|
327
|
+
wizard_id: Wizard identifier
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
Dictionary with wizard metadata
|
|
331
|
+
|
|
332
|
+
"""
|
|
333
|
+
wizard_class = self.get_wizard(wizard_id)
|
|
334
|
+
if not wizard_class:
|
|
335
|
+
return None
|
|
336
|
+
|
|
337
|
+
# Create temporary instance to get metadata
|
|
338
|
+
# (wizards should be lightweight to construct)
|
|
339
|
+
# Subclasses provide their own defaults for name, domain, empathy_level
|
|
340
|
+
temp_instance = wizard_class() # type: ignore[call-arg]
|
|
341
|
+
|
|
342
|
+
return {
|
|
343
|
+
"id": wizard_id,
|
|
344
|
+
"name": temp_instance.name,
|
|
345
|
+
"domain": temp_instance.domain,
|
|
346
|
+
"empathy_level": temp_instance.empathy_level,
|
|
347
|
+
"category": temp_instance.category,
|
|
348
|
+
"required_context": temp_instance.get_required_context(),
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
class PluginError(Exception):
|
|
353
|
+
"""Base exception for plugin-related errors"""
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
class PluginLoadError(PluginError):
|
|
357
|
+
"""Raised when plugin fails to load"""
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
class PluginValidationError(PluginError):
|
|
361
|
+
"""Raised when plugin fails validation"""
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"""Empathy Framework - Plugin Registry
|
|
2
|
+
|
|
3
|
+
Auto-discovery and management of domain plugins.
|
|
4
|
+
|
|
5
|
+
Copyright 2025 Smart AI Memory, LLC
|
|
6
|
+
Licensed under Fair Source 0.9
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
from importlib.metadata import entry_points
|
|
11
|
+
|
|
12
|
+
from .base import BasePlugin, BaseWizard, PluginValidationError
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class PluginRegistry:
|
|
18
|
+
"""Central registry for managing domain plugins.
|
|
19
|
+
|
|
20
|
+
Features:
|
|
21
|
+
- Auto-discovery via entry points
|
|
22
|
+
- Manual registration
|
|
23
|
+
- Lazy initialization
|
|
24
|
+
- Graceful degradation (missing plugins don't crash)
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self):
|
|
28
|
+
self._plugins: dict[str, BasePlugin] = {}
|
|
29
|
+
self._auto_discovered = False
|
|
30
|
+
self.logger = logging.getLogger("empathy.plugins.registry")
|
|
31
|
+
|
|
32
|
+
def auto_discover(self) -> None:
|
|
33
|
+
"""Automatically discover plugins via entry points.
|
|
34
|
+
|
|
35
|
+
Plugins register themselves in setup.py/pyproject.toml:
|
|
36
|
+
|
|
37
|
+
[project.entry-points."empathy_framework.plugins"]
|
|
38
|
+
software = "empathy_software.plugin:SoftwarePlugin"
|
|
39
|
+
healthcare = "empathy_healthcare.plugin:HealthcarePlugin"
|
|
40
|
+
"""
|
|
41
|
+
if self._auto_discovered:
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
self.logger.info("Auto-discovering plugins...")
|
|
45
|
+
|
|
46
|
+
# Python 3.10+ has modern entry_points API with group parameter
|
|
47
|
+
discovered = entry_points(group="empathy_framework.plugins")
|
|
48
|
+
|
|
49
|
+
for ep in discovered:
|
|
50
|
+
try:
|
|
51
|
+
self.logger.info(f"Loading plugin '{ep.name}' from entry point")
|
|
52
|
+
plugin_class = ep.load()
|
|
53
|
+
plugin_instance = plugin_class()
|
|
54
|
+
self.register_plugin(ep.name, plugin_instance)
|
|
55
|
+
self.logger.info(f"Successfully loaded plugin: {ep.name}")
|
|
56
|
+
except Exception as e:
|
|
57
|
+
# Graceful degradation: log but don't crash
|
|
58
|
+
self.logger.warning(f"Failed to load plugin '{ep.name}': {e}", exc_info=True)
|
|
59
|
+
|
|
60
|
+
self._auto_discovered = True
|
|
61
|
+
self.logger.info(f"Auto-discovery complete. {len(self._plugins)} plugins loaded.")
|
|
62
|
+
|
|
63
|
+
def register_plugin(self, name: str, plugin: BasePlugin) -> None:
|
|
64
|
+
"""Manually register a plugin.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
name: Plugin identifier (e.g., 'software', 'healthcare')
|
|
68
|
+
plugin: Plugin instance
|
|
69
|
+
|
|
70
|
+
Raises:
|
|
71
|
+
PluginValidationError: If plugin is invalid
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
# Validate plugin
|
|
75
|
+
try:
|
|
76
|
+
metadata = plugin.get_metadata()
|
|
77
|
+
if not metadata.name:
|
|
78
|
+
raise PluginValidationError("Plugin metadata missing 'name'")
|
|
79
|
+
if not metadata.domain:
|
|
80
|
+
raise PluginValidationError("Plugin metadata missing 'domain'")
|
|
81
|
+
except Exception as e:
|
|
82
|
+
raise PluginValidationError(f"Invalid plugin metadata: {e}") from e
|
|
83
|
+
|
|
84
|
+
# Register
|
|
85
|
+
self._plugins[name] = plugin
|
|
86
|
+
self.logger.info(
|
|
87
|
+
f"Registered plugin '{name}' (domain: {metadata.domain}, version: {metadata.version})",
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
def get_plugin(self, name: str) -> BasePlugin | None:
|
|
91
|
+
"""Get a plugin by name.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
name: Plugin identifier
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
Plugin instance or None if not found
|
|
98
|
+
|
|
99
|
+
"""
|
|
100
|
+
if not self._auto_discovered:
|
|
101
|
+
self.auto_discover()
|
|
102
|
+
|
|
103
|
+
plugin = self._plugins.get(name)
|
|
104
|
+
if plugin and not plugin._initialized:
|
|
105
|
+
plugin.initialize()
|
|
106
|
+
|
|
107
|
+
return plugin
|
|
108
|
+
|
|
109
|
+
def list_plugins(self) -> list[str]:
|
|
110
|
+
"""List all registered plugin names.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
List of plugin identifiers
|
|
114
|
+
|
|
115
|
+
"""
|
|
116
|
+
if not self._auto_discovered:
|
|
117
|
+
self.auto_discover()
|
|
118
|
+
|
|
119
|
+
return list(self._plugins.keys())
|
|
120
|
+
|
|
121
|
+
def list_all_wizards(self) -> dict[str, list[str]]:
|
|
122
|
+
"""List all wizards from all plugins.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Dictionary mapping plugin_name -> list of wizard_ids
|
|
126
|
+
|
|
127
|
+
"""
|
|
128
|
+
if not self._auto_discovered:
|
|
129
|
+
self.auto_discover()
|
|
130
|
+
|
|
131
|
+
result = {}
|
|
132
|
+
for plugin_name, plugin in self._plugins.items():
|
|
133
|
+
result[plugin_name] = plugin.list_wizards()
|
|
134
|
+
|
|
135
|
+
return result
|
|
136
|
+
|
|
137
|
+
def get_wizard(self, plugin_name: str, wizard_id: str) -> type[BaseWizard] | None:
|
|
138
|
+
"""Get a wizard from a specific plugin.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
plugin_name: Plugin identifier
|
|
142
|
+
wizard_id: Wizard identifier within plugin
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
Wizard class or None if not found
|
|
146
|
+
|
|
147
|
+
"""
|
|
148
|
+
plugin = self.get_plugin(plugin_name)
|
|
149
|
+
if not plugin:
|
|
150
|
+
self.logger.warning(f"Plugin '{plugin_name}' not found")
|
|
151
|
+
return None
|
|
152
|
+
|
|
153
|
+
return plugin.get_wizard(wizard_id)
|
|
154
|
+
|
|
155
|
+
def get_wizard_info(self, plugin_name: str, wizard_id: str) -> dict | None:
|
|
156
|
+
"""Get information about a wizard.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
plugin_name: Plugin identifier
|
|
160
|
+
wizard_id: Wizard identifier
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
Dictionary with wizard metadata or None
|
|
164
|
+
|
|
165
|
+
"""
|
|
166
|
+
plugin = self.get_plugin(plugin_name)
|
|
167
|
+
if not plugin:
|
|
168
|
+
return None
|
|
169
|
+
|
|
170
|
+
return plugin.get_wizard_info(wizard_id)
|
|
171
|
+
|
|
172
|
+
def find_wizards_by_level(self, empathy_level: int) -> list[dict]:
|
|
173
|
+
"""Find all wizards operating at a specific empathy level.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
empathy_level: Target empathy level (1-5)
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
List of wizard info dictionaries
|
|
180
|
+
|
|
181
|
+
"""
|
|
182
|
+
if not self._auto_discovered:
|
|
183
|
+
self.auto_discover()
|
|
184
|
+
|
|
185
|
+
results = []
|
|
186
|
+
for plugin_name, plugin in self._plugins.items():
|
|
187
|
+
for wizard_id in plugin.list_wizards():
|
|
188
|
+
info = plugin.get_wizard_info(wizard_id)
|
|
189
|
+
if info and info.get("empathy_level") == empathy_level:
|
|
190
|
+
info["plugin"] = plugin_name
|
|
191
|
+
results.append(info)
|
|
192
|
+
|
|
193
|
+
return results
|
|
194
|
+
|
|
195
|
+
def find_wizards_by_domain(self, domain: str) -> list[dict]:
|
|
196
|
+
"""Find all wizards for a specific domain.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
domain: Domain identifier (e.g., 'software', 'healthcare')
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
List of wizard info dictionaries
|
|
203
|
+
|
|
204
|
+
"""
|
|
205
|
+
if not self._auto_discovered:
|
|
206
|
+
self.auto_discover()
|
|
207
|
+
|
|
208
|
+
results = []
|
|
209
|
+
for plugin_name, plugin in self._plugins.items():
|
|
210
|
+
metadata = plugin.get_metadata()
|
|
211
|
+
if metadata.domain == domain:
|
|
212
|
+
for wizard_id in plugin.list_wizards():
|
|
213
|
+
info = plugin.get_wizard_info(wizard_id)
|
|
214
|
+
if info:
|
|
215
|
+
info["plugin"] = plugin_name
|
|
216
|
+
results.append(info)
|
|
217
|
+
|
|
218
|
+
return results
|
|
219
|
+
|
|
220
|
+
def get_statistics(self) -> dict:
|
|
221
|
+
"""Get registry statistics.
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
Dictionary with counts and metadata
|
|
225
|
+
|
|
226
|
+
"""
|
|
227
|
+
if not self._auto_discovered:
|
|
228
|
+
self.auto_discover()
|
|
229
|
+
|
|
230
|
+
total_wizards = sum(len(plugin.list_wizards()) for plugin in self._plugins.values())
|
|
231
|
+
|
|
232
|
+
# Count wizards by level
|
|
233
|
+
wizards_by_level = {}
|
|
234
|
+
for level in range(1, 6):
|
|
235
|
+
wizards_by_level[f"level_{level}"] = len(self.find_wizards_by_level(level))
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
"total_plugins": len(self._plugins),
|
|
239
|
+
"total_wizards": total_wizards,
|
|
240
|
+
"plugins": [
|
|
241
|
+
{
|
|
242
|
+
"name": name,
|
|
243
|
+
"domain": plugin.get_metadata().domain,
|
|
244
|
+
"version": plugin.get_metadata().version,
|
|
245
|
+
"wizard_count": len(plugin.list_wizards()),
|
|
246
|
+
}
|
|
247
|
+
for name, plugin in self._plugins.items()
|
|
248
|
+
],
|
|
249
|
+
"wizards_by_level": wizards_by_level,
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
# Global registry instance
|
|
254
|
+
_global_registry: PluginRegistry | None = None
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def get_global_registry() -> PluginRegistry:
|
|
258
|
+
"""Get the global plugin registry instance (singleton).
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
Global PluginRegistry instance
|
|
262
|
+
|
|
263
|
+
"""
|
|
264
|
+
global _global_registry
|
|
265
|
+
if _global_registry is None:
|
|
266
|
+
_global_registry = PluginRegistry()
|
|
267
|
+
_global_registry.auto_discover()
|
|
268
|
+
return _global_registry
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Project Index - Codebase Intelligence Layer
|
|
2
|
+
|
|
3
|
+
Tracks metadata about all files in a project to enable:
|
|
4
|
+
- Test coverage gap analysis
|
|
5
|
+
- Staleness detection (code changed, tests didn't)
|
|
6
|
+
- Dependency mapping
|
|
7
|
+
- Project health reports
|
|
8
|
+
- Workflow intelligence
|
|
9
|
+
|
|
10
|
+
Storage:
|
|
11
|
+
- Primary: .empathy/project_index.json
|
|
12
|
+
- Real-time: Redis (when short-term memory enabled)
|
|
13
|
+
|
|
14
|
+
Copyright 2025 Smart AI Memory, LLC
|
|
15
|
+
Licensed under Fair Source 0.9
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from .index import ProjectIndex
|
|
19
|
+
from .models import FileRecord, IndexConfig, ProjectSummary
|
|
20
|
+
from .reports import ReportGenerator
|
|
21
|
+
from .scanner import ProjectScanner
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"FileRecord",
|
|
25
|
+
"IndexConfig",
|
|
26
|
+
"ProjectIndex",
|
|
27
|
+
"ProjectScanner",
|
|
28
|
+
"ProjectSummary",
|
|
29
|
+
"ReportGenerator",
|
|
30
|
+
]
|