kailash 0.1.3__py3-none-any.whl → 0.1.5__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 (40) hide show
  1. kailash/__init__.py +1 -1
  2. kailash/api/__init__.py +11 -1
  3. kailash/api/gateway.py +394 -0
  4. kailash/api/mcp_integration.py +478 -0
  5. kailash/api/workflow_api.py +29 -13
  6. kailash/nodes/ai/__init__.py +40 -4
  7. kailash/nodes/ai/a2a.py +1143 -0
  8. kailash/nodes/ai/agents.py +120 -6
  9. kailash/nodes/ai/ai_providers.py +224 -30
  10. kailash/nodes/ai/embedding_generator.py +34 -38
  11. kailash/nodes/ai/intelligent_agent_orchestrator.py +2114 -0
  12. kailash/nodes/ai/llm_agent.py +351 -356
  13. kailash/nodes/ai/self_organizing.py +1624 -0
  14. kailash/nodes/api/http.py +106 -25
  15. kailash/nodes/api/rest.py +116 -21
  16. kailash/nodes/base.py +60 -64
  17. kailash/nodes/code/python.py +61 -42
  18. kailash/nodes/data/__init__.py +10 -10
  19. kailash/nodes/data/readers.py +117 -66
  20. kailash/nodes/data/retrieval.py +1 -1
  21. kailash/nodes/data/sharepoint_graph.py +23 -25
  22. kailash/nodes/data/sql.py +24 -26
  23. kailash/nodes/data/writers.py +41 -44
  24. kailash/nodes/logic/__init__.py +9 -3
  25. kailash/nodes/logic/async_operations.py +60 -21
  26. kailash/nodes/logic/operations.py +43 -22
  27. kailash/nodes/logic/workflow.py +26 -18
  28. kailash/nodes/mcp/client.py +29 -33
  29. kailash/nodes/transform/__init__.py +8 -1
  30. kailash/nodes/transform/formatters.py +1 -1
  31. kailash/nodes/transform/processors.py +119 -4
  32. kailash/tracking/metrics_collector.py +6 -7
  33. kailash/utils/export.py +2 -2
  34. kailash/utils/templates.py +16 -16
  35. {kailash-0.1.3.dist-info → kailash-0.1.5.dist-info}/METADATA +293 -29
  36. {kailash-0.1.3.dist-info → kailash-0.1.5.dist-info}/RECORD +40 -35
  37. {kailash-0.1.3.dist-info → kailash-0.1.5.dist-info}/WHEEL +0 -0
  38. {kailash-0.1.3.dist-info → kailash-0.1.5.dist-info}/entry_points.txt +0 -0
  39. {kailash-0.1.3.dist-info → kailash-0.1.5.dist-info}/licenses/LICENSE +0 -0
  40. {kailash-0.1.3.dist-info → kailash-0.1.5.dist-info}/top_level.txt +0 -0
kailash/nodes/api/http.py CHANGED
@@ -57,33 +57,114 @@ class HTTPResponse(BaseModel):
57
57
 
58
58
  @register_node()
59
59
  class HTTPRequestNode(Node):
60
- """Enhanced node for making HTTP requests to external APIs.
61
-
62
- This node provides a flexible interface for making HTTP requests with support for:
63
- * All common HTTP methods (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
64
- * Multiple authentication methods (Bearer, Basic, API Key, OAuth2)
65
- * JSON, form, and multipart request bodies
66
- * Custom headers and query parameters
67
- * Response parsing (JSON, text, binary)
68
- * Error handling and retries with recovery suggestions
69
- * Rate limiting support
70
- * Request/response logging
71
-
72
- Design Purpose:
73
- * Enable workflow integration with external HTTP APIs
74
- * Provide a consistent interface for HTTP operations
75
- * Support common authentication patterns
76
- * Handle response parsing and error handling
77
- * Offer enterprise-grade features like rate limiting
78
-
79
- Upstream Usage:
80
- * Workflow: Creates and configures node for API integration
81
- * Specialized API nodes: May extend this node for specific APIs
60
+ """
61
+ Enhanced node for making HTTP requests to external APIs.
62
+
63
+ This node provides a comprehensive HTTP client with enterprise-grade features for
64
+ integrating external APIs into Kailash workflows. It supports all common HTTP
65
+ operations with built-in authentication, error handling, and response parsing,
66
+ making it the foundation for API integration in the SDK.
67
+
68
+ Design Philosophy:
69
+ The HTTPRequestNode embodies the principle of "API integration made simple."
70
+ It abstracts the complexity of HTTP operations behind a clean interface while
71
+ providing advanced features when needed. The design prioritizes flexibility,
72
+ reliability, and ease of use, supporting everything from simple REST calls
73
+ to complex authentication flows and multipart uploads.
74
+
75
+ Upstream Dependencies:
76
+ - Workflow orchestrators configuring API endpoints
77
+ - Authentication nodes providing credentials
78
+ - Configuration systems supplying API settings
79
+ - Data transformation nodes preparing request payloads
80
+ - Rate limiting controllers managing API quotas
82
81
 
