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,163 @@
|
|
|
1
|
+
"""Session Start Hook
|
|
2
|
+
|
|
3
|
+
Loads previous context and patterns on new session start.
|
|
4
|
+
Ported from everything-claude-code/scripts/hooks/session-start.js
|
|
5
|
+
|
|
6
|
+
Copyright 2025 Smart-AI-Memory
|
|
7
|
+
Licensed under Fair Source License 0.9
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import logging
|
|
12
|
+
from datetime import datetime, timedelta
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_sessions_dir() -> Path:
|
|
20
|
+
"""Get the sessions directory path."""
|
|
21
|
+
return Path.home() / ".empathy" / "sessions"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_patterns_dir() -> Path:
|
|
25
|
+
"""Get the patterns directory path."""
|
|
26
|
+
return Path.home() / ".empathy" / "patterns"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def get_learned_skills_dir() -> Path:
|
|
30
|
+
"""Get the learned skills directory path."""
|
|
31
|
+
return Path.home() / ".empathy" / "skills" / "learned"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def find_recent_files(
|
|
35
|
+
directory: Path,
|
|
36
|
+
pattern: str = "*.json",
|
|
37
|
+
max_age_days: int = 7,
|
|
38
|
+
) -> list[Path]:
|
|
39
|
+
"""Find files matching pattern modified within max_age_days.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
directory: Directory to search
|
|
43
|
+
pattern: Glob pattern for files
|
|
44
|
+
max_age_days: Maximum file age in days
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
List of matching file paths, sorted by modification time (newest first)
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
if not directory.exists():
|
|
51
|
+
return []
|
|
52
|
+
|
|
53
|
+
cutoff = datetime.now() - timedelta(days=max_age_days)
|
|
54
|
+
matching = []
|
|
55
|
+
|
|
56
|
+
for file_path in directory.glob(pattern):
|
|
57
|
+
if file_path.is_file():
|
|
58
|
+
mtime = datetime.fromtimestamp(file_path.stat().st_mtime)
|
|
59
|
+
if mtime >= cutoff:
|
|
60
|
+
matching.append((file_path, mtime))
|
|
61
|
+
|
|
62
|
+
# Sort by modification time, newest first
|
|
63
|
+
matching.sort(key=lambda x: x[1], reverse=True)
|
|
64
|
+
return [path for path, _ in matching]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def load_session_state(session_file: Path) -> dict[str, Any] | None:
|
|
68
|
+
"""Load session state from a file.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
session_file: Path to session state file
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Session state dict or None if failed
|
|
75
|
+
|
|
76
|
+
"""
|
|
77
|
+
try:
|
|
78
|
+
with open(session_file) as f:
|
|
79
|
+
return json.load(f)
|
|
80
|
+
except (json.JSONDecodeError, OSError) as e:
|
|
81
|
+
logger.warning("Failed to load session state from %s: %s", session_file, e)
|
|
82
|
+
return None
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def main(**context: Any) -> dict[str, Any]:
|
|
86
|
+
"""Session start hook main function.
|
|
87
|
+
|
|
88
|
+
Loads:
|
|
89
|
+
- Previous session state (trust level, patterns, preferences)
|
|
90
|
+
- Learned skills from previous sessions
|
|
91
|
+
- Project-specific patterns
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
**context: Hook context (session_id, project_path, etc.)
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
Session initialization data
|
|
98
|
+
|
|
99
|
+
"""
|
|
100
|
+
sessions_dir = get_sessions_dir()
|
|
101
|
+
patterns_dir = get_patterns_dir()
|
|
102
|
+
learned_dir = get_learned_skills_dir()
|
|
103
|
+
|
|
104
|
+
# Ensure directories exist
|
|
105
|
+
sessions_dir.mkdir(parents=True, exist_ok=True)
|
|
106
|
+
patterns_dir.mkdir(parents=True, exist_ok=True)
|
|
107
|
+
learned_dir.mkdir(parents=True, exist_ok=True)
|
|
108
|
+
|
|
109
|
+
result = {
|
|
110
|
+
"initialized": True,
|
|
111
|
+
"timestamp": datetime.now().isoformat(),
|
|
112
|
+
"loaded_state": None,
|
|
113
|
+
"learned_skills_count": 0,
|
|
114
|
+
"patterns_count": 0,
|
|
115
|
+
"messages": [],
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# Find and load recent session state
|
|
119
|
+
recent_sessions = find_recent_files(sessions_dir, "*.json", max_age_days=7)
|
|
120
|
+
|
|
121
|
+
if recent_sessions:
|
|
122
|
+
latest = recent_sessions[0]
|
|
123
|
+
state = load_session_state(latest)
|
|
124
|
+
|
|
125
|
+
if state:
|
|
126
|
+
result["loaded_state"] = {
|
|
127
|
+
"file": str(latest),
|
|
128
|
+
"trust_level": state.get("trust_level"),
|
|
129
|
+
"interaction_count": state.get("interaction_count", 0),
|
|
130
|
+
"patterns_detected": len(state.get("detected_patterns", [])),
|
|
131
|
+
}
|
|
132
|
+
result["messages"].append(f"[SessionStart] Restored state from {latest.name}")
|
|
133
|
+
logger.info("Loaded session state from %s", latest)
|
|
134
|
+
|
|
135
|
+
# Count learned skills
|
|
136
|
+
learned_skills = list(learned_dir.glob("*.md"))
|
|
137
|
+
result["learned_skills_count"] = len(learned_skills)
|
|
138
|
+
|
|
139
|
+
if learned_skills:
|
|
140
|
+
result["messages"].append(
|
|
141
|
+
f"[SessionStart] {len(learned_skills)} learned skill(s) available"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# Count patterns
|
|
145
|
+
pattern_files = list(patterns_dir.glob("*.json"))
|
|
146
|
+
result["patterns_count"] = len(pattern_files)
|
|
147
|
+
|
|
148
|
+
if pattern_files:
|
|
149
|
+
result["messages"].append(f"[SessionStart] {len(pattern_files)} pattern file(s) loaded")
|
|
150
|
+
|
|
151
|
+
# Log summary
|
|
152
|
+
for msg in result["messages"]:
|
|
153
|
+
logger.info(msg)
|
|
154
|
+
|
|
155
|
+
return result
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
if __name__ == "__main__":
|
|
159
|
+
# Allow running as a script for testing
|
|
160
|
+
|
|
161
|
+
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
|
162
|
+
result = main()
|
|
163
|
+
print(json.dumps(result, indent=2))
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"""Suggest Compact Hook
|
|
2
|
+
|
|
3
|
+
Suggests strategic compaction at logical breakpoints to manage context window.
|
|
4
|
+
Ported from everything-claude-code/scripts/hooks/suggest-compact.js
|
|
5
|
+
|
|
6
|
+
Copyright 2025 Smart-AI-Memory
|
|
7
|
+
Licensed under Fair Source License 0.9
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import logging
|
|
12
|
+
import os
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Configuration
|
|
21
|
+
DEFAULT_COMPACT_THRESHOLD = 50 # Tool calls before first suggestion
|
|
22
|
+
DEFAULT_REMINDER_INTERVAL = 25 # Interval between reminders
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_compaction_state_file() -> Path:
|
|
26
|
+
"""Get the compaction state file path."""
|
|
27
|
+
return Path.home() / ".empathy" / "compaction_state.json"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def load_compaction_state() -> dict[str, Any]:
|
|
31
|
+
"""Load compaction tracking state.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Current compaction state
|
|
35
|
+
|
|
36
|
+
"""
|
|
37
|
+
state_file = get_compaction_state_file()
|
|
38
|
+
|
|
39
|
+
if state_file.exists():
|
|
40
|
+
try:
|
|
41
|
+
with open(state_file) as f:
|
|
42
|
+
return json.load(f)
|
|
43
|
+
except (json.JSONDecodeError, OSError):
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
"tool_call_count": 0,
|
|
48
|
+
"last_suggestion": None,
|
|
49
|
+
"last_compaction": None,
|
|
50
|
+
"suggestion_count": 0,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def save_compaction_state(state: dict[str, Any]) -> None:
|
|
55
|
+
"""Save compaction tracking state.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
state: State to save
|
|
59
|
+
|
|
60
|
+
"""
|
|
61
|
+
state_file = get_compaction_state_file()
|
|
62
|
+
state_file.parent.mkdir(parents=True, exist_ok=True)
|
|
63
|
+
|
|
64
|
+
with open(state_file, "w") as f:
|
|
65
|
+
json.dump(state, f, indent=2)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def should_suggest_compaction(
|
|
69
|
+
state: dict[str, Any],
|
|
70
|
+
threshold: int = DEFAULT_COMPACT_THRESHOLD,
|
|
71
|
+
interval: int = DEFAULT_REMINDER_INTERVAL,
|
|
72
|
+
) -> tuple[bool, str]:
|
|
73
|
+
"""Determine if compaction should be suggested.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
state: Current compaction state
|
|
77
|
+
threshold: Tool calls before first suggestion
|
|
78
|
+
interval: Interval between reminders
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
Tuple of (should_suggest, reason)
|
|
82
|
+
|
|
83
|
+
"""
|
|
84
|
+
count = state.get("tool_call_count", 0)
|
|
85
|
+
|
|
86
|
+
# First threshold
|
|
87
|
+
if count == threshold:
|
|
88
|
+
return True, f"Reached {threshold} tool calls - good time to compact"
|
|
89
|
+
|
|
90
|
+
# Periodic reminders after threshold
|
|
91
|
+
if count > threshold and (count - threshold) % interval == 0:
|
|
92
|
+
return True, f"At {count} tool calls - consider compacting"
|
|
93
|
+
|
|
94
|
+
return False, ""
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def get_compaction_recommendations(context: dict[str, Any]) -> list[str]:
|
|
98
|
+
"""Get recommendations for what to compact.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
context: Current session context
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
List of recommendations
|
|
105
|
+
|
|
106
|
+
"""
|
|
107
|
+
recommendations = []
|
|
108
|
+
|
|
109
|
+
# Check completed phases
|
|
110
|
+
completed_phases = context.get("completed_phases", [])
|
|
111
|
+
|
|
112
|
+
if completed_phases:
|
|
113
|
+
recommendations.append(
|
|
114
|
+
f"Completed phases ({', '.join(completed_phases)}) can be summarized"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# Check for exploration context
|
|
118
|
+
if context.get("exploration_complete", False):
|
|
119
|
+
recommendations.append("Exploration context can be compacted to findings only")
|
|
120
|
+
|
|
121
|
+
# Check for research context
|
|
122
|
+
if context.get("research_complete", False):
|
|
123
|
+
recommendations.append("Research context can be compacted to conclusions")
|
|
124
|
+
|
|
125
|
+
# General recommendations
|
|
126
|
+
if not recommendations:
|
|
127
|
+
recommendations = [
|
|
128
|
+
"Summarize completed work before starting new tasks",
|
|
129
|
+
"Keep implementation plan, compact exploration details",
|
|
130
|
+
"Preserve critical decisions and constraints",
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
return recommendations
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def main(**context: Any) -> dict[str, Any]:
|
|
137
|
+
"""Suggest compact hook main function.
|
|
138
|
+
|
|
139
|
+
Tracks tool usage and suggests compaction at strategic points.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
**context: Hook context (tool name, current phase, etc.)
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
Compaction suggestion result
|
|
146
|
+
|
|
147
|
+
"""
|
|
148
|
+
threshold = int(os.environ.get("COMPACT_THRESHOLD", DEFAULT_COMPACT_THRESHOLD))
|
|
149
|
+
interval = int(os.environ.get("COMPACT_INTERVAL", DEFAULT_REMINDER_INTERVAL))
|
|
150
|
+
|
|
151
|
+
# Load and update state
|
|
152
|
+
state = load_compaction_state()
|
|
153
|
+
state["tool_call_count"] = state.get("tool_call_count", 0) + 1
|
|
154
|
+
|
|
155
|
+
result = {
|
|
156
|
+
"tool_call_count": state["tool_call_count"],
|
|
157
|
+
"suggest_compaction": False,
|
|
158
|
+
"reason": "",
|
|
159
|
+
"recommendations": [],
|
|
160
|
+
"messages": [],
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
# Check if we should suggest compaction
|
|
164
|
+
should_suggest, reason = should_suggest_compaction(state, threshold, interval)
|
|
165
|
+
|
|
166
|
+
if should_suggest:
|
|
167
|
+
result["suggest_compaction"] = True
|
|
168
|
+
result["reason"] = reason
|
|
169
|
+
result["recommendations"] = get_compaction_recommendations(context)
|
|
170
|
+
|
|
171
|
+
state["last_suggestion"] = datetime.now().isoformat()
|
|
172
|
+
state["suggestion_count"] = state.get("suggestion_count", 0) + 1
|
|
173
|
+
|
|
174
|
+
result["messages"].append(f"[SuggestCompact] {reason}")
|
|
175
|
+
for rec in result["recommendations"]:
|
|
176
|
+
result["messages"].append(f"[SuggestCompact] - {rec}")
|
|
177
|
+
|
|
178
|
+
# Save updated state
|
|
179
|
+
save_compaction_state(state)
|
|
180
|
+
|
|
181
|
+
# Log messages
|
|
182
|
+
for msg in result["messages"]:
|
|
183
|
+
logger.info(msg)
|
|
184
|
+
|
|
185
|
+
return result
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def reset_on_compaction(**context: Any) -> dict[str, Any]:
|
|
189
|
+
"""Reset compaction state after a compaction event.
|
|
190
|
+
|
|
191
|
+
Called by PreCompact hook.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
**context: Hook context
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
Reset confirmation
|
|
198
|
+
|
|
199
|
+
"""
|
|
200
|
+
state = load_compaction_state()
|
|
201
|
+
state["tool_call_count"] = 0
|
|
202
|
+
state["last_compaction"] = datetime.now().isoformat()
|
|
203
|
+
save_compaction_state(state)
|
|
204
|
+
|
|
205
|
+
logger.info("[SuggestCompact] Reset after compaction")
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
"reset": True,
|
|
209
|
+
"timestamp": datetime.now().isoformat(),
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
if __name__ == "__main__":
|
|
214
|
+
# Allow running as a script for testing
|
|
215
|
+
|
|
216
|
+
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
|
217
|
+
|
|
218
|
+
# Simulate tool calls
|
|
219
|
+
for i in range(60):
|
|
220
|
+
result = main(current_phase="implementation")
|
|
221
|
+
if result["suggest_compaction"]:
|
|
222
|
+
print(f"\nCall {i + 1}: SUGGEST COMPACTION")
|
|
223
|
+
print(f" Reason: {result['reason']}")
|
|
224
|
+
for rec in result["recommendations"]:
|
|
225
|
+
print(f" - {rec}")
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Continuous Learning Module for Empathy Framework
|
|
2
|
+
|
|
3
|
+
Automatic pattern extraction from sessions to enable learning and improvement.
|
|
4
|
+
Identifies valuable patterns from user interactions for future application.
|
|
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 attune_llm.learning.evaluator import SessionEvaluator, SessionQuality
|
|
15
|
+
from attune_llm.learning.extractor import (
|
|
16
|
+
ExtractedPattern,
|
|
17
|
+
PatternCategory,
|
|
18
|
+
PatternExtractor,
|
|
19
|
+
)
|
|
20
|
+
from attune_llm.learning.storage import LearnedSkill, LearnedSkillsStorage
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"ExtractedPattern",
|
|
24
|
+
"LearnedSkill",
|
|
25
|
+
"LearnedSkillsStorage",
|
|
26
|
+
"PatternCategory",
|
|
27
|
+
"PatternExtractor",
|
|
28
|
+
"SessionEvaluator",
|
|
29
|
+
"SessionQuality",
|
|
30
|
+
]
|