praisonaiagents 0.0.85__py3-none-any.whl → 0.0.86__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.
@@ -526,6 +526,44 @@ Your Goal: {self.goal}
526
526
  tools=self.tools
527
527
  )
528
528
 
529
+ def _cast_arguments(self, func, arguments):
530
+ """Cast arguments to their expected types based on function signature."""
531
+ if not callable(func) or not arguments:
532
+ return arguments
533
+
534
+ try:
535
+ sig = inspect.signature(func)
536
+ casted_args = {}
537
+
538
+ for param_name, arg_value in arguments.items():
539
+ if param_name in sig.parameters:
540
+ param = sig.parameters[param_name]
541
+ if param.annotation != inspect.Parameter.empty:
542
+ # Handle common type conversions
543
+ if param.annotation == int and isinstance(arg_value, (str, float)):
544
+ try:
545
+ casted_args[param_name] = int(float(arg_value))
546
+ except (ValueError, TypeError):
547
+ casted_args[param_name] = arg_value
548
+ elif param.annotation == float and isinstance(arg_value, (str, int)):
549
+ try:
550
+ casted_args[param_name] = float(arg_value)
551
+ except (ValueError, TypeError):
552
+ casted_args[param_name] = arg_value
553
+ elif param.annotation == bool and isinstance(arg_value, str):
554
+ casted_args[param_name] = arg_value.lower() in ('true', '1', 'yes', 'on')
555
+ else:
556
+ casted_args[param_name] = arg_value
557
+ else:
558
+ casted_args[param_name] = arg_value
559
+ else:
560
+ casted_args[param_name] = arg_value
561
+
562
+ return casted_args
563
+ except Exception as e:
564
+ logging.debug(f"Type casting failed for {getattr(func, '__name__', 'unknown function')}: {e}")
565
+ return arguments
566
+
529
567
  def execute_tool(self, function_name, arguments):
