praisonaiagents 0.0.115__tar.gz → 0.0.117__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 (70) hide show
  1. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/PKG-INFO +1 -1
  2. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/agent/agent.py +109 -10
  3. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/agents/agents.py +1 -1
  4. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/agents/autoagents.py +13 -1
  5. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/llm/llm.py +51 -3
  6. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/main.py +0 -19
  7. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/process/process.py +4 -2
  8. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents.egg-info/PKG-INFO +1 -1
  9. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/pyproject.toml +1 -1
  10. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/README.md +0 -0
  11. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/__init__.py +0 -0
  12. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/agent/__init__.py +0 -0
  13. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/agent/handoff.py +0 -0
  14. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/agent/image_agent.py +0 -0
  15. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/agents/__init__.py +0 -0
  16. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/approval.py +0 -0
  17. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/guardrails/__init__.py +0 -0
  18. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/guardrails/guardrail_result.py +0 -0
  19. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/guardrails/llm_guardrail.py +0 -0
  20. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/knowledge/__init__.py +0 -0
  21. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/knowledge/chunking.py +0 -0
  22. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/knowledge/knowledge.py +0 -0
  23. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/llm/__init__.py +0 -0
  24. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/llm/openai_client.py +0 -0
  25. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/mcp/__init__.py +0 -0
  26. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/mcp/mcp.py +0 -0
  27. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/mcp/mcp_sse.py +0 -0
  28. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/memory/__init__.py +0 -0
  29. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/memory/memory.py +0 -0
  30. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/process/__init__.py +0 -0
  31. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/session.py +0 -0
  32. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/task/__init__.py +0 -0
  33. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/task/task.py +0 -0
  34. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/telemetry/__init__.py +0 -0
  35. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/telemetry/integration.py +0 -0
  36. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/telemetry/telemetry.py +0 -0
  37. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/README.md +0 -0
  38. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/__init__.py +0 -0
  39. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/arxiv_tools.py +0 -0
  40. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/calculator_tools.py +0 -0
  41. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/csv_tools.py +0 -0
  42. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/duckdb_tools.py +0 -0
  43. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/duckduckgo_tools.py +0 -0
  44. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/excel_tools.py +0 -0
  45. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/file_tools.py +0 -0
  46. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/json_tools.py +0 -0
  47. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/newspaper_tools.py +0 -0
  48. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/pandas_tools.py +0 -0
  49. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/python_tools.py +0 -0
  50. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/searxng_tools.py +0 -0
  51. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/shell_tools.py +0 -0
  52. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/spider_tools.py +0 -0
  53. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/test.py +0 -0
  54. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/tools.py +0 -0
  55. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/train/data/generatecot.py +0 -0
  56. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/wikipedia_tools.py +0 -0
  57. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/xml_tools.py +0 -0
  58. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/yaml_tools.py +0 -0
  59. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents/tools/yfinance_tools.py +0 -0
  60. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents.egg-info/SOURCES.txt +0 -0
  61. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents.egg-info/dependency_links.txt +0 -0
  62. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents.egg-info/requires.txt +0 -0
  63. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/praisonaiagents.egg-info/top_level.txt +0 -0
  64. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/setup.cfg +0 -0
  65. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/tests/test-graph-memory.py +0 -0
  66. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/tests/test.py +0 -0
  67. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/tests/test_handoff_compatibility.py +0 -0
  68. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/tests/test_ollama_async_fix.py +0 -0
  69. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/tests/test_ollama_fix.py +0 -0
  70. {praisonaiagents-0.0.115 → praisonaiagents-0.0.117}/tests/test_posthog_fixed.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: praisonaiagents
3
- Version: 0.0.115
3
+ Version: 0.0.117
4
4
  Summary: Praison AI agents for completing complex tasks with Self Reflection Agents
5
5
  Author: Mervin Praison
6
6
  Requires-Python: >=3.10
@@ -354,8 +354,10 @@ class Agent:
354
354
  # Check for model name in environment variable if not provided
355
355
  self._using_custom_llm = False
356
356
 
