quantalogic 0.50.24__py3-none-any.whl → 0.50.25__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.
@@ -1,254 +1,364 @@
1
- # Import statements
2
- # import os
3
- # from typing import Any
4
- # from loguru import logger
5
- # from quantalogic.agent import Agent, AgentMemory
6
- # from quantalogic.agent_tools import (
7
- # AgentTool,
8
- # DownloadHttpFileTool,
9
- # DuckDuckGoSearchTool,
10
- # EditWholeContentTool,
11
- # ExecuteBashCommandTool,
12
- # InputQuestionTool,
13
- # ListDirectoryTool,
14
- # LLMTool,
15
- # LLMVisionTool,
16
- # LLMImageGenerationTool,
17
- # MarkitdownTool,
18
- # NodeJsTool,
19
- # PythonTool,
20
- # ReadFileBlockTool,
21
- # ReadFileTool,
22
- # ReadHTMLTool,
23
- # ReplaceInFileTool,
24
- # RipgrepTool,
25
- # SafePythonInterpreterTool,
26
- # SearchDefinitionNames,
27
- # TaskCompleteTool,
28
- # WikipediaSearchTool,
29
- # WriteFileTool,
30
- # GoogleNewsTool,
31
- # PresentationLLMTool,
32
- # SequenceTool,
33
- # SQLQueryTool,
34
- # SQLQueryToolAdvanced,
35
- # CloneRepoTool,
36
- # BitbucketCloneTool,
37
- # BitbucketOperationsTool,
38
- # GitOperationsTool,
39
- # MarkdownToPdfTool,
40
- # MarkdownToPptxTool,
41
- # MarkdownToHtmlTool,
42
- # MarkdownToEpubTool,
43
- # MarkdownToIpynbTool,
44
- # MarkdownToLatexTool,
45
- # MarkdownToDocxTool,
46
- # CSVProcessorTool,
47
- # MermaidValidatorTool,
48
- # PrepareDownloadTool,
49
- # ComposioTool,
50
- # NasaNeoWsTool,
51
- # NasaApodTool,
52
- # ProductHuntTool,
53
- # RagTool
54
- # )
55
- # from quantalogic.event_emitter import EventEmitter
56
- # from quantalogic.console_token_printer import console_print_token
57
-
58
- # Function to create a custom agent
59
- # def create_custom_agent(
60
- # model_name: str,
61
- # vision_model_name: str | None = None,
62
- # no_stream: bool = False,
63
- # compact_every_n_iteration: int | None = None,
64
- # max_tokens_working_memory: int | None = None,
65
- # specific_expertise: str = "",
66
- # tools: list[Any] | None = None,
67
- # memory: AgentMemory | None = None
68
- # ) -> Agent:
69
- # """Create an agent with the specified model and tools.
70
-
71
- # Args:
72
- # model_name (str): Name of the model to use
73
- # vision_model_name (str | None): Name of the vision model to use
74
- # no_stream (bool, optional): If True, the agent will not stream results.
75
- # compact_every_n_iteration (int | None, optional): Frequency of memory compaction.
76
- # max_tokens_working_memory (int | None, optional): Maximum tokens for working memory.
77
- # specific_expertise (str, optional): Specific expertise of the agent.
78
- # tools (list[Any], optional): List of tool configurations to add to the agent.
79
- # Each tool config should have:
80
- # - type: str - The type of tool
81
- # - parameters: dict - The parameters required for the tool
82
- # memory (AgentMemory, optional): Memory object to use for the agent.
83
-
84
- # Returns:
85
- # Agent: An agent with the specified model and tools
86
- # """
87
- # # Create storage directory for RAG
88
- # # storage_dir = os.path.join(os.path.dirname(__file__), "storage", "rag")
89
- # # os.makedirs(storage_dir, exist_ok=True)
1
+ import importlib
2
+ import os
3
+ from typing import Any, Optional, Type
4
+
5
+ from loguru import logger
6
+
7
+ from quantalogic.agent import Agent, AgentMemory
8
+ from quantalogic.console_print_events import console_print_events
9
+ from quantalogic.console_print_token import console_print_token
10
+ from quantalogic.event_emitter import EventEmitter
11
+ from quantalogic.tools.tool import Tool
12
+
13
+ # Configure loguru to output debug messages
14
+ logger.remove() # Remove default handler
15
+ logger.add(sink=lambda msg: print(msg, end=""), level="DEBUG") # Add a new handler that prints to console
16
+
17
+
18
+ def _import_tool(module_path: str, class_name: str) -> Type[Tool]:
19
+ """
20
+ Import a tool class from a module path using standard Python imports.
21
+
22
+ Args:
23
+ module_path: The module path to import from
24
+ class_name: The name of the class to import
25
+
26
+ Returns:
27
+ The imported tool class, or None if import fails
28
+ """
29
+ try:
30
+ module = importlib.import_module(module_path)
31
+ return getattr(module, class_name)
32
+ except ImportError as e:
33
+ logger.warning(f"Failed to import {class_name} from {module_path}: {str(e)}")
34
+ return None
35
+ except AttributeError as e:
36
+ logger.warning(f"Failed to find {class_name} in {module_path}: {str(e)}")
37
+ return None
38
+ except Exception as e:
39
+ logger.error(f"Unexpected error importing {class_name} from {module_path}: {str(e)}")
40
+ return None
41
+
42
+ # Helper function to create tool instances
43
+ def create_tool_instance(tool_class, **kwargs):
44
+ """
45
+ Creates an instance of a tool class with appropriate parameters.
46
+
47
+ Args:
48
+ tool_class: The tool class to instantiate
49
+ **kwargs: Parameters to pass to the tool constructor
50
+
51
+ Returns:
52
+ An instance of the tool class, or None if instantiation fails
53
+ """
54
+ if tool_class is None:
55
+ return None
56
+
57
+ try:
58
+ # Extract the name from the class name if not provided
59
+ if 'name' not in kwargs:
60
+ class_name = tool_class.__name__
61
+ kwargs['name'] = class_name.lower().replace('tool', '')
62
+
63
+ # Create and return the tool instance
64
+ instance = tool_class(**kwargs)
65
+ logger.debug(f"Successfully created tool instance: {kwargs.get('name')}")
66
+ return instance
67
+ except Exception as e:
68
+ logger.error(f"Failed to instantiate {tool_class.__name__}: {str(e)}")
69
+ return None
70
+
71
+ # Lazy loading tool imports using a dictionary of functions that return tool classes
72
+ TOOL_IMPORTS = {
73
+ # LLM Tools
74
+ "llm": lambda: _import_tool("quantalogic.tools.llm_tool", "LLMTool"),
75
+ "llm_vision": lambda: _import_tool("quantalogic.tools.llm_tool", "LLMVisionTool"),
76
+ "llm_image_generation": lambda: _import_tool("quantalogic.tools.llm_tool", "LLMImageGenerationTool"),
77
+
78
+ # File Tools
79
+ "download_http_file": lambda: _import_tool("quantalogic.tools.download_file_tool", "PrepareDownloadTool"),
80
+ "write_file": lambda: _import_tool("quantalogic.tools.write_file_tool", "WriteFileTool"),
81
+ "edit_whole_content": lambda: _import_tool("quantalogic.tools.file_tools", "EditWholeContentTool"),
82
+ "read_file_block": lambda: _import_tool("quantalogic.tools.file_tools", "ReadFileBlockTool"),
83
+ "read_file": lambda: _import_tool("quantalogic.tools.file_tools", "ReadFileTool"),
84
+ "replace_in_file": lambda: _import_tool("quantalogic.tools.file_tools", "ReplaceInFileTool"),
85
+ "list_directory": lambda: _import_tool("quantalogic.tools.file_tools", "ListDirectoryTool"),
86
+
87
+ # Search Tools
88
+ "duck_duck_go_search": lambda: _import_tool("quantalogic.tools", "DuckDuckGoSearchTool"),
89
+ "wikipedia_search": lambda: _import_tool("quantalogic.tools", "WikipediaSearchTool"),
90
+ "google_news": lambda: _import_tool("quantalogic.tools", "GoogleNewsTool"),
91
+ "search_definition_names": lambda: _import_tool("quantalogic.tools", "SearchDefinitionNames"),
92
+ "ripgrep": lambda: _import_tool("quantalogic.tools", "RipgrepTool"),
93
+
94
+ # Execution Tools
95
+ "execute_bash_command": lambda: _import_tool("quantalogic.tools.execution_tools", "ExecuteBashCommandTool"),
96
+ "nodejs": lambda: _import_tool("quantalogic.tools.execution_tools", "NodeJsTool"),
97
+ "python": lambda: _import_tool("quantalogic.tools.execution_tools", "PythonTool"),
98
+ "safe_python_interpreter": lambda: _import_tool("quantalogic.tools.execution_tools", "SafePythonInterpreterTool"),
99
+
100
+ # Database Tools
101
+ "sql_query": lambda: _import_tool("quantalogic.tools.database", "SQLQueryTool"),
102
+ "sql_query_advanced": lambda: _import_tool("quantalogic.tools.database", "SQLQueryToolAdvanced"),
103
+
104
+ # Document Tools
105
+ "markdown_to_pdf": lambda: _import_tool("quantalogic.tools.document_tools", "MarkdownToPdfTool"),
106
+ "markdown_to_pptx": lambda: _import_tool("quantalogic.tools.document_tools", "MarkdownToPptxTool"),
107
+ "markdown_to_html": lambda: _import_tool("quantalogic.tools.document_tools", "MarkdownToHtmlTool"),
108
+ "markdown_to_epub": lambda: _import_tool("quantalogic.tools.document_tools", "MarkdownToEpubTool"),
109
+ "markdown_to_ipynb": lambda: _import_tool("quantalogic.tools.document_tools", "MarkdownToIpynbTool"),
110
+ "markdown_to_latex": lambda: _import_tool("quantalogic.tools.document_tools", "MarkdownToLatexTool"),
111
+ "markdown_to_docx": lambda: _import_tool("quantalogic.tools.document_tools", "MarkdownToDocxTool"),
112
+
113
+ # Git Tools
114
+ "clone_repo_tool": lambda: _import_tool("quantalogic.tools.git", "CloneRepoTool"),
115
+ "bitbucket_clone_repo_tool": lambda: _import_tool("quantalogic.tools.git", "BitbucketCloneTool"),
116
+ "bitbucket_operations_tool": lambda: _import_tool("quantalogic.tools.git", "BitbucketOperationsTool"),
117
+ "git_operations_tool": lambda: _import_tool("quantalogic.tools.git", "GitOperationsTool"),
118
+
119
+ # NASA Tools
120
+ "nasa_neows_tool": lambda: _import_tool("quantalogic.tools.nasa_packages", "NasaNeoWsTool"),
121
+ "nasa_apod_tool": lambda: _import_tool("quantalogic.tools.nasa_packages", "NasaApodTool"),
122
+
123
+ # Composio Tools
124
+ "email_tool": lambda: _import_tool("quantalogic.tools.composio", "ComposioTool"),
125
+ "callendar_tool": lambda: _import_tool("quantalogic.tools.composio", "ComposioTool"),
126
+ "weather_tool": lambda: _import_tool("quantalogic.tools.composio", "ComposioTool"),
90
127
 
91
- # # Rebuild AgentTool to resolve forward references
92
- # # AgentTool.model_rebuild()
93
-
94
- # # Create event emitter
95
- # # event_emitter = EventEmitter()
96
-
97
- # # Define tool mapping with their parameter requirements
98
- # # tool_mapping = {
99
- # # "llm": lambda params: LLMTool(
100
- # # model_name=params.get("model_name", model_name),
101
- # # on_token=console_print_token if not no_stream else None,
102
- # # event_emitter=event_emitter
103
- # # ),
104
- # # "llm_vision": lambda params: LLMVisionTool(
105
- # # model_name=params.get("vision_model_name") or vision_model_name,
106
- # # on_token=console_print_token if not no_stream else None,
107
- # # event_emitter=event_emitter
108
- # # ),
109
- # # "llm_image_generation": lambda params: LLMImageGenerationTool(
110
- # # provider="dall-e",
111
- # # model_name="openai/dall-e-3",
112
- # # on_token=console_print_token if not no_stream else None,
113
- # # ),
114
- # # "download_http_file": lambda params: DownloadHttpFileTool(),
115
- # # "duck_duck_go_search": lambda params: DuckDuckGoSearchTool(),
116
- # # "edit_whole_content": lambda params: EditWholeContentTool(),
117
- # # "execute_bash_command": lambda params: ExecuteBashCommandTool(),
118
- # # "input_question": lambda params: InputQuestionTool(),
119
- # # "list_directory": lambda params: ListDirectoryTool(),
120
- # # "markitdown": lambda params: MarkitdownTool(),
121
- # # "nodejs": lambda params: NodeJsTool(),
122
- # # "python": lambda params: PythonTool(),
123
- # # "read_file_block": lambda params: ReadFileBlockTool(),
124
- # # "read_file": lambda params: ReadFileTool(),
125
- # # "read_html": lambda params: ReadHTMLTool(),
126
- # # "replace_in_file": lambda params: ReplaceInFileTool(),
127
- # # "ripgrep": lambda params: RipgrepTool(),
128
- # # "safe_python_interpreter": lambda params: SafePythonInterpreterTool(),
129
- # # "search_definition_names": lambda params: SearchDefinitionNames(),
130
- # # "wikipedia_search": lambda params: WikipediaSearchTool(),
131
- # # "write_file": lambda params: WriteFileTool(),
132
- # # "google_news": lambda params: GoogleNewsTool(
133
- # # model_name=params.get("model_name", model_name),
134
- # # on_token=console_print_token if not no_stream else None,
135
- # # event_emitter=event_emitter
136
- # # ),
137
- # # "presentation_llm": lambda params: PresentationLLMTool(
138
- # # model_name=params.get("model_name", model_name),
139
- # # additional_info=params.get("additional_info", ""),
140
- # # on_token=console_print_token if not no_stream else None,
141
- # # event_emitter=event_emitter
142
- # # ),
143
- # # "sequence": lambda params: SequenceTool(
144
- # # model_name=params.get("model_name", model_name),
145
- # # on_token=console_print_token if not no_stream else None,
146
- # # event_emitter=event_emitter
147
- # # ),
148
- # # "sql_query": lambda params: SQLQueryTool(
149
- # # connection_string=params.get("connection_string", ""),
150
- # # model_name=params.get("model_name", model_name),
151
- # # on_token=console_print_token if not no_stream else None,
152
- # # event_emitter=event_emitter
153
- # # ),
154
- # # "sql_query_advanced": lambda params: SQLQueryToolAdvanced(
155
- # # connection_string=params.get("connection_string", ""),
156
- # # model_name=params.get("model_name", model_name),
157
- # # on_token=console_print_token if not no_stream else None,
158
- # # event_emitter=event_emitter
159
- # # ),
160
- # # "clone_repo_tool": lambda params: CloneRepoTool(auth_token=params.get("auth_token", "")),
161
- # # "bitbucket_clone_repo_tool": lambda params: BitbucketCloneTool(access_token=params.get("access_token", "")),
162
- # # "bitbucket_operations_tool": lambda params: BitbucketOperationsTool(access_token=params.get("access_token", "")),
163
- # # "git_operations_tool": lambda params: GitOperationsTool(auth_token=params.get("auth_token", "")),
164
- # # "markdown_to_pdf": lambda params: MarkdownToPdfTool(),
165
- # # "markdown_to_pptx": lambda params: MarkdownToPptxTool(),
166
- # # "markdown_to_html": lambda params: MarkdownToHtmlTool(),
167
- # # "markdown_to_epub": lambda params: MarkdownToEpubTool(),
168
- # # "markdown_to_ipynb": lambda params: MarkdownToIpynbTool(),
169
- # # "markdown_to_latex": lambda params: MarkdownToLatexTool(),
170
- # # "markdown_to_docx": lambda params: MarkdownToDocxTool(),
171
- # # "csv_processor": lambda params: CSVProcessorTool(),
172
- # # "mermaid_validator_tool": lambda params: MermaidValidatorTool(),
173
- # # "download_file_tool": lambda params: PrepareDownloadTool(),
174
- # # "email_tool": lambda params: ComposioTool(
175
- # # action="GMAIL_SEND_EMAIL",
176
- # # name="email_tool",
177
- # # description="Send emails via Gmail",
178
- # # need_validation=False
179
- # # ),
180
- # # "callendar_tool": lambda params: ComposioTool(
181
- # # action="GOOGLECALENDAR_CREATE_EVENT",
182
- # # name="callendar_tool",
183
- # # description="Create events in Google Calendar",
184
- # # need_validation=False
185
- # # ),
186
- # # "weather_tool": lambda params: ComposioTool(
187
- # # action="WEATHERMAP_WEATHER",
188
- # # name="weather_tool",
189
- # # description="Get weather information for a location"
190
- # # ),
191
- # # "nasa_neows_tool": lambda params: NasaNeoWsTool(),
192
- # # "nasa_apod_tool": lambda params: NasaApodTool(),
193
- # # "product_hunt_tool": lambda params : ProductHuntTool(),
194
- # # "rag_tool": lambda params: RagTool(
195
- # # vector_store=params.get("vector_store", "chroma"),
196
- # # embedding_model=params.get("embedding_model", "openai"),
197
- # # persist_dir=storage_dir,
198
- # # document_paths=params.get("document_paths", [])
199
- # # )
200
- # # }
201
-
202
- # # Define write tools that should trigger automatic download tool addition
203
- # # write_tools = {"write_file", "edit_whole_content", "replace_in_file"}
128
+ # Product Hunt Tools
129
+ "product_hunt_tool": lambda: _import_tool("quantalogic.tools.product_hunt", "ProductHuntTool"),
204
130
 
205
- # # Initialize agent tools list
206
- # # agent_tools = []
207
- # # Check if any write tools are present
208
- # # has_write_tool = any(
209
- # # tool_config.get("type") in write_tools
210
- # # for tool_config in (tools or [])
211
- # # )
212
-
213
- # # Add tools only if they are provided
214
- # # if tools:
215
- # # for tool_config in tools:
216
- # # tool_type = tool_config.get("type")
217
- # # logger.debug(f"Processing tool type: {tool_type}")
131
+ # RAG Tools
132
+ "rag_tool": lambda: _import_tool("quantalogic.tools.rag_tool", "RagTool"),
133
+
134
+ # Utility Tools
135
+ "task_complete": lambda: _import_tool("quantalogic.tools.task_complete_tool", "TaskCompleteTool"),
136
+ "input_question": lambda: _import_tool("quantalogic.tools.utilities", "InputQuestionTool"),
137
+ "markitdown": lambda: _import_tool("quantalogic.tools.utilities", "MarkitdownTool"),
138
+ "read_html": lambda: _import_tool("quantalogic.tools.utilities", "ReadHTMLTool"),
139
+ "presentation_llm": lambda: _import_tool("quantalogic.tools.presentation_tools", "PresentationLLMTool"),
140
+ "sequence": lambda: _import_tool("quantalogic.tools.utilities", "SequenceTool"),
141
+ "csv_processor": lambda: _import_tool("quantalogic.tools.utilities", "CSVProcessorTool"),
142
+ "mermaid_validator_tool": lambda: _import_tool("quantalogic.tools.utilities", "MermaidValidatorTool"),
143
+ "download_file_tool": lambda: _import_tool("quantalogic.tools.download_file_tool", "PrepareDownloadTool"),
144
+ }
145
+
146
+ def create_custom_agent(
147
+ model_name: str,
148
+ vision_model_name: Optional[str] = None,
149
+ no_stream: bool = False,
150
+ compact_every_n_iteration: Optional[int] = None,
151
+ max_tokens_working_memory: Optional[int] = None,
152
+ specific_expertise: str = "",
153
+ tools: Optional[list[dict[str, Any]]] = None,
154
+ memory: Optional[AgentMemory] = None
155
+ ) -> Agent:
156
+ """Create an agent with lazy-loaded tools and graceful error handling.
157
+
158
+ Args:
159
+ model_name: Name of the model to use
160
+ vision_model_name: Name of the vision model to use
161
+ no_stream: If True, disable streaming
162
+ compact_every_n_iteration: Frequency of memory compaction
163
+ max_tokens_working_memory: Maximum tokens for working memory
164
+ specific_expertise: Specific expertise of the agent
165
+ tools: List of tool configurations with type and parameters
166
+ memory: Memory object to use for the agent
167
+
168
+ Returns:
169
+ Agent: Configured agent instance
170
+ """
171
+ # Create storage directory for RAG
172
+ storage_dir = os.path.join(os.path.dirname(__file__), "storage", "rag")
173
+ os.makedirs(storage_dir, exist_ok=True)
174
+
175
+ # Create event emitter
176
+ event_emitter = EventEmitter()
177
+
178
+ # Define tool configurations using create_tool_instance for proper instantiation
179
+ tool_configs = {
180
+ "llm": lambda params: create_tool_instance(TOOL_IMPORTS["llm"](), **params),
181
+ "llm_vision": lambda params: create_tool_instance(TOOL_IMPORTS["llm_vision"](), **params) if vision_model_name else None,
182
+ "llm_image_generation": lambda params: create_tool_instance(TOOL_IMPORTS["llm_image_generation"](), **params),
183
+ "download_http_file": lambda params: create_tool_instance(TOOL_IMPORTS["download_http_file"](), **params),
184
+ "duck_duck_go_search": lambda params: create_tool_instance(TOOL_IMPORTS["duck_duck_go_search"](), **params),
185
+ "write_file": lambda params: create_tool_instance(TOOL_IMPORTS["write_file"](), **params),
186
+ "task_complete": lambda params: create_tool_instance(TOOL_IMPORTS["task_complete"](), **params),
187
+ "edit_whole_content": lambda params: create_tool_instance(TOOL_IMPORTS["edit_whole_content"](), name="edit_whole_content", **params),
188
+ "execute_bash_command": lambda params: create_tool_instance(TOOL_IMPORTS["execute_bash_command"](), name="execute_bash_command", **params),
189
+ "input_question": lambda params: create_tool_instance(TOOL_IMPORTS["input_question"](), name="input_question", **params),
190
+ "list_directory": lambda params: create_tool_instance(TOOL_IMPORTS["list_directory"](), name="list_directory", **params),
191
+ "markitdown": lambda params: create_tool_instance(TOOL_IMPORTS["markitdown"](), name="markitdown", **params),
192
+ "nodejs": lambda params: create_tool_instance(TOOL_IMPORTS["nodejs"](), name="nodejs", **params),
193
+ "python": lambda params: create_tool_instance(TOOL_IMPORTS["python"](), name="python", **params),
194
+ "read_file_block": lambda params: create_tool_instance(TOOL_IMPORTS["read_file_block"](), name="read_file_block", **params),
195
+ "read_file": lambda params: create_tool_instance(TOOL_IMPORTS["read_file"](), name="read_file", **params),
196
+ "read_html": lambda params: create_tool_instance(TOOL_IMPORTS["read_html"](), name="read_html", **params),
197
+ "replace_in_file": lambda params: create_tool_instance(TOOL_IMPORTS["replace_in_file"](), name="replace_in_file", **params),
198
+ "ripgrep": lambda params: create_tool_instance(TOOL_IMPORTS["ripgrep"](), name="ripgrep", **params),
199
+ "safe_python_interpreter": lambda params: create_tool_instance(TOOL_IMPORTS["safe_python_interpreter"](), name="safe_python_interpreter", **params),
200
+ "search_definition_names": lambda params: create_tool_instance(TOOL_IMPORTS["search_definition_names"](), name="search_definition_names", **params),
201
+ "wikipedia_search": lambda params: create_tool_instance(TOOL_IMPORTS["wikipedia_search"](), name="wikipedia_search", **params),
202
+ "google_news": lambda params: create_tool_instance(TOOL_IMPORTS["google_news"](), name="google_news", **params),
203
+ "presentation_llm": lambda params: create_tool_instance(TOOL_IMPORTS["presentation_llm"](), name="presentation_llm", **params),
204
+ "sequence": lambda params: create_tool_instance(TOOL_IMPORTS["sequence"](), name="sequence", **params),
205
+ "sql_query": lambda params: create_tool_instance(TOOL_IMPORTS["sql_query"](), name="sql_query", **params),
206
+ "sql_query_advanced": lambda params: create_tool_instance(TOOL_IMPORTS["sql_query_advanced"](), name="sql_query_advanced", **params),
207
+ "clone_repo_tool": lambda params: create_tool_instance(TOOL_IMPORTS["clone_repo_tool"](), name="clone_repo_tool", **params),
208
+ "bitbucket_clone_repo_tool": lambda params: create_tool_instance(TOOL_IMPORTS["bitbucket_clone_repo_tool"](), name="bitbucket_clone_repo_tool", **params),
209
+ "bitbucket_operations_tool": lambda params: create_tool_instance(TOOL_IMPORTS["bitbucket_operations_tool"](), name="bitbucket_operations_tool", **params),
210
+ "git_operations_tool": lambda params: create_tool_instance(TOOL_IMPORTS["git_operations_tool"](), name="git_operations_tool", **params),
211
+ "markdown_to_pdf": lambda params: create_tool_instance(TOOL_IMPORTS["markdown_to_pdf"](), name="markdown_to_pdf", **params),
212
+ "markdown_to_pptx": lambda params: create_tool_instance(TOOL_IMPORTS["markdown_to_pptx"](), name="markdown_to_pptx", **params),
213
+ "markdown_to_html": lambda params: create_tool_instance(TOOL_IMPORTS["markdown_to_html"](), name="markdown_to_html", **params),
214
+ "markdown_to_epub": lambda params: create_tool_instance(TOOL_IMPORTS["markdown_to_epub"](), name="markdown_to_epub", **params),
215
+ "markdown_to_ipynb": lambda params: create_tool_instance(TOOL_IMPORTS["markdown_to_ipynb"](), name="markdown_to_ipynb", **params),
216
+ "markdown_to_latex": lambda params: create_tool_instance(TOOL_IMPORTS["markdown_to_latex"](), name="markdown_to_latex", **params),
217
+ "markdown_to_docx": lambda params: create_tool_instance(TOOL_IMPORTS["markdown_to_docx"](), name="markdown_to_docx", **params),
218
+ "csv_processor": lambda params: create_tool_instance(TOOL_IMPORTS["csv_processor"](), name="csv_processor", **params),
219
+ "mermaid_validator_tool": lambda params: create_tool_instance(TOOL_IMPORTS["mermaid_validator_tool"](), name="mermaid_validator_tool", **params),
220
+ "download_file_tool": lambda params: create_tool_instance(TOOL_IMPORTS["download_file_tool"](), name="download_file_tool", **params),
221
+ "email_tool": lambda params: create_tool_instance(TOOL_IMPORTS["email_tool"](), name="email_tool", **params),
222
+ "callendar_tool": lambda params: create_tool_instance(TOOL_IMPORTS["callendar_tool"](), name="callendar_tool", **params),
223
+ "weather_tool": lambda params: create_tool_instance(TOOL_IMPORTS["weather_tool"](), name="weather_tool", **params),
224
+ "nasa_neows_tool": lambda params: create_tool_instance(TOOL_IMPORTS["nasa_neows_tool"](), name="nasa_neows_tool", **params),
225
+ "nasa_apod_tool": lambda params: create_tool_instance(TOOL_IMPORTS["nasa_apod_tool"](), name="nasa_apod_tool", **params),
226
+ "product_hunt_tool": lambda params: create_tool_instance(TOOL_IMPORTS["product_hunt_tool"](), name="product_hunt_tool", **params),
227
+ "rag_tool": lambda params: create_tool_instance(TOOL_IMPORTS["rag_tool"](), name="rag_tool", **params),
228
+
229
+ # Special handling for Composio tools
230
+ "email_tool": lambda params: create_tool_instance(TOOL_IMPORTS["email_tool"](), action="EMAIL", name="email_tool", **params),
231
+ "callendar_tool": lambda params: create_tool_instance(TOOL_IMPORTS["callendar_tool"](), action="CALLENDAR", name="callendar_tool", **params),
232
+ "weather_tool": lambda params: create_tool_instance(TOOL_IMPORTS["weather_tool"](), action="WEATHER", name="weather_tool", **params),
233
+ }
234
+
235
+ # Log available tool types before processing
236
+ logger.debug("Available tool types:")
237
+ for tool_type in tool_configs.keys():
238
+ logger.debug(f"- {tool_type}")
239
+
240
+ # Define write tools that trigger automatic download tool addition
241
+ write_tools = {"write_file", "edit_whole_content", "replace_in_file"}
242
+ agent_tools = []
243
+ has_write_tool = False
244
+
245
+ # Process requested tools
246
+ if tools:
247
+ logger.debug(f"Total tools to process: {len(tools)}")
248
+ for tool_config in tools:
249
+ tool_type = tool_config.get("type")
250
+ logger.debug(f"Processing tool type: {tool_type}")
218
251
 