83
82
  Downstream Consumers:
84
- * Data processing nodes: Consume API response data
85
- * Decision nodes: Route workflow based on API responses
86
- * Custom nodes: Process API-specific data formats
83
+ - Data processing nodes consuming API responses
84
+ - Decision nodes routing based on HTTP status
85
+ - Error handling nodes managing failures
86
+ - Caching nodes storing API results
87
+ - Analytics nodes tracking API usage
88
+
89
+ Configuration:
90
+ The node supports extensive configuration options:
91
+ - URL with template variable support
92
+ - All standard HTTP methods
93
+ - Custom headers and query parameters
94
+ - Multiple body formats (JSON, form, multipart)
95
+ - Authentication methods (Bearer, Basic, API Key, OAuth2)
96
+ - Timeout and retry settings
97
+ - Response format preferences
98
+
99
+ Implementation Details:
100
+ - Uses requests library for synchronous operations
101
+ - Automatic response format detection based on Content-Type
102
+ - Built-in JSON parsing with error handling
103
+ - Support for binary responses (files, images)
104
+ - Connection pooling for performance
105
+ - Comprehensive error messages with recovery hints
106
+ - Optional request/response logging
107
+ - Metrics collection for monitoring
108
+
109
+ Error Handling:
110
+ - Connection errors with retry suggestions
111
+ - Timeout handling with configurable limits
112
+ - HTTP error status codes with detailed messages
113
+ - JSON parsing errors with fallback to text
114
+ - Authentication failures with setup guidance
115
+ - Rate limit detection and backoff
116
+
117
+ Side Effects:
118
+ - Makes external HTTP requests
119
+ - May consume API rate limits
120
+ - Logs requests/responses when enabled
121
+ - Updates internal metrics
122
+ - May modify external resources (POST/PUT/DELETE)
123
+
124
+ Examples:
125
+ >>> # Simple GET request
126
+ >>> node = HTTPRequestNode()
127
+ >>> result = node.run(
128
+ ... url="https://api.example.com/users",
129
+ ... method="GET",
130
+ ... headers={"Accept": "application/json"}
131
+ ... )
132
+ >>> assert result["status_code"] == 200
133
+ >>> assert isinstance(result["content"], dict)
134
+ >>>
135
+ >>> # POST request with JSON body
136
+ >>> result = node.run(
137
+ ... url="https://api.example.com/users",
138
+ ... method="POST",
139
+ ... json_data={"name": "John", "email": "john@example.com"},
140
+ ... headers={"Authorization": "Bearer token123"}
141
+ ... )
142
+ >>> assert result["status_code"] in [200, 201]
143
+ >>> assert result["headers"]["content-type"].startswith("application/json")
144
+ >>>
145
+ >>> # Form data submission
146
+ >>> result = node.run(
147
+ ... url="https://api.example.com/form",
148
+ ... method="POST",
149
+ ... data={"field1": "value1", "field2": "value2"},
150
+ ... headers={"Content-Type": "application/x-www-form-urlencoded"}
151
+ ... )
152
+ >>>
153
+ >>> # File upload with multipart
154
+ >>> result = node.run(
155
+ ... url="https://api.example.com/upload",
156
+ ... method="POST",
157
+ ... files={"file": ("data.csv", b"col1,col2\\n1,2", "text/csv")},
158
+ ... data={"description": "Sample data"}
159
+ ... )
160
+ >>>
161
+ >>> # Error handling example
162
+ >>> result = node.run(
163
+ ... url="https://api.example.com/protected",
164
+ ... method="GET"
165
+ ... )
166
+ >>> if result["status_code"] == 401:
167
+ ... print("Authentication required")
87
168
  """
88
169
 
89
170
  def __init__(self, **kwargs):
kailash/nodes/api/rest.py CHANGED
@@ -20,29 +20,124 @@ from kailash.sdk_exceptions import NodeExecutionError, NodeValidationError
20
20
 
21
21
  @register_node()
22
22
  class RESTClientNode(Node):
23
- """Node for interacting with REST APIs.
24
-
25
- This node provides a higher-level interface for interacting with REST APIs,
26
- with built-in support for:
27
- * Resource-based operations (e.g., GET /users/{id})
28
- * Common REST patterns (list, get, create, update, delete)
29
- * Pagination handling
30
- * Response schema validation
31
- * Error response handling
32
-
33
- Design Purpose:
34
- * Simplify REST API integration in workflows
35
- * Provide consistent interfaces for common REST operations
36
- * Support standard REST conventions and patterns
37
- * Handle common REST-specific error cases
38
-
39
- Upstream Usage:
40
- * Workflow: Creates and configures for specific REST APIs
41
- * API integration workflows: Uses for external service integration
23
+ """
24
+ Node for interacting with REST APIs using resource-oriented patterns.
25
+
26
+ This node provides a higher-level abstraction over HTTP operations, specifically
27
+ designed for REST APIs. It understands REST conventions and provides convenient
28
+ methods for resource-based operations, making it easier to integrate RESTful
29
+ services into Kailash workflows.
30
+
31
+ Design Philosophy:
32
+ The RESTClientNode embraces REST principles and conventions, providing an
33
+ intuitive interface for resource manipulation. It abstracts common patterns
34
+ like path parameter substitution, pagination, and error handling while
35
+ maintaining flexibility for API-specific requirements. The design promotes
36
+ clean, maintainable API integration code.
37
+
38
+ Upstream Dependencies:
39
+ - Workflow orchestrators defining API endpoints
40
+ - Configuration nodes providing API credentials
41
+ - Data transformation nodes preparing resources
42
+ - Authentication nodes managing tokens
43
+ - Schema validation nodes defining expected formats
42
44
 
43
45
  Downstream Consumers:
44
- * Data processing nodes: Consume API response data
45
- * Custom nodes: Process API-specific data formats
46
+ - Data processing nodes working with API responses
47
+ - Pagination handlers managing result sets
48
+ - Error recovery nodes handling failures
49
+ - Caching nodes storing resource data
50
+ - Analytics nodes tracking API usage patterns
51
+
52
+ Configuration:
53
+ The node supports REST-specific configuration:
54
+ - Base URL for API endpoints
55
+ - Resource paths with parameter placeholders
56
+ - Default headers and authentication
57
+ - API versioning strategies
58
+ - Pagination parameters
59
+ - Response format expectations
60
+
61
+ Implementation Details:
62
+ - Built on HTTPRequestNode for core functionality
63
+ - Automatic URL construction from base + resource
64
+ - Path parameter substitution (e.g., /users/{id})
65
+ - Query parameter handling with encoding
66
+ - Standard REST method mapping
67
+ - Response format negotiation
68
+ - Error response parsing for API-specific errors
69
+ - Link header parsing for pagination
70
+
71
+ Error Handling:
72
+ - 404 errors for missing resources
73
+ - 422 validation errors with field details
74
+ - 401/403 authentication/authorization errors
75
+ - Rate limiting (429) with retry headers
76
+ - 5xx server errors with backoff
77
+ - Network failures with retry logic
78
+ - Malformed response handling
79
+
80
+ Side Effects:
81
+ - Performs HTTP requests to external APIs
82
+ - May modify remote resources (POST/PUT/DELETE)
83
+ - Consumes API rate limits
84
+ - May trigger webhooks or notifications
85
+ - Updates internal request metrics
86
+
87
+ Examples:
88
+ >>> # Initialize REST client
89
+ >>> client = RESTClientNode()
90
+ >>>
91
+ >>> # Get a single resource
92
+ >>> result = client.run(
93
+ ... base_url="https://api.example.com/v1",
94
+ ... resource="users/{id}",
95
+ ... method="GET",
96
+ ... path_params={"id": 123},
97
+ ... headers={"Authorization": "Bearer token"}
98
+ ... )
99
+ >>> assert result["status_code"] == 200
100
+ >>> user = result["content"]
101
+ >>> assert user["id"] == 123
102
+ >>>
103
+ >>> # List resources with pagination
104
+ >>> result = client.run(
105
+ ... base_url="https://api.example.com/v1",
106
+ ... resource="products",
107
+ ... method="GET",
108
+ ... query_params={"page": 1, "per_page": 20, "category": "electronics"}
109
+ ... )
110
+ >>> assert len(result["content"]) <= 20
111
+ >>>
112
+ >>> # Create a new resource
113
+ >>> result = client.run(
114
+ ... base_url="https://api.example.com/v1",
115
+ ... resource="posts",
116
+ ... method="POST",
117
+ ... data={"title": "New Post", "content": "Post content"},
118
+ ... headers={"Content-Type": "application/json"}
119
+ ... )
120
+ >>> assert result["status_code"] == 201
121
+ >>> assert "id" in result["content"]
122
+ >>>
123
+ >>> # Update a resource
124
+ >>> result = client.run(
125
+ ... base_url="https://api.example.com/v1",
126
+ ... resource="users/{id}",
127
+ ... method="PATCH",
128
+ ... path_params={"id": 123},
129
+ ... data={"email": "newemail@example.com"}
130
+ ... )
131
+ >>> assert result["status_code"] == 200
132
+ >>>
133
+ >>> # Delete a resource
134
+ >>> result = client.run(
135
+ ... base_url="https://api.example.com/v1",
136
+ ... resource="comments/{id}",
137
+ ... method="DELETE",
138
+ ... path_params={"id": 456}
139
+ ... )
140
+ >>> assert result["status_code"] in [200, 204]
46
141
  """
