kailash 0.2.2__py3-none-any.whl → 0.3.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 (117) hide show
  1. kailash/__init__.py +1 -1
  2. kailash/access_control.py +40 -39
  3. kailash/api/auth.py +26 -32
  4. kailash/api/custom_nodes.py +29 -29
  5. kailash/api/custom_nodes_secure.py +35 -35
  6. kailash/api/database.py +17 -17
  7. kailash/api/gateway.py +19 -19
  8. kailash/api/mcp_integration.py +24 -23
  9. kailash/api/studio.py +45 -45
  10. kailash/api/workflow_api.py +8 -8
  11. kailash/cli/commands.py +5 -8
  12. kailash/manifest.py +42 -42
  13. kailash/mcp/__init__.py +1 -1
  14. kailash/mcp/ai_registry_server.py +20 -20
  15. kailash/mcp/client.py +9 -11
  16. kailash/mcp/client_new.py +10 -10
  17. kailash/mcp/server.py +1 -2
  18. kailash/mcp/server_enhanced.py +449 -0
  19. kailash/mcp/servers/ai_registry.py +6 -6
  20. kailash/mcp/utils/__init__.py +31 -0
  21. kailash/mcp/utils/cache.py +267 -0
  22. kailash/mcp/utils/config.py +263 -0
  23. kailash/mcp/utils/formatters.py +293 -0
  24. kailash/mcp/utils/metrics.py +418 -0
  25. kailash/nodes/ai/agents.py +9 -9
  26. kailash/nodes/ai/ai_providers.py +33 -34
  27. kailash/nodes/ai/embedding_generator.py +31 -32
  28. kailash/nodes/ai/intelligent_agent_orchestrator.py +62 -66
  29. kailash/nodes/ai/iterative_llm_agent.py +48 -48
  30. kailash/nodes/ai/llm_agent.py +32 -33
  31. kailash/nodes/ai/models.py +13 -13
  32. kailash/nodes/ai/self_organizing.py +44 -44
  33. kailash/nodes/api/__init__.py +5 -0
  34. kailash/nodes/api/auth.py +11 -11
  35. kailash/nodes/api/graphql.py +13 -13
  36. kailash/nodes/api/http.py +19 -19
  37. kailash/nodes/api/monitoring.py +463 -0
  38. kailash/nodes/api/rate_limiting.py +9 -13
  39. kailash/nodes/api/rest.py +29 -29
  40. kailash/nodes/api/security.py +819 -0
  41. kailash/nodes/base.py +24 -26
  42. kailash/nodes/base_async.py +7 -7
  43. kailash/nodes/base_cycle_aware.py +12 -12
  44. kailash/nodes/base_with_acl.py +5 -5
  45. kailash/nodes/code/python.py +56 -55
  46. kailash/nodes/data/__init__.py +6 -0
  47. kailash/nodes/data/directory.py +6 -6
  48. kailash/nodes/data/event_generation.py +297 -0
  49. kailash/nodes/data/file_discovery.py +598 -0
  50. kailash/nodes/data/readers.py +8 -8
  51. kailash/nodes/data/retrieval.py +10 -10
  52. kailash/nodes/data/sharepoint_graph.py +17 -17
  53. kailash/nodes/data/sources.py +5 -5
  54. kailash/nodes/data/sql.py +13 -13
  55. kailash/nodes/data/streaming.py +25 -25
  56. kailash/nodes/data/vector_db.py +22 -22
  57. kailash/nodes/data/writers.py +7 -7
  58. kailash/nodes/logic/async_operations.py +17 -17
  59. kailash/nodes/logic/convergence.py +11 -11
  60. kailash/nodes/logic/loop.py +4 -4
  61. kailash/nodes/logic/operations.py +11 -11
  62. kailash/nodes/logic/workflow.py +8 -9
  63. kailash/nodes/mixins/mcp.py +17 -17
  64. kailash/nodes/mixins.py +8 -10
  65. kailash/nodes/transform/chunkers.py +3 -3
  66. kailash/nodes/transform/formatters.py +7 -7
  67. kailash/nodes/transform/processors.py +11 -11
  68. kailash/runtime/access_controlled.py +18 -18
  69. kailash/runtime/async_local.py +18 -20
  70. kailash/runtime/docker.py +24 -26
  71. kailash/runtime/local.py +55 -31
  72. kailash/runtime/parallel.py +25 -25
  73. kailash/runtime/parallel_cyclic.py +29 -29
  74. kailash/runtime/runner.py +6 -6
  75. kailash/runtime/testing.py +22 -22
  76. kailash/sdk_exceptions.py +0 -58
  77. kailash/security.py +14 -26
  78. kailash/tracking/manager.py +38 -38
  79. kailash/tracking/metrics_collector.py +15 -14
  80. kailash/tracking/models.py +53 -53
  81. kailash/tracking/storage/base.py +7 -17
  82. kailash/tracking/storage/database.py +22 -23
  83. kailash/tracking/storage/filesystem.py +38 -40
  84. kailash/utils/export.py +21 -21
  85. kailash/utils/templates.py +8 -9
  86. kailash/visualization/api.py +30 -34
  87. kailash/visualization/dashboard.py +17 -17
  88. kailash/visualization/performance.py +32 -19
  89. kailash/visualization/reports.py +30 -28
  90. kailash/workflow/builder.py +8 -8
  91. kailash/workflow/convergence.py +13 -12
  92. kailash/workflow/cycle_analyzer.py +38 -33
  93. kailash/workflow/cycle_builder.py +12 -12
  94. kailash/workflow/cycle_config.py +16 -15
  95. kailash/workflow/cycle_debugger.py +40 -40
  96. kailash/workflow/cycle_exceptions.py +29 -29
  97. kailash/workflow/cycle_profiler.py +21 -21
  98. kailash/workflow/cycle_state.py +20 -22
  99. kailash/workflow/cyclic_runner.py +45 -45
  100. kailash/workflow/graph.py +57 -45
  101. kailash/workflow/mermaid_visualizer.py +9 -11
  102. kailash/workflow/migration.py +22 -22
  103. kailash/workflow/mock_registry.py +6 -6
  104. kailash/workflow/runner.py +9 -9
  105. kailash/workflow/safety.py +12 -13
  106. kailash/workflow/state.py +8 -11
  107. kailash/workflow/templates.py +19 -19
  108. kailash/workflow/validation.py +14 -14
  109. kailash/workflow/visualization.py +32 -24
  110. kailash-0.3.1.dist-info/METADATA +476 -0
  111. kailash-0.3.1.dist-info/RECORD +136 -0
  112. kailash-0.2.2.dist-info/METADATA +0 -121
  113. kailash-0.2.2.dist-info/RECORD +0 -126
  114. {kailash-0.2.2.dist-info → kailash-0.3.1.dist-info}/WHEEL +0 -0
  115. {kailash-0.2.2.dist-info → kailash-0.3.1.dist-info}/entry_points.txt +0 -0
  116. {kailash-0.2.2.dist-info → kailash-0.3.1.dist-info}/licenses/LICENSE +0 -0
  117. {kailash-0.2.2.dist-info → kailash-0.3.1.dist-info}/top_level.txt +0 -0