219
- # # if tool_type in tool_mapping:
220
- # # try:
221
- # # # Get tool parameters or empty dict if not provided
222
- # # tool_params = tool_config.get("parameters", {})
252
+ if tool_type in tool_configs:
253
+ try:
254
+ # Get the tool creation function
255
+ tool_create_func = tool_configs.get(tool_type)
256
+ if not tool_create_func:
257
+ logger.warning(f"No creation function found for tool type: {tool_type}")
258
+ continue
223
259
 
224
- # # # Create tool instance with parameters
225
- # # tool = tool_mapping[tool_type](tool_params)
226
- # # logger.debug(f"Created tool instance: {tool}")
260
+ # Create tool instance with parameters
261
+ tool_params = tool_config.get("parameters", {})
227
262
 
228
- # # if tool: # Some tools (like llm_vision) might return None
229
- # # agent_tools.append(tool)
230
- # # logger.info(f"Added tool: {tool_type}")
231
- # # except Exception as e:
232
- # # logger.error(f"Failed to create tool {tool_type}: {str(e)}")
233
-
234
- # # If any write tool was added, also add the download tool
235
- # # if has_write_tool:
236
- # # try:
237
- # # agent_tools.append(PrepareDownloadTool())
238
- # # logger.info("Added download tool automatically")
239
- # # except Exception as e:
240
- # # logger.error(f"Failed to add download tool: {str(e)}")
241
-
242
- # # Always add TaskCompleteTool
243
- # # agent_tools.append(TaskCompleteTool())
263
+ # Create tool instance with parameters
264
+ tool_instance = tool_create_func(tool_params)
265
+
266
+ if tool_instance: # Check if tool creation was successful
267
+ agent_tools.append(tool_instance)
268
+ logger.info(f"Successfully added tool: {tool_type}")
269
+ if tool_type in write_tools:
270
+ has_write_tool = True
271
+ else:
272
+ logger.warning(f"Tool {tool_type} was not created (returned None)")
273
+ except ImportError as e:
274
+ logger.warning(f"Failed to load tool {tool_type}: Required library missing - {str(e)}")
275
+ except ValueError as e:
276
+ if "API_KEY" in str(e):
277
+ logger.warning(f"Failed to create tool {tool_type}: Missing API key - {str(e)}")
278
+ else:
279
+ logger.error(f"Failed to create tool {tool_type}: {str(e)}", exc_info=True)
280
+ except Exception as e:
281
+ logger.error(f"Failed to create tool {tool_type}: {str(e)}", exc_info=True)
282
+ else:
283
+ logger.warning(f"Unknown tool type: {tool_type} - Skipping")
284
+
285
+ # Add download tool if any write tool is present
286
+ if has_write_tool:
287
+ try:
288
+ # Get the tool class first
289
+ download_tool_class = TOOL_IMPORTS["download_file_tool"]()
290
+ if download_tool_class:
291
+ # Create an instance with the name 'download'
292
+ download_tool = create_tool_instance(download_tool_class, name="download")
293
+ if download_tool:
294
+ agent_tools.append(download_tool)
295
+ logger.info("Added download tool automatically due to write tool presence")
296
+ else:
297
+ logger.warning("Failed to instantiate download tool")
298
+ else:
299
+ logger.warning("Download tool class not found")
300
+ except ImportError as e:
301
+ logger.warning(f"Failed to load download tool: Required library missing - {str(e)}")
302
+ except Exception as e:
303
+ logger.error(f"Failed to add download tool: {str(e)}")
304
+
305
+
306
+ # Create and return the agent
307
+ try:
308
+ return Agent(
309
+ model_name=model_name,
310
+ tools=agent_tools,
311
+ event_emitter=event_emitter,
312
+ compact_every_n_iterations=compact_every_n_iteration,
313
+ max_tokens_working_memory=max_tokens_working_memory,
314
+ specific_expertise=specific_expertise,
315
+ memory=memory if memory else AgentMemory(),
316
+ )
317
+ except Exception as e:
318
+ logger.error(f"Failed to create agent: {str(e)}")
319
+ raise
320
+
321
+ if __name__ == "__main__":
322
+ # Example usage
323
+ tools_config = [
324
+ {"type": "duck_duck_go_search", "parameters": {}},
325
+ ]
244
326
 