47
142
 
48
143
  def __init__(self, **kwargs):
kailash/nodes/base.py CHANGED
@@ -214,24 +214,23 @@ class Node(ABC):
214
214
  - During workflow creation: Used for connection validation
215
215
  - During export: Included in workflow manifests
216
216
 
217
- Example::
218
-
219
- def get_parameters(self):
220
- return {
221
- 'input_file': NodeParameter(
222
- name='input_file',
223
- type=str,
224
- required=True,
225
- description='Path to input CSV file'
226
- ),
227
- 'delimiter': NodeParameter(
228
- name='delimiter',
229
- type=str,
230
- required=False,
231
- default=',',
232
- description='CSV delimiter character'
233
- )
234
- }
217
+ Example:
218
+ >>> def get_parameters(self):
219
+ ... return {
220
+ ... 'input_file': NodeParameter(
221
+ ... name='input_file',
222
+ ... type=str,
223
+ ... required=True,
224
+ ... description='Path to input CSV file'
225
+ ... ),
226
+ ... 'delimiter': NodeParameter(
227
+ ... name='delimiter',
228
+ ... type=str,
229
+ ... required=False,
230
+ ... default=',',
231
+ ... description='CSV delimiter character'
232
+ ... )
233
+ ... }
235
234
 
236
235
  Returns:
