crackerjack 0.31.10__py3-none-any.whl → 0.31.12__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.
Potentially problematic release.
This version of crackerjack might be problematic. Click here for more details.
- crackerjack/CLAUDE.md +288 -705
- crackerjack/__main__.py +22 -8
- crackerjack/agents/__init__.py +0 -3
- crackerjack/agents/architect_agent.py +0 -43
- crackerjack/agents/base.py +1 -9
- crackerjack/agents/coordinator.py +2 -148
- crackerjack/agents/documentation_agent.py +109 -81
- crackerjack/agents/dry_agent.py +122 -97
- crackerjack/agents/formatting_agent.py +3 -16
- crackerjack/agents/import_optimization_agent.py +1174 -130
- crackerjack/agents/performance_agent.py +956 -188
- crackerjack/agents/performance_helpers.py +229 -0
- crackerjack/agents/proactive_agent.py +1 -48
- crackerjack/agents/refactoring_agent.py +516 -246
- crackerjack/agents/refactoring_helpers.py +282 -0
- crackerjack/agents/security_agent.py +393 -90
- crackerjack/agents/test_creation_agent.py +1776 -120
- crackerjack/agents/test_specialist_agent.py +59 -15
- crackerjack/agents/tracker.py +0 -102
- crackerjack/api.py +145 -37
- crackerjack/cli/handlers.py +48 -30
- crackerjack/cli/interactive.py +11 -11
- crackerjack/cli/options.py +66 -4
- crackerjack/code_cleaner.py +808 -148
- crackerjack/config/global_lock_config.py +110 -0
- crackerjack/config/hooks.py +43 -64
- crackerjack/core/async_workflow_orchestrator.py +247 -97
- crackerjack/core/autofix_coordinator.py +192 -109
- crackerjack/core/enhanced_container.py +46 -63
- crackerjack/core/file_lifecycle.py +549 -0
- crackerjack/core/performance.py +9 -8
- crackerjack/core/performance_monitor.py +395 -0
- crackerjack/core/phase_coordinator.py +281 -94
- crackerjack/core/proactive_workflow.py +9 -58
- crackerjack/core/resource_manager.py +501 -0
- crackerjack/core/service_watchdog.py +490 -0
- crackerjack/core/session_coordinator.py +4 -8
- crackerjack/core/timeout_manager.py +504 -0
- crackerjack/core/websocket_lifecycle.py +475 -0
- crackerjack/core/workflow_orchestrator.py +343 -209
- crackerjack/dynamic_config.py +47 -6
- crackerjack/errors.py +3 -4
- crackerjack/executors/async_hook_executor.py +63 -13
- crackerjack/executors/cached_hook_executor.py +14 -14
- crackerjack/executors/hook_executor.py +100 -37
- crackerjack/executors/hook_lock_manager.py +856 -0
- crackerjack/executors/individual_hook_executor.py +120 -86
- crackerjack/intelligence/__init__.py +0 -7
- crackerjack/intelligence/adaptive_learning.py +13 -86
- crackerjack/intelligence/agent_orchestrator.py +15 -78
- crackerjack/intelligence/agent_registry.py +12 -59
- crackerjack/intelligence/agent_selector.py +31 -92
- crackerjack/intelligence/integration.py +1 -41
- crackerjack/interactive.py +9 -9
- crackerjack/managers/async_hook_manager.py +25 -8
- crackerjack/managers/hook_manager.py +9 -9
- crackerjack/managers/publish_manager.py +57 -59
- crackerjack/managers/test_command_builder.py +6 -36
- crackerjack/managers/test_executor.py +9 -61
- crackerjack/managers/test_manager.py +17 -63
- crackerjack/managers/test_manager_backup.py +77 -127
- crackerjack/managers/test_progress.py +4 -23
- crackerjack/mcp/cache.py +5 -12
- crackerjack/mcp/client_runner.py +10 -10
- crackerjack/mcp/context.py +64 -6
- crackerjack/mcp/dashboard.py +14 -11
- crackerjack/mcp/enhanced_progress_monitor.py +55 -55
- crackerjack/mcp/file_monitor.py +72 -42
- crackerjack/mcp/progress_components.py +103 -84
- crackerjack/mcp/progress_monitor.py +122 -49
- crackerjack/mcp/rate_limiter.py +12 -12
- crackerjack/mcp/server_core.py +16 -22
- crackerjack/mcp/service_watchdog.py +26 -26
- crackerjack/mcp/state.py +15 -0
- crackerjack/mcp/tools/core_tools.py +95 -39
- crackerjack/mcp/tools/error_analyzer.py +6 -32
- crackerjack/mcp/tools/execution_tools.py +1 -56
- crackerjack/mcp/tools/execution_tools_backup.py +35 -131
- crackerjack/mcp/tools/intelligence_tool_registry.py +0 -36
- crackerjack/mcp/tools/intelligence_tools.py +2 -55
- crackerjack/mcp/tools/monitoring_tools.py +308 -145
- crackerjack/mcp/tools/proactive_tools.py +12 -42
- crackerjack/mcp/tools/progress_tools.py +23 -15
- crackerjack/mcp/tools/utility_tools.py +3 -40
- crackerjack/mcp/tools/workflow_executor.py +40 -60
- crackerjack/mcp/websocket/app.py +0 -3
- crackerjack/mcp/websocket/endpoints.py +206 -268
- crackerjack/mcp/websocket/jobs.py +213 -66
- crackerjack/mcp/websocket/server.py +84 -6
- crackerjack/mcp/websocket/websocket_handler.py +137 -29
- crackerjack/models/config_adapter.py +3 -16
- crackerjack/models/protocols.py +162 -3
- crackerjack/models/resource_protocols.py +454 -0
- crackerjack/models/task.py +3 -3
- crackerjack/monitoring/__init__.py +0 -0
- crackerjack/monitoring/ai_agent_watchdog.py +25 -71
- crackerjack/monitoring/regression_prevention.py +28 -87
- crackerjack/orchestration/advanced_orchestrator.py +44 -78
- crackerjack/orchestration/coverage_improvement.py +10 -60
- crackerjack/orchestration/execution_strategies.py +16 -16
- crackerjack/orchestration/test_progress_streamer.py +61 -53
- crackerjack/plugins/base.py +1 -1
- crackerjack/plugins/managers.py +22 -20
- crackerjack/py313.py +65 -21
- crackerjack/services/backup_service.py +467 -0
- crackerjack/services/bounded_status_operations.py +627 -0
- crackerjack/services/cache.py +7 -9
- crackerjack/services/config.py +35 -52
- crackerjack/services/config_integrity.py +5 -16
- crackerjack/services/config_merge.py +542 -0
- crackerjack/services/contextual_ai_assistant.py +17 -19
- crackerjack/services/coverage_ratchet.py +44 -73
- crackerjack/services/debug.py +25 -39
- crackerjack/services/dependency_monitor.py +52 -50
- crackerjack/services/enhanced_filesystem.py +14 -11
- crackerjack/services/file_hasher.py +1 -1
- crackerjack/services/filesystem.py +1 -12
- crackerjack/services/git.py +71 -47
- crackerjack/services/health_metrics.py +31 -27
- crackerjack/services/initialization.py +276 -428
- crackerjack/services/input_validator.py +760 -0
- crackerjack/services/log_manager.py +16 -16
- crackerjack/services/logging.py +7 -6
- crackerjack/services/metrics.py +43 -43
- crackerjack/services/pattern_cache.py +2 -31
- crackerjack/services/pattern_detector.py +26 -63
- crackerjack/services/performance_benchmarks.py +20 -45
- crackerjack/services/regex_patterns.py +2887 -0
- crackerjack/services/regex_utils.py +537 -0
- crackerjack/services/secure_path_utils.py +683 -0
- crackerjack/services/secure_status_formatter.py +534 -0
- crackerjack/services/secure_subprocess.py +605 -0
- crackerjack/services/security.py +47 -10
- crackerjack/services/security_logger.py +492 -0
- crackerjack/services/server_manager.py +109 -50
- crackerjack/services/smart_scheduling.py +8 -25
- crackerjack/services/status_authentication.py +603 -0
- crackerjack/services/status_security_manager.py +442 -0
- crackerjack/services/thread_safe_status_collector.py +546 -0
- crackerjack/services/tool_version_service.py +1 -23
- crackerjack/services/unified_config.py +36 -58
- crackerjack/services/validation_rate_limiter.py +269 -0
- crackerjack/services/version_checker.py +9 -40
- crackerjack/services/websocket_resource_limiter.py +572 -0
- crackerjack/slash_commands/__init__.py +52 -2
- crackerjack/tools/__init__.py +0 -0
- crackerjack/tools/validate_input_validator_patterns.py +262 -0
- crackerjack/tools/validate_regex_patterns.py +198 -0
- {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/METADATA +197 -12
- crackerjack-0.31.12.dist-info/RECORD +178 -0
- crackerjack/cli/facade.py +0 -104
- crackerjack-0.31.10.dist-info/RECORD +0 -149
- {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/WHEEL +0 -0
- {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.31.10.dist-info → crackerjack-0.31.12.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
"""Adaptive Learning System for Agent Selection.
|
|
2
|
-
|
|
3
|
-
Learns from execution results to improve agent selection over time through
|
|
4
|
-
success tracking, capability refinement, and performance optimization.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
1
|
import asyncio
|
|
8
2
|
import json
|
|
9
3
|
import logging
|
|
@@ -19,8 +13,6 @@ from .agent_selector import AgentScore, TaskDescription
|
|
|
19
13
|
|
|
20
14
|
@dataclass
|
|
21
15
|
class ExecutionRecord:
|
|
22
|
-
"""Record of an agent execution."""
|
|
23
|
-
|
|
24
16
|
timestamp: datetime
|
|
25
17
|
agent_name: str
|
|
26
18
|
agent_source: str
|
|
@@ -31,13 +23,11 @@ class ExecutionRecord:
|
|
|
31
23
|
confidence_score: float
|
|
32
24
|
final_score: float
|
|
33
25
|
error_message: str | None = None
|
|
34
|
-
task_hash: str | None = None
|
|
26
|
+
task_hash: str | None = None
|
|
35
27
|
|
|
36
28
|
|
|
37
29
|
@dataclass
|
|
38
30
|
class AgentPerformanceMetrics:
|
|
39
|
-
"""Performance metrics for an agent."""
|
|
40
|
-
|
|
41
31
|
total_executions: int = 0
|
|
42
32
|
successful_executions: int = 0
|
|
43
33
|
failed_executions: int = 0
|
|
@@ -45,25 +35,21 @@ class AgentPerformanceMetrics:
|
|
|
45
35
|
average_confidence: float = 0.0
|
|
46
36
|
success_rate: float = 0.0
|
|
47
37
|
capability_success_rates: dict[str, float] = field(default_factory=dict)
|
|
48
|
-
recent_performance_trend: float = 0.0
|
|
38
|
+
recent_performance_trend: float = 0.0
|
|
49
39
|
last_updated: datetime = field(default_factory=datetime.now)
|
|
50
40
|
|
|
51
41
|
|
|
52
42
|
@dataclass
|
|
53
43
|
class LearningInsight:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
insight_type: str # "capability_strength", "task_pattern", "failure_pattern"
|
|
44
|
+
insight_type: str
|
|
57
45
|
agent_name: str
|
|
58
|
-
confidence: float
|
|
46
|
+
confidence: float
|
|
59
47
|
description: str
|
|
60
48
|
supporting_evidence: dict[str, t.Any]
|
|
61
49
|
discovered_at: datetime = field(default_factory=datetime.now)
|
|
62
50
|
|
|
63
51
|
|
|
64
52
|
class AdaptiveLearningSystem:
|
|
65
|
-
"""System that learns from agent execution results."""
|
|
66
|
-
|
|
67
53
|
def __init__(self, data_dir: Path | None = None) -> None:
|
|
68
54
|
self.logger = logging.getLogger(__name__)
|
|
69
55
|
self.data_dir = data_dir or Path.home() / ".crackerjack" / "intelligence"
|
|
@@ -80,7 +66,6 @@ class AdaptiveLearningSystem:
|
|
|
80
66
|
self._load_existing_data()
|
|
81
67
|
|
|
82
68
|
def _load_existing_data(self) -> None:
|
|
83
|
-
"""Load existing learning data from disk."""
|
|
84
69
|
try:
|
|
85
70
|
self._load_execution_records()
|
|
86
71
|
self._load_agent_metrics()
|
|
@@ -89,7 +74,6 @@ class AdaptiveLearningSystem:
|
|
|
89
74
|
self.logger.warning(f"Error loading existing learning data: {e}")
|
|
90
75
|
|
|
91
76
|
def _load_execution_records(self) -> None:
|
|
92
|
-
"""Load execution records from disk."""
|
|
93
77
|
if not self.execution_log_path.exists():
|
|
94
78
|
return
|
|
95
79
|
|
|
@@ -104,7 +88,6 @@ class AdaptiveLearningSystem:
|
|
|
104
88
|
self.logger.debug(f"Loaded {len(self._execution_records)} execution records")
|
|
105
89
|
|
|
106
90
|
def _load_agent_metrics(self) -> None:
|
|
107
|
-
"""Load agent metrics from disk."""
|
|
108
91
|
if not self.metrics_path.exists():
|
|
109
92
|
return
|
|
110
93
|
|
|
@@ -117,7 +100,6 @@ class AdaptiveLearningSystem:
|
|
|
117
100
|
self.logger.debug(f"Loaded metrics for {len(self._agent_metrics)} agents")
|
|
118
101
|
|
|
119
102
|
def _load_learning_insights(self) -> None:
|
|
120
|
-
"""Load learning insights from disk."""
|
|
121
103
|
if not self.insights_path.exists():
|
|
122
104
|
return
|
|
123
105
|
|
|
@@ -141,9 +123,7 @@ class AdaptiveLearningSystem:
|
|
|
141
123
|
agent_score: AgentScore,
|
|
142
124
|
error_message: str | None = None,
|
|
143
125
|
) -> None:
|
|
144
|
-
"""Record the result of an agent execution."""
|
|
145
126
|
try:
|
|
146
|
-
# Create execution record
|
|
147
127
|
record = ExecutionRecord(
|
|
148
128
|
timestamp=datetime.now(),
|
|
149
129
|
agent_name=agent.metadata.name,
|
|
@@ -160,16 +140,12 @@ class AdaptiveLearningSystem:
|
|
|
160
140
|
task_hash=self._hash_task(task),
|
|
161
141
|
)
|
|
162
142
|
|
|
163
|
-
# Add to records
|
|
164
143
|
self._execution_records.append(record)
|
|
165
144
|
|
|
166
|
-
# Update agent metrics
|
|
167
145
|
await self._update_agent_metrics(record)
|
|
168
146
|
|
|
169
|
-
# Persist to disk
|
|
170
147
|
await self._persist_execution_record(record)
|
|
171
148
|
|
|
172
|
-
# Trigger learning analysis (async)
|
|
173
149
|
asyncio.create_task(self._analyze_and_learn())
|
|
174
150
|
|
|
175
151
|
self.logger.debug(
|
|
@@ -181,11 +157,9 @@ class AdaptiveLearningSystem:
|
|
|
181
157
|
self.logger.error(f"Error recording execution: {e}")
|
|
182
158
|
|
|
183
159
|
def _infer_task_capabilities(self, task: TaskDescription) -> set[AgentCapability]:
|
|
184
|
-
"""Infer capabilities needed for a task (simplified version)."""
|
|
185
160
|
capabilities = set()
|
|
186
161
|
text = task.description.lower()
|
|
187
162
|
|
|
188
|
-
# Capability mapping for efficiency
|
|
189
163
|
capability_keywords = {
|
|
190
164
|
AgentCapability.ARCHITECTURE: ("architect", "design", "structure"),
|
|
191
165
|
AgentCapability.REFACTORING: ("refactor", "clean", "improve"),
|
|
@@ -207,16 +181,11 @@ class AdaptiveLearningSystem:
|
|
|
207
181
|
return capabilities
|
|
208
182
|
|
|
209
183
|
def _hash_task(self, task: TaskDescription) -> str:
|
|
210
|
-
"""Create a hash for grouping similar tasks."""
|
|
211
|
-
# Simple hash based on key words
|
|
212
184
|
words = task.description.lower().split()
|
|
213
|
-
key_words = [w for w in words if len(w) > 3][
|
|
214
|
-
:10
|
|
215
|
-
] # Take first 10 significant words
|
|
185
|
+
key_words = [w for w in words if len(w) > 3][:10]
|
|
216
186
|
return "_".join(sorted(key_words))
|
|
217
187
|
|
|
218
188
|
async def _update_agent_metrics(self, record: ExecutionRecord) -> None:
|
|
219
|
-
"""Update metrics for an agent based on execution record."""
|
|
220
189
|
agent_name = record.agent_name
|
|
221
190
|
metrics = self._ensure_agent_metrics(agent_name)
|
|
222
191
|
|
|
@@ -229,7 +198,6 @@ class AdaptiveLearningSystem:
|
|
|
229
198
|
await self._persist_agent_metrics()
|
|
230
199
|
|
|
231
200
|
def _ensure_agent_metrics(self, agent_name: str) -> AgentPerformanceMetrics:
|
|
232
|
-
"""Ensure agent metrics exist and return them."""
|
|
233
201
|
if agent_name not in self._agent_metrics:
|
|
234
202
|
self._agent_metrics[agent_name] = AgentPerformanceMetrics()
|
|
235
203
|
return self._agent_metrics[agent_name]
|
|
@@ -237,7 +205,6 @@ class AdaptiveLearningSystem:
|
|
|
237
205
|
def _update_basic_counters(
|
|
238
206
|
self, metrics: AgentPerformanceMetrics, record: ExecutionRecord
|
|
239
207
|
) -> None:
|
|
240
|
-
"""Update basic execution counters and success rate."""
|
|
241
208
|
metrics.total_executions += 1
|
|
242
209
|
if record.success:
|
|
243
210
|
metrics.successful_executions += 1
|
|
@@ -248,7 +215,6 @@ class AdaptiveLearningSystem:
|
|
|
248
215
|
def _update_execution_averages(
|
|
249
216
|
self, metrics: AgentPerformanceMetrics, record: ExecutionRecord
|
|
250
217
|
) -> None:
|
|
251
|
-
"""Update execution time and confidence averages."""
|
|
252
218
|
if metrics.total_executions == 1:
|
|
253
219
|
metrics.average_execution_time = record.execution_time
|
|
254
220
|
metrics.average_confidence = record.confidence_score
|
|
@@ -266,7 +232,6 @@ class AdaptiveLearningSystem:
|
|
|
266
232
|
def _update_capability_success_rates(
|
|
267
233
|
self, metrics: AgentPerformanceMetrics, record: ExecutionRecord, agent_name: str
|
|
268
234
|
) -> None:
|
|
269
|
-
"""Update capability-specific success rates."""
|
|
270
235
|
success_value = 1.0 if record.success else 0.0
|
|
271
236
|
|
|
272
237
|
for capability in record.task_capabilities:
|
|
@@ -293,7 +258,6 @@ class AdaptiveLearningSystem:
|
|
|
293
258
|
def _update_performance_trend(
|
|
294
259
|
self, metrics: AgentPerformanceMetrics, agent_name: str
|
|
295
260
|
) -> None:
|
|
296
|
-
"""Update recent performance trend."""
|
|
297
261
|
recent_records = [
|
|
298
262
|
r for r in self._execution_records[-20:] if r.agent_name == agent_name
|
|
299
263
|
][-10:]
|
|
@@ -313,7 +277,6 @@ class AdaptiveLearningSystem:
|
|
|
313
277
|
def _calculate_windowed_success_rates(
|
|
314
278
|
self, recent_records: list[ExecutionRecord]
|
|
315
279
|
) -> list[float]:
|
|
316
|
-
"""Calculate success rates using sliding window."""
|
|
317
280
|
window_size = 3
|
|
318
281
|
success_rates = []
|
|
319
282
|
|
|
@@ -325,7 +288,6 @@ class AdaptiveLearningSystem:
|
|
|
325
288
|
return success_rates
|
|
326
289
|
|
|
327
290
|
async def _persist_execution_record(self, record: ExecutionRecord) -> None:
|
|
328
|
-
"""Persist execution record to disk."""
|
|
329
291
|
try:
|
|
330
292
|
with self.execution_log_path.open("a") as f:
|
|
331
293
|
data = asdict(record)
|
|
@@ -335,7 +297,6 @@ class AdaptiveLearningSystem:
|
|
|
335
297
|
self.logger.error(f"Error persisting execution record: {e}")
|
|
336
298
|
|
|
337
299
|
async def _persist_agent_metrics(self) -> None:
|
|
338
|
-
"""Persist agent metrics to disk."""
|
|
339
300
|
try:
|
|
340
301
|
metrics_data = {}
|
|
341
302
|
for agent_name, metrics in self._agent_metrics.items():
|
|
@@ -350,7 +311,6 @@ class AdaptiveLearningSystem:
|
|
|
350
311
|
self.logger.error(f"Error persisting agent metrics: {e}")
|
|
351
312
|
|
|
352
313
|
async def _persist_learning_insights(self) -> None:
|
|
353
|
-
"""Persist learning insights to disk."""
|
|
354
314
|
try:
|
|
355
315
|
insights_data = []
|
|
356
316
|
for insight in self._learning_insights:
|
|
@@ -365,36 +325,29 @@ class AdaptiveLearningSystem:
|
|
|
365
325
|
self.logger.error(f"Error persisting learning insights: {e}")
|
|
366
326
|
|
|
367
327
|
async def _analyze_and_learn(self) -> None:
|
|
368
|
-
"""Analyze execution data and generate learning insights."""
|
|
369
328
|
try:
|
|
370
329
|
new_insights = []
|
|
371
330
|
|
|
372
|
-
# Analyze capability strengths
|
|
373
331
|
capability_insights = self._analyze_capability_strengths()
|
|
374
332
|
new_insights.extend(capability_insights)
|
|
375
333
|
|
|
376
|
-
# Analyze failure patterns
|
|
377
334
|
failure_insights = self._analyze_failure_patterns()
|
|
378
335
|
new_insights.extend(failure_insights)
|
|
379
336
|
|
|
380
|
-
# Analyze task patterns
|
|
381
337
|
task_pattern_insights = self._analyze_task_patterns()
|
|
382
338
|
new_insights.extend(task_pattern_insights)
|
|
383
339
|
|
|
384
|
-
# Add new insights (avoid duplicates)
|
|
385
340
|
for insight in new_insights:
|
|
386
341
|
if not self._is_duplicate_insight(insight):
|
|
387
342
|
self._learning_insights.append(insight)
|
|
388
343
|
self.logger.debug(f"New learning insight: {insight.description}")
|
|
389
344
|
|
|
390
|
-
# Persist insights
|
|
391
345
|
await self._persist_learning_insights()
|
|
392
346
|
|
|
393
347
|
except Exception as e:
|
|
394
348
|
self.logger.error(f"Error in learning analysis: {e}")
|
|
395
349
|
|
|
396
350
|
def _analyze_capability_strengths(self) -> list[LearningInsight]:
|
|
397
|
-
"""Analyze which agents excel at which capabilities."""
|
|
398
351
|
capability_performance = self._group_capability_performance()
|
|
399
352
|
insights = []
|
|
400
353
|
|
|
@@ -404,7 +357,6 @@ class AdaptiveLearningSystem:
|
|
|
404
357
|
return insights
|
|
405
358
|
|
|
406
359
|
def _group_capability_performance(self) -> dict[str, dict[str, list[bool]]]:
|
|
407
|
-
"""Group execution records by capability and agent."""
|
|
408
360
|
capability_performance = defaultdict(lambda: defaultdict(list))
|
|
409
361
|
|
|
410
362
|
for record in self._execution_records[-100:]:
|
|
@@ -418,19 +370,18 @@ class AdaptiveLearningSystem:
|
|
|
418
370
|
def _find_capability_experts(
|
|
419
371
|
self, capability: str, agents: dict[str, list[bool]]
|
|
420
372
|
) -> list[LearningInsight]:
|
|
421
|
-
"""Find agents with exceptional performance in a specific capability."""
|
|
422
373
|
insights = []
|
|
423
374
|
|
|
424
375
|
for agent_name, successes in agents.items():
|
|
425
|
-
if len(successes) >= 3:
|
|
376
|
+
if len(successes) >= 3:
|
|
426
377
|
success_rate = sum(successes) / len(successes)
|
|
427
378
|
|
|
428
|
-
if success_rate >= 0.9:
|
|
379
|
+
if success_rate >= 0.9:
|
|
429
380
|
insight = LearningInsight(
|
|
430
381
|
insight_type="capability_strength",
|
|
431
382
|
agent_name=agent_name,
|
|
432
383
|
confidence=min(success_rate, len(successes) / 10.0),
|
|
433
|
-
description=f"{agent_name} excels at {capability} tasks (success rate: {success_rate
|
|
384
|
+
description=f"{agent_name} excels at {capability} tasks (success rate: {success_rate: .1 %})",
|
|
434
385
|
supporting_evidence={
|
|
435
386
|
"capability": capability,
|
|
436
387
|
"success_rate": success_rate,
|
|
@@ -443,12 +394,10 @@ class AdaptiveLearningSystem:
|
|
|
443
394
|
return insights
|
|
444
395
|
|
|
445
396
|
def _analyze_failure_patterns(self) -> list[LearningInsight]:
|
|
446
|
-
"""Analyze common failure patterns."""
|
|
447
397
|
failure_patterns = self._group_failure_patterns()
|
|
448
398
|
return self._extract_significant_failure_insights(failure_patterns)
|
|
449
399
|
|
|
450
400
|
def _group_failure_patterns(self) -> dict[str, dict[str, int]]:
|
|
451
|
-
"""Group failure patterns by agent and error type."""
|
|
452
401
|
failure_patterns = defaultdict(lambda: defaultdict(int))
|
|
453
402
|
|
|
454
403
|
for record in self._execution_records[-100:]:
|
|
@@ -464,7 +413,6 @@ class AdaptiveLearningSystem:
|
|
|
464
413
|
def _extract_significant_failure_insights(
|
|
465
414
|
self, failure_patterns: dict[str, dict[str, int]]
|
|
466
415
|
) -> list[LearningInsight]:
|
|
467
|
-
"""Extract significant failure pattern insights."""
|
|
468
416
|
insights = []
|
|
469
417
|
|
|
470
418
|
for agent_name, patterns in failure_patterns.items():
|
|
@@ -476,14 +424,13 @@ class AdaptiveLearningSystem:
|
|
|
476
424
|
def _extract_agent_failure_insights(
|
|
477
425
|
self, agent_name: str, patterns: dict[str, int]
|
|
478
426
|
) -> list[LearningInsight]:
|
|
479
|
-
"""Extract failure insights for a specific agent."""
|
|
480
427
|
total_failures = sum(patterns.values())
|
|
481
|
-
if total_failures < 3:
|
|
428
|
+
if total_failures < 3:
|
|
482
429
|
return []
|
|
483
430
|
|
|
484
431
|
insights = []
|
|
485
432
|
for error_type, count in patterns.items():
|
|
486
|
-
if count / total_failures >= 0.5:
|
|
433
|
+
if count / total_failures >= 0.5:
|
|
487
434
|
insight = self._create_failure_insight(
|
|
488
435
|
agent_name, error_type, count, total_failures
|
|
489
436
|
)
|
|
@@ -494,7 +441,6 @@ class AdaptiveLearningSystem:
|
|
|
494
441
|
def _create_failure_insight(
|
|
495
442
|
self, agent_name: str, error_type: str, count: int, total_failures: int
|
|
496
443
|
) -> LearningInsight:
|
|
497
|
-
"""Create a failure pattern insight."""
|
|
498
444
|
return LearningInsight(
|
|
499
445
|
insight_type="failure_pattern",
|
|
500
446
|
agent_name=agent_name,
|
|
@@ -509,12 +455,11 @@ class AdaptiveLearningSystem:
|
|
|
509
455
|
)
|
|
510
456
|
|
|
511
457
|
def _analyze_task_patterns(self) -> list[LearningInsight]:
|
|
512
|
-
"""Analyze task patterns and agent preferences."""
|
|
513
458
|
task_performance = self._group_task_performance()
|
|
514
459
|
insights = []
|
|
515
460
|
|
|
516
461
|
for task_hash, agents in task_performance.items():
|
|
517
|
-
if len(agents) > 1:
|
|
462
|
+
if len(agents) > 1:
|
|
518
463
|
best_agent, best_rate = self._find_best_performing_agent(agents)
|
|
519
464
|
|
|
520
465
|
if best_agent and best_rate >= 0.8:
|
|
@@ -526,7 +471,6 @@ class AdaptiveLearningSystem:
|
|
|
526
471
|
return insights
|
|
527
472
|
|
|
528
473
|
def _group_task_performance(self) -> dict[str, dict[str, list[bool]]]:
|
|
529
|
-
"""Group task performance by hash and agent."""
|
|
530
474
|
task_performance = defaultdict(lambda: defaultdict(list))
|
|
531
475
|
|
|
532
476
|
for record in self._execution_records[-100:]:
|
|
@@ -540,12 +484,11 @@ class AdaptiveLearningSystem:
|
|
|
540
484
|
def _find_best_performing_agent(
|
|
541
485
|
self, agents: dict[str, list[bool]]
|
|
542
486
|
) -> tuple[str | None, float]:
|
|
543
|
-
"""Find the best performing agent for a task pattern."""
|
|
544
487
|
best_agent = None
|
|
545
488
|
best_rate = 0.0
|
|
546
489
|
|
|
547
490
|
for agent_name, successes in agents.items():
|
|
548
|
-
if len(successes) >= 2:
|
|
491
|
+
if len(successes) >= 2:
|
|
549
492
|
success_rate = sum(successes) / len(successes)
|
|
550
493
|
if success_rate > best_rate:
|
|
551
494
|
best_rate = success_rate
|
|
@@ -560,7 +503,6 @@ class AdaptiveLearningSystem:
|
|
|
560
503
|
best_rate: float,
|
|
561
504
|
agents: dict[str, list[bool]],
|
|
562
505
|
) -> LearningInsight:
|
|
563
|
-
"""Create a task pattern insight."""
|
|
564
506
|
example_task = next(
|
|
565
507
|
(
|
|
566
508
|
r.task_description
|
|
@@ -584,7 +526,6 @@ class AdaptiveLearningSystem:
|
|
|
584
526
|
)
|
|
585
527
|
|
|
586
528
|
def _categorize_error(self, error_message: str) -> str:
|
|
587
|
-
"""Categorize error message into type."""
|
|
588
529
|
error_lower = error_message.lower()
|
|
589
530
|
|
|
590
531
|
if "timeout" in error_lower:
|
|
@@ -603,7 +544,6 @@ class AdaptiveLearningSystem:
|
|
|
603
544
|
return "other"
|
|
604
545
|
|
|
605
546
|
def _is_duplicate_insight(self, new_insight: LearningInsight) -> bool:
|
|
606
|
-
"""Check if insight already exists."""
|
|
607
547
|
for existing in self._learning_insights:
|
|
608
548
|
if (
|
|
609
549
|
existing.insight_type == new_insight.insight_type
|
|
@@ -618,7 +558,6 @@ class AdaptiveLearningSystem:
|
|
|
618
558
|
task: TaskDescription,
|
|
619
559
|
candidate_agents: list[str],
|
|
620
560
|
) -> dict[str, float]:
|
|
621
|
-
"""Get recommendations for agents based on learning."""
|
|
622
561
|
task_capabilities = [cap.value for cap in self._infer_task_capabilities(task)]
|
|
623
562
|
task_hash = self._hash_task(task)
|
|
624
563
|
|
|
@@ -633,15 +572,12 @@ class AdaptiveLearningSystem:
|
|
|
633
572
|
def _calculate_agent_score(
|
|
634
573
|
self, agent_name: str, task_capabilities: list[str], task_hash: str
|
|
635
574
|
) -> float:
|
|
636
|
-
"""Calculate recommendation score for a specific agent."""
|
|
637
575
|
score = 0.0
|
|
638
576
|
|
|
639
|
-
# Base score from metrics
|
|
640
577
|
if agent_name in self._agent_metrics:
|
|
641
578
|
metrics = self._agent_metrics[agent_name]
|
|
642
579
|
score += self._calculate_metrics_score(metrics, task_capabilities)
|
|
643
580
|
|
|
644
|
-
# Insights bonus/penalty
|
|
645
581
|
score += self._calculate_insights_score(
|
|
646
582
|
agent_name, task_capabilities, task_hash
|
|
647
583
|
)
|
|
@@ -651,10 +587,8 @@ class AdaptiveLearningSystem:
|
|
|
651
587
|
def _calculate_metrics_score(
|
|
652
588
|
self, metrics: AgentPerformanceMetrics, task_capabilities: list[str]
|
|
653
589
|
) -> float:
|
|
654
|
-
"""Calculate score based on agent metrics."""
|
|
655
590
|
score = metrics.success_rate * 0.4
|
|
656
591
|
|
|
657
|
-
# Capability-specific performance
|
|
658
592
|
capability_scores = [
|
|
659
593
|
metrics.capability_success_rates[capability]
|
|
660
594
|
for capability in task_capabilities
|
|
@@ -664,18 +598,16 @@ class AdaptiveLearningSystem:
|
|
|
664
598
|
if capability_scores:
|
|
665
599
|
score += (sum(capability_scores) / len(capability_scores)) * 0.4
|
|
666
600
|
|
|
667
|
-
# Recent trend adjustment
|
|
668
601
|
if metrics.recent_performance_trend > 0:
|
|
669
602
|
score += metrics.recent_performance_trend * 0.1
|
|
670
603
|
elif metrics.recent_performance_trend < 0:
|
|
671
|
-
score += metrics.recent_performance_trend * 0.05
|
|
604
|
+
score += metrics.recent_performance_trend * 0.05
|
|
672
605
|
|
|
673
606
|
return score
|
|
674
607
|
|
|
675
608
|
def _calculate_insights_score(
|
|
676
609
|
self, agent_name: str, task_capabilities: list[str], task_hash: str
|
|
677
610
|
) -> float:
|
|
678
|
-
"""Calculate score adjustment based on learning insights."""
|
|
679
611
|
relevant_insights = [
|
|
680
612
|
insight
|
|
681
613
|
for insight in self._learning_insights
|
|
@@ -697,7 +629,6 @@ class AdaptiveLearningSystem:
|
|
|
697
629
|
return score_adjustment
|
|
698
630
|
|
|
699
631
|
def get_learning_summary(self) -> dict[str, t.Any]:
|
|
700
|
-
"""Get a summary of learning progress."""
|
|
701
632
|
total_records = len(self._execution_records)
|
|
702
633
|
|
|
703
634
|
if total_records == 0:
|
|
@@ -708,7 +639,6 @@ class AdaptiveLearningSystem:
|
|
|
708
639
|
recent_records
|
|
709
640
|
)
|
|
710
641
|
|
|
711
|
-
# Agent performance summary
|
|
712
642
|
agent_summary = {}
|
|
713
643
|
for agent_name, metrics in self._agent_metrics.items():
|
|
714
644
|
agent_summary[agent_name] = {
|
|
@@ -717,7 +647,6 @@ class AdaptiveLearningSystem:
|
|
|
717
647
|
"trend": metrics.recent_performance_trend,
|
|
718
648
|
}
|
|
719
649
|
|
|
720
|
-
# Insights summary
|
|
721
650
|
insights_by_type = defaultdict(int)
|
|
722
651
|
for insight in self._learning_insights:
|
|
723
652
|
insights_by_type[insight.insight_type] += 1
|
|
@@ -737,12 +666,10 @@ class AdaptiveLearningSystem:
|
|
|
737
666
|
}
|
|
738
667
|
|
|
739
668
|
|
|
740
|
-
# Global learning system instance
|
|
741
669
|
_learning_system_instance: AdaptiveLearningSystem | None = None
|
|
742
670
|
|
|
743
671
|
|
|
744
672
|
async def get_learning_system() -> AdaptiveLearningSystem:
|
|
745
|
-
"""Get or create the global learning system."""
|
|
746
673
|
global _learning_system_instance
|
|
747
674
|
|
|
748
675
|
if _learning_system_instance is None:
|