245
- # # Return the configured Agent
246
- # # return Agent(
247
- # # model_name=model_name,
248
- # # tools=agent_tools,
249
- # # event_emitter=event_emitter,
250
- # # compact_every_n_iterations=compact_every_n_iteration,
251
- # # max_tokens_working_memory=max_tokens_working_memory,
252
- # # specific_expertise=specific_expertise,
253
- # # memory=memory,
254
- # # )
327
+ agent = create_custom_agent(
328
+ model_name="openrouter/openai/gpt-4o-mini",
329
+ specific_expertise="General purpose assistant",
330
+ tools=tools_config
331
+ )
332
+ print(f"Created agent with {len(agent.tools.tool_names())} tools")
333
+
334
+ # Display all tool names
335
+ print("Agent Tools:")
336
+ for tool_name in agent.tools.tool_names():
337
+ print(f"- {tool_name}")
338
+
339
+ # Set up event monitoring to track agent's lifecycle
340
+ # The event system provides:
341
+ # 1. Real-time observability into the agent's operations
342
+ # 2. Debugging and performance monitoring
343
+ # 3. Support for future analytics and optimization efforts
344
+ agent.event_emitter.on(
345
+ event=[
346
+ "task_complete",
347
+ "task_think_start",
348
+ "task_think_end",
349
+ "tool_execution_start",
350
+ "tool_execution_end",
351
+ "error_max_iterations_reached",
352
+ "memory_full",
353
+ "memory_compacted",
354
+ "memory_summary",
355
+ ],
356
+ listener=console_print_events,
357
+ )
358
+
359
+ # Enable token streaming for detailed output
360
+ agent.event_emitter.on(event=["stream_chunk"], listener=console_print_token)
361
+
362
+ # Solve task with streaming enabled
363
+ result = agent.solve_task("Who is the Prime Minister of France in 2025 ?", max_iterations=10, streaming=True)
364
+ print(result)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: quantalogic
3
- Version: 0.50.24
3
+ Version: 0.50.25
4
4
  Summary: QuantaLogic ReAct Agents
5
5
  Author: Raphaël MANSUY
6
6
  Author-email: raphael.mansuy@gmail.com
@@ -6,7 +6,7 @@ quantalogic/coding_agent.py,sha256=A-firiPWQjMC56B329Ne606_v2GsoF5-nxcuz3rVbYM,5
6
6
  quantalogic/config.py,sha256=lsJxfWFWEMqS2Asus8z4A3W7X8JWoMi3-VHxfltvSfA,423
7
7
  quantalogic/console_print_events.py,sha256=yDtfOr7s5r_gLTgwkl_XoKSkUqNRZhqqq4hwR_oJsUw,2050
8
8
  quantalogic/console_print_token.py,sha256=5IRVoPhwWZtSc4LpNoAsCQhCB_RnAW9chycGgyD3_5U,437
9
- quantalogic/create_custom_agent.py,sha256=4CoaJaGVQcQrJR3BMUqee3HG2K3LwxEMK-kfg1ZhU64,11306
9
+ quantalogic/create_custom_agent.py,sha256=1ZMsbpQGHFueJJpfJIuYCWvR3LUsEtDYqDbr6OcwlWw,20850
10
10
  quantalogic/docs_cli.py,sha256=Ie6NwKQuxLKwVQ-cjhFMCttXeiHDjGhNY4hSmMtc0Qg,1664