530
568
  """
531
569
  Execute a tool dynamically based on the function name and arguments.
@@ -576,7 +614,8 @@ Your Goal: {self.goal}
576
614
  run_params = {k: v for k, v in arguments.items()
577
615
  if k in inspect.signature(instance.run).parameters
578
616
  and k != 'self'}
579
- return instance.run(**run_params)
617
+ casted_params = self._cast_arguments(instance.run, run_params)
618
+ return instance.run(**casted_params)
580
619
 
581
620
  # CrewAI: If it's a class with an _run method, instantiate and call _run
582
621
  elif inspect.isclass(func) and hasattr(func, '_run'):
@@ -584,11 +623,13 @@ Your Goal: {self.goal}
584
623
  run_params = {k: v for k, v in arguments.items()
585
624
  if k in inspect.signature(instance._run).parameters
586
625
  and k != 'self'}
587
- return instance._run(**run_params)
626
+ casted_params = self._cast_arguments(instance._run, run_params)
627
+ return instance._run(**casted_params)
588
628
 
589
629
  # Otherwise treat as regular function
590
630
  elif callable(func):
591
- return func(**arguments)
631
+ casted_arguments = self._cast_arguments(func, arguments)
632
+ return func(**casted_arguments)
592
633
  except Exception as e:
593
634
  error_msg = str(e)
594
635
  logging.error(f"Error executing tool {function_name}: {error_msg}")
@@ -13,6 +13,16 @@ from ..task.task import Task
13
13
  from ..process.process import Process, LoopItems
14
14
  import asyncio
15
15
  import uuid
16
+ from enum import Enum
17
+
18
+ # Task status constants
19
+ class TaskStatus(Enum):
20
+ """Enumeration for task status values to ensure consistency"""
21
+ COMPLETED = "completed"
22
+ IN_PROGRESS = "in progress"
23
+ NOT_STARTED = "not started"
24
+ FAILED = "failed"
25
+ UNKNOWN = "unknown"
16
26
 
17
27
  # Set up logger
18
28
  logger = logging.getLogger(__name__)
@@ -49,6 +59,55 @@ def process_video(video_path: str, seconds_per_frame=2):
49
59
  video.release()
50
60
  return base64_frames
51
61
 
62
+ def process_task_context(context_item, verbose=0, user_id=None):
63
+ """
64
+ Process a single context item for task execution.
65
+ This helper function avoids code duplication between async and sync execution methods.
66
+
67
+ Args:
68
+ context_item: The context item to process (can be string, list, task object, or dict)
69
+ verbose: Verbosity level for logging
70
+ user_id: User ID for database queries
71
+
72
+ Returns:
73
+ str: Formatted context string for this item
74
+ """
75
+ if isinstance(context_item, str):
76
+ return f"Input Content:\n{context_item}"
77
+ elif isinstance(context_item, list):
78
+ return f"Input Content: {' '.join(str(x) for x in context_item)}"
79
+ elif hasattr(context_item, 'result'): # Task object
80
+ # Ensure the previous task is completed before including its result
81
+ task_status = getattr(context_item, 'status', None)
82
+ task_name = context_item.name if context_item.name else context_item.description
83
+
84
+ if context_item.result and task_status == TaskStatus.COMPLETED.value:
85
+ return f"Result of previous task {task_name}:\n{context_item.result.raw}"
86
+ elif task_status == TaskStatus.COMPLETED.value and not context_item.result:
87
+ return f"Previous task {task_name} completed but produced no result."
88
+ else:
89
+ return f"Previous task {task_name} is not yet completed (status: {task_status or TaskStatus.UNKNOWN.value})."
90
+ elif isinstance(context_item, dict) and "vector_store" in context_item:
91
+ from ..knowledge.knowledge import Knowledge
92
+ try:
93
+ # Handle both string and dict configs
94
+ cfg = context_item["vector_store"]
95
+ if isinstance(cfg, str):
96
+ cfg = json.loads(cfg)
97
+
98
+ knowledge = Knowledge(config={"vector_store": cfg}, verbose=verbose)
99
+
100
+ # Only use user_id as filter
101
+ db_results = knowledge.search(
102
+ context_item.get("query", ""), # Use query from context if available
103
+ user_id=user_id if user_id else None
104
+ )
105
+ return f"[DB Context]: {str(db_results)}"
106
+ except Exception as e:
107
+ return f"[Vector DB Error]: {e}"
108
+ else:
109
+ return str(context_item) # Fallback for unknown types
110
+
52
111
  class PraisonAIAgents:
53
112
  def __init__(self, agents, tasks=None, verbose=0, completion_checker=None, max_retries=5, process="sequential", manager_llm=None, memory=False, memory_config=None, embedder=None, user_id=None, max_iter=10, stream=True, name: Optional[str] = None):
54
113
  # Add check at the start if memory is requested
@@ -250,44 +309,20 @@ Expected Output: {task.expected_output}.
250
309
  if task.context:
251
310
  context_results = [] # Use list to avoid duplicates
252
311
  for context_item in task.context:
253
- if isinstance(context_item, str):
254
- context_results.append(f"Input Content:\n{context_item}")
255
- elif isinstance(context_item, list):
256
- context_results.append(f"Input Content: {' '.join(str(x) for x in context_item)}")
257
- elif hasattr(context_item, 'result'): # Task object
258
- if context_item.result:
259
- context_results.append(
260
- f"Result of previous task {context_item.name if context_item.name else context_item.description}:\n{context_item.result.raw}"
261
- )
262
- else:
263
- context_results.append(
264
- f"Previous task {context_item.name if context_item.name else context_item.description} has no result yet."
265
- )
266
- elif isinstance(context_item, dict) and "vector_store" in context_item:
267
- from ..knowledge.knowledge import Knowledge
268
- try:
269
- # Handle both string and dict configs
270
- cfg = context_item["vector_store"]
271
- if isinstance(cfg, str):
272
- cfg = json.loads(cfg)
273
-
274
- knowledge = Knowledge(config={"vector_store": cfg}, verbose=self.verbose)
275
-
276
- # Only use user_id as filter
277
- db_results = knowledge.search(
278
- task.description,
279
- user_id=self.user_id if self.user_id else None
280
- )
281
- context_results.append(f"[DB Context]: {str(db_results)}")
282
- except Exception as e:
283
- context_results.append(f"[Vector DB Error]: {e}")
312
+ # Use the centralized helper function
313
+ context_str = process_task_context(context_item, self.verbose, self.user_id)
314
+ context_results.append(context_str)
284
315
 
285
- # Join unique context results
316
+ # Join unique context results with proper formatting
286
317
  unique_contexts = list(dict.fromkeys(context_results)) # Remove duplicates
318
+ if self.verbose >= 3:
319
+ logger.info(f"Task {task_id} context items: {len(unique_contexts)}")
320
+ for i, ctx in enumerate(unique_contexts):
321
+ logger.info(f"Context {i+1}: {ctx[:100]}...")
287
322
  task_prompt += f"""