@@ -49,7 +49,7 @@ import json
49
49
  import logging
50
50
  from dataclasses import dataclass, field
51
51
  from datetime import datetime
52
- from typing import Any, Dict, List, Optional, Tuple
52
+ from typing import Any
53
53
 
54
54
  logger = logging.getLogger(__name__)
55
55
 
@@ -79,18 +79,18 @@ class CycleIteration:
79
79
 
80
80
  iteration_number: int
81
81
  start_time: datetime
82
- end_time: Optional[datetime] = None
83
- execution_time: Optional[float] = None
84
- input_data: Dict[str, Any] = field(default_factory=dict)
85
- output_data: Optional[Dict[str, Any]] = None
86
- memory_usage_mb: Optional[float] = None
87
- cpu_usage_percent: Optional[float] = None
88
- convergence_value: Optional[float] = None
89
- error: Optional[str] = None
90
- node_executions: List[str] = field(default_factory=list)
82
+ end_time: datetime | None = None
83
+ execution_time: float | None = None
84
+ input_data: dict[str, Any] = field(default_factory=dict)
85
+ output_data: dict[str, Any] | None = None
86
+ memory_usage_mb: float | None = None
87
+ cpu_usage_percent: float | None = None
88
+ convergence_value: float | None = None
89
+ error: str | None = None
90
+ node_executions: list[str] = field(default_factory=list)
91
91
 