237
236
  Dictionary mapping parameter names to their definitions
@@ -265,29 +264,28 @@ class Node(ABC):
265
264
  3. Workflow connection validation
266
265
  4. Export manifest generation
267
266
 
268
- Example::
269
-
270
- def get_output_schema(self):
271
- return {
272
- 'dataframe': NodeParameter(
273
- name='dataframe',
274
- type=dict,
275
- required=True,
276
- description='Processed data as dictionary'
277
- ),
278
- 'row_count': NodeParameter(
279
- name='row_count',
280
- type=int,
281
- required=True,
282
- description='Number of rows processed'
283
- ),
284
- 'processing_time': NodeParameter(
285
- name='processing_time',
286
- type=float,
287
- required=False,
288
- description='Time taken to process in seconds'
289
- )
290
- }
267
+ Example:
268
+ >>> def get_output_schema(self):
269
+ ... return {
270
+ ... 'dataframe': NodeParameter(
271
+ ... name='dataframe',
272
+ ... type=dict,
273
+ ... required=True,
274
+ ... description='Processed data as dictionary'
275
+ ... ),
276
+ ... 'row_count': NodeParameter(
277
+ ... name='row_count',
278
+ ... type=int,
279
+ ... required=True,
280
+ ... description='Number of rows processed'
281
+ ... ),
282
+ ... 'processing_time': NodeParameter(
283
+ ... name='processing_time',
284
+ ... type=float,
285
+ ... required=False,
286
+ ... description='Time taken to process in seconds'
287
+ ... )
288
+ ... }
291
289
 
292
290
  Returns:
293
291
  Dictionary mapping output names to their parameter definitions
