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
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
"""Context Manager for Empathy Framework
|
|
2
|
+
|
|
3
|
+
Orchestrates context compaction, state preservation, and restoration.
|
|
4
|
+
Integrates with the hook system to handle compaction events automatically.
|
|
5
|
+
|
|
6
|
+
Architectural patterns inspired by everything-claude-code by Affaan Mustafa.
|
|
7
|
+
See: https://github.com/affaan-m/everything-claude-code (MIT License)
|
|
8
|
+
See: ACKNOWLEDGMENTS.md for full attribution.
|
|
9
|
+
|
|
10
|
+
Copyright 2025 Smart AI Memory, LLC
|
|
11
|
+
Licensed under Fair Source 0.9
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import TYPE_CHECKING, Any
|
|
19
|
+
|
|
20
|
+
from attune_llm.context.compaction import (
|
|
21
|
+
CompactionStateManager,
|
|
22
|
+
CompactState,
|
|
23
|
+
PatternSummary,
|
|
24
|
+
SBARHandoff,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from attune_llm.state import CollaborationState, UserPattern
|
|
29
|
+
|
|
30
|
+
logger = logging.getLogger(__name__)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ContextManager:
|
|
34
|
+
"""Manages context compaction and restoration for the Empathy Framework.
|
|
35
|
+
|
|
36
|
+
This class coordinates:
|
|
37
|
+
- Converting CollaborationState to CompactState for preservation
|
|
38
|
+
- Restoring state after context window resets
|
|
39
|
+
- Generating restoration prompts
|
|
40
|
+
- Handling SBAR handoffs for work continuity
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
storage_dir: str | Path = ".attune/compact_states",
|
|
46
|
+
token_threshold: int = 50, # Percentage at which to suggest compaction
|
|
47
|
+
auto_save: bool = True,
|
|
48
|
+
):
|
|
49
|
+
"""Initialize the ContextManager.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
storage_dir: Directory for state persistence
|
|
53
|
+
token_threshold: Token usage percentage to trigger compaction suggestions
|
|
54
|
+
auto_save: Whether to auto-save state on compaction
|
|
55
|
+
"""
|
|
56
|
+
self._state_manager = CompactionStateManager(storage_dir=storage_dir)
|
|
57
|
+
self._token_threshold = token_threshold
|
|
58
|
+
self._auto_save = auto_save
|
|
59
|
+
self._current_session_id: str = ""
|
|
60
|
+
self._current_phase: str = ""
|
|
61
|
+
self._completed_phases: list[str] = []
|
|
62
|
+
self._pending_handoff: SBARHandoff | None = None
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def session_id(self) -> str:
|
|
66
|
+
"""Get current session ID."""
|
|
67
|
+
return self._current_session_id
|
|
68
|
+
|
|
69
|
+
@session_id.setter
|
|
70
|
+
def session_id(self, value: str) -> None:
|
|
71
|
+
"""Set current session ID."""
|
|
72
|
+
self._current_session_id = value
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def current_phase(self) -> str:
|
|
76
|
+
"""Get current work phase."""
|
|
77
|
+
return self._current_phase
|
|
78
|
+
|
|
79
|
+
@current_phase.setter
|
|
80
|
+
def current_phase(self, value: str) -> None:
|
|
81
|
+
"""Set current work phase."""
|
|
82
|
+
self._current_phase = value
|
|
83
|
+
|
|
84
|
+
def complete_phase(self, phase: str) -> None:
|
|
85
|
+
"""Mark a phase as completed.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
phase: Name of the completed phase
|
|
89
|
+
"""
|
|
90
|
+
if phase not in self._completed_phases:
|
|
91
|
+
self._completed_phases.append(phase)
|
|
92
|
+
logger.debug(f"Completed phase: {phase}")
|
|
93
|
+
|
|
94
|
+
def set_handoff(
|
|
95
|
+
self,
|
|
96
|
+
situation: str,
|
|
97
|
+
background: str,
|
|
98
|
+
assessment: str,
|
|
99
|
+
recommendation: str,
|
|
100
|
+
priority: str = "normal",
|
|
101
|
+
**metadata: Any,
|
|
102
|
+
) -> SBARHandoff:
|
|
103
|
+
"""Set a pending handoff for work continuity.
|
|
104
|
+
|
|
105
|
+
Uses SBAR format for clear communication:
|
|
106
|
+
- Situation: What's happening now
|
|
107
|
+
- Background: Relevant context
|
|
108
|
+
- Assessment: Current understanding
|
|
109
|
+
- Recommendation: Suggested next action
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
situation: Current situation description
|
|
113
|
+
background: Relevant background information
|
|
114
|
+
assessment: Current assessment
|
|
115
|
+
recommendation: Recommended next action
|
|
116
|
+
priority: Priority level (low, normal, high, critical)
|
|
117
|
+
**metadata: Additional metadata
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
The created SBARHandoff
|
|
121
|
+
"""
|
|
122
|
+
self._pending_handoff = SBARHandoff(
|
|
123
|
+
situation=situation,
|
|
124
|
+
background=background,
|
|
125
|
+
assessment=assessment,
|
|
126
|
+
recommendation=recommendation,
|
|
127
|
+
priority=priority,
|
|
128
|
+
metadata=metadata,
|
|
129
|
+
)
|
|
130
|
+
return self._pending_handoff
|
|
131
|
+
|
|
132
|
+
def clear_handoff(self) -> None:
|
|
133
|
+
"""Clear the pending handoff after it's been addressed."""
|
|
134
|
+
self._pending_handoff = None
|
|
135
|
+
|
|
136
|
+
def extract_compact_state(
|
|
137
|
+
self,
|
|
138
|
+
collaboration_state: CollaborationState,
|
|
139
|
+
) -> CompactState:
|
|
140
|
+
"""Extract CompactState from full CollaborationState.
|
|
141
|
+
|
|
142
|
+
Converts the rich collaboration state into a compact form
|
|
143
|
+
suitable for preservation through context resets.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
collaboration_state: Full collaboration state
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
Compact state for preservation
|
|
150
|
+
"""
|
|
151
|
+
# Convert patterns to summaries
|
|
152
|
+
pattern_summaries = [
|
|
153
|
+
self._pattern_to_summary(p)
|
|
154
|
+
for p in collaboration_state.detected_patterns[:10] # Top 10
|
|
155
|
+
]
|
|
156
|
+
|
|
157
|
+
# Extract key preferences (limit to essentials)
|
|
158
|
+
key_preferences = self._extract_key_preferences(collaboration_state.preferences)
|
|
159
|
+
|
|
160
|
+
return CompactState(
|
|
161
|
+
user_id=collaboration_state.user_id,
|
|
162
|
+
trust_level=collaboration_state.trust_level,
|
|
163
|
+
empathy_level=collaboration_state.current_level,
|
|
164
|
+
detected_patterns=pattern_summaries,
|
|
165
|
+
session_id=self._current_session_id,
|
|
166
|
+
current_phase=self._current_phase,
|
|
167
|
+
completed_phases=list(self._completed_phases),
|
|
168
|
+
pending_handoff=self._pending_handoff,
|
|
169
|
+
interaction_count=len(collaboration_state.interactions),
|
|
170
|
+
successful_actions=collaboration_state.successful_actions,
|
|
171
|
+
failed_actions=collaboration_state.failed_actions,
|
|
172
|
+
preferences=key_preferences,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
def _pattern_to_summary(self, pattern: UserPattern) -> PatternSummary:
|
|
176
|
+
"""Convert UserPattern to PatternSummary.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
pattern: Full pattern object
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
Compact pattern summary
|
|
183
|
+
"""
|
|
184
|
+
return PatternSummary(
|
|
185
|
+
pattern_type=pattern.pattern_type.value,
|
|
186
|
+
trigger=pattern.trigger,
|
|
187
|
+
action=pattern.action,
|
|
188
|
+
confidence=pattern.confidence,
|
|
189
|
+
occurrences=pattern.occurrences,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
def _extract_key_preferences(
|
|
193
|
+
self,
|
|
194
|
+
preferences: dict[str, Any],
|
|
195
|
+
max_items: int = 10,
|
|
196
|
+
) -> dict[str, Any]:
|
|
197
|
+
"""Extract key preferences for compaction.
|
|
198
|
+
|
|
199
|
+
Filters and limits preferences to essential items.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
preferences: Full preferences dict
|
|
203
|
+
max_items: Maximum items to include
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
Filtered preferences dict
|
|
207
|
+
"""
|
|
208
|
+
# Priority keys to always include if present
|
|
209
|
+
priority_keys = {
|
|
210
|
+
"response_style",
|
|
211
|
+
"code_style",
|
|
212
|
+
"verbosity",
|
|
213
|
+
"confirmation_level",
|
|
214
|
+
"tool_usage",
|
|
215
|
+
"language",
|
|
216
|
+
"timezone",
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
result: dict[str, Any] = {}
|
|
220
|
+
|
|
221
|
+
# Add priority keys first
|
|
222
|
+
for key in priority_keys:
|
|
223
|
+
if key in preferences:
|
|
224
|
+
result[key] = preferences[key]
|
|
225
|
+
if len(result) >= max_items:
|
|
226
|
+
return result
|
|
227
|
+
|
|
228
|
+
# Add remaining keys up to limit
|
|
229
|
+
for key, value in preferences.items():
|
|
230
|
+
if key not in result:
|
|
231
|
+
# Skip complex nested structures
|
|
232
|
+
if isinstance(value, (str, int, float, bool)):
|
|
233
|
+
result[key] = value
|
|
234
|
+
elif isinstance(value, list) and len(value) <= 5:
|
|
235
|
+
result[key] = value
|
|
236
|
+
|
|
237
|
+
if len(result) >= max_items:
|
|
238
|
+
break
|
|
239
|
+
|
|
240
|
+
return result
|
|
241
|
+
|
|
242
|
+
def save_for_compaction(
|
|
243
|
+
self,
|
|
244
|
+
collaboration_state: CollaborationState,
|
|
245
|
+
) -> Path:
|
|
246
|
+
"""Save state for upcoming compaction.
|
|
247
|
+
|
|
248
|
+
Called before context compaction to preserve state.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
collaboration_state: Current collaboration state
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
Path to saved state file
|
|
255
|
+
"""
|
|
256
|
+
compact_state = self.extract_compact_state(collaboration_state)
|
|
257
|
+
return self._state_manager.save_state(compact_state)
|
|
258
|
+
|
|
259
|
+
def restore_state(self, user_id: str) -> CompactState | None:
|
|
260
|
+
"""Restore the most recent state for a user.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
user_id: User identifier
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
Most recent CompactState or None
|
|
267
|
+
"""
|
|
268
|
+
state = self._state_manager.load_latest_state(user_id)
|
|
269
|
+
|
|
270
|
+
if state:
|
|
271
|
+
# Restore session tracking
|
|
272
|
+
self._current_session_id = state.session_id
|
|
273
|
+
self._current_phase = state.current_phase
|
|
274
|
+
self._completed_phases = list(state.completed_phases)
|
|
275
|
+
self._pending_handoff = state.pending_handoff
|
|
276
|
+
|
|
277
|
+
logger.info(f"Restored state for user {user_id}")
|
|
278
|
+
|
|
279
|
+
return state
|
|
280
|
+
|
|
281
|
+
def restore_by_session(self, session_id: str) -> CompactState | None:
|
|
282
|
+
"""Restore state for a specific session.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
session_id: Session identifier
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
CompactState for session or None
|
|
289
|
+
"""
|
|
290
|
+
state = self._state_manager.load_state_by_session(session_id)
|
|
291
|
+
|
|
292
|
+
if state:
|
|
293
|
+
self._current_session_id = state.session_id
|
|
294
|
+
self._current_phase = state.current_phase
|
|
295
|
+
self._completed_phases = list(state.completed_phases)
|
|
296
|
+
self._pending_handoff = state.pending_handoff
|
|
297
|
+
|
|
298
|
+
logger.info(f"Restored state for session {session_id}")
|
|
299
|
+
|
|
300
|
+
return state
|
|
301
|
+
|
|
302
|
+
def generate_restoration_prompt(self, user_id: str) -> str | None:
|
|
303
|
+
"""Generate a restoration prompt for session continuity.
|
|
304
|
+
|
|
305
|
+
Loads the most recent state and formats it as a prompt
|
|
306
|
+
that can be injected at session start.
|
|
307
|
+
|
|
308
|
+
Args:
|
|
309
|
+
user_id: User identifier
|
|
310
|
+
|
|
311
|
+
Returns:
|
|
312
|
+
Formatted restoration prompt or None if no state
|
|
313
|
+
"""
|
|
314
|
+
state = self.restore_state(user_id)
|
|
315
|
+
|
|
316
|
+
if not state:
|
|
317
|
+
return None
|
|
318
|
+
|
|
319
|
+
return state.format_restoration_prompt()
|
|
320
|
+
|
|
321
|
+
def should_suggest_compaction(
|
|
322
|
+
self,
|
|
323
|
+
token_usage_percent: float,
|
|
324
|
+
message_count: int | None = None,
|
|
325
|
+
) -> bool:
|
|
326
|
+
"""Determine if compaction should be suggested.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
token_usage_percent: Current token usage as percentage (0-100)
|
|
330
|
+
message_count: Optional message count for additional heuristic
|
|
331
|
+
|
|
332
|
+
Returns:
|
|
333
|
+
True if compaction should be suggested
|
|
334
|
+
"""
|
|
335
|
+
# Primary check: token usage
|
|
336
|
+
if token_usage_percent >= self._token_threshold:
|
|
337
|
+
return True
|
|
338
|
+
|
|
339
|
+
# Secondary check: message count (if provided)
|
|
340
|
+
if message_count and message_count >= 50:
|
|
341
|
+
return True
|
|
342
|
+
|
|
343
|
+
return False
|
|
344
|
+
|
|
345
|
+
def get_compaction_message(
|
|
346
|
+
self,
|
|
347
|
+
token_usage_percent: float,
|
|
348
|
+
) -> str:
|
|
349
|
+
"""Generate a compaction suggestion message.
|
|
350
|
+
|
|
351
|
+
Args:
|
|
352
|
+
token_usage_percent: Current token usage percentage
|
|
353
|
+
|
|
354
|
+
Returns:
|
|
355
|
+
Formatted suggestion message
|
|
356
|
+
"""
|
|
357
|
+
return (
|
|
358
|
+
f"Context usage at {token_usage_percent:.0f}%. "
|
|
359
|
+
"Consider running `/compact` to preserve state and free context space. "
|
|
360
|
+
"Your collaboration state, trust level, and detected patterns will be preserved."
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
def apply_state_to_collaboration(
|
|
364
|
+
self,
|
|
365
|
+
compact_state: CompactState,
|
|
366
|
+
collaboration_state: CollaborationState,
|
|
367
|
+
) -> None:
|
|
368
|
+
"""Apply restored CompactState to CollaborationState.
|
|
369
|
+
|
|
370
|
+
Updates a CollaborationState with values from a restored CompactState.
|
|
371
|
+
|
|
372
|
+
Args:
|
|
373
|
+
compact_state: State to restore from
|
|
374
|
+
collaboration_state: State to update
|
|
375
|
+
"""
|
|
376
|
+
# Restore trust level
|
|
377
|
+
collaboration_state.trust_level = compact_state.trust_level
|
|
378
|
+
|
|
379
|
+
# Restore empathy level
|
|
380
|
+
collaboration_state.current_level = compact_state.empathy_level
|
|
381
|
+
|
|
382
|
+
# Restore counters
|
|
383
|
+
collaboration_state.successful_actions = compact_state.successful_actions
|
|
384
|
+
collaboration_state.failed_actions = compact_state.failed_actions
|
|
385
|
+
|
|
386
|
+
# Restore preferences
|
|
387
|
+
collaboration_state.preferences.update(compact_state.preferences)
|
|
388
|
+
|
|
389
|
+
# Note: Patterns and interactions are not restored from compact state
|
|
390
|
+
# as the full state would be needed for those
|
|
391
|
+
|
|
392
|
+
logger.info(
|
|
393
|
+
f"Applied compact state to collaboration: "
|
|
394
|
+
f"trust={compact_state.trust_level:.2f}, "
|
|
395
|
+
f"level={compact_state.empathy_level}"
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
def get_state_summary(self, user_id: str) -> dict[str, Any] | None:
|
|
399
|
+
"""Get a summary of saved states for a user.
|
|
400
|
+
|
|
401
|
+
Args:
|
|
402
|
+
user_id: User identifier
|
|
403
|
+
|
|
404
|
+
Returns:
|
|
405
|
+
Summary dict or None if no states
|
|
406
|
+
"""
|
|
407
|
+
states = self._state_manager.get_all_states(user_id)
|
|
408
|
+
|
|
409
|
+
if not states:
|
|
410
|
+
return None
|
|
411
|
+
|
|
412
|
+
latest = states[0]
|
|
413
|
+
|
|
414
|
+
return {
|
|
415
|
+
"user_id": user_id,
|
|
416
|
+
"states_count": len(states),
|
|
417
|
+
"latest_saved": latest.saved_at,
|
|
418
|
+
"latest_trust_level": latest.trust_level,
|
|
419
|
+
"latest_empathy_level": latest.empathy_level,
|
|
420
|
+
"latest_session_id": latest.session_id,
|
|
421
|
+
"patterns_count": len(latest.detected_patterns),
|
|
422
|
+
"has_pending_handoff": latest.pending_handoff is not None,
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
def clear_states(self, user_id: str) -> int:
|
|
426
|
+
"""Clear all saved states for a user.
|
|
427
|
+
|
|
428
|
+
Args:
|
|
429
|
+
user_id: User identifier
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
Number of states cleared
|
|
433
|
+
"""
|
|
434
|
+
return self._state_manager.clear_user_states(user_id)
|