92
92
  def complete(
93
- self, output_data: Dict[str, Any], convergence_value: Optional[float] = None
93
+ self, output_data: dict[str, Any], convergence_value: float | None = None
94
94
  ):
95
95
  """
96
96
  Mark iteration as complete with output data.
@@ -131,7 +131,7 @@ class CycleIteration:
131
131
  """
132
132
  return self.end_time is not None and self.error is None
133
133
 
134
- def to_dict(self) -> Dict[str, Any]:
134
+ def to_dict(self) -> dict[str, Any]:
135
135
  """Convert iteration to dictionary for serialization.
136
136
 
137
137
  Returns:
@@ -179,17 +179,17 @@ class CycleExecutionTrace:
179
179
  cycle_id: str
180
180
  workflow_id: str
181
181
  start_time: datetime
182
- end_time: Optional[datetime] = None
183
- total_execution_time: Optional[float] = None
184
- iterations: List[CycleIteration] = field(default_factory=list)
182
+ end_time: datetime | None = None
183
+ total_execution_time: float | None = None
184
+ iterations: list[CycleIteration] = field(default_factory=list)
185
185
  converged: bool = False
186
- convergence_iteration: Optional[int] = None
186
+ convergence_iteration: int | None = None
187
187
  termination_reason: str = "unknown"
188
- max_iterations_configured: Optional[int] = None
189
- timeout_configured: Optional[float] = None
190
- convergence_condition: Optional[str] = None
191
- memory_peak_mb: Optional[float] = None
192
- cpu_peak_percent: Optional[float] = None
188
+ max_iterations_configured: int | None = None
189
+ timeout_configured: float | None = None
190
+ convergence_condition: str | None = None
191
+ memory_peak_mb: float | None = None
192
+ cpu_peak_percent: float | None = None
193
193
 
194
194
  def add_iteration(self, iteration: CycleIteration):
195
195
  """
@@ -216,7 +216,7 @@ class CycleExecutionTrace:
216
216
  self,
217
217
  converged: bool,
218
218
  termination_reason: str,
219
- convergence_iteration: Optional[int] = None,
219
+ convergence_iteration: int | None = None,
220
220
  ):
221
221
  """
222
222
  Mark cycle execution as complete.
@@ -232,7 +232,7 @@ class CycleExecutionTrace:
232
232
  self.termination_reason = termination_reason
233
233
  self.convergence_iteration = convergence_iteration
234
234
 
235
- def get_statistics(self) -> Dict[str, Any]:
235
+ def get_statistics(self) -> dict[str, Any]:
236
236
  """
237
237
  Get comprehensive statistics about the cycle execution.
238
238
 
@@ -316,7 +316,7 @@ class CycleExecutionTrace:
316
316
 
317
317
  return stats
318
318
 
319
- def get_convergence_trend(self) -> List[Tuple[int, Optional[float]]]:
319
+ def get_convergence_trend(self) -> list[tuple[int, float | None]]:
320
320
  """
321
321
  Get convergence values over iterations for trend analysis.
322
322
 
@@ -335,7 +335,7 @@ class CycleExecutionTrace:
335
335
  (iter.iteration_number, iter.convergence_value) for iter in self.iterations
336
336
  ]
337
337
 
338
- def to_dict(self) -> Dict[str, Any]:
338
+ def to_dict(self) -> dict[str, Any]:
339
339
  """Convert trace to dictionary for serialization."""
340
340
  return {
341
341
  "cycle_id": self.cycle_id,
@@ -411,7 +411,7 @@ class CycleDebugger:
411
411
  """
412
412
  self.debug_level = debug_level
413
413
  self.enable_profiling = enable_profiling
414
- self.active_traces: Dict[str, CycleExecutionTrace] = {}
414
+ self.active_traces: dict[str, CycleExecutionTrace] = {}
415
415
 
416
416
  # Configure logging based on debug level
417
417
  if debug_level == "verbose":
@@ -425,9 +425,9 @@ class CycleDebugger:
425
425
  self,
426
426
  cycle_id: str,
427
427
  workflow_id: str,
