kailash 0.3.0__py3-none-any.whl → 0.3.2__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/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/auth.py +11 -11
- kailash/nodes/api/graphql.py +13 -13
- kailash/nodes/api/http.py +19 -19
- kailash/nodes/api/monitoring.py +20 -20
- kailash/nodes/api/rate_limiting.py +9 -13
- kailash/nodes/api/rest.py +29 -29
- kailash/nodes/api/security.py +44 -47
- kailash/nodes/base.py +21 -23
- 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 +66 -57
- kailash/nodes/data/directory.py +6 -6
- kailash/nodes/data/event_generation.py +10 -10
- kailash/nodes/data/file_discovery.py +28 -31
- 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 +10 -10
- kailash/runtime/access_controlled.py +18 -18
- kailash/runtime/async_local.py +17 -19
- kailash/runtime/docker.py +20 -22
- kailash/runtime/local.py +16 -16
- kailash/runtime/parallel.py +23 -23
- kailash/runtime/parallel_cyclic.py +27 -27
- kailash/runtime/runner.py +6 -6
- kailash/runtime/testing.py +20 -20
- 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 +2 -3
- kailash/visualization/api.py +30 -34
- kailash/visualization/dashboard.py +17 -17
- kailash/visualization/performance.py +16 -16
- kailash/visualization/reports.py +25 -27
- kailash/workflow/builder.py +8 -8
- kailash/workflow/convergence.py +13 -12
- kailash/workflow/cycle_analyzer.py +30 -32
- 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 +44 -44
- kailash/workflow/graph.py +40 -40
- 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 +22 -22
- {kailash-0.3.0.dist-info → kailash-0.3.2.dist-info}/METADATA +53 -5
- kailash-0.3.2.dist-info/RECORD +136 -0
- kailash-0.3.0.dist-info/RECORD +0 -130
- {kailash-0.3.0.dist-info → kailash-0.3.2.dist-info}/WHEEL +0 -0
- {kailash-0.3.0.dist-info → kailash-0.3.2.dist-info}/entry_points.txt +0 -0
- {kailash-0.3.0.dist-info → kailash-0.3.2.dist-info}/licenses/LICENSE +0 -0
- {kailash-0.3.0.dist-info → kailash-0.3.2.dist-info}/top_level.txt +0 -0
kailash/nodes/data/streaming.py
CHANGED
@@ -44,7 +44,7 @@ Example:
|
|
44
44
|
"""
|
45
45
|
|
46
46
|
import time
|
47
|
-
from typing import Any
|
47
|
+
from typing import Any
|
48
48
|
|
49
49
|
from kailash.nodes.base import Node, NodeMetadata, NodeParameter, register_node
|
50
50
|
from kailash.sdk_exceptions import NodeConfigurationError, NodeExecutionError
|
@@ -148,7 +148,7 @@ class KafkaConsumerNode(Node):
|
|
148
148
|
self._consumer = None
|
149
149
|
self._topic = None
|
150
150
|
|
151
|
-
def get_parameters(self) ->
|
151
|
+
def get_parameters(self) -> dict[str, NodeParameter]:
|
152
152
|
"""Define parameters for the Kafka consumer node."""
|
153
153
|
return {
|
154
154
|
"bootstrap_servers": NodeParameter(
|
@@ -206,7 +206,7 @@ class KafkaConsumerNode(Node):
|
|
206
206
|
),
|
207
207
|
}
|
208
208
|
|
209
|
-
def configure(self, config:
|
209
|
+
def configure(self, config: dict[str, Any]) -> None:
|
210
210
|
"""Configure the Kafka consumer.
|
211
211
|
|
212
212
|
Creates and configures the Kafka consumer with the specified
|
@@ -241,7 +241,7 @@ class KafkaConsumerNode(Node):
|
|
241
241
|
self._consumer = f"kafka_consumer_{self.config['group_id']}"
|
242
242
|
self._topic = self.config["topic"]
|
243
243
|
|
244
|
-
def run(self, **kwargs) ->
|
244
|
+
def run(self, **kwargs) -> dict[str, Any]:
|
245
245
|
"""Consume messages from Kafka.
|
246
246
|
|
247
247
|
Implementation of the abstract run method from the base Node class.
|
@@ -254,7 +254,7 @@ class KafkaConsumerNode(Node):
|
|
254
254
|
"""
|
255
255
|
return self.execute(kwargs)
|
256
256
|
|
257
|
-
def execute(self, inputs:
|
257
|
+
def execute(self, inputs: dict[str, Any]) -> dict[str, Any]:
|
258
258
|
"""Consume messages from Kafka.
|
259
259
|
|
260
260
|
Polls for messages up to the specified limit or timeout.
|
@@ -286,7 +286,7 @@ class KafkaConsumerNode(Node):
|
|
286
286
|
except Exception as e:
|
287
287
|
raise NodeExecutionError(f"Failed to consume messages: {str(e)}")
|
288
288
|
|
289
|
-
def _consume_messages(self, max_messages: int, timeout_ms: int) ->
|
289
|
+
def _consume_messages(self, max_messages: int, timeout_ms: int) -> list[dict]:
|
290
290
|
"""Consume messages from Kafka.
|
291
291
|
|
292
292
|
This is a placeholder for actual message consumption logic.
|
@@ -420,7 +420,7 @@ class StreamPublisherNode(Node):
|
|
420
420
|
self._publisher = None
|
421
421
|
self._protocol = None
|
422
422
|
|
423
|
-
def get_parameters(self) ->
|
423
|
+
def get_parameters(self) -> dict[str, NodeParameter]:
|
424
424
|
"""Define parameters for the stream publisher node."""
|
425
425
|
return {
|
426
426
|
"protocol": NodeParameter(
|
@@ -465,7 +465,7 @@ class StreamPublisherNode(Node):
|
|
465
465
|
),
|
466
466
|
}
|
467
467
|
|
468
|
-
def configure(self, config:
|
468
|
+
def configure(self, config: dict[str, Any]) -> None:
|
469
469
|
"""Configure the stream publisher.
|
470
470
|
|
471
471
|
Creates the appropriate publisher based on the protocol.
|
@@ -499,7 +499,7 @@ class StreamPublisherNode(Node):
|
|
499
499
|
# Placeholder for actual publisher creation
|
500
500
|
self._publisher = f"{self._protocol}_publisher"
|
501
501
|
|
502
|
-
def run(self, **kwargs) ->
|
502
|
+
def run(self, **kwargs) -> dict[str, Any]:
|
503
503
|
"""Publish messages to the streaming platform.
|
504
504
|
|
505
505
|
Implementation of the abstract run method from the base Node class.
|
@@ -512,7 +512,7 @@ class StreamPublisherNode(Node):
|
|
512
512
|
"""
|
513
513
|
return self.execute(kwargs)
|
514
514
|
|
515
|
-
def execute(self, inputs:
|
515
|
+
def execute(self, inputs: dict[str, Any]) -> dict[str, Any]:
|
516
516
|
"""Publish messages to the streaming platform.
|
517
517
|
|
518
518
|
Args:
|
@@ -541,7 +541,7 @@ class StreamPublisherNode(Node):
|
|
541
541
|
except Exception as e:
|
542
542
|
raise NodeExecutionError(f"Failed to publish messages: {str(e)}")
|
543
543
|
|
544
|
-
def _publish_messages(self, messages:
|
544
|
+
def _publish_messages(self, messages: list[dict], headers: dict) -> dict[str, Any]:
|
545
545
|
"""Publish messages to the stream.
|
546
546
|
|
547
547
|
This is a placeholder for actual publishing logic.
|
@@ -683,7 +683,7 @@ class WebSocketNode(Node):
|
|
683
683
|
self._connected = False
|
684
684
|
self._message_queue = []
|
685
685
|
|
686
|
-
def get_parameters(self) ->
|
686
|
+
def get_parameters(self) -> dict[str, NodeParameter]:
|
687
687
|
"""Get the parameters for this node.
|
688
688
|
|
689
689
|
Returns:
|
@@ -750,7 +750,7 @@ class WebSocketNode(Node):
|
|
750
750
|
),
|
751
751
|
}
|
752
752
|
|
753
|
-
def configure(self, config:
|
753
|
+
def configure(self, config: dict[str, Any]) -> None:
|
754
754
|
"""Configure the WebSocket connection.
|
755
755
|
|
756
756
|
Validates the URL and prepares connection parameters.
|
@@ -770,7 +770,7 @@ class WebSocketNode(Node):
|
|
770
770
|
if not url.startswith(("ws://", "wss://")):
|
771
771
|
raise NodeConfigurationError("URL must start with ws:// or wss://")
|
772
772
|
|
773
|
-
def run(self, **kwargs) ->
|
773
|
+
def run(self, **kwargs) -> dict[str, Any]:
|
774
774
|
"""Run the WebSocket node.
|
775
775
|
|
776
776
|
This method fulfills the abstract run method requirement from the base Node class.
|
@@ -786,7 +786,7 @@ class WebSocketNode(Node):
|
|
786
786
|
"""
|
787
787
|
return self.execute(kwargs)
|
788
788
|
|
789
|
-
def execute(self, inputs:
|
789
|
+
def execute(self, inputs: dict[str, Any]) -> dict[str, Any]:
|
790
790
|
"""Execute WebSocket operations.
|
791
791
|
|
792
792
|
Performs the requested action (connect, send, receive, disconnect).
|
@@ -816,7 +816,7 @@ class WebSocketNode(Node):
|
|
816
816
|
except Exception as e:
|
817
817
|
raise NodeExecutionError(f"WebSocket operation failed: {str(e)}")
|
818
818
|
|
819
|
-
def _connect(self) ->
|
819
|
+
def _connect(self) -> dict[str, Any]:
|
820
820
|
"""Connect to the WebSocket server.
|
821
821
|
|
822
822
|
Returns:
|
@@ -832,7 +832,7 @@ class WebSocketNode(Node):
|
|
832
832
|
"metadata": {"timestamp": time.time()},
|
833
833
|
}
|
834
834
|
|
835
|
-
def _send_message(self, message: Any) ->
|
835
|
+
def _send_message(self, message: Any) -> dict[str, Any]:
|
836
836
|
"""Send a message through the WebSocket.
|
837
837
|
|
838
838
|
Args:
|
@@ -851,7 +851,7 @@ class WebSocketNode(Node):
|
|
851
851
|
"metadata": {"timestamp": time.time()},
|
852
852
|
}
|
853
853
|
|
854
|
-
def _receive_messages(self, timeout: float) ->
|
854
|
+
def _receive_messages(self, timeout: float) -> dict[str, Any]:
|
855
855
|
"""Receive messages from the WebSocket.
|
856
856
|
|
857
857
|
Args:
|
@@ -877,7 +877,7 @@ class WebSocketNode(Node):
|
|
877
877
|
"metadata": {"count": len(messages), "timeout": timeout},
|
878
878
|
}
|
879
879
|
|
880
|
-
def _disconnect(self) ->
|
880
|
+
def _disconnect(self) -> dict[str, Any]:
|
881
881
|
"""Disconnect from the WebSocket server.
|
882
882
|
|
883
883
|
Returns:
|
@@ -994,7 +994,7 @@ class EventStreamNode(Node):
|
|
994
994
|
self._connected = False
|
995
995
|
self._last_event_id = None
|
996
996
|
|
997
|
-
def get_parameters(self) ->
|
997
|
+
def get_parameters(self) -> dict[str, NodeParameter]:
|
998
998
|
"""Get the parameters for this node.
|
999
999
|
|
1000
1000
|
Returns:
|
@@ -1048,7 +1048,7 @@ class EventStreamNode(Node):
|
|
1048
1048
|
),
|
1049
1049
|
}
|
1050
1050
|
|
1051
|
-
def run(self, **kwargs) ->
|
1051
|
+
def run(self, **kwargs) -> dict[str, Any]:
|
1052
1052
|
"""Run the EventStream node.
|
1053
1053
|
|
1054
1054
|
This method fulfills the abstract run method requirement from the base Node class.
|
@@ -1064,7 +1064,7 @@ class EventStreamNode(Node):
|
|
1064
1064
|
"""
|
1065
1065
|
return self.execute(kwargs)
|
1066
1066
|
|
1067
|
-
def execute(self, inputs:
|
1067
|
+
def execute(self, inputs: dict[str, Any]) -> dict[str, Any]:
|
1068
1068
|
"""Execute EventStream operations.
|
1069
1069
|
|
1070
1070
|
Args:
|
@@ -1090,7 +1090,7 @@ class EventStreamNode(Node):
|
|
1090
1090
|
except Exception as e:
|
1091
1091
|
raise NodeExecutionError(f"EventStream operation failed: {str(e)}")
|
1092
1092
|
|
1093
|
-
def _start_stream(self) ->
|
1093
|
+
def _start_stream(self) -> dict[str, Any]:
|
1094
1094
|
"""Start the event stream connection.
|
1095
1095
|
|
1096
1096
|
Returns:
|
@@ -1106,7 +1106,7 @@ class EventStreamNode(Node):
|
|
1106
1106
|
"metadata": {"timestamp": time.time()},
|
1107
1107
|
}
|
1108
1108
|
|
1109
|
-
def _stop_stream(self) ->
|
1109
|
+
def _stop_stream(self) -> dict[str, Any]:
|
1110
1110
|
"""Stop the event stream connection.
|
1111
1111
|
|
1112
1112
|
Returns:
|
@@ -1124,7 +1124,7 @@ class EventStreamNode(Node):
|
|
1124
1124
|
},
|
1125
1125
|
}
|
1126
1126
|
|
1127
|
-
def _receive_events(self, max_events: int) ->
|
1127
|
+
def _receive_events(self, max_events: int) -> dict[str, Any]:
|
1128
1128
|
"""Receive events from the stream.
|
1129
1129
|
|
1130
1130
|
Args:
|
kailash/nodes/data/vector_db.py
CHANGED
@@ -44,7 +44,7 @@ Example:
|
|
44
44
|
... })
|
45
45
|
"""
|
46
46
|
|
47
|
-
from typing import Any
|
47
|
+
from typing import Any
|
48
48
|
|
49
49
|
import numpy as np
|
50
50
|
|
@@ -142,7 +142,7 @@ class EmbeddingNode(Node):
|
|
142
142
|
self._model = None
|
143
143
|
self._model_info = {}
|
144
144
|
|
145
|
-
def get_parameters(self) ->
|
145
|
+
def get_parameters(self) -> dict[str, NodeParameter]:
|
146
146
|
"""Define parameters for the embedding node."""
|
147
147
|
return {
|
148
148
|
"model": NodeParameter(
|
@@ -188,7 +188,7 @@ class EmbeddingNode(Node):
|
|
188
188
|
),
|
189
189
|
}
|
190
190
|
|
191
|
-
def configure(self, config:
|
191
|
+
def configure(self, config: dict[str, Any]) -> None:
|
192
192
|
"""Configure the embedding node with model settings.
|
193
193
|
|
194
194
|
Validates configuration, initializes the embedding model, and
|
@@ -241,7 +241,7 @@ class EmbeddingNode(Node):
|
|
241
241
|
"max_tokens": self.config.get("max_tokens", 8192),
|
242
242
|
}
|
243
243
|
|
244
|
-
def run(self, **kwargs) ->
|
244
|
+
def run(self, **kwargs) -> dict[str, Any]:
|
245
245
|
"""Generate embeddings for input texts.
|
246
246
|
|
247
247
|
Implementation of the abstract run method from the base Node class.
|
@@ -254,7 +254,7 @@ class EmbeddingNode(Node):
|
|
254
254
|
"""
|
255
255
|
return self.execute(kwargs)
|
256
256
|
|
257
|
-
def execute(self, inputs:
|
257
|
+
def execute(self, inputs: dict[str, Any]) -> dict[str, Any]:
|
258
258
|
"""Generate embeddings for input texts.
|
259
259
|
|
260
260
|
Processes the input texts through the configured embedding model,
|
@@ -295,7 +295,7 @@ class EmbeddingNode(Node):
|
|
295
295
|
except Exception as e:
|
296
296
|
raise NodeExecutionError(f"Failed to generate embeddings: {str(e)}")
|
297
297
|
|
298
|
-
def _generate_embeddings(self, texts:
|
298
|
+
def _generate_embeddings(self, texts: list[str]) -> list[list[float]]:
|
299
299
|
"""Generate embeddings for a batch of texts.
|
300
300
|
|
301
301
|
This is a placeholder for actual embedding generation logic.
|
@@ -310,7 +310,7 @@ class EmbeddingNode(Node):
|
|
310
310
|
dim = self._model_info.get("dimensions", 768)
|
311
311
|
return [np.random.randn(dim).tolist() for _ in texts]
|
312
312
|
|
313
|
-
def _normalize_embeddings(self, embeddings:
|
313
|
+
def _normalize_embeddings(self, embeddings: list[list[float]]) -> list[list[float]]:
|
314
314
|
"""Normalize embedding vectors to unit length.
|
315
315
|
|
316
316
|
Normalizes each embedding vector to have a magnitude of 1.0,
|
@@ -442,7 +442,7 @@ class VectorDatabaseNode(Node):
|
|
442
442
|
self._client = None
|
443
443
|
self._index = None
|
444
444
|
|
445
|
-
def get_parameters(self) ->
|
445
|
+
def get_parameters(self) -> dict[str, NodeParameter]:
|
446
446
|
"""Define parameters for the vector database node."""
|
447
447
|
return {
|
448
448
|
"provider": NodeParameter(
|
@@ -484,7 +484,7 @@ class VectorDatabaseNode(Node):
|
|
484
484
|
),
|
485
485
|
}
|
486
486
|
|
487
|
-
def configure(self, config:
|
487
|
+
def configure(self, config: dict[str, Any]) -> None:
|
488
488
|
"""Configure the vector database connection.
|
489
489
|
|
490
490
|
Establishes connection to the vector database, validates the index,
|
@@ -529,7 +529,7 @@ class VectorDatabaseNode(Node):
|
|
529
529
|
self._client = f"{provider}_client"
|
530
530
|
self._index = self.config.get("index_name")
|
531
531
|
|
532
|
-
def run(self, **kwargs) ->
|
532
|
+
def run(self, **kwargs) -> dict[str, Any]:
|
533
533
|
"""Execute vector database operations.
|
534
534
|
|
535
535
|
Implementation of the abstract run method from the base Node class.
|
@@ -542,7 +542,7 @@ class VectorDatabaseNode(Node):
|
|
542
542
|
"""
|
543
543
|
return self.execute(kwargs)
|
544
544
|
|
545
|
-
def execute(self, inputs:
|
545
|
+
def execute(self, inputs: dict[str, Any]) -> dict[str, Any]:
|
546
546
|
"""Execute vector database operations.
|
547
547
|
|
548
548
|
Performs the requested operation (upsert, query, delete, fetch)
|
@@ -573,7 +573,7 @@ class VectorDatabaseNode(Node):
|
|
573
573
|
except Exception as e:
|
574
574
|
raise NodeExecutionError(f"Vector operation failed: {str(e)}")
|
575
575
|
|
576
|
-
def _upsert_vectors(self, inputs:
|
576
|
+
def _upsert_vectors(self, inputs: dict[str, Any]) -> dict[str, Any]:
|
577
577
|
"""Insert or update vectors in the database.
|
578
578
|
|
579
579
|
Args:
|
@@ -600,7 +600,7 @@ class VectorDatabaseNode(Node):
|
|
600
600
|
"index": self._index,
|
601
601
|
}
|
602
602
|
|
603
|
-
def _query_vectors(self, inputs:
|
603
|
+
def _query_vectors(self, inputs: dict[str, Any]) -> dict[str, Any]:
|
604
604
|
"""Query similar vectors from the database.
|
605
605
|
|
606
606
|
Args:
|
@@ -631,7 +631,7 @@ class VectorDatabaseNode(Node):
|
|
631
631
|
"count": min(k, 5),
|
632
632
|
}
|
633
633
|
|
634
|
-
def _delete_vectors(self, inputs:
|
634
|
+
def _delete_vectors(self, inputs: dict[str, Any]) -> dict[str, Any]:
|
635
635
|
"""Delete vectors from the database.
|
636
636
|
|
637
637
|
Args:
|
@@ -648,7 +648,7 @@ class VectorDatabaseNode(Node):
|
|
648
648
|
# Placeholder for actual deletion
|
649
649
|
return {"operation": "delete", "status": "success", "count": len(ids)}
|
650
650
|
|
651
|
-
def _fetch_vectors(self, inputs:
|
651
|
+
def _fetch_vectors(self, inputs: dict[str, Any]) -> dict[str, Any]:
|
652
652
|
"""Fetch specific vectors by ID.
|
653
653
|
|
654
654
|
Args:
|
@@ -748,7 +748,7 @@ class TextSplitterNode(Node):
|
|
748
748
|
tags={"text", "processing", "nlp"},
|
749
749
|
)
|
750
750
|
|
751
|
-
def get_parameters(self) ->
|
751
|
+
def get_parameters(self) -> dict[str, NodeParameter]:
|
752
752
|
"""Define parameters for the text splitter node."""
|
753
753
|
return {
|
754
754
|
"strategy": NodeParameter(
|
@@ -788,7 +788,7 @@ class TextSplitterNode(Node):
|
|
788
788
|
),
|
789
789
|
}
|
790
790
|
|
791
|
-
def run(self, **kwargs) ->
|
791
|
+
def run(self, **kwargs) -> dict[str, Any]:
|
792
792
|
"""Split text into chunks using configured strategy.
|
793
793
|
|
794
794
|
Implementation of the abstract run method from the base Node class.
|
@@ -801,7 +801,7 @@ class TextSplitterNode(Node):
|
|
801
801
|
"""
|
802
802
|
return self.execute(kwargs)
|
803
803
|
|
804
|
-
def execute(self, inputs:
|
804
|
+
def execute(self, inputs: dict[str, Any]) -> dict[str, Any]:
|
805
805
|
"""Split text into chunks using configured strategy.
|
806
806
|
|
807
807
|
Args:
|
@@ -854,7 +854,7 @@ class TextSplitterNode(Node):
|
|
854
854
|
except Exception as e:
|
855
855
|
raise NodeExecutionError(f"Text splitting failed: {str(e)}")
|
856
856
|
|
857
|
-
def _recursive_split(self, text: str) ->
|
857
|
+
def _recursive_split(self, text: str) -> list[str]:
|
858
858
|
"""Split text recursively using multiple separators.
|
859
859
|
|
860
860
|
Args:
|
@@ -878,7 +878,7 @@ class TextSplitterNode(Node):
|
|
878
878
|
|
879
879
|
return chunks
|
880
880
|
|
881
|
-
def _character_split(self, text: str) ->
|
881
|
+
def _character_split(self, text: str) -> list[str]:
|
882
882
|
"""Split text by character count.
|
883
883
|
|
884
884
|
Args:
|
@@ -908,7 +908,7 @@ class TextSplitterNode(Node):
|
|
908
908
|
|
909
909
|
return chunks
|
910
910
|
|
911
|
-
def _sentence_split(self, text: str) ->
|
911
|
+
def _sentence_split(self, text: str) -> list[str]:
|
912
912
|
"""Split text by sentences.
|
913
913
|
|
914
914
|
Args:
|
@@ -936,7 +936,7 @@ class TextSplitterNode(Node):
|
|
936
936
|
|
937
937
|
return chunks
|
938
938
|
|
939
|
-
def _token_split(self, text: str) ->
|
939
|
+
def _token_split(self, text: str) -> list[str]:
|
940
940
|
"""Split text by token count.
|
941
941
|
|
942
942
|
Args:
|
kailash/nodes/data/writers.py
CHANGED
@@ -31,7 +31,7 @@ Downstream Consumers:
|
|
31
31
|
|
32
32
|
import csv
|
33
33
|
import json
|
34
|
-
from typing import Any
|
34
|
+
from typing import Any
|
35
35
|
|
36
36
|
from kailash.nodes.base import Node, NodeParameter, register_node
|
37
37
|
from kailash.security import safe_open, validate_file_path
|
@@ -96,7 +96,7 @@ class CSVWriterNode(Node):
|
|
96
96
|
>>> # result = {'rows_written': 2, 'file_path': 'output.csv'}
|
97
97
|
"""
|
98
98
|
|
99
|
-
def get_parameters(self) ->
|
99
|
+
def get_parameters(self) -> dict[str, NodeParameter]:
|
100
100
|
"""Define input parameters for CSV writing.
|
101
101
|
|
102
102
|
Provides comprehensive parameters for flexible CSV output,
|
@@ -144,7 +144,7 @@ class CSVWriterNode(Node):
|
|
144
144
|
),
|
145
145
|
}
|
146
146
|
|
147
|
-
def run(self, **kwargs) ->
|
147
|
+
def run(self, **kwargs) -> dict[str, Any]:
|
148
148
|
"""Execute CSV writing operation.
|
149
149
|
|
150
150
|
Intelligently handles different data structures, automatically
|
@@ -280,7 +280,7 @@ class JSONWriterNode(Node):
|
|
280
280
|
>>> # result = {'file_path': 'response.json'}
|
281
281
|
"""
|
282
282
|
|
283
|
-
def get_parameters(self) ->
|
283
|
+
def get_parameters(self) -> dict[str, NodeParameter]:
|
284
284
|
"""Define input parameters for JSON writing.
|
285
285
|
|
286
286
|
Minimal parameters reflecting JSON's flexibility while
|
@@ -320,7 +320,7 @@ class JSONWriterNode(Node):
|
|
320
320
|
),
|
321
321
|
}
|
322
322
|
|
323
|
-
def run(self, **kwargs) ->
|
323
|
+
def run(self, **kwargs) -> dict[str, Any]:
|
324
324
|
"""Execute JSON writing operation.
|
325
325
|
|
326
326
|
Serializes data to JSON format with proper formatting
|
@@ -431,7 +431,7 @@ class TextWriterNode(Node):
|
|
431
431
|
>>> # result = {'file_path': 'app.log', 'bytes_written': 25}
|
432
432
|
"""
|
433
433
|
|
434
|
-
def get_parameters(self) ->
|
434
|
+
def get_parameters(self) -> dict[str, NodeParameter]:
|
435
435
|
"""Define input parameters for text writing.
|
436
436
|
|
437
437
|
Comprehensive parameters supporting various text writing
|
@@ -478,7 +478,7 @@ class TextWriterNode(Node):
|
|
478
478
|
),
|
479
479
|
}
|
480
480
|
|
481
|
-
def run(self, **kwargs) ->
|
481
|
+
def run(self, **kwargs) -> dict[str, Any]:
|
482
482
|
"""Execute text writing operation.
|
483
483
|
|
484
484
|
Writes text to file with specified encoding and mode.
|
@@ -6,7 +6,7 @@ data processing tasks in workflows.
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
import asyncio
|
9
|
-
from typing import Any
|
9
|
+
from typing import Any
|
10
10
|
|
11
11
|
from kailash.nodes.base import NodeParameter, register_node
|
12
12
|
from kailash.nodes.base_async import AsyncNode
|
@@ -53,7 +53,7 @@ class AsyncMergeNode(AsyncNode):
|
|
53
53
|
[1, 2, 3, 4]
|
54
54
|
"""
|
55
55
|
|
56
|
-
def get_parameters(self) ->
|
56
|
+
def get_parameters(self) -> dict[str, NodeParameter]:
|
57
57
|
"""Define parameters for the AsyncMergeNode."""
|
58
58
|
# Reuse parameters from SyncMerge
|
59
59
|
return {
|
@@ -116,7 +116,7 @@ class AsyncMergeNode(AsyncNode):
|
|
116
116
|
),
|
117
117
|
}
|
118
118
|
|
119
|
-
def get_output_schema(self) ->
|
119
|
+
def get_output_schema(self) -> dict[str, NodeParameter]:
|
120
120
|
"""Define the output schema for AsyncMergeNode."""
|
121
121
|
return {
|
122
122
|
"merged_data": NodeParameter(
|
@@ -127,7 +127,7 @@ class AsyncMergeNode(AsyncNode):
|
|
127
127
|
)
|
128
128
|
}
|
129
129
|
|
130
|
-
async def async_run(self, **kwargs) ->
|
130
|
+
async def async_run(self, **kwargs) -> dict[str, Any]:
|
131
131
|
"""Asynchronously execute the merge operation.
|
132
132
|
|
133
133
|
This implementation provides efficient processing for large datasets by:
|
@@ -199,7 +199,7 @@ class AsyncMergeNode(AsyncNode):
|
|
199
199
|
|
200
200
|
return {"merged_data": result}
|
201
201
|
|
202
|
-
def run(self, **kwargs) ->
|
202
|
+
def run(self, **kwargs) -> dict[str, Any]:
|
203
203
|
"""Synchronous execution method that delegates to the async implementation.
|
204
204
|
|
205
205
|
This method is required by the Node abstract base class but shouldn't
|
@@ -220,7 +220,7 @@ class AsyncMergeNode(AsyncNode):
|
|
220
220
|
"AsyncMergeNode.run() was called directly. Use execute() or execute_async() instead."
|
221
221
|
)
|
222
222
|
|
223
|
-
async def _async_concat(self, data_inputs:
|
223
|
+
async def _async_concat(self, data_inputs: list[Any], chunk_size: int) -> Any:
|
224
224
|
"""Asynchronously concatenate data.
|
225
225
|
|
226
226
|
Args:
|
@@ -254,7 +254,7 @@ class AsyncMergeNode(AsyncNode):
|
|
254
254
|
|
255
255
|
return result
|
256
256
|
|
257
|
-
async def _async_zip(self, data_inputs:
|
257
|
+
async def _async_zip(self, data_inputs: list[Any]) -> list[tuple]:
|
258
258
|
"""Asynchronously zip data.
|
259
259
|
|
260
260
|
Args:
|
@@ -275,10 +275,10 @@ class AsyncMergeNode(AsyncNode):
|
|
275
275
|
await asyncio.sleep(0.005)
|
276
276
|
|
277
277
|
# Zip the lists together
|
278
|
-
return list(zip(*normalized_inputs))
|
278
|
+
return list(zip(*normalized_inputs, strict=False))
|
279
279
|
|
280
280
|
async def _async_merge_dict(
|
281
|
-
self, data_inputs:
|
281
|
+
self, data_inputs: list[Any], key: str | None, chunk_size: int
|
282
282
|
) -> Any:
|
283
283
|
"""Asynchronously merge dictionaries.
|
284
284
|
|
@@ -326,7 +326,7 @@ class AsyncMergeNode(AsyncNode):
|
|
326
326
|
)
|
327
327
|
|
328
328
|
async def _merge_dict_chunk(
|
329
|
-
self, result:
|
329
|
+
self, result: list[dict], data: list[dict], key: str
|
330
330
|
) -> None:
|
331
331
|
"""Merge a chunk of dictionaries into the result list.
|
332
332
|
|
@@ -405,7 +405,7 @@ class AsyncSwitchNode(AsyncNode):
|
|
405
405
|
{'priority': 'high', 'task': 'urgent'}
|
406
406
|
"""
|
407
407
|
|
408
|
-
def get_parameters(self) ->
|
408
|
+
def get_parameters(self) -> dict[str, NodeParameter]:
|
409
409
|
"""Define parameters for the AsyncSwitchNode."""
|
410
410
|
return {
|
411
411
|
"input_data": NodeParameter(
|
@@ -469,7 +469,7 @@ class AsyncSwitchNode(AsyncNode):
|
|
469
469
|
),
|
470
470
|
}
|
471
471
|
|
472
|
-
def get_output_schema(self) ->
|
472
|
+
def get_output_schema(self) -> dict[str, NodeParameter]:
|
473
473
|
"""Dynamic schema with standard outputs."""
|
474
474
|
return {
|
475
475
|
"true_output": NodeParameter(
|
@@ -499,7 +499,7 @@ class AsyncSwitchNode(AsyncNode):
|
|
499
499
|
# Note: case_X outputs are dynamic and not listed here
|
500
500
|
}
|
501
501
|
|
502
|
-
async def async_run(self, **kwargs) ->
|
502
|
+
async def async_run(self, **kwargs) -> dict[str, Any]:
|
503
503
|
"""Asynchronously execute the switch operation.
|
504
504
|
|
505
505
|
Args:
|
@@ -624,7 +624,7 @@ class AsyncSwitchNode(AsyncNode):
|
|
624
624
|
self.logger.debug(f"AsyncSwitch node result keys: {list(result.keys())}")
|
625
625
|
return result
|
626
626
|
|
627
|
-
def run(self, **kwargs) ->
|
627
|
+
def run(self, **kwargs) -> dict[str, Any]:
|
628
628
|
"""Synchronous execution method that delegates to the async implementation.
|
629
629
|
|
630
630
|
This method is required by the Node abstract base class but shouldn't
|
@@ -693,12 +693,12 @@ class AsyncSwitchNode(AsyncNode):
|
|
693
693
|
|
694
694
|
async def _handle_list_grouping(
|
695
695
|
self,
|
696
|
-
groups:
|
697
|
-
cases:
|
696
|
+
groups: dict[Any, list],
|
697
|
+
cases: list[Any],
|
698
698
|
case_prefix: str,
|
699
699
|
default_field: str,
|
700
700
|
pass_condition_result: bool,
|
701
|
-
) ->
|
701
|
+
) -> dict[str, Any]:
|
702
702
|
"""Asynchronously handle routing when input is a list of dictionaries.
|
703
703
|
|
704
704
|
This method creates outputs for each case with the filtered data.
|