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.
- kailash/__init__.py +1 -1
- kailash/access_control.py +40 -39
- kailash/api/auth.py +26 -32
- kailash/api/custom_nodes.py +29 -29
- kailash/api/custom_nodes_secure.py +35 -35
- kailash/api/database.py +17 -17
- kailash/api/gateway.py +19 -19
- kailash/api/mcp_integration.py +24 -23
- kailash/api/studio.py +45 -45
- kailash/api/workflow_api.py +8 -8
- kailash/cli/commands.py +5 -8
- kailash/manifest.py +42 -42
- kailash/mcp/__init__.py +1 -1
- kailash/mcp/ai_registry_server.py +20 -20
- kailash/mcp/client.py +9 -11
- kailash/mcp/client_new.py +10 -10
- kailash/mcp/server.py +1 -2
- kailash/mcp/server_enhanced.py +449 -0
- kailash/mcp/servers/ai_registry.py +6 -6
- kailash/mcp/utils/__init__.py +31 -0
- kailash/mcp/utils/cache.py +267 -0
- kailash/mcp/utils/config.py +263 -0
- kailash/mcp/utils/formatters.py +293 -0
- kailash/mcp/utils/metrics.py +418 -0
- kailash/nodes/ai/agents.py +9 -9
- kailash/nodes/ai/ai_providers.py +33 -34
- kailash/nodes/ai/embedding_generator.py +31 -32
- kailash/nodes/ai/intelligent_agent_orchestrator.py +62 -66
- kailash/nodes/ai/iterative_llm_agent.py +48 -48
- kailash/nodes/ai/llm_agent.py +32 -33
- kailash/nodes/ai/models.py +13 -13
- kailash/nodes/ai/self_organizing.py +44 -44
- kailash/nodes/api/__init__.py +5 -0
- kailash/nodes/api/auth.py +11 -11
- kailash/nodes/api/graphql.py +13 -13
- kailash/nodes/api/http.py +19 -19
- kailash/nodes/api/monitoring.py +463 -0
- kailash/nodes/api/rate_limiting.py +9 -13
- kailash/nodes/api/rest.py +29 -29
- kailash/nodes/api/security.py +819 -0
- kailash/nodes/base.py +24 -26
- kailash/nodes/base_async.py +7 -7
- kailash/nodes/base_cycle_aware.py +12 -12
- kailash/nodes/base_with_acl.py +5 -5
- kailash/nodes/code/python.py +56 -55
- kailash/nodes/data/__init__.py +6 -0
- kailash/nodes/data/directory.py +6 -6
- kailash/nodes/data/event_generation.py +297 -0
- kailash/nodes/data/file_discovery.py +598 -0
- kailash/nodes/data/readers.py +8 -8
- kailash/nodes/data/retrieval.py +10 -10
- kailash/nodes/data/sharepoint_graph.py +17 -17
- kailash/nodes/data/sources.py +5 -5
- kailash/nodes/data/sql.py +13 -13
- kailash/nodes/data/streaming.py +25 -25
- kailash/nodes/data/vector_db.py +22 -22
- kailash/nodes/data/writers.py +7 -7
- kailash/nodes/logic/async_operations.py +17 -17
- kailash/nodes/logic/convergence.py +11 -11
- kailash/nodes/logic/loop.py +4 -4
- kailash/nodes/logic/operations.py +11 -11
- kailash/nodes/logic/workflow.py +8 -9
- kailash/nodes/mixins/mcp.py +17 -17
- kailash/nodes/mixins.py +8 -10
- kailash/nodes/transform/chunkers.py +3 -3
- kailash/nodes/transform/formatters.py +7 -7
- kailash/nodes/transform/processors.py +11 -11
- kailash/runtime/access_controlled.py +18 -18
- kailash/runtime/async_local.py +18 -20
- kailash/runtime/docker.py +24 -26
- kailash/runtime/local.py +55 -31
- kailash/runtime/parallel.py +25 -25
- kailash/runtime/parallel_cyclic.py +29 -29
- kailash/runtime/runner.py +6 -6
- kailash/runtime/testing.py +22 -22
- kailash/sdk_exceptions.py +0 -58
- kailash/security.py +14 -26
- kailash/tracking/manager.py +38 -38
- kailash/tracking/metrics_collector.py +15 -14
- kailash/tracking/models.py +53 -53
- kailash/tracking/storage/base.py +7 -17
- kailash/tracking/storage/database.py +22 -23
- kailash/tracking/storage/filesystem.py +38 -40
- kailash/utils/export.py +21 -21
- kailash/utils/templates.py +8 -9
- kailash/visualization/api.py +30 -34
- kailash/visualization/dashboard.py +17 -17
- kailash/visualization/performance.py +32 -19
- kailash/visualization/reports.py +30 -28
- kailash/workflow/builder.py +8 -8
- kailash/workflow/convergence.py +13 -12
- kailash/workflow/cycle_analyzer.py +38 -33
- kailash/workflow/cycle_builder.py +12 -12
- kailash/workflow/cycle_config.py +16 -15
- kailash/workflow/cycle_debugger.py +40 -40
- kailash/workflow/cycle_exceptions.py +29 -29
- kailash/workflow/cycle_profiler.py +21 -21
- kailash/workflow/cycle_state.py +20 -22
- kailash/workflow/cyclic_runner.py +45 -45
- kailash/workflow/graph.py +57 -45
- kailash/workflow/mermaid_visualizer.py +9 -11
- kailash/workflow/migration.py +22 -22
- kailash/workflow/mock_registry.py +6 -6
- kailash/workflow/runner.py +9 -9
- kailash/workflow/safety.py +12 -13
- kailash/workflow/state.py +8 -11
- kailash/workflow/templates.py +19 -19
- kailash/workflow/validation.py +14 -14
- kailash/workflow/visualization.py +32 -24
- kailash-0.3.1.dist-info/METADATA +476 -0
- kailash-0.3.1.dist-info/RECORD +136 -0
- kailash-0.2.2.dist-info/METADATA +0 -121
- kailash-0.2.2.dist-info/RECORD +0 -126
- {kailash-0.2.2.dist-info → kailash-0.3.1.dist-info}/WHEEL +0 -0
- {kailash-0.2.2.dist-info → kailash-0.3.1.dist-info}/entry_points.txt +0 -0
- {kailash-0.2.2.dist-info → kailash-0.3.1.dist-info}/licenses/LICENSE +0 -0
- {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
|
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:
|
83
|
-
execution_time:
|
84
|
-
input_data:
|
85
|
-
output_data:
|
86
|
-
memory_usage_mb:
|
87
|
-
cpu_usage_percent:
|
88
|
-
convergence_value:
|
89
|
-
error:
|
90
|
-
node_executions:
|
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:
|
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) ->
|
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:
|
183
|
-
total_execution_time:
|
184
|
-
iterations:
|
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:
|
186
|
+
convergence_iteration: int | None = None
|
187
187
|
termination_reason: str = "unknown"
|
188
|
-
max_iterations_configured:
|
189
|
-
timeout_configured:
|
190
|
-
convergence_condition:
|
191
|
-
memory_peak_mb:
|
192
|
-
cpu_peak_percent:
|
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:
|
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) ->
|
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) ->
|
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) ->
|
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:
|
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:
|
429
|
-
timeout:
|
430
|
-
convergence_condition:
|
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:
|
477
|
-
iteration_number:
|
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:
|
537
|
-
convergence_value:
|
538
|
-
node_executions:
|
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:
|
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) ->
|
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:
|
695
|
-
) ->
|
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:
|
752
|
-
) ->
|
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
|
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:
|
59
|
-
suggestions:
|
60
|
-
documentation_url:
|
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:
|
152
|
-
invalid_params:
|
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:
|
220
|
-
target_node:
|
221
|
-
available_nodes:
|
222
|
-
mapping_errors:
|
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:
|
298
|
-
validation_failures:
|
299
|
-
conflicting_values:
|
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:
|
369
|
-
current_iteration:
|
370
|
-
max_iterations:
|
371
|
-
timeout_seconds:
|
372
|
-
memory_usage_mb:
|
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:
|
469
|
-
evaluation_error:
|
470
|
-
available_variables:
|
471
|
-
cycle_data:
|
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:
|
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:
|
554
|
-
target_node:
|
555
|
-
available_nodes:
|
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:
|
587
|
-
current_iteration:
|
588
|
-
max_iterations:
|
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
|
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:
|
87
|
-
cpu_stats:
|
88
|
-
convergence_stats:
|
89
|
-
bottlenecks:
|
90
|
-
optimization_opportunities:
|
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) ->
|
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:
|
145
|
-
self.performance_history:
|
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:
|
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:
|
342
|
-
) ->
|
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) ->
|
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:
|
564
|
-
) ->
|
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:
|
586
|
-
) ->
|
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) ->
|
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) ->
|
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) ->
|
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) ->
|
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"}
|
kailash/workflow/cycle_state.py
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
import logging
|
4
4
|
import time
|
5
|
-
from datetime import
|
6
|
-
from typing import Any
|
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:
|
23
|
-
self.metadata:
|
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:
|
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:
|
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(
|
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) ->
|
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) ->
|
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 = "") ->
|
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) ->
|
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) ->
|
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:
|
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:
|
268
|
-
self.active_cycles:
|
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) ->
|
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) ->
|
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) ->
|
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:
|
322
|
+
def clear(self, cycle_id: str | None = None) -> None:
|
325
323
|
"""Clear cycle state(s).
|
326
324
|
|
327
325
|
Args:
|