288
323
  Context:
289
324
 
290
- {' '.join(unique_contexts)}
325
+ {'\n\n'.join(unique_contexts)}
291
326
  """
292
327
  task_prompt += "Please provide only the final result of your work. Do not add any conversation or extra explanation."
293
328
 
@@ -573,44 +608,20 @@ Expected Output: {task.expected_output}.
573
608
  if task.context:
574
609
  context_results = [] # Use list to avoid duplicates
575
610
  for context_item in task.context:
576
- if isinstance(context_item, str):
577
- context_results.append(f"Input Content:\n{context_item}")
578
- elif isinstance(context_item, list):
579
- context_results.append(f"Input Content: {' '.join(str(x) for x in context_item)}")
580
- elif hasattr(context_item, 'result'): # Task object
581
- if context_item.result:
582
- context_results.append(
583
- f"Result of previous task {context_item.name if context_item.name else context_item.description}:\n{context_item.result.raw}"
584
- )
585
- else:
586
- context_results.append(
587
- f"Previous task {context_item.name if context_item.name else context_item.description} has no result yet."
588
- )
589
- elif isinstance(context_item, dict) and "vector_store" in context_item:
590
- from ..knowledge.knowledge import Knowledge
591
- try:
592
- # Handle both string and dict configs
593
- cfg = context_item["vector_store"]
594
- if isinstance(cfg, str):
595
- cfg = json.loads(cfg)
596
-
597
- knowledge = Knowledge(config={"vector_store": cfg}, verbose=self.verbose)
598
-
599
- # Only use user_id as filter
600
- db_results = knowledge.search(
601
- task.description,
602
- user_id=self.user_id if self.user_id else None
603
- )
604
- context_results.append(f"[DB Context]: {str(db_results)}")
605
- except Exception as e:
606
- context_results.append(f"[Vector DB Error]: {e}")
611
+ # Use the centralized helper function
612
+ context_str = process_task_context(context_item, self.verbose, self.user_id)
613
+ context_results.append(context_str)
607
614
 
608
- # Join unique context results
615
+ # Join unique context results with proper formatting
609
616
  unique_contexts = list(dict.fromkeys(context_results)) # Remove duplicates
617
+ if self.verbose >= 3:
618
+ logger.info(f"Task {task_id} context items: {len(unique_contexts)}")
619
+ for i, ctx in enumerate(unique_contexts):
620
+ logger.info(f"Context {i+1}: {ctx[:100]}...")
610
621
  task_prompt += f"""
611
622
  Context:
612
623
 