428
- max_iterations: Optional[int] = None,
429
- timeout: Optional[float] = None,
430
- convergence_condition: Optional[str] = None,
428
+ max_iterations: int | None = None,
429
+ timeout: float | None = None,
430
+ convergence_condition: str | None = None,
431
431
  ) -> CycleExecutionTrace:
432
432
  """
433
433
  Start debugging a new cycle execution.
@@ -473,8 +473,8 @@ class CycleDebugger:
473
473
  def start_iteration(
474
474
  self,
475
475
  trace: CycleExecutionTrace,
476
- input_data: Dict[str, Any],
477
- iteration_number: Optional[int] = None,
476
+ input_data: dict[str, Any],
477
+ iteration_number: int | None = None,
478
478
  ) -> CycleIteration:
479
479
  """
480
480
  Start debugging a new cycle iteration.
@@ -533,9 +533,9 @@ class CycleDebugger:
533
533
  self,
534
534
  trace: CycleExecutionTrace,
535
535
  iteration: CycleIteration,
536
- output_data: Dict[str, Any],
537
- convergence_value: Optional[float] = None,
538
- node_executions: Optional[List[str]] = None,
536
+ output_data: dict[str, Any],
537
+ convergence_value: float | None = None,
538
+ node_executions: list[str] | None = None,
539
539
  ):
540
540
  """
541
541
  Complete iteration tracking with output data and metrics.
@@ -598,7 +598,7 @@ class CycleDebugger:
598
598
  trace: CycleExecutionTrace,
599
599
  converged: bool,
600
600
  termination_reason: str,
601
- convergence_iteration: Optional[int] = None,
601
+ convergence_iteration: int | None = None,
602
602
  ):
603
603
  """
604
604
  Complete cycle tracking with final results and analysis.
@@ -632,7 +632,7 @@ class CycleDebugger:
632
632
  f"converged={converged}, efficiency={stats['efficiency_score']:.2f}"
633
633
  )
634
634
 
635
- def generate_report(self, trace: CycleExecutionTrace) -> Dict[str, Any]:
635
+ def generate_report(self, trace: CycleExecutionTrace) -> dict[str, Any]:
636
636
  """
637
637
  Generate comprehensive debugging report for a cycle execution.
638
638
 
@@ -691,8 +691,8 @@ class CycleDebugger:
691
691
  return report
692
692
 
693
693
  def _analyze_convergence(
694
- self, convergence_trend: List[Tuple[int, Optional[float]]]
695
- ) -> Dict[str, Any]:
694
+ self, convergence_trend: list[tuple[int, float | None]]
695
+ ) -> dict[str, Any]:
696
696
  """Analyze convergence pattern from trend data."""
697
697
  if not convergence_trend or all(
698
698
  value is None for _, value in convergence_trend
@@ -748,8 +748,8 @@ class CycleDebugger:
748
748
  }
749
749
 
750
750
  def _generate_recommendations(
751
- self, trace: CycleExecutionTrace, stats: Dict[str, Any]
752
- ) -> List[str]:
751
+ self, trace: CycleExecutionTrace, stats: dict[str, Any]
752
+ ) -> list[str]:
753
753
  """Generate optimization recommendations based on execution analysis."""
754
754
  recommendations = []
755
755
 
@@ -7,7 +7,7 @@ replace generic errors with detailed diagnostics to improve developer experience
7
7
  """
8
8
 
9
9
  import logging
10
- from typing import Any, Dict, List, Optional
10
+ from typing import Any
11
11
 
12
12
  from kailash.sdk_exceptions import WorkflowException
13
13
 
@@ -55,9 +55,9 @@ class CycleException(WorkflowException):
55
55
  self,
56
56
  message: str,
57
57
  error_code: str = "CYCLE_ERROR",
58
- context: Optional[Dict[str, Any]] = None,
59
- suggestions: Optional[List[str]] = None,
60
- documentation_url: Optional[str] = None,
58
+ context: dict[str, Any] | None = None,
59
+ suggestions: list[str] | None = None,
60
+ documentation_url: str | None = None,
61
61
  ):
62
62
  """
63
63
  Initialize cycle exception with enhanced error information.
@@ -148,8 +148,8 @@ class CycleConfigurationError(CycleException):
148
148
  def __init__(
149
149
  self,
150
150
  message: str,
151
- cycle_id: Optional[str] = None,
152
- invalid_params: Optional[Dict[str, Any]] = None,
151
+ cycle_id: str | None = None,
152
+ invalid_params: dict[str, Any] | None = None,
153
153
  **kwargs,
154
154
  ):
155
155
  """
