kailash 0.9.7__py3-none-any.whl → 0.9.9__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 CHANGED
@@ -50,7 +50,7 @@ except ImportError:
50
50
  # For backward compatibility
51
51
  WorkflowGraph = Workflow
52
52
 
53
- __version__ = "0.9.7"
53
+ __version__ = "0.9.9"
54
54
 
55
55
  __all__ = [
56
56
  # Core workflow components
@@ -94,41 +94,37 @@ class IterativeLLMAgentNode(LLMAgentNode):
94
94
  Key Features:
95
95
  - Progressive MCP discovery without pre-configuration
96
96
  - 6-phase iterative process (Discovery → Planning → Execution → Reflection → Convergence → Synthesis)
97
- - **Real MCP tool execution** - Calls actual MCP tools instead of mock execution
97
+ - Real MCP tool execution with fallback to LLM capabilities
98
98
  - Semantic tool understanding and capability mapping
99
99
  - Adaptive strategy based on iteration results
100
100
  - Smart convergence criteria and resource management
101
- - Configurable execution modes (real MCP vs mock for testing)
102
101
 
103
102
  Examples:
104
- >>> # Basic iterative agent with real MCP execution
103
+ >>> # Basic iterative agent execution
105
104
  >>> agent = IterativeLLMAgentNode()
106
105
  >>> result = agent.execute(
107
106
  ... messages=[{"role": "user", "content": "Find and analyze healthcare AI trends"}],
108
107
  ... mcp_servers=["http://localhost:8080"],
109
- ... max_iterations=3,
110
- ... use_real_mcp=True # Enables real MCP tool execution
108
+ ... max_iterations=3
111
109
  ... )
112
110
 
113
- >>> # Advanced iterative agent with custom convergence and real MCP
111
+ >>> # Advanced iterative agent with custom convergence
114
112
  >>> result = agent.execute(
115
113
  ... messages=[{"role": "user", "content": "Research and recommend AI implementation strategy"}],
116
114
  ... mcp_servers=["http://ai-registry:8080", "http://knowledge-base:8081"],
117
115
  ... max_iterations=5,
118
116
  ... discovery_mode="semantic",
119
- ... use_real_mcp=True, # Use real MCP tools
120
117
  ... convergence_criteria={
121
118
  ... "goal_satisfaction": {"threshold": 0.9},
122
119
  ... "diminishing_returns": {"min_improvement": 0.1}
123
120
  ... }
124
121
  ... )
125
122
 
126
- >>> # Test mode with mock execution for development
123
+ >>> # Simple execution example
127
124
  >>> result = agent.execute(
128
125
  ... messages=[{"role": "user", "content": "Test query"}],
129
126
  ... mcp_servers=["http://localhost:8080"],
130
- ... max_iterations=2,
131
- ... use_real_mcp=False # Uses mock execution for testing
127
+ ... max_iterations=2
132
128
  ... )
133
129
  """
134
130
 
@@ -232,18 +228,16 @@ class IterativeLLMAgentNode(LLMAgentNode):
232
228
  default=300,
233
229
  description="Timeout for each iteration in seconds",
234
230
  ),
235
- # MCP Execution Control
236
- "use_real_mcp": NodeParameter(
237
- name="use_real_mcp",
238
- type=bool,
239
- required=False,
240
- default=True,
241
- description="Use real MCP tool execution instead of mock execution",
242
- ),
243
231
  }
244
232
 
245
233
  # Merge base parameters with iterative parameters
246
234
  base_params.update(iterative_params)
235
+
236
+ # Remove deprecated mock-related parameters since this node always uses real execution
237
+ deprecated_params = ["use_real_mcp", "mock_mode"]
238
+ for param_name in deprecated_params:
239
+ base_params.pop(param_name, None)
240
+
247
241
  return base_params
248
242
 
249
243
  def run(self, **kwargs) -> dict[str, Any]:
@@ -582,7 +576,7 @@ class IterativeLLMAgentNode(LLMAgentNode):
582
576
  self, server_config: Any, budget: dict[str, Any]
583
577
  ) -> list[dict[str, Any]]:
584
578
  """Discover resources from a specific MCP server."""
585
- # Mock implementation - in real version would use MCP resource discovery
579
+ # Default implementation - provides basic resource discovery
586
580
  try:
587
581
  server_id = (
588
582
  server_config
@@ -591,8 +585,8 @@ class IterativeLLMAgentNode(LLMAgentNode):
591
585
  )
592
586
  max_resources = budget.get("max_resources", 50)
593
587
 
594
- # Mock discovered resources
595
- mock_resources = [
588
+ # Default discovered resources
589
+ default_resources = [
596
590
  {
597
591
  "uri": f"{server_id}/resource/data/overview",
598
592
  "name": "Data Overview",
@@ -607,7 +601,7 @@ class IterativeLLMAgentNode(LLMAgentNode):
607
601
  },
608
602
  ]
609
603
 
610
- return mock_resources[:max_resources]
604
+ return default_resources[:max_resources]
611
605
 
612
606
  except Exception as e:
613
607
  self.logger.debug(f"Resource discovery failed: {e}")
@@ -669,7 +663,7 @@ class IterativeLLMAgentNode(LLMAgentNode):
669
663
  domain=domain,
670
664
  complexity=complexity,
671
665
  dependencies=[],
672
- confidence=0.8, # Mock confidence
666
+ confidence=0.8, # Default confidence estimate
673
667
  server_source=server_id,
674
668
  )
675
669
 
@@ -779,9 +773,6 @@ class IterativeLLMAgentNode(LLMAgentNode):
779
773
  "errors": [],
780
774
  }
781
775
 
782
- # Check if we should use real MCP tool execution
783
- use_real_mcp = kwargs.get("use_real_mcp", True)
784
-
785
776
  # Handle direct LLM response mode
786
777
  if plan.get("planning_mode") == "direct_llm":
787
778
  try:
@@ -828,21 +819,11 @@ class IterativeLLMAgentNode(LLMAgentNode):
828
819
  tools = step.get("tools", [])
829
820
 
830
821
  try:
831
- if use_real_mcp and tools:
822
+ if tools:
832
823
  # Real MCP tool execution
833
824
  step_result = self._execute_tools_with_mcp(
834
825
  step_num, action, tools, discoveries, kwargs
835
826
  )
836
- elif tools:
837
- # Mock tool execution for backward compatibility
838
- step_result = {
839
- "step": step_num,
840
- "action": action,
841
- "tools_used": tools,
842
- "output": f"Mock execution result for {action} using tools: {', '.join(tools)}",
843
- "success": True,
844
- "duration": 1.5,
845
- }
846
827
  else:
847
828
  # No tools available, try direct LLM call for this step
848
829
  self.logger.info(
@@ -1814,7 +1795,7 @@ provide your best analysis of the query directly.""",
1814
1795
  "total_tools_used": total_tools_used,
1815
1796
  "total_api_calls": total_api_calls,
1816
1797
  "average_iteration_time": total_duration / max(len(iterations), 1),
1817
- "estimated_cost_usd": total_api_calls * 0.01, # Mock cost calculation
1798
+ "estimated_cost_usd": total_api_calls * 0.01, # Simple cost estimation
1818
1799
  }
