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.
- kailash/__init__.py +1 -1
- kailash/api/__init__.py +11 -1
- kailash/api/gateway.py +394 -0
- kailash/api/mcp_integration.py +478 -0
- kailash/api/workflow_api.py +29 -13
- kailash/nodes/ai/__init__.py +40 -4
- kailash/nodes/ai/a2a.py +1143 -0
- kailash/nodes/ai/agents.py +120 -6
- kailash/nodes/ai/ai_providers.py +224 -30
- kailash/nodes/ai/embedding_generator.py +34 -38
- kailash/nodes/ai/intelligent_agent_orchestrator.py +2114 -0
- kailash/nodes/ai/llm_agent.py +351 -356
- kailash/nodes/ai/self_organizing.py +1624 -0
- kailash/nodes/api/http.py +106 -25
- kailash/nodes/api/rest.py +116 -21
- kailash/nodes/base.py +60 -64
- kailash/nodes/code/python.py +61 -42
- kailash/nodes/data/__init__.py +10 -10
- kailash/nodes/data/readers.py +117 -66
- kailash/nodes/data/retrieval.py +1 -1
- kailash/nodes/data/sharepoint_graph.py +23 -25
- kailash/nodes/data/sql.py +24 -26
- kailash/nodes/data/writers.py +41 -44
- kailash/nodes/logic/__init__.py +9 -3
- kailash/nodes/logic/async_operations.py +60 -21
- kailash/nodes/logic/operations.py +43 -22
- kailash/nodes/logic/workflow.py +26 -18
- kailash/nodes/mcp/client.py +29 -33
- kailash/nodes/transform/__init__.py +8 -1
- kailash/nodes/transform/formatters.py +1 -1
- kailash/nodes/transform/processors.py +119 -4
- kailash/tracking/metrics_collector.py +6 -7
- kailash/utils/export.py +2 -2
- kailash/utils/templates.py +16 -16
- {kailash-0.1.3.dist-info → kailash-0.1.5.dist-info}/METADATA +293 -29
- {kailash-0.1.3.dist-info → kailash-0.1.5.dist-info}/RECORD +40 -35
- {kailash-0.1.3.dist-info → kailash-0.1.5.dist-info}/WHEEL +0 -0
- {kailash-0.1.3.dist-info → kailash-0.1.5.dist-info}/entry_points.txt +0 -0
- {kailash-0.1.3.dist-info → kailash-0.1.5.dist-info}/licenses/LICENSE +0 -0
- {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
|
-
"""
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
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
|
-
|
85
|
-
|
86
|
-
|
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
|
-
"""
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
45
|
-
|
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
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
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
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
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
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
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
|
-
|
1016
|
-
|
1017
|
-
|
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
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
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]):
|
kailash/nodes/code/python.py
CHANGED
@@ -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
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
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
|
|
kailash/nodes/data/__init__.py
CHANGED
@@ -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',
|
60
|
+
workflow.add_node('read', CSVReaderNode(file_path='input.csv'))
|
61
61
|
workflow.add_node('transform', DataTransform())
|
62
|
-
workflow.add_node('write',
|
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
|
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
|
102
|
+
from kailash.nodes.data.writers import CSVWriterNode, JSONWriterNode, TextWriterNode
|
103
103
|
|
104
104
|
__all__ = [
|
105
105
|
# Readers
|
106
|
-
"
|
107
|
-
"
|
108
|
-
"
|
106
|
+
"CSVReaderNode",
|
107
|
+
"JSONReaderNode",
|
108
|
+
"TextReaderNode",
|
109
109
|
"SharePointGraphReader",
|
110
110
|
# Writers
|
111
|
-
"
|
112
|
-
"
|
113
|
-
"
|
111
|
+
"CSVWriterNode",
|
112
|
+
"JSONWriterNode",
|
113
|
+
"TextWriterNode",
|
114
114
|
"SharePointGraphWriter",
|
115
115
|
# Sources
|
116
116
|
"DocumentSourceNode",
|