attune-ai 2.1.5__py3-none-any.whl → 2.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. attune/cli/__init__.py +3 -59
  2. attune/cli/commands/batch.py +4 -12
  3. attune/cli/commands/cache.py +8 -16
  4. attune/cli/commands/provider.py +17 -0
  5. attune/cli/commands/routing.py +3 -1
  6. attune/cli/commands/setup.py +122 -0
  7. attune/cli/commands/tier.py +1 -3
  8. attune/cli/commands/workflow.py +31 -0
  9. attune/cli/parsers/cache.py +1 -0
  10. attune/cli/parsers/help.py +1 -3
  11. attune/cli/parsers/provider.py +7 -0
  12. attune/cli/parsers/routing.py +1 -3
  13. attune/cli/parsers/setup.py +7 -0
  14. attune/cli/parsers/status.py +1 -3
  15. attune/cli/parsers/tier.py +1 -3
  16. attune/cli_minimal.py +9 -3
  17. attune/cli_router.py +9 -7
  18. attune/cli_unified.py +3 -0
  19. attune/dashboard/app.py +3 -1
  20. attune/dashboard/simple_server.py +3 -1
  21. attune/dashboard/standalone_server.py +7 -3
  22. attune/mcp/server.py +54 -102
  23. attune/memory/long_term.py +0 -2
  24. attune/memory/short_term/__init__.py +84 -0
  25. attune/memory/short_term/base.py +465 -0
  26. attune/memory/short_term/batch.py +219 -0
  27. attune/memory/short_term/caching.py +227 -0
  28. attune/memory/short_term/conflicts.py +265 -0
  29. attune/memory/short_term/cross_session.py +122 -0
  30. attune/memory/short_term/facade.py +653 -0
  31. attune/memory/short_term/pagination.py +207 -0
  32. attune/memory/short_term/patterns.py +271 -0
  33. attune/memory/short_term/pubsub.py +286 -0
  34. attune/memory/short_term/queues.py +244 -0
  35. attune/memory/short_term/security.py +300 -0
  36. attune/memory/short_term/sessions.py +250 -0
  37. attune/memory/short_term/streams.py +242 -0
  38. attune/memory/short_term/timelines.py +234 -0
  39. attune/memory/short_term/transactions.py +184 -0
  40. attune/memory/short_term/working.py +252 -0
  41. attune/meta_workflows/cli_commands/__init__.py +3 -0
  42. attune/meta_workflows/cli_commands/agent_commands.py +0 -4
  43. attune/meta_workflows/cli_commands/analytics_commands.py +0 -6
  44. attune/meta_workflows/cli_commands/config_commands.py +0 -5
  45. attune/meta_workflows/cli_commands/memory_commands.py +0 -5
  46. attune/meta_workflows/cli_commands/template_commands.py +0 -5
  47. attune/meta_workflows/cli_commands/workflow_commands.py +0 -6
  48. attune/meta_workflows/plan_generator.py +2 -4
  49. attune/models/adaptive_routing.py +4 -8
  50. attune/models/auth_cli.py +3 -9
  51. attune/models/auth_strategy.py +2 -4
  52. attune/models/telemetry/analytics.py +0 -2
  53. attune/models/telemetry/backend.py +0 -3
  54. attune/models/telemetry/storage.py +0 -2
  55. attune/monitoring/alerts.py +6 -10
  56. attune/orchestration/_strategies/__init__.py +156 -0
  57. attune/orchestration/_strategies/base.py +227 -0
  58. attune/orchestration/_strategies/conditional_strategies.py +365 -0
  59. attune/orchestration/_strategies/conditions.py +369 -0
  60. attune/orchestration/_strategies/core_strategies.py +479 -0
  61. attune/orchestration/_strategies/data_classes.py +64 -0
  62. attune/orchestration/_strategies/nesting.py +233 -0
  63. attune/orchestration/execution_strategies.py +58 -1567
  64. attune/orchestration/meta_orchestrator.py +1 -3
  65. attune/project_index/scanner.py +1 -3
  66. attune/project_index/scanner_parallel.py +7 -5
  67. attune/socratic/storage.py +2 -4
  68. attune/socratic_router.py +1 -3
  69. attune/telemetry/agent_coordination.py +9 -3
  70. attune/telemetry/agent_tracking.py +16 -3
  71. attune/telemetry/approval_gates.py +22 -5
  72. attune/telemetry/cli.py +1 -3
  73. attune/telemetry/commands/dashboard_commands.py +24 -8
  74. attune/telemetry/event_streaming.py +8 -2
  75. attune/telemetry/feedback_loop.py +10 -2
  76. attune/tools.py +2 -1
  77. attune/workflow_commands.py +1 -3
  78. attune/workflow_patterns/structural.py +4 -8
  79. attune/workflows/__init__.py +54 -10
  80. attune/workflows/autonomous_test_gen.py +158 -102
  81. attune/workflows/base.py +48 -672
  82. attune/workflows/batch_processing.py +1 -3
  83. attune/workflows/compat.py +156 -0
  84. attune/workflows/cost_mixin.py +141 -0
  85. attune/workflows/data_classes.py +92 -0
  86. attune/workflows/document_gen/workflow.py +11 -14
  87. attune/workflows/history.py +16 -9
  88. attune/workflows/llm_base.py +1 -3
  89. attune/workflows/migration.py +432 -0
  90. attune/workflows/output.py +2 -7
  91. attune/workflows/parsing_mixin.py +427 -0
  92. attune/workflows/perf_audit.py +3 -1
  93. attune/workflows/progress.py +9 -11
  94. attune/workflows/release_prep.py +5 -1
  95. attune/workflows/routing.py +0 -2
  96. attune/workflows/secure_release.py +4 -1
  97. attune/workflows/security_audit.py +20 -14
  98. attune/workflows/security_audit_phase3.py +28 -22
  99. attune/workflows/seo_optimization.py +27 -27
  100. attune/workflows/test_gen/test_templates.py +1 -4
  101. attune/workflows/test_gen/workflow.py +0 -2
  102. attune/workflows/test_gen_behavioral.py +6 -19
  103. attune/workflows/test_gen_parallel.py +8 -6
  104. {attune_ai-2.1.5.dist-info → attune_ai-2.2.1.dist-info}/METADATA +4 -3
  105. {attune_ai-2.1.5.dist-info → attune_ai-2.2.1.dist-info}/RECORD +121 -96
  106. {attune_ai-2.1.5.dist-info → attune_ai-2.2.1.dist-info}/entry_points.txt +0 -2
  107. attune_healthcare/monitors/monitoring/__init__.py +9 -9
  108. attune_llm/agent_factory/__init__.py +6 -6
  109. attune_llm/agent_factory/adapters/haystack_adapter.py +1 -4
  110. attune_llm/commands/__init__.py +10 -10
  111. attune_llm/commands/models.py +3 -3
  112. attune_llm/config/__init__.py +8 -8
  113. attune_llm/learning/__init__.py +3 -3
  114. attune_llm/learning/extractor.py +5 -3
  115. attune_llm/learning/storage.py +5 -3
  116. attune_llm/security/__init__.py +17 -17
  117. attune_llm/utils/tokens.py +3 -1
  118. attune/cli_legacy.py +0 -3978
  119. attune/memory/short_term.py +0 -2192
  120. attune/workflows/manage_docs.py +0 -87
  121. attune/workflows/test5.py +0 -125
  122. {attune_ai-2.1.5.dist-info → attune_ai-2.2.1.dist-info}/WHEEL +0 -0
  123. {attune_ai-2.1.5.dist-info → attune_ai-2.2.1.dist-info}/licenses/LICENSE +0 -0
  124. {attune_ai-2.1.5.dist-info → attune_ai-2.2.1.dist-info}/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +0 -0
  125. {attune_ai-2.1.5.dist-info → attune_ai-2.2.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,156 @@
1
+ """Execution strategies for agent composition patterns.
2
+
3
+ This submodule implements the grammar rules for composing agents:
4
+ 1. Sequential (A → B → C)
5
+ 2. Parallel (A || B || C)
6
+ 3. Debate (A ⇄ B ⇄ C → Synthesis)
7
+ 4. Teaching (Junior → Expert validation)
8
+ 5. Refinement (Draft → Review → Polish)
9
+ 6. Adaptive (Classifier → Specialist)
10
+ 7. Conditional (if X then A else B) - branching based on gates
11
+
12
+ This package provides modular organization of execution strategies:
13
+ - data_classes: AgentResult, StrategyResult
14
+ - conditions: ConditionType, Condition, Branch, ConditionEvaluator
15
+ - nesting: WorkflowReference, InlineWorkflow, NestingContext, WorkflowDefinition
16
+ - base: ExecutionStrategy ABC
17
+ - core_strategies: Sequential, Parallel, Debate, Teaching, Refinement, Adaptive
18
+ - conditional_strategies: Conditional, MultiConditional, Nested, NestedSequential
19
+ - advanced: ToolEnhanced, PromptCached, etc. (TODO)
20
+
21
+ Copyright 2025 Smart-AI-Memory
22
+ Licensed under Fair Source License 0.9
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ # Base strategy class
28
+ from .base import ExecutionStrategy
29
+
30
+ # Conditional and nested strategies
31
+ from .conditional_strategies import (
32
+ ConditionalStrategy,
33
+ MultiConditionalStrategy,
34
+ NestedSequentialStrategy,
35
+ NestedStrategy,
36
+ StepDefinition,
37
+ )
38
+
39
+ # Condition types and evaluator
40
+ from .conditions import Branch, Condition, ConditionEvaluator, ConditionType
41
+
42
+ # Core strategies
43
+ from .core_strategies import (
44
+ AdaptiveStrategy,
45
+ DebateStrategy,
46
+ ParallelStrategy,
47
+ RefinementStrategy,
48
+ SequentialStrategy,
49
+ TeachingStrategy,
50
+ )
51
+
52
+ # Data classes
53
+ from .data_classes import AgentResult, StrategyResult
54
+
55
+ # Nesting support
56
+ from .nesting import (
57
+ WORKFLOW_REGISTRY,
58
+ InlineWorkflow,
59
+ NestingContext,
60
+ WorkflowDefinition,
61
+ WorkflowReference,
62
+ get_workflow,
63
+ register_workflow,
64
+ )
65
+
66
+ # Strategy registry for lookup by name (partial - advanced strategies added in main module)
67
+ _STRATEGY_REGISTRY: dict[str, type[ExecutionStrategy]] = {
68
+ # Core patterns (1-6)
69
+ "sequential": SequentialStrategy,
70
+ "parallel": ParallelStrategy,
71
+ "debate": DebateStrategy,
72
+ "teaching": TeachingStrategy,
73
+ "refinement": RefinementStrategy,
74
+ "adaptive": AdaptiveStrategy,
75
+ # Conditional patterns (7+)
76
+ "conditional": ConditionalStrategy,
77
+ "multi_conditional": MultiConditionalStrategy,
78
+ "nested": NestedStrategy,
79
+ "nested_sequential": NestedSequentialStrategy,
80
+ }
81
+
82
+
83
+ def get_strategy(strategy_name: str) -> ExecutionStrategy:
84
+ """Get strategy instance by name.
85
+
86
+ Args:
87
+ strategy_name: Strategy name (e.g., "sequential", "parallel")
88
+
89
+ Returns:
90
+ ExecutionStrategy instance
91
+
92
+ Raises:
93
+ ValueError: If strategy name is invalid
94
+
95
+ Example:
96
+ >>> strategy = get_strategy("sequential")
97
+ >>> isinstance(strategy, SequentialStrategy)
98
+ True
99
+ """
100
+ if strategy_name not in _STRATEGY_REGISTRY:
101
+ raise ValueError(
102
+ f"Unknown strategy: {strategy_name}. Available: {list(_STRATEGY_REGISTRY.keys())}"
103
+ )
104
+
105
+ strategy_class = _STRATEGY_REGISTRY[strategy_name]
106
+ return strategy_class()
107
+
108
+
109
+ def register_strategy(name: str, strategy_class: type[ExecutionStrategy]) -> None:
110
+ """Register a strategy class by name.
111
+
112
+ Used by main module to add advanced strategies.
113
+
114
+ Args:
115
+ name: Strategy name
116
+ strategy_class: Strategy class
117
+ """
118
+ _STRATEGY_REGISTRY[name] = strategy_class
119
+
120
+
121
+ __all__ = [
122
+ # Data classes
123
+ "AgentResult",
124
+ "StrategyResult",
125
+ # Conditions
126
+ "Branch",
127
+ "Condition",
128
+ "ConditionEvaluator",
129
+ "ConditionType",
130
+ # Nesting
131
+ "InlineWorkflow",
132
+ "NestingContext",
133
+ "WORKFLOW_REGISTRY",
134
+ "WorkflowDefinition",
135
+ "WorkflowReference",
136
+ "get_workflow",
137
+ "register_workflow",
138
+ # Base strategy
139
+ "ExecutionStrategy",
140
+ # Core strategies
141
+ "AdaptiveStrategy",
142
+ "DebateStrategy",
143
+ "ParallelStrategy",
144
+ "RefinementStrategy",
145
+ "SequentialStrategy",
146
+ "TeachingStrategy",
147
+ # Conditional strategies
148
+ "ConditionalStrategy",
149
+ "MultiConditionalStrategy",
150
+ "NestedSequentialStrategy",
151
+ "NestedStrategy",
152
+ "StepDefinition",
153
+ # Functions
154
+ "get_strategy",
155
+ "register_strategy",
156
+ ]
@@ -0,0 +1,227 @@
1
+ """Base class for agent composition strategies.
2
+
3
+ This module defines the ExecutionStrategy abstract base class that all
4
+ strategy implementations must inherit from.
5
+
6
+ Security:
7
+ - All agent outputs validated before passing to next agent
8
+ - No eval() or exec() usage
9
+ - Timeout enforcement at strategy level
10
+
11
+ Copyright 2025 Smart-AI-Memory
12
+ Licensed under Fair Source License 0.9
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import logging
18
+ from abc import ABC, abstractmethod
19
+ from typing import TYPE_CHECKING, Any
20
+
21
+ from .data_classes import AgentResult, StrategyResult
22
+
23
+ if TYPE_CHECKING:
24
+ from ..agent_templates import AgentTemplate
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+
29
+ class ExecutionStrategy(ABC):
30
+ """Base class for agent composition strategies.
31
+
32
+ All strategies must implement execute() method to define
33
+ how agents are coordinated and results aggregated.
34
+ """
35
+
36
+ @abstractmethod
37
+ async def execute(self, agents: list[AgentTemplate], context: dict[str, Any]) -> StrategyResult:
38
+ """Execute agents using this strategy.
39
+
40
+ Args:
41
+ agents: List of agent templates to execute
42
+ context: Initial context for execution
43
+
44
+ Returns:
45
+ StrategyResult with aggregated outputs
46
+
47
+ Raises:
48
+ ValueError: If agents list is empty
49
+ TimeoutError: If execution exceeds timeout
50
+ """
51
+ pass
52
+
53
+ async def _execute_agent(self, agent: AgentTemplate, context: dict[str, Any]) -> AgentResult:
54
+ """Execute a single agent with real analysis tools.
55
+
56
+ Maps agent capabilities to real tool implementations and executes them.
57
+
58
+ Args:
59
+ agent: Agent template to execute
60
+ context: Execution context
61
+
62
+ Returns:
63
+ AgentResult with execution outcome
64
+ """
65
+ import time
66
+
67
+ from ..real_tools import (
68
+ RealCodeQualityAnalyzer,
69
+ RealCoverageAnalyzer,
70
+ RealDocumentationAnalyzer,
71
+ RealSecurityAuditor,
72
+ )
73
+
74
+ logger.info(f"Executing agent: {agent.id} ({agent.role})")
75
+ start_time = time.perf_counter()
76
+
77
+ # Get project root from context
78
+ project_root = context.get("project_root", ".")
79
+ target_path = context.get("target_path", "src")
80
+
81
+ try:
82
+ # Map agent ID to real tool implementation
83
+ if agent.id == "security_auditor" or "security" in agent.role.lower():
84
+ auditor = RealSecurityAuditor(project_root)
85
+ report = auditor.audit(target_path)
86
+
87
+ output = {
88
+ "agent_role": agent.role,
89
+ "total_issues": report.total_issues,
90
+ "critical_issues": report.critical_count, # Match workflow field name
91
+ "high_issues": report.high_count, # Match workflow field name
92
+ "medium_issues": report.medium_count, # Match workflow field name
93
+ "passed": report.passed,
94
+ "issues_by_file": report.issues_by_file,
95
+ }
96
+ success = report.passed
97
+ confidence = 1.0 if report.total_issues == 0 else 0.7
98
+
99
+ elif agent.id == "test_coverage_analyzer" or "coverage" in agent.role.lower():
100
+ analyzer = RealCoverageAnalyzer(project_root)
101
+ report = analyzer.analyze() # Analyzes all packages automatically
102
+
103
+ output = {
104
+ "agent_role": agent.role,
105
+ "coverage_percent": report.total_coverage, # Match workflow field name
106
+ "total_coverage": report.total_coverage, # Keep for compatibility
107
+ "files_analyzed": report.files_analyzed,
108
+ "uncovered_files": report.uncovered_files,
109
+ "passed": report.total_coverage >= 80.0,
110
+ }
111
+ success = report.total_coverage >= 80.0
112
+ confidence = min(report.total_coverage / 100.0, 1.0)
113
+
114
+ elif agent.id == "code_reviewer" or "quality" in agent.role.lower():
115
+ analyzer = RealCodeQualityAnalyzer(project_root)
116
+ report = analyzer.analyze(target_path)
117
+
118
+ output = {
119
+ "agent_role": agent.role,
120
+ "quality_score": report.quality_score,
121
+ "ruff_issues": report.ruff_issues,
122
+ "mypy_issues": report.mypy_issues,
123
+ "total_files": report.total_files,
124
+ "passed": report.passed,
125
+ }
126
+ success = report.passed
127
+ confidence = report.quality_score / 10.0
128
+
129
+ elif agent.id == "documentation_writer" or "documentation" in agent.role.lower():
130
+ analyzer = RealDocumentationAnalyzer(project_root)
131
+ report = analyzer.analyze(target_path)
132
+
133
+ output = {
134
+ "agent_role": agent.role,
135
+ "completeness": report.completeness_percentage,
136
+ "coverage_percent": report.completeness_percentage, # Match Release Prep field name
137
+ "total_functions": report.total_functions,
138
+ "documented_functions": report.documented_functions,
139
+ "total_classes": report.total_classes,
140
+ "documented_classes": report.documented_classes,
141
+ "missing_docstrings": report.missing_docstrings,
142
+ "passed": report.passed,
143
+ }
144
+ success = report.passed
145
+ confidence = report.completeness_percentage / 100.0
146
+
147
+ elif agent.id == "performance_optimizer" or "performance" in agent.role.lower():
148
+ # Performance analysis placeholder - mark as passed for now
149
+ # TODO: Implement real performance profiling
150
+ logger.warning("Performance analysis not yet implemented, returning placeholder")
151
+ output = {
152
+ "agent_role": agent.role,
153
+ "message": "Performance analysis not yet implemented",
154
+ "passed": True,
155
+ "placeholder": True,
156
+ }
157
+ success = True
158
+ confidence = 1.0
159
+
160
+ elif agent.id == "test_generator":
161
+ # Test generation requires different handling (LLM-based)
162
+ logger.info("Test generation requires manual invocation, returning placeholder")
163
+ output = {
164
+ "agent_role": agent.role,
165
+ "message": "Test generation requires manual invocation",
166
+ "passed": True,
167
+ }
168
+ success = True
169
+ confidence = 0.8
170
+
171
+ else:
172
+ # Unknown agent type - log warning and return placeholder
173
+ logger.warning(f"Unknown agent type: {agent.id}, returning placeholder")
174
+ output = {
175
+ "agent_role": agent.role,
176
+ "agent_id": agent.id,
177
+ "message": "Unknown agent type - no real implementation",
178
+ "passed": True,
179
+ }
180
+ success = True
181
+ confidence = 0.5
182
+
183
+ duration = time.perf_counter() - start_time
184
+
185
+ logger.info(
186
+ f"Agent {agent.id} completed: success={success}, "
187
+ f"confidence={confidence:.2f}, duration={duration:.2f}s"
188
+ )
189
+
190
+ return AgentResult(
191
+ agent_id=agent.id,
192
+ success=success,
193
+ output=output,
194
+ confidence=confidence,
195
+ duration_seconds=duration,
196
+ )
197
+
198
+ except Exception as e:
199
+ duration = time.perf_counter() - start_time
200
+ logger.error(f"Agent {agent.id} failed: {e}")
201
+
202
+ return AgentResult(
203
+ agent_id=agent.id,
204
+ success=False,
205
+ output={"agent_role": agent.role, "error_details": str(e)},
206
+ error=str(e),
207
+ confidence=0.0,
208
+ duration_seconds=duration,
209
+ )
210
+
211
+ def _aggregate_results(self, results: list[AgentResult]) -> dict[str, Any]:
212
+ """Aggregate results from multiple agents.
213
+
214
+ Args:
215
+ results: List of agent results
216
+
217
+ Returns:
218
+ Aggregated output dictionary
219
+ """
220
+ return {
221
+ "num_agents": len(results),
222
+ "all_succeeded": all(r.success for r in results),
223
+ "avg_confidence": (
224
+ sum(r.confidence for r in results) / len(results) if results else 0.0
225
+ ),
226
+ "outputs": [r.output for r in results],
227
+ }