1819
1800
 
1820
1801
  def _phase_convergence_with_mode(
kailash/nodes/base.py CHANGED
@@ -216,17 +216,58 @@ class Node(ABC):
216
216
  )
217
217
  self.logger = logging.getLogger(f"kailash.nodes.{self.id}")
218
218
 
219
- # Filter out internal fields from config
220
- internal_fields = {
219
+ # Filter out internal fields from config with comprehensive parameter handling
220
+ # Get parameter definitions once and cache for both filtering and validation
221
+ try:
222
+ if not hasattr(self, "_temp_param_definitions"):
223
+ self._temp_param_definitions = self.get_parameters()
224
+ defined_params = set(self._temp_param_definitions.keys())
225
+ except Exception as e:
226
+ # If get_parameters() fails, log but continue with safe defaults
227
+ self.logger.debug(
228
+ f"Could not get parameter definitions during init: {e}"
229
+ )
230
+ defined_params = set()
231
+ self._temp_param_definitions = {}
232
+
233
+ # Comprehensive parameter filtering: handle ALL potential conflicts
234
+ # Fields that are always internal (never user parameters)
235
+ always_internal = {"metadata"}
236
+
237
+ # Fields that can be either internal or user parameters
238
+ potentially_user_params = {
221
239
  "id",
222
240
  "name",
223
241
  "description",
224
242
  "version",
225
243
  "author",
226
244
  "tags",
227
- "metadata",
228
245
  }
229
- self.config = {k: v for k, v in kwargs.items() if k not in internal_fields}
246
+
247
+ # Build dynamic filter list based on user-defined parameters
248
+ internal_fields = always_internal.copy()
249
+ for field in potentially_user_params:
250
+ if field not in defined_params:
251
+ # Field is not user-defined, so treat as internal field
252
+ internal_fields.add(field)
253
+ # If field IS user-defined, don't add to internal_fields (preserve it)
254
+
255
+ # Also filter any field that starts with metadata prefix or other internal patterns
256
+ # This handles cases like 'metadata_name', 'metadata_*', etc.
257
+ def is_internal_field(field_name: str) -> bool:
258
+ # Check if it's in our explicit internal fields list
259
+ if field_name in internal_fields:
260
+ return True
261
+ # Check for metadata-related field patterns
262
+ if field_name.startswith("metadata_"):
263
+ return True
264
+ # Check for other internal patterns
265
+ if field_name.startswith("_"): # Private fields
266
+ return True
267
+ return False
268
+
269
+ # Apply comprehensive filtering
270
+ self.config = {k: v for k, v in kwargs.items() if not is_internal_field(k)}
230
271
 
231
272
  # Parameter resolution cache - initialize before validation
232
273
  cache_size = int(
@@ -554,11 +595,23 @@ class Node(ABC):
554
595
  return bool(re.match(r"^\$\{[^}]+\}$", value))
555
596
 
556
597
  def _get_cached_parameters(self) -> dict[str, NodeParameter]:
557
- """Get cached parameter definitions.
598
+ """Get cached parameter definitions with optimal performance.
599
+
600
+ Uses parameters cached during initialization to avoid duplicate get_parameters() calls.
558
601
 
559
602
  Returns:
560
603
  Dictionary of parameter definitions, cached for performance
561
604
  """
605
+ # First check if we have parameters cached from initialization
606
+ if hasattr(self, "_temp_param_definitions") and self._temp_param_definitions:
607
+ # Use cached parameters from init and clean up temporary cache
608
+ if self._cached_params is None:
609
+ self._cached_params = self._temp_param_definitions
610
+ # Clean up temporary cache to free memory
611
+ delattr(self, "_temp_param_definitions")
612
+ return self._cached_params
613
+
614
+ # Fallback to original behavior if no cached parameters from init
562
615
  if self._cached_params is None:
563
616
  try:
564
617
  self._cached_params = self.get_parameters()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kailash
3
- Version: 0.9.7
3
+ Version: 0.9.9
4
4
  Summary: Python SDK for the Kailash container-node architecture
5
5
  Home-page: https://github.com/integrum/kailash-python-sdk
6
6
  Author: Integrum
@@ -1,4 +1,4 @@
1
- kailash/__init__.py,sha256=E3eRrjccUAH1875857yUosDh9qAHt-Inu_Q383PARDA,2771
1
+ kailash/__init__.py,sha256=FUBzXZ35fF3M-aPSgCf_FFdhXfG8KWO_ymwnSP78xgI,2771
2
2
  kailash/__main__.py,sha256=vr7TVE5o16V6LsTmRFKG6RDKUXHpIWYdZ6Dok2HkHnI,198
3
3
  kailash/access_control.py,sha256=MjKtkoQ2sg1Mgfe7ovGxVwhAbpJKvaepPWr8dxOueMA,26058
4
4
  kailash/access_control_abac.py,sha256=FPfa_8PuDP3AxTjdWfiH3ntwWO8NodA0py9W8SE5dno,30263
@@ -140,7 +140,7 @@ kailash/monitoring/__init__.py,sha256=C5WmkNpk_mmAScqMWiCfkUbjhM5W16dsnRnc3Ial-U
140
140
  kailash/monitoring/alerts.py,sha256=eKX4ooPw1EicumPuswlR_nU18UgRETWvFg8FzCW5pVU,21416
141
141
  kailash/monitoring/metrics.py,sha256=SiAnL3o6K0QaJHgfAuWBa-0pTkW5zymhuPEsj4bgOgM,22022
142
142
  kailash/nodes/__init__.py,sha256=p2KSo0dyUBCLClU123qpQ0tyv5S_36PTxosNyW58nyY,1031
143
- kailash/nodes/base.py,sha256=3KPCp2PDLCPGm4VHSHt8QSONLTX9y3UhQ-3ldQf4oUg,82623
143
+ kailash/nodes/base.py,sha256=GR2E1fWf8j1yMvJic7m2NAih7kjY1NtoDi47hHwoZ40,85437
144
144
  kailash/nodes/base_async.py,sha256=whxepCiVplrltfzEQuabmnGCpEV5WgfqwgxbLdCyiDk,8864
145
145
  kailash/nodes/base_cycle_aware.py,sha256=Xpze9xZzLepWeLpi9Y3tMn1dm2LVv-omr5TSQuGTtWo,13377
146
146
  kailash/nodes/base_with_acl.py,sha256=ZfrkLPgrEBcNbG0LKvtq6glDxyOYOMRw3VXX4vWX6bI,11852
@@ -166,7 +166,7 @@ kailash/nodes/ai/ai_providers.py,sha256=egfiOZzPmZ10d3wBCJ6ST4tRFrrtq0kt1VyCqxVp
166
166
  kailash/nodes/ai/embedding_generator.py,sha256=akGCzz7zLRSziqEQCiPwL2qWhRWxuM_1RQh-YtVEddw,31879
167
167
  kailash/nodes/ai/hybrid_search.py,sha256=k26uDDP_bwrIpv7Yl7PBCPvWSyQEmTlBjI1IpbgDsO4,35446
168
168
  kailash/nodes/ai/intelligent_agent_orchestrator.py,sha256=LvBqMKc64zSxFWVCjbLKKel2QwEzoTeJAEgna7rZw00,83097
169
- kailash/nodes/ai/iterative_llm_agent.py,sha256=G6pQnvSJcMBxloBvLBletFdiIRZGntNaMaVx2no0igY,101273
169
+ kailash/nodes/ai/iterative_llm_agent.py,sha256=Q_letP5mHtO225LBX0Tq5GlPkXkk-yWf3oFEOJTP6Z0,100289
170
170
  kailash/nodes/ai/llm_agent.py,sha256=NeNJZbV_VOUbULug2LASwyzLyoUO5wi58Bc9sXTubuc,90181
171
171
  kailash/nodes/ai/models.py,sha256=wsEeUTuegy87mnLtKgSTg7ggCXvC1n3MsL-iZ4qujHs,16393
172
172
  kailash/nodes/ai/self_organizing.py,sha256=B7NwKaBW8OHQBf5b0F9bSs8Wm-5BDJ9IjIkxS9h00mg,62885
@@ -403,9 +403,9 @@ kailash/workflow/templates.py,sha256=XQMAKZXC2dlxgMMQhSEOWAF3hIbe9JJt9j_THchhAm8
403
403
  kailash/workflow/type_inference.py,sha256=i1F7Yd_Z3elTXrthsLpqGbOnQBIVVVEjhRpI0HrIjd0,24492
404
404
  kailash/workflow/validation.py,sha256=r2zApGiiG8UEn7p5Ji842l8OR1_KftzDkWc7gg0cac0,44675
405
405
  kailash/workflow/visualization.py,sha256=nHBW-Ai8QBMZtn2Nf3EE1_aiMGi9S6Ui_BfpA5KbJPU,23187
406
- kailash-0.9.7.dist-info/licenses/LICENSE,sha256=Axe6g7bTrJkToK9h9j2SpRUKKNaDZDCo2lQ2zPxCE6s,1065
407
- kailash-0.9.7.dist-info/METADATA,sha256=yo7vzKt8ikuCZCQBcsJeDPMm8VRW421kg8-U64whL0w,22298
408
- kailash-0.9.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
409
- kailash-0.9.7.dist-info/entry_points.txt,sha256=M_q3b8PG5W4XbhSgESzIJjh3_4OBKtZFYFsOdkr2vO4,45
410
- kailash-0.9.7.dist-info/top_level.txt,sha256=z7GzH2mxl66498pVf5HKwo5wwfPtt9Aq95uZUpH6JV0,8
411
- kailash-0.9.7.dist-info/RECORD,,
406
+ kailash-0.9.9.dist-info/licenses/LICENSE,sha256=Axe6g7bTrJkToK9h9j2SpRUKKNaDZDCo2lQ2zPxCE6s,1065
407
+ kailash-0.9.9.dist-info/METADATA,sha256=MR4Ore7NAIr_V4yKTpwxqL4EVyoFMjO2hlYZRReAigQ,22298
408
+ kailash-0.9.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
409
+ kailash-0.9.9.dist-info/entry_points.txt,sha256=M_q3b8PG5W4XbhSgESzIJjh3_4OBKtZFYFsOdkr2vO4,45
410
+ kailash-0.9.9.dist-info/top_level.txt,sha256=z7GzH2mxl66498pVf5HKwo5wwfPtt9Aq95uZUpH6JV0,8
411
+ kailash-0.9.9.dist-info/RECORD,,