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,429 @@
|
|
|
1
|
+
"""Command Registry
|
|
2
|
+
|
|
3
|
+
Central registry for managing available commands.
|
|
4
|
+
|
|
5
|
+
Architectural patterns inspired by everything-claude-code by Affaan Mustafa.
|
|
6
|
+
See: https://github.com/affaan-m/everything-claude-code (MIT License)
|
|
7
|
+
See: ACKNOWLEDGMENTS.md for full attribution.
|
|
8
|
+
|
|
9
|
+
Copyright 2025 Smart AI Memory, LLC
|
|
10
|
+
Licensed under Fair Source 0.9
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import logging
|
|
16
|
+
from collections.abc import Iterator
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
from attune_llm.commands.loader import CommandLoader, get_default_commands_directory
|
|
21
|
+
from attune_llm.commands.models import CommandCategory, CommandConfig
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class CommandRegistry:
|
|
27
|
+
"""Central registry for command configurations.
|
|
28
|
+
|
|
29
|
+
Provides a single point of access for all available commands,
|
|
30
|
+
supporting both programmatic registration and directory loading.
|
|
31
|
+
Includes alias resolution for flexible command invocation.
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
# Create registry and load commands
|
|
35
|
+
registry = CommandRegistry()
|
|
36
|
+
registry.load_from_directory(".claude/commands/")
|
|
37
|
+
|
|
38
|
+
# Get a command by name
|
|
39
|
+
commit = registry.get("commit")
|
|
40
|
+
|
|
41
|
+
# Get by alias
|
|
42
|
+
compact = registry.get("comp") # Resolves alias
|
|
43
|
+
|
|
44
|
+
# Register a custom command
|
|
45
|
+
registry.register(my_custom_config)
|
|
46
|
+
|
|
47
|
+
# List all available commands
|
|
48
|
+
for name in registry.list_commands():
|
|
49
|
+
print(name)
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
_instance: CommandRegistry | None = None
|
|
53
|
+
|
|
54
|
+
def __init__(self):
|
|
55
|
+
"""Initialize the registry."""
|
|
56
|
+
self._commands: dict[str, CommandConfig] = {}
|
|
57
|
+
self._aliases: dict[str, str] = {} # alias -> command name
|
|
58
|
+
self._loader: CommandLoader = CommandLoader()
|
|
59
|
+
self._load_paths: list[Path] = []
|
|
60
|
+
|
|
61
|
+
@classmethod
|
|
62
|
+
def get_instance(cls) -> CommandRegistry:
|
|
63
|
+
"""Get the singleton registry instance.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
The global CommandRegistry instance
|
|
67
|
+
|
|
68
|
+
"""
|
|
69
|
+
if cls._instance is None:
|
|
70
|
+
cls._instance = cls()
|
|
71
|
+
return cls._instance
|
|
72
|
+
|
|
73
|
+
@classmethod
|
|
74
|
+
def reset_instance(cls) -> None:
|
|
75
|
+
"""Reset the singleton instance (mainly for testing)."""
|
|
76
|
+
cls._instance = None
|
|
77
|
+
|
|
78
|
+
def register(
|
|
79
|
+
self,
|
|
80
|
+
config: CommandConfig,
|
|
81
|
+
overwrite: bool = False,
|
|
82
|
+
) -> None:
|
|
83
|
+
"""Register a command configuration.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
config: Command configuration to register
|
|
87
|
+
overwrite: If True, overwrite existing command with same name
|
|
88
|
+
|
|
89
|
+
Raises:
|
|
90
|
+
ValueError: If command name already exists and overwrite=False
|
|
91
|
+
|
|
92
|
+
"""
|
|
93
|
+
if config.name in self._commands and not overwrite:
|
|
94
|
+
raise ValueError(
|
|
95
|
+
f"Command '{config.name}' already registered. Use overwrite=True to replace."
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
self._commands[config.name] = config
|
|
99
|
+
|
|
100
|
+
# Register aliases
|
|
101
|
+
for alias in config.aliases:
|
|
102
|
+
if alias in self._aliases and not overwrite:
|
|
103
|
+
logger.warning(
|
|
104
|
+
"Alias '%s' already registered for '%s', skipping",
|
|
105
|
+
alias,
|
|
106
|
+
self._aliases[alias],
|
|
107
|
+
)
|
|
108
|
+
continue
|
|
109
|
+
self._aliases[alias] = config.name
|
|
110
|
+
|
|
111
|
+
logger.debug("Registered command: %s", config.name)
|
|
112
|
+
|
|
113
|
+
def unregister(self, name: str) -> bool:
|
|
114
|
+
"""Unregister a command by name.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
name: Command name to remove
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
True if command was found and removed
|
|
121
|
+
|
|
122
|
+
"""
|
|
123
|
+
if name in self._commands:
|
|
124
|
+
config = self._commands[name]
|
|
125
|
+
|
|
126
|
+
# Remove aliases
|
|
127
|
+
for alias in config.aliases:
|
|
128
|
+
if self._aliases.get(alias) == name:
|
|
129
|
+
del self._aliases[alias]
|
|
130
|
+
|
|
131
|
+
del self._commands[name]
|
|
132
|
+
logger.debug("Unregistered command: %s", name)
|
|
133
|
+
return True
|
|
134
|
+
return False
|
|
135
|
+
|
|
136
|
+
def get(self, name: str) -> CommandConfig | None:
|
|
137
|
+
"""Get a command configuration by name or alias.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
name: Command name or alias
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Command config or None if not found
|
|
144
|
+
|
|
145
|
+
"""
|
|
146
|
+
# Direct lookup
|
|
147
|
+
if name in self._commands:
|
|
148
|
+
return self._commands[name]
|
|
149
|
+
|
|
150
|
+
# Alias lookup
|
|
151
|
+
if name in self._aliases:
|
|
152
|
+
return self._commands.get(self._aliases[name])
|
|
153
|
+
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
def get_required(self, name: str) -> CommandConfig:
|
|
157
|
+
"""Get a command configuration, raising if not found.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
name: Command name or alias
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
Command configuration
|
|
164
|
+
|
|
165
|
+
Raises:
|
|
166
|
+
KeyError: If command not found
|
|
167
|
+
|
|
168
|
+
"""
|
|
169
|
+
config = self.get(name)
|
|
170
|
+
if config is None:
|
|
171
|
+
available = ", ".join(sorted(self._commands.keys()))
|
|
172
|
+
raise KeyError(f"Command '{name}' not found. Available commands: {available}")
|
|
173
|
+
return config
|
|
174
|
+
|
|
175
|
+
def has(self, name: str) -> bool:
|
|
176
|
+
"""Check if a command is registered.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
name: Command name or alias
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
True if command exists
|
|
183
|
+
|
|
184
|
+
"""
|
|
185
|
+
return name in self._commands or name in self._aliases
|
|
186
|
+
|
|
187
|
+
def resolve_alias(self, name: str) -> str:
|
|
188
|
+
"""Resolve an alias to command name.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
name: Name or alias
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
Resolved command name
|
|
195
|
+
|
|
196
|
+
"""
|
|
197
|
+
return self._aliases.get(name, name)
|
|
198
|
+
|
|
199
|
+
def list_commands(self) -> list[str]:
|
|
200
|
+
"""Get list of all registered command names.
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
Sorted list of command names
|
|
204
|
+
|
|
205
|
+
"""
|
|
206
|
+
return sorted(self._commands.keys())
|
|
207
|
+
|
|
208
|
+
def list_aliases(self) -> dict[str, str]:
|
|
209
|
+
"""Get all registered aliases.
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
Dictionary mapping aliases to command names
|
|
213
|
+
|
|
214
|
+
"""
|
|
215
|
+
return dict(self._aliases)
|
|
216
|
+
|
|
217
|
+
def iter_commands(self) -> Iterator[CommandConfig]:
|
|
218
|
+
"""Iterate over all registered commands.
|
|
219
|
+
|
|
220
|
+
Yields:
|
|
221
|
+
Command configurations
|
|
222
|
+
|
|
223
|
+
"""
|
|
224
|
+
for name in sorted(self._commands.keys()):
|
|
225
|
+
yield self._commands[name]
|
|
226
|
+
|
|
227
|
+
def load_from_directory(
|
|
228
|
+
self,
|
|
229
|
+
directory: str | Path,
|
|
230
|
+
recursive: bool = False,
|
|
231
|
+
overwrite: bool = False,
|
|
232
|
+
) -> int:
|
|
233
|
+
"""Load commands from a directory.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
directory: Directory containing .md command files
|
|
237
|
+
recursive: If True, scan subdirectories
|
|
238
|
+
overwrite: If True, overwrite existing commands
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
Number of commands loaded
|
|
242
|
+
|
|
243
|
+
"""
|
|
244
|
+
directory = Path(directory)
|
|
245
|
+
# Track loaded paths for reload (avoid duplicates)
|
|
246
|
+
if directory not in self._load_paths:
|
|
247
|
+
self._load_paths.append(directory)
|
|
248
|
+
|
|
249
|
+
commands = self._loader.load_directory(directory, recursive=recursive)
|
|
250
|
+
|
|
251
|
+
loaded = 0
|
|
252
|
+
for _name, config in commands.items():
|
|
253
|
+
try:
|
|
254
|
+
self.register(config, overwrite=overwrite)
|
|
255
|
+
loaded += 1
|
|
256
|
+
except ValueError as e:
|
|
257
|
+
logger.warning("Skipping command: %s", e)
|
|
258
|
+
|
|
259
|
+
logger.info("Loaded %d command(s) from %s", loaded, directory)
|
|
260
|
+
return loaded
|
|
261
|
+
|
|
262
|
+
def load_from_file(
|
|
263
|
+
self,
|
|
264
|
+
file_path: str | Path,
|
|
265
|
+
overwrite: bool = False,
|
|
266
|
+
) -> CommandConfig:
|
|
267
|
+
"""Load a single command from a file.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
file_path: Path to command markdown file
|
|
271
|
+
overwrite: If True, overwrite existing command
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
Loaded command configuration
|
|
275
|
+
|
|
276
|
+
"""
|
|
277
|
+
config = self._loader.load(file_path)
|
|
278
|
+
self.register(config, overwrite=overwrite)
|
|
279
|
+
return config
|
|
280
|
+
|
|
281
|
+
def load_default_commands(self, overwrite: bool = False) -> int:
|
|
282
|
+
"""Load commands from default directory.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
overwrite: If True, overwrite existing commands
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
Number of commands loaded
|
|
289
|
+
|
|
290
|
+
"""
|
|
291
|
+
default_dir = get_default_commands_directory()
|
|
292
|
+
|
|
293
|
+
if not default_dir.exists():
|
|
294
|
+
logger.info("Default commands directory not found: %s", default_dir)
|
|
295
|
+
return 0
|
|
296
|
+
|
|
297
|
+
return self.load_from_directory(default_dir, overwrite=overwrite)
|
|
298
|
+
|
|
299
|
+
def reload(self) -> int:
|
|
300
|
+
"""Reload all commands from previously loaded directories.
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
Total number of commands after reload
|
|
304
|
+
|
|
305
|
+
"""
|
|
306
|
+
self._commands.clear()
|
|
307
|
+
self._aliases.clear()
|
|
308
|
+
|
|
309
|
+
# Copy _load_paths and clear it to avoid duplicates when load_from_directory appends
|
|
310
|
+
paths_to_reload = list(self._load_paths)
|
|
311
|
+
self._load_paths.clear()
|
|
312
|
+
|
|
313
|
+
for directory in paths_to_reload:
|
|
314
|
+
if directory.exists():
|
|
315
|
+
self.load_from_directory(directory, overwrite=True)
|
|
316
|
+
|
|
317
|
+
return len(self._commands)
|
|
318
|
+
|
|
319
|
+
def get_by_category(self, category: CommandCategory) -> list[CommandConfig]:
|
|
320
|
+
"""Get all commands with a specific category.
|
|
321
|
+
|
|
322
|
+
Args:
|
|
323
|
+
category: Category to filter by
|
|
324
|
+
|
|
325
|
+
Returns:
|
|
326
|
+
List of matching command configs
|
|
327
|
+
|
|
328
|
+
"""
|
|
329
|
+
return [config for config in self._commands.values() if config.category == category]
|
|
330
|
+
|
|
331
|
+
def get_by_tag(self, tag: str) -> list[CommandConfig]:
|
|
332
|
+
"""Get all commands with a specific tag.
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
tag: Tag to filter by
|
|
336
|
+
|
|
337
|
+
Returns:
|
|
338
|
+
List of matching command configs
|
|
339
|
+
|
|
340
|
+
"""
|
|
341
|
+
tag = tag.lower()
|
|
342
|
+
return [
|
|
343
|
+
config
|
|
344
|
+
for config in self._commands.values()
|
|
345
|
+
if tag in [t.lower() for t in config.metadata.tags]
|
|
346
|
+
]
|
|
347
|
+
|
|
348
|
+
def search(self, query: str) -> list[CommandConfig]:
|
|
349
|
+
"""Search commands by name, description, or tags.
|
|
350
|
+
|
|
351
|
+
Args:
|
|
352
|
+
query: Search query
|
|
353
|
+
|
|
354
|
+
Returns:
|
|
355
|
+
List of matching commands
|
|
356
|
+
|
|
357
|
+
"""
|
|
358
|
+
query = query.lower()
|
|
359
|
+
results: list[CommandConfig] = []
|
|
360
|
+
|
|
361
|
+
for config in self._commands.values():
|
|
362
|
+
if query in config.name.lower():
|
|
363
|
+
results.append(config)
|
|
364
|
+
elif query in config.description.lower():
|
|
365
|
+
results.append(config)
|
|
366
|
+
elif any(query in tag.lower() for tag in config.metadata.tags):
|
|
367
|
+
results.append(config)
|
|
368
|
+
|
|
369
|
+
return results
|
|
370
|
+
|
|
371
|
+
def get_summary(self) -> dict[str, Any]:
|
|
372
|
+
"""Get a summary of registered commands.
|
|
373
|
+
|
|
374
|
+
Returns:
|
|
375
|
+
Summary dictionary
|
|
376
|
+
|
|
377
|
+
"""
|
|
378
|
+
by_category: dict[str, int] = {}
|
|
379
|
+
|
|
380
|
+
for config in self._commands.values():
|
|
381
|
+
cat = config.category.value
|
|
382
|
+
by_category[cat] = by_category.get(cat, 0) + 1
|
|
383
|
+
|
|
384
|
+
return {
|
|
385
|
+
"total_commands": len(self._commands),
|
|
386
|
+
"total_aliases": len(self._aliases),
|
|
387
|
+
"command_names": self.list_commands(),
|
|
388
|
+
"by_category": by_category,
|
|
389
|
+
"load_paths": [str(p) for p in self._load_paths],
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
def format_help(self) -> str:
|
|
393
|
+
"""Format help text listing all commands.
|
|
394
|
+
|
|
395
|
+
Returns:
|
|
396
|
+
Formatted help string
|
|
397
|
+
|
|
398
|
+
"""
|
|
399
|
+
lines = ["# Available Commands", ""]
|
|
400
|
+
|
|
401
|
+
# Group by category
|
|
402
|
+
by_category: dict[CommandCategory, list[CommandConfig]] = {}
|
|
403
|
+
for config in self._commands.values():
|
|
404
|
+
cat = config.category
|
|
405
|
+
if cat not in by_category:
|
|
406
|
+
by_category[cat] = []
|
|
407
|
+
by_category[cat].append(config)
|
|
408
|
+
|
|
409
|
+
for category in CommandCategory:
|
|
410
|
+
commands = by_category.get(category, [])
|
|
411
|
+
if not commands:
|
|
412
|
+
continue
|
|
413
|
+
|
|
414
|
+
lines.append(f"## {category.value.title()}")
|
|
415
|
+
lines.append("")
|
|
416
|
+
|
|
417
|
+
for config in sorted(commands, key=lambda c: c.name):
|
|
418
|
+
lines.append(config.format_for_display())
|
|
419
|
+
|
|
420
|
+
lines.append("")
|
|
421
|
+
|
|
422
|
+
return "\n".join(lines)
|
|
423
|
+
|
|
424
|
+
def clear(self) -> None:
|
|
425
|
+
"""Clear all registered commands."""
|
|
426
|
+
self._commands.clear()
|
|
427
|
+
self._aliases.clear()
|
|
428
|
+
self._load_paths.clear()
|
|
429
|
+
logger.debug("Cleared command registry")
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Empathy Framework Configuration Module
|
|
2
|
+
|
|
3
|
+
Provides unified configuration models for agents, wizards, and workflows.
|
|
4
|
+
|
|
5
|
+
Copyright 2025 Smart-AI-Memory
|
|
6
|
+
Licensed under Fair Source License 0.9
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from attune_llm.config.unified import (
|
|
10
|
+
AgentOperationError,
|
|
11
|
+
BookProductionConfig,
|
|
12
|
+
MemDocsConfig,
|
|
13
|
+
ModelTier,
|
|
14
|
+
Provider,
|
|
15
|
+
RedisConfig,
|
|
16
|
+
UnifiedAgentConfig,
|
|
17
|
+
WorkflowMode,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"AgentOperationError",
|
|
22
|
+
"BookProductionConfig",
|
|
23
|
+
"MemDocsConfig",
|
|
24
|
+
"ModelTier",
|
|
25
|
+
"Provider",
|
|
26
|
+
"RedisConfig",
|
|
27
|
+
"UnifiedAgentConfig",
|
|
28
|
+
"WorkflowMode",
|
|
29
|
+
]
|