kailash 0.2.0__tar.gz → 0.2.2__tar.gz

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 (138) hide show
  1. kailash-0.2.2/PKG-INFO +121 -0
  2. kailash-0.2.2/README.md +51 -0
  3. {kailash-0.2.0 → kailash-0.2.2}/pyproject.toml +4 -1
  4. {kailash-0.2.0 → kailash-0.2.2}/setup.py +1 -1
  5. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/api/custom_nodes_secure.py +2 -2
  6. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/api/studio_secure.py +1 -1
  7. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/mcp/client_new.py +1 -1
  8. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/mcp/server_new.py +6 -6
  9. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/ai/a2a.py +1 -1
  10. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/api/__init__.py +21 -0
  11. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/code/python.py +6 -0
  12. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/data/__init__.py +4 -2
  13. kailash-0.2.2/src/kailash/nodes/data/directory.py +278 -0
  14. kailash-0.2.2/src/kailash/nodes/data/sql.py +823 -0
  15. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/transform/processors.py +31 -0
  16. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/runtime/local.py +13 -0
  17. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/convergence.py +1 -1
  18. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/cycle_analyzer.py +346 -225
  19. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/cycle_builder.py +75 -69
  20. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/cycle_config.py +62 -46
  21. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/cycle_debugger.py +284 -184
  22. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/cycle_exceptions.py +111 -97
  23. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/cycle_profiler.py +272 -202
  24. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/graph.py +15 -0
  25. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/migration.py +238 -197
  26. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/templates.py +124 -105
  27. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/validation.py +356 -298
  28. kailash-0.2.2/src/kailash.egg-info/PKG-INFO +121 -0
  29. {kailash-0.2.0 → kailash-0.2.2}/src/kailash.egg-info/SOURCES.txt +1 -0
  30. {kailash-0.2.0 → kailash-0.2.2}/src/kailash.egg-info/requires.txt +3 -0
  31. kailash-0.2.0/PKG-INFO +0 -1614
  32. kailash-0.2.0/README.md +0 -1547
  33. kailash-0.2.0/src/kailash/nodes/data/sql.py +0 -380
  34. kailash-0.2.0/src/kailash.egg-info/PKG-INFO +0 -1614
  35. {kailash-0.2.0 → kailash-0.2.2}/LICENSE +0 -0
  36. {kailash-0.2.0 → kailash-0.2.2}/MANIFEST.in +0 -0
  37. {kailash-0.2.0 → kailash-0.2.2}/setup.cfg +0 -0
  38. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/__init__.py +0 -0
  39. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/__main__.py +0 -0
  40. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/access_control.py +0 -0
  41. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/api/__init__.py +0 -0
  42. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/api/__main__.py +0 -0
  43. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/api/auth.py +0 -0
  44. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/api/custom_nodes.py +0 -0
  45. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/api/database.py +0 -0
  46. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/api/gateway.py +0 -0
  47. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/api/mcp_integration.py +0 -0
  48. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/api/studio.py +0 -0
  49. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/api/workflow_api.py +0 -0
  50. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/cli/__init__.py +0 -0
  51. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/cli/commands.py +0 -0
  52. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/manifest.py +0 -0
  53. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/mcp/__init__.py +0 -0
  54. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/mcp/__main__.py +0 -0
  55. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/mcp/ai_registry_server.py +0 -0
  56. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/mcp/client.py +0 -0
  57. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/mcp/server.py +0 -0
  58. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/mcp/servers/__init__.py +0 -0
  59. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/mcp/servers/ai_registry.py +0 -0
  60. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/__init__.py +0 -0
  61. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/ai/__init__.py +0 -0
  62. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/ai/agents.py +0 -0
  63. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/ai/ai_providers.py +0 -0
  64. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/ai/embedding_generator.py +0 -0
  65. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/ai/intelligent_agent_orchestrator.py +0 -0
  66. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/ai/iterative_llm_agent.py +0 -0
  67. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/ai/llm_agent.py +0 -0
  68. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/ai/models.py +0 -0
  69. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/ai/self_organizing.py +0 -0
  70. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/api/auth.py +0 -0
  71. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/api/graphql.py +0 -0
  72. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/api/http.py +0 -0
  73. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/api/rate_limiting.py +0 -0
  74. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/api/rest.py +0 -0
  75. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/base.py +0 -0
  76. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/base_async.py +0 -0
  77. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/base_cycle_aware.py +0 -0
  78. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/base_with_acl.py +0 -0
  79. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/code/__init__.py +0 -0
  80. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/data/readers.py +0 -0
  81. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/data/retrieval.py +0 -0
  82. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/data/sharepoint_graph.py +0 -0
  83. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/data/sources.py +0 -0
  84. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/data/streaming.py +0 -0
  85. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/data/vector_db.py +0 -0
  86. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/data/writers.py +0 -0
  87. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/logic/__init__.py +0 -0
  88. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/logic/async_operations.py +0 -0
  89. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/logic/convergence.py +0 -0
  90. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/logic/loop.py +0 -0
  91. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/logic/operations.py +0 -0
  92. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/logic/workflow.py +0 -0
  93. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/mixins/__init__.py +0 -0
  94. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/mixins/mcp.py +0 -0
  95. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/mixins.py +0 -0
  96. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/transform/__init__.py +0 -0
  97. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/transform/chunkers.py +0 -0
  98. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/nodes/transform/formatters.py +0 -0
  99. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/runtime/__init__.py +0 -0
  100. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/runtime/access_controlled.py +0 -0
  101. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/runtime/async_local.py +0 -0
  102. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/runtime/docker.py +0 -0
  103. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/runtime/parallel.py +0 -0
  104. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/runtime/parallel_cyclic.py +0 -0
  105. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/runtime/runner.py +0 -0
  106. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/runtime/testing.py +0 -0
  107. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/sdk_exceptions.py +0 -0
  108. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/security.py +0 -0
  109. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/tracking/__init__.py +0 -0
  110. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/tracking/manager.py +0 -0
  111. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/tracking/metrics_collector.py +0 -0
  112. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/tracking/models.py +0 -0
  113. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/tracking/storage/__init__.py +0 -0
  114. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/tracking/storage/base.py +0 -0
  115. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/tracking/storage/database.py +0 -0
  116. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/tracking/storage/filesystem.py +0 -0
  117. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/utils/__init__.py +0 -0
  118. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/utils/export.py +0 -0
  119. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/utils/templates.py +0 -0
  120. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/visualization/__init__.py +0 -0
  121. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/visualization/api.py +0 -0
  122. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/visualization/dashboard.py +0 -0
  123. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/visualization/performance.py +0 -0
  124. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/visualization/reports.py +0 -0
  125. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/__init__.py +0 -0
  126. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/builder.py +0 -0
  127. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/cycle_state.py +0 -0
  128. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/cyclic_runner.py +0 -0
  129. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/mermaid_visualizer.py +0 -0
  130. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/mock_registry.py +0 -0
  131. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/runner.py +0 -0
  132. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/safety.py +0 -0
  133. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/state.py +0 -0
  134. {kailash-0.2.0 → kailash-0.2.2}/src/kailash/workflow/visualization.py +0 -0
  135. {kailash-0.2.0 → kailash-0.2.2}/src/kailash.egg-info/dependency_links.txt +0 -0
  136. {kailash-0.2.0 → kailash-0.2.2}/src/kailash.egg-info/entry_points.txt +0 -0
  137. {kailash-0.2.0 → kailash-0.2.2}/src/kailash.egg-info/not-zip-safe +0 -0
  138. {kailash-0.2.0 → kailash-0.2.2}/src/kailash.egg-info/top_level.txt +0 -0