@@ -325,15 +323,14 @@ class Node(ABC):
325
323
  - Error wrapping and logging
326
324
  - Execution timing and metrics
327
325
 
328
- Example::
329
-
330
- def run(self, input_file, delimiter=','):
331
- df = pd.read_csv(input_file, delimiter=delimiter)
332
- return {
333
- 'dataframe': df.to_dict(),
334
- 'row_count': len(df),
335
- 'columns': list(df.columns)
336
- }
326
+ Example:
327
+ >>> def run(self, input_file, delimiter=','):
328
+ ... df = pd.read_csv(input_file, delimiter=delimiter)
329
+ ... return {
330
+ ... 'dataframe': df.to_dict(),
331
+ ... 'row_count': len(df),
332
+ ... 'columns': list(df.columns)
333
+ ... }
337
334
 
338
335
  Args:
339
336
  **kwargs: Validated input parameters matching get_parameters()
@@ -1010,11 +1007,11 @@ class NodeRegistry:
1010
1007
  - Logs the clearing action
1011
1008
  - Existing node instances remain valid
1012
1009
 
1013
- Warning::
1014
-
1015
- - Subsequent get() calls will fail
1016
- - Workflows may not deserialize
1017
- - Should re-register needed nodes
1010
+ Warning:
1011
+ >>> # Warning: This affects all future operations
1012
+ >>> # - Subsequent get() calls will fail
1013
+ >>> # - Workflows may not deserialize
1014
+ >>> # - Should re-register needed nodes
1018
1015
  """
1019
1016
  cls._nodes.clear()
1020
1017
  logging.info("Cleared all registered nodes")
@@ -1057,15 +1054,14 @@ def register_node(alias: Optional[str] = None):
1057
1054
  - Returns the unmodified class
1058
1055
  - Handles registration errors
1059
1056
 
1060
- Example::
1061
-
1062
- @register_node(alias='CSV')
1063
- class CSVReaderNode(Node):
1064
- def get_parameters(self):
1065
- return {'file': NodeParameter(...)}
1066
-
1067
- def run(self, file):
1068
- return pd.read_csv(file)
1057
+ Example:
1058
+ >>> @register_node(alias='CSV')
1059
+ ... class CSVReaderNode(Node):
1060
+ ... def get_parameters(self):
1061
+ ... return {'file': NodeParameter(...)}
1062
+ ...
1063
+ ... def run(self, file):
1064
+ ... return pd.read_csv(file)
1069
1065
  """
1070
1066
 
1071
1067
  def decorator(node_class: Type[Node]):
@@ -144,6 +144,7 @@ class CodeExecutor:
144
144
  "filter",
145
145
  "float",
146
146
  "int",
147
+ "isinstance", # Common type checking
147
148
  "len",
148
149
  "list",
149
150
  "map",
@@ -546,48 +547,47 @@ class PythonCodeNode(Node):
546
547
  - State management for class-based nodes
547
548
  - AST-based security validation
548
549
 