@@ -216,10 +216,10 @@ class CycleConnectionError(CycleException):
216
216
  def __init__(
217
217
  self,
218
218
  message: str,
219
- source_node: Optional[str] = None,
220
- target_node: Optional[str] = None,
221
- available_nodes: Optional[List[str]] = None,
222
- mapping_errors: Optional[Dict[str, str]] = None,
219
+ source_node: str | None = None,
220
+ target_node: str | None = None,
221
+ available_nodes: list[str] | None = None,
222
+ mapping_errors: dict[str, str] | None = None,
223
223
  **kwargs,
224
224
  ):
225
225
  """
@@ -294,9 +294,9 @@ class CycleValidationError(CycleException):
294
294
  def __init__(
295
295
  self,
296
296
  message: str,
297
- cycle_group: Optional[str] = None,
298
- validation_failures: Optional[List[str]] = None,
299
- conflicting_values: Optional[List[Any]] = None,
297
+ cycle_group: str | None = None,
298
+ validation_failures: list[str] | None = None,
299
+ conflicting_values: list[Any] | None = None,
300
300
  **kwargs,
301
301
  ):
302
302
  """
@@ -365,11 +365,11 @@ class CycleExecutionError(CycleException):
365
365
  def __init__(
366
366
  self,
367
367
  message: str,
368
- cycle_id: Optional[str] = None,
369
- current_iteration: Optional[int] = None,
370
- max_iterations: Optional[int] = None,
371
- timeout_seconds: Optional[float] = None,
372
- memory_usage_mb: Optional[int] = None,
368
+ cycle_id: str | None = None,
369
+ current_iteration: int | None = None,
370
+ max_iterations: int | None = None,
371
+ timeout_seconds: float | None = None,
372
+ memory_usage_mb: int | None = None,
373
373
  **kwargs,
374
374
  ):
375
375
  """
@@ -465,10 +465,10 @@ class CycleConvergenceError(CycleException):
465
465
  def __init__(
466
466
  self,
467
467
  message: str,
468
- convergence_expression: Optional[str] = None,
469
- evaluation_error: Optional[str] = None,
470
- available_variables: Optional[List[str]] = None,
471
- cycle_data: Optional[Dict[str, Any]] = None,
468
+ convergence_expression: str | None = None,
469
+ evaluation_error: str | None = None,
470
+ available_variables: list[str] | None = None,
471
+ cycle_data: dict[str, Any] | None = None,
472
472
  **kwargs,
473
473
  ):
474
474
  """
@@ -523,7 +523,7 @@ class CycleConvergenceError(CycleException):
523
523
 
524
524
  # Utility functions for enhanced error reporting
525
525
  def create_configuration_error(
526
- issue: str, cycle_id: Optional[str] = None, **invalid_params
526
+ issue: str, cycle_id: str | None = None, **invalid_params
527
527
  ) -> CycleConfigurationError:
528
528
  """
529
529
  Create a standardized configuration error with common suggestions.
@@ -550,9 +550,9 @@ def create_configuration_error(
550
550
 
551
551
  def create_connection_error(
552
552
  issue: str,
553
- source_node: Optional[str] = None,
554
- target_node: Optional[str] = None,
555
- available_nodes: Optional[List[str]] = None,
553
+ source_node: str | None = None,
554
+ target_node: str | None = None,
555
+ available_nodes: list[str] | None = None,
556
556
  ) -> CycleConnectionError:
557
557
  """
558
558
  Create a standardized connection error with node context.