357
- # Initialize OpenAI client for direct API calls
358
- self._openai_client = get_openai_client(api_key=api_key, base_url=base_url)
357
+ # Store OpenAI client parameters for lazy initialization
358
+ self._openai_api_key = api_key
359
+ self._openai_base_url = base_url
360
+ self.__openai_client = None
359
361
 
360
362
  # If base_url is provided, always create a custom LLM instance
361
363
  if base_url:
@@ -488,6 +490,42 @@ Your Goal: {self.goal}
488
490
  for source in knowledge:
489
491
  self._process_knowledge(source)
490
492
 
493
+ @property
494
+ def _openai_client(self):
495
+ """Lazily initialize OpenAI client only when needed."""
496
+ if self.__openai_client is None:
497
+ try:
498
+ self.__openai_client = get_openai_client(
499
+ api_key=self._openai_api_key,
500
+ base_url=self._openai_base_url
501
+ )
502
+ except ValueError as e:
503
+ # If we're using a custom LLM, we might not need the OpenAI client
504
+ # Return None and let the calling code handle it
505
+ if self._using_custom_llm:
506
+ return None
507
+ else:
508
+ raise e
509
+ return self.__openai_client
510
+
511
+ @property
512
+ def llm_model(self):
513
+ """Unified property to get the LLM model regardless of configuration type.
514
+
515
+ Returns:
516
+ The LLM model/instance being used by this agent.
517
+ - For standard models: returns the model string (e.g., "gpt-4o")
518
+ - For custom LLM instances: returns the LLM instance object
519
+ - For provider models: returns the LLM instance object
520
+ """
521
+ if hasattr(self, 'llm_instance') and self.llm_instance:
522
+ return self.llm_instance
523
+ elif hasattr(self, 'llm') and self.llm:
524
+ return self.llm
525
+ else:
526
+ # Default fallback
527
+ return "gpt-4o"
528
+
491
529
  def _process_knowledge(self, knowledge_item):
492
530
  """Process and store knowledge from a file path, URL, or string."""
493
531
  try:
@@ -694,14 +732,39 @@ Your Role: {self.role}\n
694
732
  Your Goal: {self.goal}
695
733
  """
696
734
 
697
- # Use openai_client's build_messages method
698
- messages, original_prompt = self._openai_client.build_messages(
699
- prompt=prompt,
700
- system_prompt=system_prompt,
701
- chat_history=self.chat_history,
702
- output_json=output_json,
703
- output_pydantic=output_pydantic
704
- )
735
+ # Use openai_client's build_messages method if available
736
+ if self._openai_client is not None:
737
+ messages, original_prompt = self._openai_client.build_messages(
738
+ prompt=prompt,
739
+ system_prompt=system_prompt,
740
+ chat_history=self.chat_history,
741
+ output_json=output_json,
742
+ output_pydantic=output_pydantic
743
+ )
744
+ else:
745
+ # Fallback implementation for when OpenAI client is not available
746
+ messages = []
747
+
748
+ # Add system message if provided
749
+ if system_prompt:
750
+ messages.append({"role": "system", "content": system_prompt})
751
+
752
+ # Add chat history
753
+ messages.extend(self.chat_history)
754
+
755
+ # Add user prompt
756
+ if isinstance(prompt, list):
757
+ messages.extend(prompt)
758
+ original_prompt = prompt
759
+ else:
760
+ messages.append({"role": "user", "content": str(prompt)})
761
+ original_prompt = str(prompt)
762
+
763
+ # Add JSON format instruction if needed
764
+ if output_json or output_pydantic:
765
+ model = output_pydantic or output_json
766
+ json_instruction = f"\nPlease respond with valid JSON matching this schema: {model.model_json_schema()}"
767
+ messages[-1]["content"] += json_instruction
705
768
 
706
769
  return messages, original_prompt
707
770
 
@@ -943,6 +1006,9 @@ Your Goal: {self.goal}
943
1006
 
944
1007
  def _process_stream_response(self, messages, temperature, start_time, formatted_tools=None, reasoning_steps=False):
945
1008
  """Process streaming response and return final response"""
1009
+ if self._openai_client is None:
1010
+ raise ValueError("OpenAI client is not initialized. Please provide OPENAI_API_KEY or use a custom LLM provider.")
1011
+
946
1012
  return self._openai_client.process_stream_response(
947
1013
  messages=messages,
948
1014
  model=self.llm,
@@ -1009,6 +1075,9 @@ Your Goal: {self.goal}
1009
1075
 
1010
1076
  # Note: openai_client expects tools in various formats and will format them internally
1011
1077
  # But since we already have formatted_tools, we can pass them directly
1078
+ if self._openai_client is None:
1079
+ raise ValueError("OpenAI client is not initialized. Please provide OPENAI_API_KEY or use a custom LLM provider.")
1080
+
1012
1081
  final_response = self._openai_client.chat_completion_with_tools(
1013
1082
  messages=messages,
1014
1083
  model=self.llm,
@@ -1202,6 +1271,17 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
1202
1271
  messages.append({"role": "user", "content": reflection_prompt})
1203
1272
 
1204
1273
  try:
1274
+ # Check if OpenAI client is available
1275
+ if self._openai_client is None:
1276
+ # For custom LLMs, self-reflection with structured output is not supported
1277
+ if self.verbose:
1278
+ display_self_reflection(f"Agent {self.name}: Self-reflection with structured output is not supported for custom LLM providers. Skipping reflection.", console=self.console)
1279
+ # Return the original response without reflection
1280
+ self.chat_history.append({"role": "user", "content": prompt})
1281
+ self.chat_history.append({"role": "assistant", "content": response_text})
1282
+ display_interaction(prompt, response_text, markdown=self.markdown, generation_time=time.time() - start_time, console=self.console)
1283
+ return response_text
1284
+
1205
1285
  reflection_response = self._openai_client.sync_client.beta.chat.completions.parse(
1206
1286
  model=self.reflect_llm if self.reflect_llm else self.llm,
1207
1287
  messages=messages,
@@ -1388,6 +1468,12 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
1388
1468
 
1389
1469
  # Use the new _format_tools_for_completion helper method
1390
1470
  formatted_tools = self._format_tools_for_completion(tools)
1471
+
1472
+ # Check if OpenAI client is available
1473
+ if self._openai_client is None:
1474
+ error_msg = "OpenAI client is not initialized. Please provide OPENAI_API_KEY or use a custom LLM provider."
1475
+ display_error(error_msg)
1476
+ return None
1391
1477
 
1392
1478
  # Make the API call based on the type of request
1393
1479
  if tools:
@@ -1442,6 +1528,19 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
1442
1528
  ]
1443
1529
 
1444
1530
  try:
1531
+ # Check if OpenAI client is available for self-reflection
1532
+ if self._openai_client is None:
1533
+ # For custom LLMs, self-reflection with structured output is not supported
1534
+ if self.verbose:
1535
+ display_self_reflection(f"Agent {self.name}: Self-reflection with structured output is not supported for custom LLM providers. Skipping reflection.", console=self.console)
1536
+ # Return the original response without reflection
1537
+ self.chat_history.append({"role": "user", "content": original_prompt})
1538
+ self.chat_history.append({"role": "assistant", "content": response_text})
1539
+ if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
1540
+ total_time = time.time() - start_time
1541
+ logging.debug(f"Agent.achat completed in {total_time:.2f} seconds")
1542
+ return response_text
1543
+
1445
1544
  reflection_response = await self._openai_client.async_client.beta.chat.completions.parse(
1446
1545
  model=self.reflect_llm if self.reflect_llm else self.llm,
1447
1546
  messages=reflection_messages,
@@ -7,7 +7,7 @@ from pydantic import BaseModel
7
7
  from rich.text import Text
8
8
  from rich.panel import Panel
9
9
  from rich.console import Console
10
- from ..main import display_error, TaskOutput, error_logs, client
10
+ from ..main import display_error, TaskOutput, error_logs
11
11
  from ..agent.agent import Agent
12
12
  from ..task.task import Task
13
13
  from ..process.process import Process, LoopItems
@@ -12,7 +12,8 @@ from typing import List, Any, Optional, Dict, Tuple
12
12
  import logging
13
13
  import os
14
14
  from pydantic import BaseModel, ConfigDict
15
- from ..main import display_instruction, display_tool_call, display_interaction, client
15
+ from ..main import display_instruction, display_tool_call, display_interaction
16
+ from ..llm import get_openai_client
16
17
 
17
18
  # Define Pydantic models for structured output
18
19
  class TaskConfig(BaseModel):
@@ -237,6 +238,17 @@ Return the configuration in a structured JSON format matching the AutoAgentsConf
237
238
  """
238
239
 
239
240
  try:
241
+ # Get OpenAI client
242
+ try:
243
+ client = get_openai_client()
244
+ except ValueError as e:
245
+ # AutoAgents requires OpenAI for structured output generation
246
+ raise ValueError(
247
+ "AutoAgents requires OpenAI API for automatic agent generation. "
248
+ "Please set OPENAI_API_KEY environment variable or use PraisonAIAgents class directly "
249
+ "with manually configured agents for non-OpenAI providers."
250
+ ) from e
251
+
240
252
  response = client.beta.chat.completions.parse(
241
253
  model=self.llm,
242
254
  response_format=AutoAgentsConfig,
@@ -364,6 +364,46 @@ class LLM:
364
364
 
365
365
  return messages, original_prompt
366
366
 
367
+ def _fix_array_schemas(self, schema: Dict) -> Dict:
368
+ """
369
+ Recursively fix array schemas by adding missing 'items' attribute.
370
+
371
+ This ensures compatibility with OpenAI's function calling format which
372
+ requires array types to specify the type of items they contain.
373
+
374
+ Args:
375
+ schema: The schema dictionary to fix
376
+
377
+ Returns:
378
+ dict: The fixed schema
379
+ """
380
+ if not isinstance(schema, dict):
381
+ return schema
382
+
383
+ # Create a copy to avoid modifying the original
384
+ fixed_schema = schema.copy()
385
+
386
+ # Fix array types at the current level
387
+ if fixed_schema.get("type") == "array" and "items" not in fixed_schema:
388
+ # Add a default items schema for arrays without it
389
+ fixed_schema["items"] = {"type": "string"}
390
+
391
+ # Recursively fix nested schemas in properties
392
+ if "properties" in fixed_schema and isinstance(fixed_schema["properties"], dict):
393
+ fixed_properties = {}
394
+ for prop_name, prop_schema in fixed_schema["properties"].items():
395
+ if isinstance(prop_schema, dict):
396
+ fixed_properties[prop_name] = self._fix_array_schemas(prop_schema)
397
+ else:
398
+ fixed_properties[prop_name] = prop_schema
399
+ fixed_schema["properties"] = fixed_properties
400
+
401
+ # Fix items schema if it exists
402
+ if "items" in fixed_schema and isinstance(fixed_schema["items"], dict):
403
+ fixed_schema["items"] = self._fix_array_schemas(fixed_schema["items"])
404
+
405
+ return fixed_schema
406
+
367
407
  def _format_tools_for_litellm(self, tools: Optional[List[Any]]) -> Optional[List[Dict]]:
368
408
  """Format tools for LiteLLM - handles all tool formats.
369
409
 
@@ -389,7 +429,11 @@ class LLM:
389
429
  # Validate nested dictionary structure before accessing
390
430
  if 'function' in tool and isinstance(tool['function'], dict) and 'name' in tool['function']:
391
431
  logging.debug(f"Using pre-formatted OpenAI tool: {tool['function']['name']}")
392
- formatted_tools.append(tool)
432
+ # Fix array schemas in the tool parameters
433
+ fixed_tool = tool.copy()
434
+ if 'parameters' in fixed_tool['function']:
435
+ fixed_tool['function']['parameters'] = self._fix_array_schemas(fixed_tool['function']['parameters'])
436
+ formatted_tools.append(fixed_tool)
393
437
  else:
394
438
  logging.debug(f"Skipping malformed OpenAI tool: missing function or name")
395
439
  # Handle lists of tools (e.g. from MCP.to_openai_tool())
@@ -399,7 +443,11 @@ class LLM:
399
443
  # Validate nested dictionary structure before accessing
400
444
  if 'function' in subtool and isinstance(subtool['function'], dict) and 'name' in subtool['function']:
401
445
  logging.debug(f"Using pre-formatted OpenAI tool from list: {subtool['function']['name']}")
402
- formatted_tools.append(subtool)
446
+ # Fix array schemas in the tool parameters
447
+ fixed_tool = subtool.copy()
448
+ if 'parameters' in fixed_tool['function']:
449
+ fixed_tool['function']['parameters'] = self._fix_array_schemas(fixed_tool['function']['parameters'])
450
+ formatted_tools.append(fixed_tool)
403
451
  else:
404
452
  logging.debug(f"Skipping malformed OpenAI tool in list: missing function or name")
405
453
  elif callable(tool):
@@ -2153,7 +2201,7 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
2153
2201
  "function": {
2154
2202
  "name": function_name,
2155
2203
  "description": docstring.split('\n\n')[0] if docstring else "No description available",
2156
- "parameters": parameters
2204
+ "parameters": self._fix_array_schemas(parameters)
2157
2205
  }
2158
2206
  }
2159
2207
  logging.debug(f"Generated tool definition: {tool_def}")
@@ -3,7 +3,6 @@ import time
3
3
  import json
4
4
  import logging
5
5
  from typing import List, Optional, Dict, Any, Union, Literal, Type
6
- from openai import OpenAI
7
6
  from pydantic import BaseModel, ConfigDict
8
7
  from rich import print
9
8
  from rich.console import Console
@@ -377,24 +376,6 @@ class ReflectionOutput(BaseModel):
377
376
  reflection: str
378
377
  satisfactory: Literal["yes", "no"]
379
378
 
380
- # Constants
381
- LOCAL_SERVER_API_KEY_PLACEHOLDER = "not-needed"
382
-
383
- # Initialize OpenAI client with proper API key handling
384
- api_key = os.environ.get("OPENAI_API_KEY")
385
- base_url = os.environ.get("OPENAI_API_BASE") or os.environ.get("OPENAI_BASE_URL")
386
-
387
- # For local servers like LM Studio, allow minimal API key
388
- if base_url and not api_key:
389
- api_key = LOCAL_SERVER_API_KEY_PLACEHOLDER
390
- elif not api_key:
391
- raise ValueError(
392
- "OPENAI_API_KEY environment variable is required for the default OpenAI service. "
393
- "If you are targeting a local server (e.g., LM Studio), ensure OPENAI_API_BASE is set "
394
- f"(e.g., 'http://localhost:1234/v1') and you can use a placeholder API key by setting OPENAI_API_KEY='{LOCAL_SERVER_API_KEY_PLACEHOLDER}'"
395
- )
396
-
397
- client = OpenAI(api_key=api_key, base_url=base_url)
398
379
 
399
380
  class TaskOutput(BaseModel):
400
381
  model_config = ConfigDict(arbitrary_types_allowed=True)
@@ -5,10 +5,10 @@ from typing import Dict, Optional, List, Any, AsyncGenerator
5
5
  from pydantic import BaseModel, ConfigDict
6
6
  from ..agent.agent import Agent
7
7
  from ..task.task import Task
8
- from ..main import display_error, client
8
+ from ..main import display_error
9
9
  import csv
10
10
  import os
11
- from openai import AsyncOpenAI
11
+ from openai import AsyncOpenAI, OpenAI
12
12
 
13
13
  class LoopItems(BaseModel):
14
14
  model_config = ConfigDict(arbitrary_types_allowed=True)
@@ -140,6 +140,8 @@ class Process:
140
140
 
141
141
  def _get_manager_instructions_with_fallback(self, manager_task, manager_prompt, ManagerInstructions):
142
142
  """Sync version of getting manager instructions with fallback"""
143
+ # Create OpenAI client
144
+ client = OpenAI()
143
145
  try:
144
146
  # First try structured output (OpenAI compatible)
145
147
  logging.info("Attempting structured output...")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: praisonaiagents
3
- Version: 0.0.115
3
+ Version: 0.0.117
4
4
  Summary: Praison AI agents for completing complex tasks with Self Reflection Agents
5
5
  Author: Mervin Praison
6
6
  Requires-Python: >=3.10
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "praisonaiagents"
7
- version = "0.0.115"
7
+ version = "0.0.117"
8
8
  description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
9
9
  requires-python = ">=3.10"
10
10
  authors = [