613
- {' '.join(unique_contexts)}
624
+ {'\n\n'.join(unique_contexts)}
614
625
  """
615
626
 
616
627
  # Add memory context if available
@@ -212,6 +212,18 @@ class MCP:
212
212
 
213
213
  # Set up stdio client
214
214
  self.is_sse = False
215
+
216
+ # Ensure UTF-8 encoding in environment for Docker compatibility
217
+ env = kwargs.get('env', {})
218
+ if not env:
219
+ env = os.environ.copy()
220
+ env.update({
221
+ 'PYTHONIOENCODING': 'utf-8',
222
+ 'LC_ALL': 'C.UTF-8',
223
+ 'LANG': 'C.UTF-8'
224
+ })
225
+ kwargs['env'] = env
226
+
215
227
  self.server_params = StdioServerParameters(
216
228
  command=cmd,
217
229
  args=arguments,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: praisonaiagents
3
- Version: 0.0.85
3
+ Version: 0.0.86
4
4
  Summary: Praison AI agents for completing complex tasks with Self Reflection Agents
5
5
  Author: Mervin Praison
6
6
  Requires-Dist: pydantic
@@ -1,10 +1,10 @@
1
1
  praisonaiagents/__init__.py,sha256=Z2_rSA6mYozz0r3ioUgKzl3QV8uWRDS_QaqPg2oGjqg,1324
2
2
  praisonaiagents/main.py,sha256=l29nGEbV2ReBi4szURbnH0Fk0w2F_QZTmECysyZjYcA,15066
3
3
  praisonaiagents/agent/__init__.py,sha256=j0T19TVNbfZcClvpbZDDinQxZ0oORgsMrMqx16jZ-bA,128
4
- praisonaiagents/agent/agent.py,sha256=9vexAh3Jch5Fqst2aT-jf6xU1wAr4t0NePJZMmtVK_g,84183
4
+ praisonaiagents/agent/agent.py,sha256=rnUCrrEB_7kLrSsHwZydiRg7ygIokGIrKZ0P6WYuj4M,86363
5
5
  praisonaiagents/agent/image_agent.py,sha256=-5MXG594HVwSpFMcidt16YBp7udtik-Cp7eXlzLE1fY,8696
6
6
  praisonaiagents/agents/__init__.py,sha256=_1d6Pqyk9EoBSo7E68sKyd1jDRlN1vxvVIRpoMc0Jcw,168
7
- praisonaiagents/agents/agents.py,sha256=HQXAuvV_cORa-NUNVknve4d0B1OIqS6W5jYkw_bYEyA,59519
7
+ praisonaiagents/agents/agents.py,sha256=5u-49r8vAWDA7D8mxuodhljYEE2D5x8csBTmho1cyqU,59329
8
8
  praisonaiagents/agents/autoagents.py,sha256=olYDn--rlJp-SckxILqmREkkgNlzCgEEcAUzfMj-54E,13518
9
9
  praisonaiagents/knowledge/__init__.py,sha256=xL1Eh-a3xsHyIcU4foOWF-JdWYIYBALJH9bge0Ujuto,246
10
10
  praisonaiagents/knowledge/chunking.py,sha256=G6wyHa7_8V0_7VpnrrUXbEmUmptlT16ISJYaxmkSgmU,7678
@@ -12,7 +12,7 @@ praisonaiagents/knowledge/knowledge.py,sha256=Po0JZsgjYJrXdNSggmUGOWidZEF0f8xo4n
12
12
  praisonaiagents/llm/__init__.py,sha256=ttPQQJQq6Tah-0updoEXDZFKWtJAM93rBWRoIgxRWO8,689
13
13
  praisonaiagents/llm/llm.py,sha256=Y8z7mfzL_OMhoPSIr7k7Demk8HvHmJZv80EXFY6SUEU,91863
14
14
  praisonaiagents/mcp/__init__.py,sha256=ibbqe3_7XB7VrIcUcetkZiUZS1fTVvyMy_AqCSFG8qc,240
15
- praisonaiagents/mcp/mcp.py,sha256=foarT5IoCZ6V8P9AbnqnWQHKmshJoD24gf3OP4sD_IM,16419
15
+ praisonaiagents/mcp/mcp.py,sha256=-U6md6zHoJZCWF8XFq921Yy5CcSNaGqvjg3aRT737LM,16765
16
16
  praisonaiagents/mcp/mcp_sse.py,sha256=DLh3F_aoVRM1X-7hgIOWOw4FQ1nGmn9YNbQTesykzn4,6792
17
17
  praisonaiagents/memory/memory.py,sha256=I8dOTkrl1i-GgQbDcrFOsSruzJ7MiI6Ys37DK27wrUs,35537
18
18
  praisonaiagents/process/__init__.py,sha256=lkYbL7Hn5a0ldvJtkdH23vfIIZLIcanK-65C0MwaorY,52
@@ -40,7 +40,7 @@ praisonaiagents/tools/xml_tools.py,sha256=iYTMBEk5l3L3ryQ1fkUnNVYK-Nnua2Kx2S0dxN
40
40
  praisonaiagents/tools/yaml_tools.py,sha256=uogAZrhXV9O7xvspAtcTfpKSQYL2nlOTvCQXN94-G9A,14215
41
41
  praisonaiagents/tools/yfinance_tools.py,sha256=s2PBj_1v7oQnOobo2fDbQBACEHl61ftG4beG6Z979ZE,8529
42
42
  praisonaiagents/tools/train/data/generatecot.py,sha256=H6bNh-E2hqL5MW6kX3hqZ05g9ETKN2-kudSjiuU_SD8,19403
43
- praisonaiagents-0.0.85.dist-info/METADATA,sha256=p4gpH5C_8N2UL7IKRZlaJXBd_qjL36bpdoRly8NMzoE,1244
44
- praisonaiagents-0.0.85.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
45
- praisonaiagents-0.0.85.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
46
- praisonaiagents-0.0.85.dist-info/RECORD,,
43
+ praisonaiagents-0.0.86.dist-info/METADATA,sha256=dYMYlpU7x7Brp7KqcWA1RZcNFBl3waWW-X8Dc3JZ8TA,1244
44
+ praisonaiagents-0.0.86.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
45
+ praisonaiagents-0.0.86.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
46
+ praisonaiagents-0.0.86.dist-info/RECORD,,