@@ -583,9 +583,9 @@ def create_connection_error(
583
583
 
584
584
  def create_execution_error(
585
585
  issue: str,
586
- cycle_id: Optional[str] = None,
587
- current_iteration: Optional[int] = None,
588
- max_iterations: Optional[int] = None,
586
+ cycle_id: str | None = None,
587
+ current_iteration: int | None = None,
588
+ max_iterations: int | None = None,
589
589
  ) -> CycleExecutionError:
590
590
  """
591
591
  Create a standardized execution error with runtime context.
@@ -45,7 +45,7 @@ import logging
45
45
  import statistics
46
46
  from dataclasses import dataclass, field
47
47
  from datetime import datetime
48
- from typing import Any, Dict, List, Optional, Tuple
48
+ from typing import Any
49
49
 
50
50
  from kailash.workflow.cycle_debugger import CycleExecutionTrace
51
51
 
@@ -83,13 +83,13 @@ class PerformanceMetrics:
83
83
  min_iteration_time: float = float("inf")
84
84
  max_iteration_time: float = 0.0
85
85
  iteration_time_stddev: float = 0.0
86
- memory_stats: Dict[str, float] = field(default_factory=dict)
87
- cpu_stats: Dict[str, float] = field(default_factory=dict)
88
- convergence_stats: Dict[str, Any] = field(default_factory=dict)
89
- bottlenecks: List[str] = field(default_factory=list)
90
- optimization_opportunities: List[str] = field(default_factory=list)
86
+ memory_stats: dict[str, float] = field(default_factory=dict)
87
+ cpu_stats: dict[str, float] = field(default_factory=dict)
88
+ convergence_stats: dict[str, Any] = field(default_factory=dict)
89
+ bottlenecks: list[str] = field(default_factory=list)
90
+ optimization_opportunities: list[str] = field(default_factory=list)
91
91
 
92
- def to_dict(self) -> Dict[str, Any]:
92
+ def to_dict(self) -> dict[str, Any]:
93
93
  """Convert metrics to dictionary for serialization.
94
94
 
95
95
  Returns:
@@ -141,8 +141,8 @@ class CycleProfiler:
141
141
  enable_advanced_metrics: Whether to enable advanced statistical analysis.
142
142
  """
143
143
  self.enable_advanced_metrics = enable_advanced_metrics
144
- self.traces: List[CycleExecutionTrace] = []
145
- self.performance_history: List[PerformanceMetrics] = []
144
+ self.traces: list[CycleExecutionTrace] = []
145
+ self.performance_history: list[PerformanceMetrics] = []
146
146
 
147
147
  def add_trace(self, trace: CycleExecutionTrace):
148
148
  """
@@ -260,7 +260,7 @@ class CycleProfiler:
260
260
 
261
261
  return metrics
262
262
 
263
- def compare_cycles(self, cycle_ids: List[str]) -> Dict[str, Any]:
263
+ def compare_cycles(self, cycle_ids: list[str]) -> dict[str, Any]:
264
264
  """
265
265
  Compare performance across multiple specific cycles.
266
266
 
@@ -338,8 +338,8 @@ class CycleProfiler:
338
338
  return comparison
339
339
 
340
340
  def get_optimization_recommendations(
341
- self, trace: Optional[CycleExecutionTrace] = None
342
- ) -> List[Dict[str, Any]]:
341
+ self, trace: CycleExecutionTrace | None = None
342
+ ) -> list[dict[str, Any]]:
343
343
  """
344
344
  Generate detailed optimization recommendations.
345
345
 
@@ -459,7 +459,7 @@ class CycleProfiler:
459
459
 
460
460
  return recommendations
461
461
 
462
- def generate_performance_report(self) -> Dict[str, Any]:
462
+ def generate_performance_report(self) -> dict[str, Any]:
463
463
  """
464
464
  Generate comprehensive performance report.
465
465
 
@@ -560,8 +560,8 @@ class CycleProfiler:
560
560
  logger.info(f"Exported profiling data to {filepath} in {format} format")
561
561
 
562
562
  def _analyze_convergence_performance(
563
- self, convergence_data: List[float]
564
- ) -> Dict[str, Any]:
563
+ self, convergence_data: list[float]
564
+ ) -> dict[str, Any]:
565
565
  """Analyze convergence performance characteristics."""
566
566
  if not convergence_data:
567
567
  return {}
@@ -582,8 +582,8 @@ class CycleProfiler:
582
582
  }
583
583
 
584
584
  def _analyze_convergence_pattern(
585
- self, convergence_trend: List[Tuple[int, Optional[float]]]
586
- ) -> Dict[str, Any]:
585
+ self, convergence_trend: list[tuple[int, float | None]]
586
+ ) -> dict[str, Any]:
587
587
  """Analyze convergence pattern for stability."""
588
588
  valid_points = [value for _, value in convergence_trend if value is not None]
589
589
 
@@ -608,7 +608,7 @@ class CycleProfiler:
608
608
  "reason": "high_volatility" if unstable else "stable",
609
609
  }
610
610
 
611
- def _identify_bottlenecks(self, metrics: PerformanceMetrics) -> List[str]:
611
+ def _identify_bottlenecks(self, metrics: PerformanceMetrics) -> list[str]:
612
612
  """Identify performance bottlenecks from metrics."""
613
613
  bottlenecks = []
614
614
 
@@ -636,7 +636,7 @@ class CycleProfiler:
636
636
 
637
637
  return bottlenecks
638
638
 
639
- def _identify_optimizations(self, metrics: PerformanceMetrics) -> List[str]:
639
+ def _identify_optimizations(self, metrics: PerformanceMetrics) -> list[str]:
640
640
  """Identify optimization opportunities."""
641
641
  optimizations = []
642
642
 
@@ -697,7 +697,7 @@ class CycleProfiler:
697
697
 
698
698
  return statistics.mean(score_components) if score_components else 0.5
699
699
 
700
- def _analyze_performance_trends(self) -> Dict[str, Any]:
700
+ def _analyze_performance_trends(self) -> dict[str, Any]:
701
701
  """Analyze performance trends over time."""
702
702
  if len(self.performance_history) < 2:
703
703
  return {"trend": "insufficient_data"}
@@ -720,7 +720,7 @@ class CycleProfiler:
720
720
  "performance_history_length": len(self.performance_history),
721
721
  }
722
722
 
723
- def _get_cycle_comparisons(self) -> Dict[str, Any]:
723
+ def _get_cycle_comparisons(self) -> dict[str, Any]:
724
724
  """Get comparative analysis across all cycles."""
725
725
  if len(self.traces) < 2:
726
726
  return {"comparison": "insufficient_data"}
@@ -2,8 +2,8 @@
2
2
 
3
3
  import logging
4
4
  import time
5
- from datetime import datetime, timezone
6
- from typing import Any, Dict, List, Optional
5
+ from datetime import UTC, datetime
6
+ from typing import Any
7
7
 
8
8
  logger = logging.getLogger(__name__)
9
9
 
@@ -19,11 +19,11 @@ class CycleState:
19
19
  """
20
20
  self.cycle_id = cycle_id
21
21
  self.iteration = 0
22
- self.history: List[Dict[str, Any]] = []
23
- self.metadata: Dict[str, Any] = {}
22
+ self.history: list[dict[str, Any]] = []
23
+ self.metadata: dict[str, Any] = {}
24
24
  self.start_time = time.time()
25
25
  self.last_update_time = self.start_time
26
- self.node_states: Dict[str, Any] = {} # Per-node state storage
26
+ self.node_states: dict[str, Any] = {} # Per-node state storage
27
27
 
28
28
  @property
29
29
  def elapsed_time(self) -> float:
@@ -35,7 +35,7 @@ class CycleState:
35
35
  """Get time since last iteration."""
36
36
  return time.time() - self.last_update_time
37
37
 
38
- def update(self, results: Dict[str, Any], iteration: Optional[int] = None) -> None:
38
+ def update(self, results: dict[str, Any], iteration: int | None = None) -> None:
39
39
  """Update state with iteration results.
40
40
 
41
41
  Args:
@@ -51,7 +51,7 @@ class CycleState:
51
51
  history_entry = {
52
52
  "iteration": self.iteration,
53
53
  "results": results,
54
- "timestamp": datetime.now(timezone.utc).isoformat(),
54
+ "timestamp": datetime.now(UTC).isoformat(),
55
55
  "elapsed_time": self.elapsed_time,
56
56
  "iteration_time": self.iteration_time,
57
57
  }
@@ -90,7 +90,7 @@ class CycleState:
90
90
  """
91
91
  self.node_states[node_id] = state
92
92
 
93
- def get_convergence_context(self) -> Dict[str, Any]:
93
+ def get_convergence_context(self) -> dict[str, Any]:
94
94
  """Get context for convergence evaluation.
95
95
 
96
96
  Returns:
@@ -110,7 +110,7 @@ class CycleState:
110
110
 
111
111
  return context
112
112
 
113
- def calculate_trend(self) -> Dict[str, Any]:
113
+ def calculate_trend(self) -> dict[str, Any]:
114
114
  """Calculate trends from iteration history.
115
115
 
116
116
  Returns:
@@ -159,7 +159,7 @@ class CycleState:
159
159
 
160
160
  return trends
161
161
 
162
- def _extract_numeric_keys(self, obj: Any, prefix: str = "") -> List[str]:
162
+ def _extract_numeric_keys(self, obj: Any, prefix: str = "") -> list[str]:
163
163
  """Extract all numeric value keys from nested dict."""
164
164
  keys = []
165
165
 
@@ -186,7 +186,7 @@ class CycleState:
186
186
 
187
187
  return value
188
188
 
189
- def get_summary(self) -> Dict[str, Any]:
189
+ def get_summary(self) -> dict[str, Any]:
190
190
  """Get summary of cycle execution.
191
191
 
192
192
  Returns:
@@ -196,9 +196,7 @@ class CycleState:
196
196
  "cycle_id": self.cycle_id,
197
197
  "iterations": self.iteration,
198
198
  "elapsed_time": self.elapsed_time,
199
- "start_time": datetime.fromtimestamp(
200
- self.start_time, timezone.utc
201
- ).isoformat(),
199
+ "start_time": datetime.fromtimestamp(self.start_time, UTC).isoformat(),
202
200
  "history_length": len(self.history),
203
201
  }
204
202
 
@@ -223,7 +221,7 @@ class CycleState:
223
221
 
224
222
  return summary
225
223
 
226
- def to_dict(self) -> Dict[str, Any]:
224
+ def to_dict(self) -> dict[str, Any]:
227
225
  """Serialize state to dictionary.
228
226
 
229
227
  Returns:
@@ -240,7 +238,7 @@ class CycleState:
240
238
  }