549
- Example::
550
-
551
- # Function-based node
552
- def custom_filter(data: pd.DataFrame, threshold: float) -> pd.DataFrame:
553
- return data[data['value'] > threshold]
554
-
555
- node = PythonCodeNode.from_function(
556
- func=custom_filter,
557
- name="threshold_filter"
558
- )
559
-
560
- # Class-based stateful node
561
- class MovingAverage:
562
- def __init__(self, window_size: int = 3):
563
- self.window_size = window_size
564
- self.values = []
565
-
566
- def process(self, value: float) -> float:
567
- self.values.append(value)
568
- if len(self.values) > self.window_size:
569
- self.values.pop(0)
570
- return sum(self.values) / len(self.values)
571
-
572
- node = PythonCodeNode.from_class(
573
- cls=MovingAverage,
574
- name="moving_avg"
575
- )
576
-
577
- # Code string node
578
- code = '''
579
- result = []
580
- for item in data:
581
- if item > threshold:
582
- result.append(item * 2)
583
- '''
584
-
585
- node = PythonCodeNode(
586
- name="custom_processor",
587
- code=code,
588
- input_types={'data': list, 'threshold': float},
589
- output_type=list
590
- )
550
+ Example:
551
+ >>> # Function-based node
552
+ >>> def custom_filter(data: pd.DataFrame, threshold: float) -> pd.DataFrame:
553
+ ... return data[data['value'] > threshold]
554
+
555
+ >>> node = PythonCodeNode.from_function(
556
+ ... func=custom_filter,
557
+ ... name="threshold_filter"
558
+ ... )
559
+
560
+ >>> # Class-based stateful node
561
+ >>> class MovingAverage:
562
+ ... def __init__(self, window_size: int = 3):
563
+ ... self.window_size = window_size
564
+ ... self.values = []
565
+ ...
566
+ ... def process(self, value: float) -> float:
567
+ ... self.values.append(value)
568
+ ... if len(self.values) > self.window_size:
569
+ ... self.values.pop(0)
570
+ ... return sum(self.values) / len(self.values)
571
+
572
+ >>> node = PythonCodeNode.from_class(
573
+ ... cls=MovingAverage,
574
+ ... name="moving_avg"
575
+ ... )
576
+
577
+ >>> # Code string node
578
+ >>> code = '''
579
+ ... result = []
580
+ ... for item in data:
581
+ ... if item > threshold:
582
+ ... result.append(item * 2)
583
+ ... '''
584
+
585
+ >>> node = PythonCodeNode(
586
+ ... name="custom_processor",
587
+ ... code=code,
588
+ ... input_types={'data': list, 'threshold': float},
589
+ ... output_type=list
590
+ ... )
591
591
  """
592
592
 
593
593
  def __init__(
@@ -727,6 +727,25 @@ class PythonCodeNode(Node):
727
727
 
728
728
  return parameters
729
729
 
730
+ def validate_inputs(self, **kwargs) -> Dict[str, Any]:
731
+ """Validate runtime inputs.
732
+
733
+ For code-based nodes, we accept any inputs since the code
734
+ can use whatever variables it needs.
735
+
736
+ Args:
737
+ **kwargs: Runtime inputs
738
+
739
+ Returns:
740
+ All inputs as-is for code nodes, validated inputs for function/class nodes
741
+ """
742
+ # If using code string, pass through all inputs
743
+ if self.code:
744
+ return kwargs
745
+
746
+ # Otherwise use standard validation for function/class nodes
747
+ return super().validate_inputs(**kwargs)
748
+
730
749
  def get_output_schema(self) -> Dict[str, "NodeParameter"]:
731
750
  """Define output parameters for this node.
732
751
 
@@ -57,9 +57,9 @@ All nodes provide detailed error messages for:
57
57
  Example Workflows:
58
58
  # Traditional ETL
59
59
  workflow = Workflow()
60
- workflow.add_node('read', CSVReader(file_path='input.csv'))
60
+ workflow.add_node('read', CSVReaderNode(file_path='input.csv'))
61
61
  workflow.add_node('transform', DataTransform())
62
- workflow.add_node('write', JSONWriter(file_path='output.json'))
62
+ workflow.add_node('write', JSONWriterNode(file_path='output.json'))
63
63
  workflow.connect('read', 'transform')
64
64
  workflow.connect('transform', 'write')
65
65
 
@@ -80,7 +80,7 @@ Example Workflows:
80
80
  workflow.connect('process', 'publish')
81
81
  """
82
82
 
83
- from kailash.nodes.data.readers import CSVReader, JSONReader, TextReader
83
+ from kailash.nodes.data.readers import CSVReaderNode, JSONReaderNode, TextReaderNode
84
84
  from kailash.nodes.data.retrieval import RelevanceScorerNode
85
85
  from kailash.nodes.data.sharepoint_graph import (
86
86
  SharePointGraphReader,
@@ -99,18 +99,18 @@ from kailash.nodes.data.vector_db import (
99
99
  TextSplitterNode,
100
100
  VectorDatabaseNode,
101
101
  )
102
- from kailash.nodes.data.writers import CSVWriter, JSONWriter, TextWriter
102
+ from kailash.nodes.data.writers import CSVWriterNode, JSONWriterNode, TextWriterNode
103
103
 
104
104
  __all__ = [
105
105
  # Readers
106
- "CSVReader",
107
- "JSONReader",
108
- "TextReader",
106
+ "CSVReaderNode",
107
+ "JSONReaderNode",
108
+ "TextReaderNode",
109
109
  "SharePointGraphReader",
110
110
  # Writers
111
- "CSVWriter",
112
- "JSONWriter",
113
- "TextWriter",
111
+ "CSVWriterNode",
112
+ "JSONWriterNode",
113
+ "TextWriterNode",
114
114
  "SharePointGraphWriter",
115
115
  # Sources
116
116
  "DocumentSourceNode",