praisonaiagents 0.0.31__py3-none-any.whl → 0.0.33__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.
@@ -211,6 +211,11 @@ class PraisonAIAgents:
211
211
 
212
212
  executor_agent = task.agent
213
213
 
214
+ # Ensure tools are available from both task and agent
215
+ tools = task.tools or []
216
+ if executor_agent and executor_agent.tools:
217
+ tools.extend(executor_agent.tools)
218
+
214
219
  task_prompt = f"""
215
220
  You need to do the following task: {task.description}.
216
221
  Expected Output: {task.expected_output}.
@@ -267,14 +272,14 @@ Here are the results of previous tasks that might be useful:\n
267
272
 
268
273
  agent_output = await executor_agent.achat(
269
274
  _get_multimodal_message(task_prompt, task.images),
270
- tools=task.tools,
275
+ tools=tools,
271
276
  output_json=task.output_json,
272
277
  output_pydantic=task.output_pydantic
273
278
  )
274
279
  else:
275
280
  agent_output = await executor_agent.achat(
276
281
  task_prompt,
277
- tools=task.tools,
282
+ tools=tools,
278
283
  output_json=task.output_json,
279
284
  output_pydantic=task.output_pydantic
280
285
  )
@@ -380,11 +385,25 @@ Here are the results of previous tasks that might be useful:\n
380
385
  )
381
386
 
382
387
  if self.process == "workflow":
388
+ # Collect all tasks that should run in parallel
389
+ parallel_tasks = []
383
390
  async for task_id in process.aworkflow():
384
- if self.tasks[task_id].async_execution:
385
- await self.arun_task(task_id)
386
- else:
387
- self.run_task(task_id)
391
+ if self.tasks[task_id].async_execution and self.tasks[task_id].is_start:
392
+ parallel_tasks.append(task_id)
393
+ elif parallel_tasks:
394
+ # Execute collected parallel tasks
395
+ await asyncio.gather(*[self.arun_task(t) for t in parallel_tasks])
396
+ parallel_tasks = []
397
+ # Run the current non-parallel task
398
+ if self.tasks[task_id].async_execution:
399
+ await self.arun_task(task_id)
400
+ else:
401
+ self.run_task(task_id)
402
+
403
+ # Execute any remaining parallel tasks
404
+ if parallel_tasks:
405
+ await asyncio.gather(*[self.arun_task(t) for t in parallel_tasks])
406
+
388
407
  elif self.process == "sequential":
389
408
  async for task_id in process.asequential():
390
409
  if self.tasks[task_id].async_execution:
@@ -596,8 +615,12 @@ Here are the results of previous tasks that might be useful:\n
596
615
  task.status = "completed"
597
616
  # Run execute_callback for memory operations
598
617
  try:
599
- loop = asyncio.get_event_loop()
600
- loop.run_until_complete(task.execute_callback(task_output))
618
+ if asyncio.get_event_loop().is_running():
619
+ asyncio.create_task(task.execute_callback(task_output))
620
+ else:
621
+ loop = asyncio.new_event_loop()
622
+ asyncio.set_event_loop(loop)
623
+ loop.run_until_complete(task.execute_callback(task_output))
601
624
  except Exception as e:
602
625
  logger.error(f"Error executing memory callback for task {task_id}: {e}")
603
626
  logger.exception(e)
@@ -606,7 +629,12 @@ Here are the results of previous tasks that might be useful:\n
606
629
  if task.callback:
607
630
  try:
608
631
  if asyncio.iscoroutinefunction(task.callback):
609
- loop.run_until_complete(task.callback(task_output))
632
+ if asyncio.get_event_loop().is_running():
633
+ asyncio.create_task(task.callback(task_output))
634
+ else:
635
+ loop = asyncio.new_event_loop()
636
+ asyncio.set_event_loop(loop)
637
+ loop.run_until_complete(task.callback(task_output))
610
638
  else:
611
639
  task.callback(task_output)
612
640
  except Exception as e:
@@ -130,22 +130,28 @@ Return a JSON object with an 'items' array containing the items to process.
130
130
 
131
131
  # Determine next task based on result
132
132
  next_task = None
133
- if current_task.result:
133
+ if current_task and current_task.result:
134
134
  if current_task.task_type in ["decision", "loop"]:
135
135
  result = current_task.result.raw.lower()
136
136
  # Check conditions
137
137
  for condition, tasks in current_task.condition.items():
138
- if condition.lower() in result and tasks:
139
- next_task_name = tasks[0]
138
+ if condition.lower() in result:
139
+ # Handle both list and direct string values
140
+ task_value = tasks[0] if isinstance(tasks, list) else tasks
141
+ if not task_value or task_value == "exit": # If empty or explicit exit
142
+ logging.info("Workflow exit condition met, ending workflow")
143
+ current_task = None
144
+ break
145
+ next_task_name = task_value
140
146
  next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
141
147
  # For loops, allow revisiting the same task
142
148
  if next_task and next_task.id == current_task.id:
143
149
  visited_tasks.discard(current_task.id)
144
150
  break
145
151
 
146
- if not next_task and current_task.next_tasks:
147
- next_task_name = current_task.next_tasks[0]
148
- next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
152
+ if not next_task and current_task and current_task.next_tasks:
153
+ next_task_name = current_task.next_tasks[0]
154
+ next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
149
155
 
150
156
  current_task = next_task
151
157
  if not current_task:
@@ -391,22 +397,28 @@ Return a JSON object with an 'items' array containing the items to process.
391
397
 
392
398
  # Determine next task based on result
393
399
  next_task = None
394
- if current_task.result:
400
+ if current_task and current_task.result:
395
401
  if current_task.task_type in ["decision", "loop"]:
396
402
  result = current_task.result.raw.lower()
397
403
  # Check conditions
398
404
  for condition, tasks in current_task.condition.items():
399
- if condition.lower() in result and tasks:
400
- next_task_name = tasks[0]
405
+ if condition.lower() in result:
406
+ # Handle both list and direct string values
407
+ task_value = tasks[0] if isinstance(tasks, list) else tasks
408
+ if not task_value or task_value == "exit": # If empty or explicit exit
409
+ logging.info("Workflow exit condition met, ending workflow")
410
+ current_task = None
411
+ break
412
+ next_task_name = task_value
401
413
  next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
402
414
  # For loops, allow revisiting the same task
403
415
  if next_task and next_task.id == current_task.id:
404
416
  visited_tasks.discard(current_task.id)
405
417
  break
406
418
 
407
- if not next_task and current_task.next_tasks:
408
- next_task_name = current_task.next_tasks[0]
409
- next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
419
+ if not next_task and current_task and current_task.next_tasks:
420
+ next_task_name = current_task.next_tasks[0]
421
+ next_task = next((t for t in self.tasks.values() if t.name == next_task_name), None)
410
422
 
411
423
  current_task = next_task
412
424
  if not current_task:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: praisonaiagents
3
- Version: 0.0.31
3
+ Version: 0.0.33
4
4
  Summary: Praison AI agents for completing complex tasks with Self Reflection Agents
5
5
  Author: Mervin Praison
6
6
  Requires-Dist: pydantic
@@ -3,11 +3,11 @@ praisonaiagents/main.py,sha256=uMBdwxjnJKHLPUzr_5vXlkuhCUO6EW5O8XC0M-h47sE,13915
3
3
  praisonaiagents/agent/__init__.py,sha256=sKO8wGEXvtCrvV1e834r1Okv0XAqAxqZCqz6hKLiTvA,79
4
4
  praisonaiagents/agent/agent.py,sha256=DDyA8JlHkKoKliWlBC3iNccR2q5rdYljbwogAi1vaUY,34581
5
5
  praisonaiagents/agents/__init__.py,sha256=_1d6Pqyk9EoBSo7E68sKyd1jDRlN1vxvVIRpoMc0Jcw,168
6
- praisonaiagents/agents/agents.py,sha256=N55Ae3JkjNgGQ6pXBaBpI73sA80Y-pPUZLOd1NgtiWU,29523
6
+ praisonaiagents/agents/agents.py,sha256=Os_k25-temlpzzncyElqbQI-e29nlcxqfJYy_ZUIprY,31004
7
7
  praisonaiagents/agents/autoagents.py,sha256=bjC2O5oZmoJItJXIMPTWc2lsp_AJC9tMiTQOal2hwPA,13532
8
8
  praisonaiagents/memory/memory.py,sha256=ZxqSpOUxk9jeTKGW0ZiTifC0uZtym-EZILP3kuOOKkU,35626
9
9
  praisonaiagents/process/__init__.py,sha256=lkYbL7Hn5a0ldvJtkdH23vfIIZLIcanK-65C0MwaorY,52
10
- praisonaiagents/process/process.py,sha256=4qXdrCDQPH5MtvHvdJVURXKNgSl6ae3OYTiqAF_A2ZU,24295
10
+ praisonaiagents/process/process.py,sha256=_tNdptYceCqh8tVIW7faCnxZ4fWtdT20hFfWucVhEEg,25209
11
11
  praisonaiagents/task/__init__.py,sha256=VL5hXVmyGjINb34AalxpBMl-YW9m5EDcRkMTKkSSl7c,80
12
12
  praisonaiagents/task/task.py,sha256=mwmk98nesfz102qTnHSE5VuuPIgHiPDxjeEX7b7g2BA,10023
13
13
  praisonaiagents/tools/__init__.py,sha256=-0lV5n5cG54vYW6REjXIfuJnCLKnfQIDlXsySCaPB9s,7347
@@ -30,7 +30,7 @@ praisonaiagents/tools/wikipedia_tools.py,sha256=pGko-f33wqXgxJTv8db7TbizY5XnzBQR
30
30
  praisonaiagents/tools/xml_tools.py,sha256=iYTMBEk5l3L3ryQ1fkUnNVYK-Nnua2Kx2S0dxNMMs1A,17122
31
31
  praisonaiagents/tools/yaml_tools.py,sha256=uogAZrhXV9O7xvspAtcTfpKSQYL2nlOTvCQXN94-G9A,14215
32
32
  praisonaiagents/tools/yfinance_tools.py,sha256=nmzjS7G_5GqMQD4r867mt17dHg5xvtsYDDfOPh68SgE,8105
33
- praisonaiagents-0.0.31.dist-info/METADATA,sha256=NRAZ9s36jGyIjg0HXKjwVh3_GYmCAERoDtuYH5H2SK0,306
34
- praisonaiagents-0.0.31.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
35
- praisonaiagents-0.0.31.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
36
- praisonaiagents-0.0.31.dist-info/RECORD,,
33
+ praisonaiagents-0.0.33.dist-info/METADATA,sha256=BaYWcI0jrYHHjKXo7v3zZsFIb68NtFQpQMQZQ8_9g3o,306
34
+ praisonaiagents-0.0.33.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
35
+ praisonaiagents-0.0.33.dist-info/top_level.txt,sha256=_HsRddrJ23iDx5TTqVUVvXG2HeHBL5voshncAMDGjtA,16
36
+ praisonaiagents-0.0.33.dist-info/RECORD,,