241
239
 
242
240
  @classmethod
243
- def from_dict(cls, data: Dict[str, Any]) -> "CycleState":
241
+ def from_dict(cls, data: dict[str, Any]) -> "CycleState":
244
242
  """Create CycleState from dictionary.
245
243
 
246
244
  Args:
@@ -264,8 +262,8 @@ class CycleStateManager:
264
262
 
265
263
  def __init__(self):
266
264
  """Initialize cycle state manager."""
267
- self.states: Dict[str, CycleState] = {}
268
- self.active_cycles: List[str] = []
265
+ self.states: dict[str, CycleState] = {}
266
+ self.active_cycles: list[str] = []
269
267
 
270
268
  def get_or_create_state(self, cycle_id: str) -> CycleState:
271
269
  """Get existing state or create new one.
@@ -291,7 +289,7 @@ class CycleStateManager:
291
289
  self.active_cycles.append(cycle_id)
292
290
  logger.debug(f"Pushed cycle: {cycle_id}, stack: {self.active_cycles}")
293
291
 
294
- def pop_cycle(self) -> Optional[str]:
292
+ def pop_cycle(self) -> str | None:
295
293
  """Pop cycle from active stack.
296
294
 
297
295
  Returns:
@@ -303,7 +301,7 @@ class CycleStateManager:
303
301
  return cycle_id
304
302
  return None
305
303
 
306
- def get_active_cycle(self) -> Optional[str]:
304
+ def get_active_cycle(self) -> str | None:
307
305
  """Get currently active cycle ID.
308
306
 
309
307
  Returns:
@@ -311,7 +309,7 @@ class CycleStateManager:
311
309
  """
312
310
  return self.active_cycles[-1] if self.active_cycles else None
313
311
 
314
- def get_all_summaries(self) -> Dict[str, Dict[str, Any]]:
312
+ def get_all_summaries(self) -> dict[str, dict[str, Any]]:
315
313
  """Get summaries for all cycles.
316
314
 
317
315
  Returns:
@@ -321,7 +319,7 @@ class CycleStateManager:
321
319
  cycle_id: state.get_summary() for cycle_id, state in self.states.items()
322
320
  }
323
321
 
324
- def clear(self, cycle_id: Optional[str] = None) -> None:
322
+ def clear(self, cycle_id: str | None = None) -> None:
325
323
  """Clear cycle state(s).
326
324
 
327
325
  Args: