attune-ai 2.0.0__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.
- attune/__init__.py +358 -0
- attune/adaptive/__init__.py +13 -0
- attune/adaptive/task_complexity.py +127 -0
- attune/agent_monitoring.py +414 -0
- attune/cache/__init__.py +117 -0
- attune/cache/base.py +166 -0
- attune/cache/dependency_manager.py +256 -0
- attune/cache/hash_only.py +251 -0
- attune/cache/hybrid.py +457 -0
- attune/cache/storage.py +285 -0
- attune/cache_monitor.py +356 -0
- attune/cache_stats.py +298 -0
- attune/cli/__init__.py +152 -0
- attune/cli/__main__.py +12 -0
- attune/cli/commands/__init__.py +1 -0
- attune/cli/commands/batch.py +264 -0
- attune/cli/commands/cache.py +248 -0
- attune/cli/commands/help.py +331 -0
- attune/cli/commands/info.py +140 -0
- attune/cli/commands/inspect.py +436 -0
- attune/cli/commands/inspection.py +57 -0
- attune/cli/commands/memory.py +48 -0
- attune/cli/commands/metrics.py +92 -0
- attune/cli/commands/orchestrate.py +184 -0
- attune/cli/commands/patterns.py +207 -0
- attune/cli/commands/profiling.py +202 -0
- attune/cli/commands/provider.py +98 -0
- attune/cli/commands/routing.py +285 -0
- attune/cli/commands/setup.py +96 -0
- attune/cli/commands/status.py +235 -0
- attune/cli/commands/sync.py +166 -0
- attune/cli/commands/tier.py +121 -0
- attune/cli/commands/utilities.py +114 -0
- attune/cli/commands/workflow.py +579 -0
- attune/cli/core.py +32 -0
- attune/cli/parsers/__init__.py +68 -0
- attune/cli/parsers/batch.py +118 -0
- attune/cli/parsers/cache.py +65 -0
- attune/cli/parsers/help.py +41 -0
- attune/cli/parsers/info.py +26 -0
- attune/cli/parsers/inspect.py +66 -0
- attune/cli/parsers/metrics.py +42 -0
- attune/cli/parsers/orchestrate.py +61 -0
- attune/cli/parsers/patterns.py +54 -0
- attune/cli/parsers/provider.py +40 -0
- attune/cli/parsers/routing.py +110 -0
- attune/cli/parsers/setup.py +42 -0
- attune/cli/parsers/status.py +47 -0
- attune/cli/parsers/sync.py +31 -0
- attune/cli/parsers/tier.py +33 -0
- attune/cli/parsers/workflow.py +77 -0
- attune/cli/utils/__init__.py +1 -0
- attune/cli/utils/data.py +242 -0
- attune/cli/utils/helpers.py +68 -0
- attune/cli_legacy.py +3957 -0
- attune/cli_minimal.py +1159 -0
- attune/cli_router.py +437 -0
- attune/cli_unified.py +814 -0
- attune/config/__init__.py +66 -0
- attune/config/xml_config.py +286 -0
- attune/config.py +545 -0
- attune/coordination.py +870 -0
- attune/core.py +1511 -0
- attune/core_modules/__init__.py +15 -0
- attune/cost_tracker.py +626 -0
- attune/dashboard/__init__.py +41 -0
- attune/dashboard/app.py +512 -0
- attune/dashboard/simple_server.py +435 -0
- attune/dashboard/standalone_server.py +547 -0
- attune/discovery.py +306 -0
- attune/emergence.py +306 -0
- attune/exceptions.py +123 -0
- attune/feedback_loops.py +373 -0
- attune/hot_reload/README.md +473 -0
- attune/hot_reload/__init__.py +62 -0
- attune/hot_reload/config.py +83 -0
- attune/hot_reload/integration.py +229 -0
- attune/hot_reload/reloader.py +298 -0
- attune/hot_reload/watcher.py +183 -0
- attune/hot_reload/websocket.py +177 -0
- attune/levels.py +577 -0
- attune/leverage_points.py +441 -0
- attune/logging_config.py +261 -0
- attune/mcp/__init__.py +10 -0
- attune/mcp/server.py +506 -0
- attune/memory/__init__.py +237 -0
- attune/memory/claude_memory.py +469 -0
- attune/memory/config.py +224 -0
- attune/memory/control_panel.py +1290 -0
- attune/memory/control_panel_support.py +145 -0
- attune/memory/cross_session.py +845 -0
- attune/memory/edges.py +179 -0
- attune/memory/encryption.py +159 -0
- attune/memory/file_session.py +770 -0
- attune/memory/graph.py +570 -0
- attune/memory/long_term.py +913 -0
- attune/memory/long_term_types.py +99 -0
- attune/memory/mixins/__init__.py +25 -0
- attune/memory/mixins/backend_init_mixin.py +249 -0
- attune/memory/mixins/capabilities_mixin.py +208 -0
- attune/memory/mixins/handoff_mixin.py +208 -0
- attune/memory/mixins/lifecycle_mixin.py +49 -0
- attune/memory/mixins/long_term_mixin.py +352 -0
- attune/memory/mixins/promotion_mixin.py +109 -0
- attune/memory/mixins/short_term_mixin.py +182 -0
- attune/memory/nodes.py +179 -0
- attune/memory/redis_bootstrap.py +540 -0
- attune/memory/security/__init__.py +31 -0
- attune/memory/security/audit_logger.py +932 -0
- attune/memory/security/pii_scrubber.py +640 -0
- attune/memory/security/secrets_detector.py +678 -0
- attune/memory/short_term.py +2192 -0
- attune/memory/simple_storage.py +302 -0
- attune/memory/storage/__init__.py +15 -0
- attune/memory/storage_backend.py +167 -0
- attune/memory/summary_index.py +583 -0
- attune/memory/types.py +446 -0
- attune/memory/unified.py +182 -0
- attune/meta_workflows/__init__.py +74 -0
- attune/meta_workflows/agent_creator.py +248 -0
- attune/meta_workflows/builtin_templates.py +567 -0
- attune/meta_workflows/cli_commands/__init__.py +56 -0
- attune/meta_workflows/cli_commands/agent_commands.py +321 -0
- attune/meta_workflows/cli_commands/analytics_commands.py +442 -0
- attune/meta_workflows/cli_commands/config_commands.py +232 -0
- attune/meta_workflows/cli_commands/memory_commands.py +182 -0
- attune/meta_workflows/cli_commands/template_commands.py +354 -0
- attune/meta_workflows/cli_commands/workflow_commands.py +382 -0
- attune/meta_workflows/cli_meta_workflows.py +59 -0
- attune/meta_workflows/form_engine.py +292 -0
- attune/meta_workflows/intent_detector.py +409 -0
- attune/meta_workflows/models.py +569 -0
- attune/meta_workflows/pattern_learner.py +738 -0
- attune/meta_workflows/plan_generator.py +384 -0
- attune/meta_workflows/session_context.py +397 -0
- attune/meta_workflows/template_registry.py +229 -0
- attune/meta_workflows/workflow.py +984 -0
- attune/metrics/__init__.py +12 -0
- attune/metrics/collector.py +31 -0
- attune/metrics/prompt_metrics.py +194 -0
- attune/models/__init__.py +172 -0
- attune/models/__main__.py +13 -0
- attune/models/adaptive_routing.py +437 -0
- attune/models/auth_cli.py +444 -0
- attune/models/auth_strategy.py +450 -0
- attune/models/cli.py +655 -0
- attune/models/empathy_executor.py +354 -0
- attune/models/executor.py +257 -0
- attune/models/fallback.py +762 -0
- attune/models/provider_config.py +282 -0
- attune/models/registry.py +472 -0
- attune/models/tasks.py +359 -0
- attune/models/telemetry/__init__.py +71 -0
- attune/models/telemetry/analytics.py +594 -0
- attune/models/telemetry/backend.py +196 -0
- attune/models/telemetry/data_models.py +431 -0
- attune/models/telemetry/storage.py +489 -0
- attune/models/token_estimator.py +420 -0
- attune/models/validation.py +280 -0
- attune/monitoring/__init__.py +52 -0
- attune/monitoring/alerts.py +946 -0
- attune/monitoring/alerts_cli.py +448 -0
- attune/monitoring/multi_backend.py +271 -0
- attune/monitoring/otel_backend.py +362 -0
- attune/optimization/__init__.py +19 -0
- attune/optimization/context_optimizer.py +272 -0
- attune/orchestration/__init__.py +67 -0
- attune/orchestration/agent_templates.py +707 -0
- attune/orchestration/config_store.py +499 -0
- attune/orchestration/execution_strategies.py +2111 -0
- attune/orchestration/meta_orchestrator.py +1168 -0
- attune/orchestration/pattern_learner.py +696 -0
- attune/orchestration/real_tools.py +931 -0
- attune/pattern_cache.py +187 -0
- attune/pattern_library.py +542 -0
- attune/patterns/debugging/all_patterns.json +81 -0
- attune/patterns/debugging/workflow_20260107_1770825e.json +77 -0
- attune/patterns/refactoring_memory.json +89 -0
- attune/persistence.py +564 -0
- attune/platform_utils.py +265 -0
- attune/plugins/__init__.py +28 -0
- attune/plugins/base.py +361 -0
- attune/plugins/registry.py +268 -0
- attune/project_index/__init__.py +32 -0
- attune/project_index/cli.py +335 -0
- attune/project_index/index.py +667 -0
- attune/project_index/models.py +504 -0
- attune/project_index/reports.py +474 -0
- attune/project_index/scanner.py +777 -0
- attune/project_index/scanner_parallel.py +291 -0
- attune/prompts/__init__.py +61 -0
- attune/prompts/config.py +77 -0
- attune/prompts/context.py +177 -0
- attune/prompts/parser.py +285 -0
- attune/prompts/registry.py +313 -0
- attune/prompts/templates.py +208 -0
- attune/redis_config.py +302 -0
- attune/redis_memory.py +799 -0
- attune/resilience/__init__.py +56 -0
- attune/resilience/circuit_breaker.py +256 -0
- attune/resilience/fallback.py +179 -0
- attune/resilience/health.py +300 -0
- attune/resilience/retry.py +209 -0
- attune/resilience/timeout.py +135 -0
- attune/routing/__init__.py +43 -0
- attune/routing/chain_executor.py +433 -0
- attune/routing/classifier.py +217 -0
- attune/routing/smart_router.py +234 -0
- attune/routing/workflow_registry.py +343 -0
- attune/scaffolding/README.md +589 -0
- attune/scaffolding/__init__.py +35 -0
- attune/scaffolding/__main__.py +14 -0
- attune/scaffolding/cli.py +240 -0
- attune/scaffolding/templates/base_wizard.py.jinja2 +121 -0
- attune/scaffolding/templates/coach_wizard.py.jinja2 +321 -0
- attune/scaffolding/templates/domain_wizard.py.jinja2 +408 -0
- attune/scaffolding/templates/linear_flow_wizard.py.jinja2 +203 -0
- attune/socratic/__init__.py +256 -0
- attune/socratic/ab_testing.py +958 -0
- attune/socratic/blueprint.py +533 -0
- attune/socratic/cli.py +703 -0
- attune/socratic/collaboration.py +1114 -0
- attune/socratic/domain_templates.py +924 -0
- attune/socratic/embeddings.py +738 -0
- attune/socratic/engine.py +794 -0
- attune/socratic/explainer.py +682 -0
- attune/socratic/feedback.py +772 -0
- attune/socratic/forms.py +629 -0
- attune/socratic/generator.py +732 -0
- attune/socratic/llm_analyzer.py +637 -0
- attune/socratic/mcp_server.py +702 -0
- attune/socratic/session.py +312 -0
- attune/socratic/storage.py +667 -0
- attune/socratic/success.py +730 -0
- attune/socratic/visual_editor.py +860 -0
- attune/socratic/web_ui.py +958 -0
- attune/telemetry/__init__.py +39 -0
- attune/telemetry/agent_coordination.py +475 -0
- attune/telemetry/agent_tracking.py +367 -0
- attune/telemetry/approval_gates.py +545 -0
- attune/telemetry/cli.py +1231 -0
- attune/telemetry/commands/__init__.py +14 -0
- attune/telemetry/commands/dashboard_commands.py +696 -0
- attune/telemetry/event_streaming.py +409 -0
- attune/telemetry/feedback_loop.py +567 -0
- attune/telemetry/usage_tracker.py +591 -0
- attune/templates.py +754 -0
- attune/test_generator/__init__.py +38 -0
- attune/test_generator/__main__.py +14 -0
- attune/test_generator/cli.py +234 -0
- attune/test_generator/generator.py +355 -0
- attune/test_generator/risk_analyzer.py +216 -0
- attune/test_generator/templates/unit_test.py.jinja2 +272 -0
- attune/tier_recommender.py +384 -0
- attune/tools.py +183 -0
- attune/trust/__init__.py +28 -0
- attune/trust/circuit_breaker.py +579 -0
- attune/trust_building.py +527 -0
- attune/validation/__init__.py +19 -0
- attune/validation/xml_validator.py +281 -0
- attune/vscode_bridge.py +173 -0
- attune/workflow_commands.py +780 -0
- attune/workflow_patterns/__init__.py +33 -0
- attune/workflow_patterns/behavior.py +249 -0
- attune/workflow_patterns/core.py +76 -0
- attune/workflow_patterns/output.py +99 -0
- attune/workflow_patterns/registry.py +255 -0
- attune/workflow_patterns/structural.py +288 -0
- attune/workflows/__init__.py +539 -0
- attune/workflows/autonomous_test_gen.py +1268 -0
- attune/workflows/base.py +2667 -0
- attune/workflows/batch_processing.py +342 -0
- attune/workflows/bug_predict.py +1084 -0
- attune/workflows/builder.py +273 -0
- attune/workflows/caching.py +253 -0
- attune/workflows/code_review.py +1048 -0
- attune/workflows/code_review_adapters.py +312 -0
- attune/workflows/code_review_pipeline.py +722 -0
- attune/workflows/config.py +645 -0
- attune/workflows/dependency_check.py +644 -0
- attune/workflows/document_gen/__init__.py +25 -0
- attune/workflows/document_gen/config.py +30 -0
- attune/workflows/document_gen/report_formatter.py +162 -0
- attune/workflows/document_gen/workflow.py +1426 -0
- attune/workflows/document_manager.py +216 -0
- attune/workflows/document_manager_README.md +134 -0
- attune/workflows/documentation_orchestrator.py +1205 -0
- attune/workflows/history.py +510 -0
- attune/workflows/keyboard_shortcuts/__init__.py +39 -0
- attune/workflows/keyboard_shortcuts/generators.py +391 -0
- attune/workflows/keyboard_shortcuts/parsers.py +416 -0
- attune/workflows/keyboard_shortcuts/prompts.py +295 -0
- attune/workflows/keyboard_shortcuts/schema.py +193 -0
- attune/workflows/keyboard_shortcuts/workflow.py +509 -0
- attune/workflows/llm_base.py +363 -0
- attune/workflows/manage_docs.py +87 -0
- attune/workflows/manage_docs_README.md +134 -0
- attune/workflows/manage_documentation.py +821 -0
- attune/workflows/new_sample_workflow1.py +149 -0
- attune/workflows/new_sample_workflow1_README.md +150 -0
- attune/workflows/orchestrated_health_check.py +849 -0
- attune/workflows/orchestrated_release_prep.py +600 -0
- attune/workflows/output.py +413 -0
- attune/workflows/perf_audit.py +863 -0
- attune/workflows/pr_review.py +762 -0
- attune/workflows/progress.py +785 -0
- attune/workflows/progress_server.py +322 -0
- attune/workflows/progressive/README 2.md +454 -0
- attune/workflows/progressive/README.md +454 -0
- attune/workflows/progressive/__init__.py +82 -0
- attune/workflows/progressive/cli.py +219 -0
- attune/workflows/progressive/core.py +488 -0
- attune/workflows/progressive/orchestrator.py +723 -0
- attune/workflows/progressive/reports.py +520 -0
- attune/workflows/progressive/telemetry.py +274 -0
- attune/workflows/progressive/test_gen.py +495 -0
- attune/workflows/progressive/workflow.py +589 -0
- attune/workflows/refactor_plan.py +694 -0
- attune/workflows/release_prep.py +895 -0
- attune/workflows/release_prep_crew.py +969 -0
- attune/workflows/research_synthesis.py +404 -0
- attune/workflows/routing.py +168 -0
- attune/workflows/secure_release.py +593 -0
- attune/workflows/security_adapters.py +297 -0
- attune/workflows/security_audit.py +1329 -0
- attune/workflows/security_audit_phase3.py +355 -0
- attune/workflows/seo_optimization.py +633 -0
- attune/workflows/step_config.py +234 -0
- attune/workflows/telemetry_mixin.py +269 -0
- attune/workflows/test5.py +125 -0
- attune/workflows/test5_README.md +158 -0
- attune/workflows/test_coverage_boost_crew.py +849 -0
- attune/workflows/test_gen/__init__.py +52 -0
- attune/workflows/test_gen/ast_analyzer.py +249 -0
- attune/workflows/test_gen/config.py +88 -0
- attune/workflows/test_gen/data_models.py +38 -0
- attune/workflows/test_gen/report_formatter.py +289 -0
- attune/workflows/test_gen/test_templates.py +381 -0
- attune/workflows/test_gen/workflow.py +655 -0
- attune/workflows/test_gen.py +54 -0
- attune/workflows/test_gen_behavioral.py +477 -0
- attune/workflows/test_gen_parallel.py +341 -0
- attune/workflows/test_lifecycle.py +526 -0
- attune/workflows/test_maintenance.py +627 -0
- attune/workflows/test_maintenance_cli.py +590 -0
- attune/workflows/test_maintenance_crew.py +840 -0
- attune/workflows/test_runner.py +622 -0
- attune/workflows/tier_tracking.py +531 -0
- attune/workflows/xml_enhanced_crew.py +285 -0
- attune_ai-2.0.0.dist-info/METADATA +1026 -0
- attune_ai-2.0.0.dist-info/RECORD +457 -0
- attune_ai-2.0.0.dist-info/WHEEL +5 -0
- attune_ai-2.0.0.dist-info/entry_points.txt +26 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE +201 -0
- attune_ai-2.0.0.dist-info/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +101 -0
- attune_ai-2.0.0.dist-info/top_level.txt +5 -0
- attune_healthcare/__init__.py +13 -0
- attune_healthcare/monitors/__init__.py +9 -0
- attune_healthcare/monitors/clinical_protocol_monitor.py +315 -0
- attune_healthcare/monitors/monitoring/__init__.py +44 -0
- attune_healthcare/monitors/monitoring/protocol_checker.py +300 -0
- attune_healthcare/monitors/monitoring/protocol_loader.py +214 -0
- attune_healthcare/monitors/monitoring/sensor_parsers.py +306 -0
- attune_healthcare/monitors/monitoring/trajectory_analyzer.py +389 -0
- attune_llm/README.md +553 -0
- attune_llm/__init__.py +28 -0
- attune_llm/agent_factory/__init__.py +53 -0
- attune_llm/agent_factory/adapters/__init__.py +85 -0
- attune_llm/agent_factory/adapters/autogen_adapter.py +312 -0
- attune_llm/agent_factory/adapters/crewai_adapter.py +483 -0
- attune_llm/agent_factory/adapters/haystack_adapter.py +298 -0
- attune_llm/agent_factory/adapters/langchain_adapter.py +362 -0
- attune_llm/agent_factory/adapters/langgraph_adapter.py +333 -0
- attune_llm/agent_factory/adapters/native.py +228 -0
- attune_llm/agent_factory/adapters/wizard_adapter.py +423 -0
- attune_llm/agent_factory/base.py +305 -0
- attune_llm/agent_factory/crews/__init__.py +67 -0
- attune_llm/agent_factory/crews/code_review.py +1113 -0
- attune_llm/agent_factory/crews/health_check.py +1262 -0
- attune_llm/agent_factory/crews/refactoring.py +1128 -0
- attune_llm/agent_factory/crews/security_audit.py +1018 -0
- attune_llm/agent_factory/decorators.py +287 -0
- attune_llm/agent_factory/factory.py +558 -0
- attune_llm/agent_factory/framework.py +193 -0
- attune_llm/agent_factory/memory_integration.py +328 -0
- attune_llm/agent_factory/resilient.py +320 -0
- attune_llm/agents_md/__init__.py +22 -0
- attune_llm/agents_md/loader.py +218 -0
- attune_llm/agents_md/parser.py +271 -0
- attune_llm/agents_md/registry.py +307 -0
- attune_llm/claude_memory.py +466 -0
- attune_llm/cli/__init__.py +8 -0
- attune_llm/cli/sync_claude.py +487 -0
- attune_llm/code_health.py +1313 -0
- attune_llm/commands/__init__.py +51 -0
- attune_llm/commands/context.py +375 -0
- attune_llm/commands/loader.py +301 -0
- attune_llm/commands/models.py +231 -0
- attune_llm/commands/parser.py +371 -0
- attune_llm/commands/registry.py +429 -0
- attune_llm/config/__init__.py +29 -0
- attune_llm/config/unified.py +291 -0
- attune_llm/context/__init__.py +22 -0
- attune_llm/context/compaction.py +455 -0
- attune_llm/context/manager.py +434 -0
- attune_llm/contextual_patterns.py +361 -0
- attune_llm/core.py +907 -0
- attune_llm/git_pattern_extractor.py +435 -0
- attune_llm/hooks/__init__.py +24 -0
- attune_llm/hooks/config.py +306 -0
- attune_llm/hooks/executor.py +289 -0
- attune_llm/hooks/registry.py +302 -0
- attune_llm/hooks/scripts/__init__.py +39 -0
- attune_llm/hooks/scripts/evaluate_session.py +201 -0
- attune_llm/hooks/scripts/first_time_init.py +285 -0
- attune_llm/hooks/scripts/pre_compact.py +207 -0
- attune_llm/hooks/scripts/session_end.py +183 -0
- attune_llm/hooks/scripts/session_start.py +163 -0
- attune_llm/hooks/scripts/suggest_compact.py +225 -0
- attune_llm/learning/__init__.py +30 -0
- attune_llm/learning/evaluator.py +438 -0
- attune_llm/learning/extractor.py +514 -0
- attune_llm/learning/storage.py +560 -0
- attune_llm/levels.py +227 -0
- attune_llm/pattern_confidence.py +414 -0
- attune_llm/pattern_resolver.py +272 -0
- attune_llm/pattern_summary.py +350 -0
- attune_llm/providers.py +967 -0
- attune_llm/routing/__init__.py +32 -0
- attune_llm/routing/model_router.py +362 -0
- attune_llm/security/IMPLEMENTATION_SUMMARY.md +413 -0
- attune_llm/security/PHASE2_COMPLETE.md +384 -0
- attune_llm/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
- attune_llm/security/QUICK_REFERENCE.md +316 -0
- attune_llm/security/README.md +262 -0
- attune_llm/security/__init__.py +62 -0
- attune_llm/security/audit_logger.py +929 -0
- attune_llm/security/audit_logger_example.py +152 -0
- attune_llm/security/pii_scrubber.py +640 -0
- attune_llm/security/secrets_detector.py +678 -0
- attune_llm/security/secrets_detector_example.py +304 -0
- attune_llm/security/secure_memdocs.py +1192 -0
- attune_llm/security/secure_memdocs_example.py +278 -0
- attune_llm/session_status.py +745 -0
- attune_llm/state.py +246 -0
- attune_llm/utils/__init__.py +5 -0
- attune_llm/utils/tokens.py +349 -0
- attune_software/SOFTWARE_PLUGIN_README.md +57 -0
- attune_software/__init__.py +13 -0
- attune_software/cli/__init__.py +120 -0
- attune_software/cli/inspect.py +362 -0
- attune_software/cli.py +574 -0
- attune_software/plugin.py +188 -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
attune/memory/edges.py
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"""Memory Graph Edge Types
|
|
2
|
+
|
|
3
|
+
Defines edge types for connecting nodes in the knowledge graph.
|
|
4
|
+
Edges represent relationships between entities discovered by workflows.
|
|
5
|
+
|
|
6
|
+
Copyright 2025 Smart AI Memory, LLC
|
|
7
|
+
Licensed under Fair Source 0.9
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
from enum import Enum
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class EdgeType(Enum):
|
|
17
|
+
"""Types of relationships between nodes."""
|
|
18
|
+
|
|
19
|
+
# Causal relationships
|
|
20
|
+
CAUSES = "causes" # bug causes another bug
|
|
21
|
+
CAUSED_BY = "caused_by" # reverse of causes
|
|
22
|
+
LEADS_TO = "leads_to" # issue leads to another issue
|
|
23
|
+
|
|
24
|
+
# Resolution relationships
|
|
25
|
+
FIXED_BY = "fixed_by" # bug fixed by a fix
|
|
26
|
+
FIXES = "fixes" # fix fixes a bug
|
|
27
|
+
MITIGATES = "mitigates" # partial fix
|
|
28
|
+
|
|
29
|
+
# Similarity relationships
|
|
30
|
+
SIMILAR_TO = "similar_to" # similar issues
|
|
31
|
+
RELATED_TO = "related_to" # general relation
|
|
32
|
+
DUPLICATE_OF = "duplicate_of" # same issue
|
|
33
|
+
|
|
34
|
+
# Structural relationships
|
|
35
|
+
CONTAINS = "contains" # file contains function
|
|
36
|
+
CONTAINED_IN = "contained_in" # reverse
|
|
37
|
+
DEPENDS_ON = "depends_on" # code dependency
|
|
38
|
+
IMPORTED_BY = "imported_by" # reverse
|
|
39
|
+
AFFECTS = "affects" # issue affects code
|
|
40
|
+
AFFECTED_BY = "affected_by" # code affected by issue
|
|
41
|
+
|
|
42
|
+
# Testing relationships
|
|
43
|
+
TESTED_BY = "tested_by" # code tested by test
|
|
44
|
+
TESTS = "tests" # test tests code
|
|
45
|
+
COVERS = "covers" # test covers code path
|
|
46
|
+
|
|
47
|
+
# Documentation relationships
|
|
48
|
+
DOCUMENTS = "documents" # doc documents code
|
|
49
|
+
DOCUMENTED_BY = "documented_by" # reverse
|
|
50
|
+
|
|
51
|
+
# Sequence relationships
|
|
52
|
+
PRECEDED_BY = "preceded_by" # temporal order
|
|
53
|
+
FOLLOWED_BY = "followed_by" # reverse
|
|
54
|
+
|
|
55
|
+
# Derivation relationships
|
|
56
|
+
DERIVED_FROM = "derived_from" # pattern derived from code
|
|
57
|
+
REFACTORED_TO = "refactored_to" # code refactored
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass
|
|
61
|
+
class Edge:
|
|
62
|
+
"""An edge connecting two nodes in the memory graph.
|
|
63
|
+
|
|
64
|
+
Represents a relationship between entities.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
source_id: str
|
|
68
|
+
target_id: str
|
|
69
|
+
type: EdgeType
|
|
70
|
+
|
|
71
|
+
# Edge metadata
|
|
72
|
+
weight: float = 1.0 # Strength of relationship (0.0 - 1.0)
|
|
73
|
+
confidence: float = 1.0 # How confident we are in this edge
|
|
74
|
+
|
|
75
|
+
# Context
|
|
76
|
+
description: str = ""
|
|
77
|
+
source_workflow: str = ""
|
|
78
|
+
|
|
79
|
+
# Additional data
|
|
80
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
81
|
+
|
|
82
|
+
# Timestamps
|
|
83
|
+
created_at: datetime = field(default_factory=datetime.now)
|
|
84
|
+
|
|
85
|
+
def to_dict(self) -> dict[str, Any]:
|
|
86
|
+
"""Convert edge to dictionary for JSON serialization."""
|
|
87
|
+
return {
|
|
88
|
+
"source_id": self.source_id,
|
|
89
|
+
"target_id": self.target_id,
|
|
90
|
+
"type": self.type.value,
|
|
91
|
+
"weight": self.weight,
|
|
92
|
+
"confidence": self.confidence,
|
|
93
|
+
"description": self.description,
|
|
94
|
+
"source_workflow": self.source_workflow,
|
|
95
|
+
"metadata": self.metadata,
|
|
96
|
+
"created_at": self.created_at.isoformat(),
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@classmethod
|
|
100
|
+
def from_dict(cls, data: dict[str, Any]) -> "Edge":
|
|
101
|
+
"""Create edge from dictionary."""
|
|
102
|
+
return cls(
|
|
103
|
+
source_id=data["source_id"],
|
|
104
|
+
target_id=data["target_id"],
|
|
105
|
+
type=EdgeType(data["type"]),
|
|
106
|
+
weight=data.get("weight", 1.0),
|
|
107
|
+
confidence=data.get("confidence", 1.0),
|
|
108
|
+
description=data.get("description", ""),
|
|
109
|
+
source_workflow=data.get("source_workflow", data.get("source_wizard", "")),
|
|
110
|
+
metadata=data.get("metadata", {}),
|
|
111
|
+
created_at=(
|
|
112
|
+
datetime.fromisoformat(data["created_at"])
|
|
113
|
+
if "created_at" in data
|
|
114
|
+
else datetime.now()
|
|
115
|
+
),
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def id(self) -> str:
|
|
120
|
+
"""Generate unique edge ID."""
|
|
121
|
+
return f"{self.source_id}-{self.type.value}-{self.target_id}"
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# Common edge patterns for workflow findings
|
|
125
|
+
WORKFLOW_EDGE_PATTERNS = {
|
|
126
|
+
"security-audit": [
|
|
127
|
+
(EdgeType.CAUSES, "vulnerability → vulnerability"),
|
|
128
|
+
(EdgeType.FIXED_BY, "vulnerability → fix"),
|
|
129
|
+
(EdgeType.AFFECTS, "vulnerability → file"),
|
|
130
|
+
],
|
|
131
|
+
"bug-predict": [
|
|
132
|
+
(EdgeType.CAUSES, "bug → bug"),
|
|
133
|
+
(EdgeType.SIMILAR_TO, "bug → bug"),
|
|
134
|
+
(EdgeType.FIXED_BY, "bug → fix"),
|
|
135
|
+
],
|
|
136
|
+
"perf-audit": [
|
|
137
|
+
(EdgeType.CAUSES, "performance_issue → performance_issue"),
|
|
138
|
+
(EdgeType.LEADS_TO, "code_smell → performance_issue"),
|
|
139
|
+
(EdgeType.MITIGATES, "refactor → performance_issue"),
|
|
140
|
+
],
|
|
141
|
+
"code-review": [
|
|
142
|
+
(EdgeType.CONTAINS, "file → function"),
|
|
143
|
+
(EdgeType.RELATED_TO, "code_smell → pattern"),
|
|
144
|
+
(EdgeType.REFACTORED_TO, "function → function"),
|
|
145
|
+
],
|
|
146
|
+
"test-gen": [
|
|
147
|
+
(EdgeType.TESTS, "test → function"),
|
|
148
|
+
(EdgeType.COVERS, "test → file"),
|
|
149
|
+
(EdgeType.TESTS, "test_case → bug"),
|
|
150
|
+
],
|
|
151
|
+
"dependency-check": [
|
|
152
|
+
(EdgeType.DEPENDS_ON, "file → dependency"),
|
|
153
|
+
(EdgeType.CAUSES, "dependency → vulnerability"),
|
|
154
|
+
],
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
# Reverse edge type mapping
|
|
159
|
+
REVERSE_EDGE_TYPES = {
|
|
160
|
+
EdgeType.CAUSES: EdgeType.CAUSED_BY,
|
|
161
|
+
EdgeType.CAUSED_BY: EdgeType.CAUSES,
|
|
162
|
+
EdgeType.FIXED_BY: EdgeType.FIXES,
|
|
163
|
+
EdgeType.FIXES: EdgeType.FIXED_BY,
|
|
164
|
+
EdgeType.CONTAINS: EdgeType.CONTAINED_IN,
|
|
165
|
+
EdgeType.CONTAINED_IN: EdgeType.CONTAINS,
|
|
166
|
+
EdgeType.DEPENDS_ON: EdgeType.IMPORTED_BY,
|
|
167
|
+
EdgeType.IMPORTED_BY: EdgeType.DEPENDS_ON,
|
|
168
|
+
EdgeType.TESTED_BY: EdgeType.TESTS,
|
|
169
|
+
EdgeType.TESTS: EdgeType.TESTED_BY,
|
|
170
|
+
EdgeType.DOCUMENTS: EdgeType.DOCUMENTED_BY,
|
|
171
|
+
EdgeType.DOCUMENTED_BY: EdgeType.DOCUMENTS,
|
|
172
|
+
EdgeType.PRECEDED_BY: EdgeType.FOLLOWED_BY,
|
|
173
|
+
EdgeType.FOLLOWED_BY: EdgeType.PRECEDED_BY,
|
|
174
|
+
EdgeType.SIMILAR_TO: EdgeType.SIMILAR_TO, # Symmetric
|
|
175
|
+
EdgeType.RELATED_TO: EdgeType.RELATED_TO, # Symmetric
|
|
176
|
+
EdgeType.DUPLICATE_OF: EdgeType.DUPLICATE_OF, # Symmetric
|
|
177
|
+
EdgeType.AFFECTS: EdgeType.AFFECTED_BY,
|
|
178
|
+
EdgeType.AFFECTED_BY: EdgeType.AFFECTS,
|
|
179
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""Encryption manager for long-term memory system
|
|
2
|
+
|
|
3
|
+
Provides AES-256-GCM encryption/decryption for SENSITIVE patterns.
|
|
4
|
+
Extracted from long_term.py for better modularity and testability.
|
|
5
|
+
|
|
6
|
+
Key Features:
|
|
7
|
+
- AES-256-GCM authenticated encryption
|
|
8
|
+
- Master key management (environment variable, file, or generated)
|
|
9
|
+
- Base64-encoded output for safe storage
|
|
10
|
+
- Proper error handling and security logging
|
|
11
|
+
|
|
12
|
+
Copyright 2025 Smart AI Memory, LLC
|
|
13
|
+
Licensed under Fair Source 0.9
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import base64
|
|
17
|
+
import binascii
|
|
18
|
+
import os
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
import structlog
|
|
22
|
+
|
|
23
|
+
from .long_term_types import SecurityError
|
|
24
|
+
|
|
25
|
+
logger = structlog.get_logger(__name__)
|
|
26
|
+
|
|
27
|
+
# Check for cryptography library
|
|
28
|
+
try:
|
|
29
|
+
from cryptography.exceptions import InvalidTag
|
|
30
|
+
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
|
31
|
+
|
|
32
|
+
HAS_ENCRYPTION = True
|
|
33
|
+
except ImportError:
|
|
34
|
+
HAS_ENCRYPTION = False
|
|
35
|
+
logger.warning("cryptography library not available - encryption disabled")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class EncryptionManager:
|
|
39
|
+
"""Manages encryption/decryption for SENSITIVE patterns.
|
|
40
|
+
|
|
41
|
+
Uses AES-256-GCM (Galois/Counter Mode) for authenticated encryption.
|
|
42
|
+
Keys are derived from a master key using HKDF.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self, master_key: bytes | None = None):
|
|
46
|
+
"""Initialize encryption manager.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
master_key: 32-byte master key (or None to generate/load)
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
if not HAS_ENCRYPTION:
|
|
53
|
+
logger.warning("Encryption not available - install cryptography library")
|
|
54
|
+
self.enabled = False
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
self.enabled = True
|
|
58
|
+
self.master_key = master_key or self._load_or_generate_key()
|
|
59
|
+
|
|
60
|
+
def _load_or_generate_key(self) -> bytes:
|
|
61
|
+
"""Load master key from environment or generate new one.
|
|
62
|
+
|
|
63
|
+
Production: Set EMPATHY_MASTER_KEY environment variable
|
|
64
|
+
Development: Generates ephemeral key (warning logged)
|
|
65
|
+
"""
|
|
66
|
+
# Check environment variable first
|
|
67
|
+
if env_key := os.getenv("EMPATHY_MASTER_KEY"):
|
|
68
|
+
try:
|
|
69
|
+
return base64.b64decode(env_key)
|
|
70
|
+
except (binascii.Error, ValueError) as e:
|
|
71
|
+
logger.error("invalid_master_key_in_env", error=str(e))
|
|
72
|
+
raise ValueError("Invalid EMPATHY_MASTER_KEY format") from e
|
|
73
|
+
|
|
74
|
+
# Check key file
|
|
75
|
+
key_file = Path.home() / ".empathy" / "master.key"
|
|
76
|
+
if key_file.exists():
|
|
77
|
+
try:
|
|
78
|
+
return key_file.read_bytes()
|
|
79
|
+
except (OSError, PermissionError) as e:
|
|
80
|
+
logger.error("failed_to_load_key_file", error=str(e))
|
|
81
|
+
|
|
82
|
+
# Generate ephemeral key (NOT for production)
|
|
83
|
+
logger.warning(
|
|
84
|
+
"no_master_key_found",
|
|
85
|
+
message="Generating ephemeral encryption key - set EMPATHY_MASTER_KEY for production",
|
|
86
|
+
)
|
|
87
|
+
return AESGCM.generate_key(bit_length=256)
|
|
88
|
+
|
|
89
|
+
def encrypt(self, plaintext: str) -> str:
|
|
90
|
+
"""Encrypt plaintext using AES-256-GCM.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
plaintext: Content to encrypt
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
Base64-encoded ciphertext with format: nonce||ciphertext||tag
|
|
97
|
+
|
|
98
|
+
Raises:
|
|
99
|
+
SecurityError: If encryption fails
|
|
100
|
+
|
|
101
|
+
"""
|
|
102
|
+
if not self.enabled:
|
|
103
|
+
raise SecurityError("Encryption not available - install cryptography library")
|
|
104
|
+
|
|
105
|
+
try:
|
|
106
|
+
# Generate random 96-bit nonce (12 bytes)
|
|
107
|
+
nonce = os.urandom(12)
|
|
108
|
+
|
|
109
|
+
# Create AESGCM cipher
|
|
110
|
+
aesgcm = AESGCM(self.master_key)
|
|
111
|
+
|
|
112
|
+
# Encrypt and authenticate
|
|
113
|
+
ciphertext = aesgcm.encrypt(nonce, plaintext.encode("utf-8"), None)
|
|
114
|
+
|
|
115
|
+
# Combine nonce + ciphertext for storage
|
|
116
|
+
encrypted_data = nonce + ciphertext
|
|
117
|
+
|
|
118
|
+
# Return base64-encoded
|
|
119
|
+
return base64.b64encode(encrypted_data).decode("utf-8")
|
|
120
|
+
|
|
121
|
+
except (ValueError, TypeError, UnicodeEncodeError) as e:
|
|
122
|
+
logger.error("encryption_failed", error=str(e))
|
|
123
|
+
raise SecurityError(f"Encryption failed: {e}") from e
|
|
124
|
+
|
|
125
|
+
def decrypt(self, ciphertext_b64: str) -> str:
|
|
126
|
+
"""Decrypt ciphertext using AES-256-GCM.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
ciphertext_b64: Base64-encoded encrypted data
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Decrypted plaintext
|
|
133
|
+
|
|
134
|
+
Raises:
|
|
135
|
+
SecurityError: If decryption fails (invalid key, corrupted data, etc.)
|
|
136
|
+
|
|
137
|
+
"""
|
|
138
|
+
if not self.enabled:
|
|
139
|
+
raise SecurityError("Encryption not available - install cryptography library")
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
# Decode from base64
|
|
143
|
+
encrypted_data = base64.b64decode(ciphertext_b64)
|
|
144
|
+
|
|
145
|
+
# Extract nonce (first 12 bytes) and ciphertext (rest)
|
|
146
|
+
nonce = encrypted_data[:12]
|
|
147
|
+
ciphertext = encrypted_data[12:]
|
|
148
|
+
|
|
149
|
+
# Create AESGCM cipher
|
|
150
|
+
aesgcm = AESGCM(self.master_key)
|
|
151
|
+
|
|
152
|
+
# Decrypt and verify
|
|
153
|
+
plaintext_bytes = aesgcm.decrypt(nonce, ciphertext, None)
|
|
154
|
+
|
|
155
|
+
return plaintext_bytes.decode("utf-8")
|
|
156
|
+
|
|
157
|
+
except (ValueError, TypeError, UnicodeDecodeError, binascii.Error, InvalidTag) as e:
|
|
158
|
+
logger.error("decryption_failed", error=str(e))
|
|
159
|
+
raise SecurityError(f"Decryption failed: {e}") from e
|