kailash-0.2.2/PKG-INFO ADDED
@@ -0,0 +1,121 @@
1
+ Metadata-Version: 2.4
2
+ Name: kailash
3
+ Version: 0.2.2
4
+ Summary: Python SDK for the Kailash container-node architecture
5
+ Home-page: https://github.com/integrum/kailash-python-sdk
6
+ Author: Integrum
7
+ Author-email: Integrum <info@integrum.com>
8
+ Project-URL: Homepage, https://github.com/integrum/kailash-python-sdk
9
+ Project-URL: Bug Tracker, https://github.com/integrum/kailash-python-sdk/issues
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.11
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: networkx>=2.7
19
+ Requires-Dist: pydantic>=1.9
20
+ Requires-Dist: matplotlib>=3.5
21
+ Requires-Dist: pyyaml>=6.0
22
+ Requires-Dist: click>=8.0
23
+ Requires-Dist: pytest>=8.3.5
24
+ Requires-Dist: mcp[cli]>=1.9.2
25
+ Requires-Dist: pandas>=2.2.3
26
+ Requires-Dist: numpy>=2.2.5
27
+ Requires-Dist: scipy>=1.15.3
28
+ Requires-Dist: scikit-learn>=1.6.1
29
+ Requires-Dist: requests>=2.32.3
30
+ Requires-Dist: pytest-cov>=6.1.1
31
+ Requires-Dist: isort>=6.0.1
32
+ Requires-Dist: aiohttp>=3.12.4
33
+ Requires-Dist: ruff>=0.11.12
34
+ Requires-Dist: msal>=1.32.3
35
+ Requires-Dist: sphinx>=8.2.3
36
+ Requires-Dist: sphinx-rtd-theme>=3.0.2
37
+ Requires-Dist: sphinx-copybutton>=0.5.2
38
+ Requires-Dist: sphinxcontrib-mermaid>=1.0.0
39
+ Requires-Dist: sphinx-autobuild>=2024.10.3
40
+ Requires-Dist: autodoc>=0.5.0
41
+ Requires-Dist: myst-parser>=4.0.1
42
+ Requires-Dist: black>=25.1.0
43
+ Requires-Dist: psutil>=7.0.0
44
+ Requires-Dist: fastapi>=0.115.12
45
+ Requires-Dist: uvicorn[standard]>=0.31.0
46
+ Requires-Dist: pytest-asyncio>=1.0.0
47
+ Requires-Dist: pre-commit>=4.2.0
48
+ Requires-Dist: twine>=6.1.0
49
+ Requires-Dist: ollama>=0.5.1
50
+ Requires-Dist: sqlalchemy>=2.0.0
51
+ Requires-Dist: psycopg2-binary>=2.9.0
52
+ Requires-Dist: pymysql>=1.1.0
53
+ Requires-Dist: aiosqlite>=0.19.0
54
+ Requires-Dist: websockets>=12.0
55
+ Requires-Dist: httpx>=0.25.0
56
+ Requires-Dist: python-jose>=3.5.0
57
+ Requires-Dist: pytest-xdist>=3.6.0
58
+ Requires-Dist: pytest-timeout>=2.3.0
59
+ Requires-Dist: pytest-split>=0.9.0
60
+ Provides-Extra: dev
61
+ Requires-Dist: pytest>=7.0; extra == "dev"
62
+ Requires-Dist: pytest-cov>=3.0; extra == "dev"
63
+ Requires-Dist: black>=22.0; extra == "dev"
64
+ Requires-Dist: isort>=5.10; extra == "dev"
65
+ Requires-Dist: mypy>=0.9; extra == "dev"
66
+ Dynamic: author
67
+ Dynamic: home-page
68
+ Dynamic: license-file
69
+ Dynamic: requires-python
70
+
71
+ # Kailash Python SDK - Internal Development Guide
72
+
73
+ This directory contains internal documentation for developers and contributors to the Kailash Python SDK. These documents are not included in the PyPI distribution and are only accessible to those with access to this private repository.
74
+
75
+ ## Directory Structure
76
+
77
+ ### Core Directories (with README.md):
78
+ - **`adr/`** - Architecture Decision Records (35+ design decisions)
79
+ - **`features/`** - In-depth feature implementation guides
80
+ - **`reference/`** - LLM-optimized API references and patterns
81
+ - **`instructions/`** - Detailed coding and documentation standards
82
+ - **`frontend/`** - Frontend development guide
83
+ - **`workflows/`** - Development workflows and task checklists
84
+
85
+ ### Additional Directories:
86
+ - **`development/`** - SDK development guides and tools
87
+ - **`custom-nodes/`** - Comprehensive custom node development guide (parameter types, examples, troubleshooting)
88
+ - **`pre-commit-hooks.md`** - Development workflow automation
89
+ - **`infrastructure/`** - CI/CD and runner configuration
90
+ - **`mistakes/`** - Documented mistakes and lessons learned (73+ issues, including critical v0.2.1 base node fixes)
91
+ - **`prd/`** - Product Requirements Documents
92
+ - **`todos/`** - Active task tracking system
93
+ - **`SECURITY.md`** - Comprehensive security documentation
94
+
95
+ ### In project root:
96
+ - **`CLAUDE.md`** - Compact LLM quick reference (optimized navigation)
97
+
98
+ ## Important Notes
99
+
100
+ 1. **Private Documentation**: All content in this directory is considered internal and should not be shared publicly.
101
+
102
+ 2. **Not Distributed**: These files are explicitly excluded from PyPI packages via `MANIFEST.in`.
103
+
104
+ 3. **Development Reference**: Use these documents to understand design decisions, development patterns, and project history.
105
+
106
+ ## For Contributors
107
+
108
+ When contributing to the project:
109
+ 1. Review `CLAUDE.md` for coding standards and conventions
110
+ 2. Check ADRs for architectural decisions
111
+ 3. Consult PRDs for product requirements
112
+ 4. Learn from documented mistakes to avoid common pitfalls
113
+ 5. Track tasks using the todos system
114
+ 6. **Creating custom nodes?** See `development/custom-nodes/` for critical parameter type constraints
115
+
116
+ ## Accessing Documentation
117
+
118
+ These documents are only available when:
119
+ - Cloning the repository directly from GitHub
120
+ - Having access to the private repository
121
+ - Working on development (not from PyPI installation)
@@ -0,0 +1,51 @@
1
+ # Kailash Python SDK - Internal Development Guide
2
+
3
+ This directory contains internal documentation for developers and contributors to the Kailash Python SDK. These documents are not included in the PyPI distribution and are only accessible to those with access to this private repository.
4
+
5
+ ## Directory Structure
6
+
7
+ ### Core Directories (with README.md):
8
+ - **`adr/`** - Architecture Decision Records (35+ design decisions)
9
+ - **`features/`** - In-depth feature implementation guides
10
+ - **`reference/`** - LLM-optimized API references and patterns
11
+ - **`instructions/`** - Detailed coding and documentation standards
12
+ - **`frontend/`** - Frontend development guide
13
+ - **`workflows/`** - Development workflows and task checklists
14
+
15
+ ### Additional Directories:
16
+ - **`development/`** - SDK development guides and tools
17
+ - **`custom-nodes/`** - Comprehensive custom node development guide (parameter types, examples, troubleshooting)
18
+ - **`pre-commit-hooks.md`** - Development workflow automation
19
+ - **`infrastructure/`** - CI/CD and runner configuration
20
+ - **`mistakes/`** - Documented mistakes and lessons learned (73+ issues, including critical v0.2.1 base node fixes)
21
+ - **`prd/`** - Product Requirements Documents
22
+ - **`todos/`** - Active task tracking system
23
+ - **`SECURITY.md`** - Comprehensive security documentation
24
+
25
+ ### In project root:
26
+ - **`CLAUDE.md`** - Compact LLM quick reference (optimized navigation)
27
+
28
+ ## Important Notes
29
+
30
+ 1. **Private Documentation**: All content in this directory is considered internal and should not be shared publicly.
31
+
32
+ 2. **Not Distributed**: These files are explicitly excluded from PyPI packages via `MANIFEST.in`.
33
+
34
+ 3. **Development Reference**: Use these documents to understand design decisions, development patterns, and project history.
35
+
36
+ ## For Contributors
37
+
38
+ When contributing to the project:
39
+ 1. Review `CLAUDE.md` for coding standards and conventions
40
+ 2. Check ADRs for architectural decisions
41
+ 3. Consult PRDs for product requirements
42
+ 4. Learn from documented mistakes to avoid common pitfalls
43
+ 5. Track tasks using the todos system
44
+ 6. **Creating custom nodes?** See `development/custom-nodes/` for critical parameter type constraints
45
+
46
+ ## Accessing Documentation
47
+
48
+ These documents are only available when:
49
+ - Cloning the repository directly from GitHub
50
+ - Having access to the private repository
51
+ - Working on development (not from PyPI installation)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "kailash"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "Python SDK for the Kailash container-node architecture"
9
9
  authors = [
10
10
  {name = "Integrum", email = "info@integrum.com"}
@@ -52,6 +52,9 @@ dependencies = [
52
52
  "twine>=6.1.0",
53
53
  "ollama>=0.5.1",
54
54
  "sqlalchemy>=2.0.0",
55
+ "psycopg2-binary>=2.9.0",
56
+ "pymysql>=1.1.0",
57
+ "aiosqlite>=0.19.0",
55
58
  "websockets>=12.0",
56
59
  "httpx>=0.25.0",
57
60
  "python-jose>=3.5.0",
@@ -13,7 +13,7 @@ with open(os.path.join(this_directory, "README.md"), encoding="utf-8") as f:
13
13
  # Package configuration
14
14
  setup(
15
15
  name="kailash",
16
- version="0.2.0",
16
+ version="0.2.2",
17
17
  author="Integrum",
18
18
  author_email="info@integrum.com",
19
19
  description="Python SDK for the Kailash container-node architecture",
@@ -350,7 +350,7 @@ async def _execute_api_node(
350
350
  ) -> Dict[str, Any]:
351
351
  """Execute an API-based custom node"""
352
352
 
353
- from kailash.nodes.api.http import HTTPClientNode
353
+ from kailash.nodes.api.http import HTTPRequestNode
354
354
  from kailash.security import TenantContext
355
355
 
356
356
  # Execute in tenant context
@@ -359,7 +359,7 @@ async def _execute_api_node(
359
359
  api_config = node.implementation.get("api", {})
360
360
 
361
361
  # Create HTTP client node
362
- http_node = HTTPClientNode(
362
+ http_node = HTTPRequestNode(
363
363
  url=api_config.get("url", ""),
364
364
  method=api_config.get("method", "GET"),
365
365
  headers=api_config.get("headers", {}),
@@ -369,7 +369,7 @@ class WorkflowStudioAPI:
369
369
  ),
370
370
  }
371
371
  )
372
- except:
372
+ except Exception:
373
373
  outputs.append({"name": "output", "type": "any"})
374
374
  else:
375
375
  # Default output for all nodes
@@ -292,7 +292,7 @@ class MCPClient:
292
292
 
293
293
  # Convenience functions for LLM agents
294
294
  async def discover_and_prepare_tools(
295
- mcp_servers: List[Union[str, Dict[str, Any]]]
295
+ mcp_servers: List[Union[str, Dict[str, Any]]],
296
296
  ) -> List[Dict[str, Any]]:
297
297
  """
298
298
  Discover tools from multiple MCP servers and prepare them for LLM use.
@@ -14,7 +14,7 @@ from typing import Callable, List, Optional
14
14
  try:
15
15
  from mcp.server import Server
16
16
  from mcp.server.models import InitializationOptions
17
- from mcp.types import EmbeddedResource, ImageContent, Resource, TextContent, Tool
17
+ from mcp.types import Resource, TextContent, Tool
18
18
 
19
19
  MCP_AVAILABLE = True
20
20
  except ImportError:
@@ -202,15 +202,15 @@ class MCPServer:
202
202
  # Determine type
203
203
  param_type = "string" # Default
204
204
  if param.annotation != inspect.Parameter.empty:
205
- if param.annotation == int:
205
+ if param.annotation is int:
206
206
  param_type = "integer"
207
- elif param.annotation == float:
207
+ elif param.annotation is float:
208
208
  param_type = "number"
209
- elif param.annotation == bool:
209
+ elif param.annotation is bool:
210
210
  param_type = "boolean"
211
- elif param.annotation == dict:
211
+ elif param.annotation is dict:
212
212
  param_type = "object"
213
- elif param.annotation == list:
213
+ elif param.annotation is list:
214
214
  param_type = "array"
215
215
 
216
216
  properties[param_name] = {
@@ -832,7 +832,7 @@ Focus on actionable intelligence rather than just listing what each agent said."
832
832
  summary = result.get("response", {}).get("content", "")
833
833
  if summary:
834
834
  return f"Shared Context Summary:\n{summary}"
835
- except:
835
+ except Exception:
836
836
  pass
837
837
 
838
838
  # Fallback to simple summary
@@ -18,6 +18,8 @@ Design philosophy:
18
18
  - Enable both synchronous and asynchronous operation
19
19
  """
20
20
 
21
+ import warnings
22
+
21
23
  from .auth import APIKeyNode, BasicAuthNode, OAuth2Node
22
24
  from .graphql import AsyncGraphQLClientNode, GraphQLClientNode
23
25
  from .http import AsyncHTTPRequestNode, HTTPRequestNode
@@ -32,6 +34,23 @@ from .rate_limiting import (
32
34
  )
33
35
  from .rest import AsyncRESTClientNode, RESTClientNode
34
36
 
37
+ # Backwards compatibility aliases
38
+ HTTPClientNode = HTTPRequestNode # Deprecated: Use HTTPRequestNode instead
39
+
40
+
41
+ def __getattr__(name):
42
+ """Provide deprecation warnings for backwards compatibility."""
43
+ if name == "HTTPClientNode":
44
+ warnings.warn(
45
+ "HTTPClientNode is deprecated and will be removed in v0.3.0. "
46
+ "Use HTTPRequestNode instead.",
47
+ DeprecationWarning,
48
+ stacklevel=2,
49
+ )
50
+ return HTTPRequestNode
51
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
52
+
53
+
35
54
  __all__ = [
36
55
  "HTTPRequestNode",
37
56
  "AsyncHTTPRequestNode",
@@ -49,4 +68,6 @@ __all__ = [
49
68
  "RateLimitedAPINode",
50
69
  "AsyncRateLimitedAPINode",
51
70
  "create_rate_limiter",
71
+ # Backwards compatibility
72
+ "HTTPClientNode", # Deprecated alias
52
73
  ]
@@ -93,6 +93,12 @@ ALLOWED_MODULES = {
93
93
  "matplotlib",
94
94
  "seaborn",
95
95
  "plotly",
96
+ # File processing modules
97
+ "csv", # For CSV file processing
98
+ "mimetypes", # For MIME type detection
99
+ "pathlib", # For modern path operations
100
+ "glob", # For file pattern matching
101
+ "xml", # For XML processing
96
102
  }
97
103
 
98
104
 
@@ -80,6 +80,7 @@ Example Workflows:
80
80
  workflow.connect('process', 'publish')
81
81
  """
82
82
 
83
+ from kailash.nodes.data.directory import DirectoryReaderNode
83
84
  from kailash.nodes.data.readers import CSVReaderNode, JSONReaderNode, TextReaderNode
84
85
  from kailash.nodes.data.retrieval import RelevanceScorerNode
85
86
  from kailash.nodes.data.sharepoint_graph import (
@@ -87,7 +88,7 @@ from kailash.nodes.data.sharepoint_graph import (
87
88
  SharePointGraphWriter,
88
89
  )
89
90
  from kailash.nodes.data.sources import DocumentSourceNode, QuerySourceNode
90
- from kailash.nodes.data.sql import SQLDatabaseNode, SQLQueryBuilderNode
91
+ from kailash.nodes.data.sql import SQLDatabaseNode
91
92
  from kailash.nodes.data.streaming import (
92
93
  EventStreamNode,
93
94
  KafkaConsumerNode,
@@ -102,6 +103,8 @@ from kailash.nodes.data.vector_db import (
102
103
  from kailash.nodes.data.writers import CSVWriterNode, JSONWriterNode, TextWriterNode
103
104
 
104
105
  __all__ = [
106
+ # Directory
107
+ "DirectoryReaderNode",
105
108
  # Readers
106
109
  "CSVReaderNode",
107
110
  "JSONReaderNode",
@@ -119,7 +122,6 @@ __all__ = [
119
122
  "RelevanceScorerNode",
120
123
  # SQL
121
124
  "SQLDatabaseNode",
122
- "SQLQueryBuilderNode",
123
125
  # Vector DB
124
126
  "EmbeddingNode",
125
127
  "VectorDatabaseNode",
@@ -0,0 +1,278 @@
1
+ """Directory processing nodes for file discovery and batch operations."""
2
+
3
+ import mimetypes
4
+ import os
5
+ from datetime import datetime
6
+ from typing import Any, Dict, List, Optional
7
+
8
+ from kailash.nodes.base import Node, NodeParameter, register_node
9
+ from kailash.security import validate_file_path
10
+
11
+
12
+ @register_node()
13
+ class DirectoryReaderNode(Node):
14
+ """
15
+ Discovers and catalogs files in a directory with metadata extraction.
16
+
17
+ This node provides comprehensive directory scanning capabilities, handling
18
+ file discovery, metadata extraction, and filtering. It's designed for
19
+ batch file processing workflows and dynamic data source discovery.
20
+
21
+ Design Philosophy:
22
+ The DirectoryReaderNode embodies the principle of "dynamic data discovery."
23
+ Instead of hardcoding file paths, workflows can dynamically discover
24
+ available data sources at runtime. This makes workflows more flexible
25
+ and adaptable to changing data environments.
26
+
27
+ Features:
28
+ - Recursive directory scanning
29
+ - File type detection and filtering
30
+ - Metadata extraction (size, timestamps, MIME types)
31
+ - Pattern-based filtering
32
+ - Security-validated path operations
33
+
34
+ Use Cases:
35
+ - Batch file processing workflows
36
+ - Dynamic data pipeline creation
37
+ - File monitoring and cataloging
38
+ - Multi-format document processing
39
+ - Data lake exploration
40
+
41
+ Output Format:
42
+ Returns a structured catalog of discovered files with:
43
+ - File paths and names
44
+ - File types and MIME types
45
+ - File sizes and timestamps
46
+ - Directory structure information
47
+ """
48
+
49
+ def get_parameters(self) -> Dict[str, NodeParameter]:
50
+ """Define input parameters for directory scanning."""
51
+ return {
52
+ "directory_path": NodeParameter(
53
+ name="directory_path",
54
+ type=str,
55
+ required=True,
56
+ description="Path to the directory to scan",
57
+ ),
58
+ "recursive": NodeParameter(
59
+ name="recursive",
60
+ type=bool,
61
+ required=False,
62
+ default=False,
63
+ description="Whether to scan subdirectories recursively",
64
+ ),
65
+ "file_patterns": NodeParameter(
66
+ name="file_patterns",
67
+ type=list,
68
+ required=False,
69
+ default=[],
70
+ description="List of file patterns to include (e.g., ['*.csv', '*.json'])",
71
+ ),
72
+ "exclude_patterns": NodeParameter(
73
+ name="exclude_patterns",
74
+ type=list,
75
+ required=False,
76
+ default=[],
77
+ description="List of file patterns to exclude",
78
+ ),
79
+ "include_hidden": NodeParameter(
80
+ name="include_hidden",
81
+ type=bool,
82
+ required=False,
83
+ default=False,
84
+ description="Whether to include hidden files (starting with .)",
85
+ ),
86
+ }
87
+
88
+ def run(self, **kwargs) -> Dict[str, Any]:
89
+ """Execute directory scanning operation.
90
+
91
+ Returns:
92
+ Dictionary containing:
93
+ - discovered_files: List of file information dictionaries
94
+ - files_by_type: Files grouped by type
95
+ - directory_stats: Summary statistics
96
+ """
97
+ directory_path = kwargs.get("directory_path")
98
+ recursive = kwargs.get("recursive", False)
99
+ file_patterns = kwargs.get("file_patterns", [])
100
+ exclude_patterns = kwargs.get("exclude_patterns", [])
101
+ include_hidden = kwargs.get("include_hidden", False)
102
+
103
+ # Validate directory path for security
104
+ validated_path = validate_file_path(directory_path, operation="directory scan")
105
+
106
+ if not os.path.isdir(validated_path):
107
+ raise FileNotFoundError(f"Directory not found: {directory_path}")
108
+
109
+ discovered_files = []
110
+
111
+ try:
112
+ if recursive:
113
+ # Recursive scan
114
+ for root, dirs, files in os.walk(validated_path):
115
+ for filename in files:
116
+ file_path = os.path.join(root, filename)
117
+ file_info = self._extract_file_info(
118
+ file_path,
119
+ filename,
120
+ include_hidden,
121
+ file_patterns,
122
+ exclude_patterns,
123
+ )
124
+ if file_info:
125
+ discovered_files.append(file_info)
126
+ else:
127
+ # Single directory scan
128
+ for filename in os.listdir(validated_path):
129
+ file_path = os.path.join(validated_path, filename)
130
+
131
+ # Skip directories in non-recursive mode
132
+ if os.path.isdir(file_path):
133
+ continue
134
+
135
+ file_info = self._extract_file_info(
136
+ file_path,
137
+ filename,
138
+ include_hidden,
139
+ file_patterns,
140
+ exclude_patterns,
141
+ )
142
+ if file_info:
143
+ discovered_files.append(file_info)
144
+
145
+ except PermissionError as e:
146
+ raise PermissionError(f"Permission denied accessing directory: {e}")
147
+ except Exception as e:
148
+ raise RuntimeError(f"Error scanning directory: {e}")
149
+
150
+ # Group files by type
151
+ files_by_type = {}
152
+ for file_info in discovered_files:
153
+ file_type = file_info["file_type"]
154
+ if file_type not in files_by_type:
155
+ files_by_type[file_type] = []
156
+ files_by_type[file_type].append(file_info)
157
+
158
+ # Generate directory statistics
159
+ directory_stats = {
160
+ "total_files": len(discovered_files),
161
+ "file_types": list(files_by_type.keys()),
162
+ "files_by_type_count": {
163
+ file_type: len(files) for file_type, files in files_by_type.items()
164
+ },
165
+ "total_size": sum(f["file_size"] for f in discovered_files),
166
+ "scan_time": datetime.now().isoformat(),
167
+ "directory_path": directory_path,
168
+ "recursive": recursive,
169
+ }
170
+
171
+ return {
172
+ "discovered_files": discovered_files,
173
+ "files_by_type": files_by_type,
174
+ "directory_stats": directory_stats,
175
+ }
176
+
177
+ def _extract_file_info(
178
+ self,
179
+ file_path: str,
180
+ filename: str,
181
+ include_hidden: bool,
182
+ file_patterns: List[str],
183
+ exclude_patterns: List[str],
184
+ ) -> Optional[Dict[str, Any]]:
185
+ """Extract metadata from a single file.
186
+
187
+ Args:
188
+ file_path: Full path to the file
189
+ filename: Name of the file
190
+ include_hidden: Whether to include hidden files
191
+ file_patterns: Patterns to include
192
+ exclude_patterns: Patterns to exclude
193
+
194
+ Returns:
195
+ File information dictionary or None if file should be excluded
196
+ """
197
+ # Skip hidden files if not included
198
+ if not include_hidden and filename.startswith("."):
199
+ return None
200
+
201
+ # Check exclude patterns
202
+ for pattern in exclude_patterns:
203
+ if self._matches_pattern(filename, pattern):
204
+ return None
205
+
206
+ # Check include patterns (if specified)
207
+ if file_patterns:
208
+ included = any(
209
+ self._matches_pattern(filename, pattern) for pattern in file_patterns
210
+ )
211
+ if not included:
212
+ return None
213
+
214
+ try:
215
+ # Get file statistics
216
+ file_stat = os.stat(file_path)
217
+ file_ext = os.path.splitext(filename)[1].lower()
218
+
219
+ # Map extensions to types
220
+ ext_to_type = {
221
+ ".csv": "csv",
222
+ ".json": "json",
223
+ ".txt": "txt",
224
+ ".xml": "xml",
225
+ ".md": "markdown",
226
+ ".py": "python",
227
+ ".js": "javascript",
228
+ ".html": "html",
229
+ ".css": "css",
230
+ ".pdf": "pdf",
231
+ ".doc": "word",
232
+ ".docx": "word",
233
+ ".xls": "excel",
234
+ ".xlsx": "excel",
235
+ ".png": "image",
236
+ ".jpg": "image",
237
+ ".jpeg": "image",
238
+ ".gif": "image",
239
+ ".svg": "image",
240
+ }
241
+
242
+ file_type = ext_to_type.get(file_ext, "unknown")
243
+
244
+ # Get MIME type
245
+ mime_type, _ = mimetypes.guess_type(file_path)
246
+ if not mime_type:
247
+ mime_type = "application/octet-stream"
248
+
249
+ return {
250
+ "file_path": file_path,
251
+ "file_name": filename,
252
+ "file_type": file_type,
253
+ "file_extension": file_ext,
254
+ "file_size": file_stat.st_size,
255
+ "mime_type": mime_type,
256
+ "created_time": datetime.fromtimestamp(file_stat.st_ctime).isoformat(),
257
+ "modified_time": datetime.fromtimestamp(file_stat.st_mtime).isoformat(),
258
+ "discovered_at": datetime.now().isoformat(),
259
+ }
260
+
261
+ except (OSError, PermissionError) as e:
262
+ # Log error but continue with other files
263
+ self.logger.warning(f"Could not process file {file_path}: {e}")
264
+ return None
265
+
266
+ def _matches_pattern(self, filename: str, pattern: str) -> bool:
267
+ """Check if filename matches a glob-style pattern.
268
+
269
+ Args:
270
+ filename: Name of the file to check
271
+ pattern: Glob pattern (e.g., '*.csv', 'data*', 'file?.txt')
272
+
273
+ Returns:
274
+ True if filename matches pattern
275
+ """
276
+ import fnmatch
277
+
278
+ return fnmatch.fnmatch(filename, pattern)