11
11
  quantalogic/event_emitter.py,sha256=e_1r6hvx5GmW84iuRkoqcjpjRiYHBk4hzujd5ZoUC6U,16777
12
12
  quantalogic/flow/__init__.py,sha256=asLVwbDH6zVFhILschBOuZZWyKvMGdqhQbB1rd2RXHo,590
@@ -153,8 +153,8 @@ quantalogic/version_check.py,sha256=JyQFTNMDWtpHCLnN-BiakzB2cyXf6kUFsTjvmSruZi4,
153
153
  quantalogic/welcome_message.py,sha256=o4tHdgabNuIV9kbIDPgS3_2yzJhayK30oKad2UouYDc,3020
154
154
  quantalogic/xml_parser.py,sha256=AKuMdJC3QAX3Z_tErHVlZ-msjPemWaZUFiTwkHz76jg,11614
155
155
  quantalogic/xml_tool_parser.py,sha256=Vz4LEgDbelJynD1siLOVkJ3gLlfHsUk65_gCwbYJyGc,3784
156
- quantalogic-0.50.24.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
157
- quantalogic-0.50.24.dist-info/METADATA,sha256=HQo5TMjYcTsQfO5-A8rbGgvo1cFEz7UgrlfaFIZOPcM,23848
158
- quantalogic-0.50.24.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
159
- quantalogic-0.50.24.dist-info/entry_points.txt,sha256=h74O_Q3qBRCrDR99qvwB4BpBGzASPUIjCfxHq6Qnups,183
160
- quantalogic-0.50.24.dist-info/RECORD,,
156
+ quantalogic-0.50.25.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
157
+ quantalogic-0.50.25.dist-info/METADATA,sha256=rfMT6IvBPHGzsaOYMIBQV7K6oLk4vMoRlqCmGj0G8rw,23848
158
+ quantalogic-0.50.25.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
159
+ quantalogic-0.50.25.dist-info/entry_points.txt,sha256=h74O_Q3qBRCrDR99qvwB4BpBGzASPUIjCfxHq6Qnups,183
160
+ quantalogic-0.50.25.dist-info/RECORD,,