quantalogic 0.2.10__py3-none-any.whl → 0.2.13__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.
- quantalogic/agent.py +5 -7
- quantalogic/agent_config.py +1 -1
- quantalogic/coding_agent.py +2 -2
- quantalogic/generative_model.py +14 -15
- quantalogic/main.py +51 -9
- quantalogic/print_event.py +3 -1
- quantalogic/search_agent.py +41 -0
- quantalogic/server/agent_server.py +13 -13
- quantalogic/server/state.py +5 -5
- quantalogic/tool_manager.py +4 -4
- quantalogic/tools/__init__.py +4 -0
- quantalogic/tools/agent_tool.py +1 -1
- quantalogic/tools/elixir_tool.py +1 -1
- quantalogic/tools/llm_tool.py +12 -3
- quantalogic/tools/llm_vision_tool.py +4 -17
- quantalogic/tools/nodejs_tool.py +2 -2
- quantalogic/tools/python_tool.py +2 -2
- quantalogic/tools/replace_in_file_tool.py +3 -3
- quantalogic/tools/ripgrep_tool.py +3 -3
- quantalogic/tools/serpapi_search_tool.py +169 -0
- quantalogic/tools/tool.py +3 -3
- quantalogic/tools/unified_diff_tool.py +1 -0
- quantalogic/tools/wikipedia_search_tool.py +169 -0
- quantalogic/tools/write_file_tool.py +1 -0
- quantalogic/utils/check_version.py +37 -0
- quantalogic/utils/download_http_file.py +4 -4
- quantalogic/utils/read_http_text_content.py +2 -2
- quantalogic/version.py +3 -2
- {quantalogic-0.2.10.dist-info → quantalogic-0.2.13.dist-info}/METADATA +61 -8
- {quantalogic-0.2.10.dist-info → quantalogic-0.2.13.dist-info}/RECORD +33 -29
- {quantalogic-0.2.10.dist-info → quantalogic-0.2.13.dist-info}/LICENSE +0 -0
- {quantalogic-0.2.10.dist-info → quantalogic-0.2.13.dist-info}/WHEEL +0 -0
- {quantalogic-0.2.10.dist-info → quantalogic-0.2.13.dist-info}/entry_points.txt +0 -0
@@ -204,7 +204,7 @@ class ReplaceInFileTool(Tool):
|
|
204
204
|
if not block.search:
|
205
205
|
if block.replace:
|
206
206
|
content += f"\n{block.replace}"
|
207
|
-
logger.
|
207
|
+
logger.debug(f"Block {idx}: Appended content")
|
208
208
|
continue
|
209
209
|
|
210
210
|
match_found = False
|
@@ -218,7 +218,7 @@ class ReplaceInFileTool(Tool):
|
|
218
218
|
content = f"{content[:start]}{content[end:]}"
|
219
219
|
changes.append((start, start + len(block.replace) if block.replace else start))
|
220
220
|
match_found = True
|
221
|
-
logger.
|
221
|
+
logger.debug(f"Block {idx}: Exact match {'replaced' if block.replace else 'deleted'}")
|
222
222
|
|
223
223
|
if not match_found:
|
224
224
|
similarity, matched_str = self.find_similar_match(block.search, content)
|
@@ -232,7 +232,7 @@ class ReplaceInFileTool(Tool):
|
|
232
232
|
else:
|
233
233
|
content = f"{content[:start]}{content[end:]}"
|
234
234
|
changes.append((start, start + len(block.replace) if block.replace else start))
|
235
|
-
logger.
|
235
|
+
logger.debug(
|
236
236
|
f"Block {idx}: Similar match (similarity={similarity:.1%}) "
|
237
237
|
f"{'replaced' if block.replace else 'deleted'}"
|
238
238
|
)
|
@@ -136,7 +136,7 @@ class RipgrepTool(Tool):
|
|
136
136
|
return "No files matching the pattern (after .gitignore filtering)"
|
137
137
|
|
138
138
|
try:
|
139
|
-
logger.
|
139
|
+
logger.debug(f"Executing ripgrep with args: {args}")
|
140
140
|
# Add filtered files to ripgrep command
|
141
141
|
args.extend(filtered_files)
|
142
142
|
output = subprocess.check_output([rg_path] + args, text=True, cwd=cwd)
|
@@ -194,7 +194,7 @@ class RipgrepTool(Tool):
|
|
194
194
|
for path in system_paths + node_paths:
|
195
195
|
full_path = Path(__file__).parent.parent / path if str(path).startswith("node_modules") else path
|
196
196
|
if full_path.exists():
|
197
|
-
logger.
|
197
|
+
logger.debug(f"Found ripgrep at: {full_path}")
|
198
198
|
return str(full_path)
|
199
199
|
|
200
200
|
# Check system PATH using which/where
|
@@ -202,7 +202,7 @@ class RipgrepTool(Tool):
|
|
202
202
|
command = "where" if os.name == "nt" else "which"
|
203
203
|
rg_path = subprocess.check_output([command, bin_name], text=True).strip()
|
204
204
|
if rg_path:
|
205
|
-
logger.
|
205
|
+
logger.debug(f"Found ripgrep in PATH at: {rg_path}")
|
206
206
|
return rg_path
|
207
207
|
except subprocess.CalledProcessError:
|
208
208
|
logger.debug("Ripgrep not found in system PATH")
|
@@ -0,0 +1,169 @@
|
|
1
|
+
"""Tool for interacting with SerpApi for search results."""
|
2
|
+
|
3
|
+
import os
|
4
|
+
|
5
|
+
from serpapi.google_search import GoogleSearch
|
6
|
+
|
7
|
+
from quantalogic.tools.tool import Tool, ToolArgument
|
8
|
+
|
9
|
+
|
10
|
+
class SerpApiSearchTool(Tool):
|
11
|
+
"""Tool for retrieving paginated search results from SerpApi.
|
12
|
+
|
13
|
+
This tool provides a convenient interface to SerpAPI's search capabilities,
|
14
|
+
supporting pagination and structured result formatting.
|
15
|
+
|
16
|
+
Example usage:
|
17
|
+
```python
|
18
|
+
tool = SerpApiTool()
|
19
|
+
results = tool.execute(
|
20
|
+
query="machine learning",
|
21
|
+
page=1,
|
22
|
+
num_results=10
|
23
|
+
)
|
24
|
+
print(results)
|
25
|
+
```
|
26
|
+
|
27
|
+
The tool handles:
|
28
|
+
- Query validation
|
29
|
+
- Pagination management
|
30
|
+
- API error handling
|
31
|
+
- Result formatting
|
32
|
+
"""
|
33
|
+
|
34
|
+
name: str = "serpapi_tool"
|
35
|
+
description: str = (
|
36
|
+
"Retrieves search results from SerpAPI (Google Search) with pagination support. "
|
37
|
+
"Handles multiple pages of results and provides structured output."
|
38
|
+
)
|
39
|
+
arguments: list = [
|
40
|
+
ToolArgument(
|
41
|
+
name="query",
|
42
|
+
arg_type="string",
|
43
|
+
description="The search query to execute",
|
44
|
+
required=True,
|
45
|
+
example="machine learning",
|
46
|
+
),
|
47
|
+
ToolArgument(
|
48
|
+
name="page",
|
49
|
+
arg_type="int",
|
50
|
+
description="The page number to retrieve (1-based)",
|
51
|
+
required=True,
|
52
|
+
default="1",
|
53
|
+
example="2",
|
54
|
+
),
|
55
|
+
ToolArgument(
|
56
|
+
name="num_results",
|
57
|
+
arg_type="int",
|
58
|
+
description="Number of results to retrieve per page",
|
59
|
+
required=True,
|
60
|
+
default="10",
|
61
|
+
example="20",
|
62
|
+
),
|
63
|
+
]
|
64
|
+
|
65
|
+
def execute(self, query: str, page: int = 1, num_results: int = 10) -> str:
|
66
|
+
"""Execute a search query using SerpAPI and return results.
|
67
|
+
|
68
|
+
Args:
|
69
|
+
query: The search query to execute
|
70
|
+
page: The page number to retrieve (1-based)
|
71
|
+
num_results: Number of results to retrieve per page (1-100)
|
72
|
+
|
73
|
+
Returns:
|
74
|
+
Formatted search results as a string with the following format:
|
75
|
+
==== Page X of results ====
|
76
|
+
1. Title
|
77
|
+
URL
|
78
|
+
Description
|
79
|
+
2. Title
|
80
|
+
URL
|
81
|
+
Description
|
82
|
+
==== End of page X ====
|
83
|
+
|
84
|
+
Raises:
|
85
|
+
ValueError: If any parameter is invalid
|
86
|
+
RuntimeError: If API request fails or environment variable is missing
|
87
|
+
"""
|
88
|
+
# Validate and convert query
|
89
|
+
if not query:
|
90
|
+
raise ValueError("Query must be a non-empty string")
|
91
|
+
try:
|
92
|
+
query = str(query)
|
93
|
+
except (TypeError, ValueError) as e:
|
94
|
+
raise ValueError(f"Query must be convertible to string: {str(e)}")
|
95
|
+
|
96
|
+
# Validate and convert page
|
97
|
+
try:
|
98
|
+
page = int(page)
|
99
|
+
if page < 1:
|
100
|
+
raise ValueError("Page number must be positive")
|
101
|
+
except (TypeError, ValueError) as e:
|
102
|
+
raise ValueError(f"Invalid page number: {str(e)}")
|
103
|
+
|
104
|
+
# Validate and convert num_results
|
105
|
+
try:
|
106
|
+
num_results = int(num_results)
|
107
|
+
if num_results < 1 or num_results > 100:
|
108
|
+
raise ValueError("Number of results must be between 1 and 100")
|
109
|
+
except (TypeError, ValueError) as e:
|
110
|
+
raise ValueError(f"Invalid number of results: {str(e)}")
|
111
|
+
|
112
|
+
api_key = os.getenv("SERPAPI_API_KEY")
|
113
|
+
if not api_key:
|
114
|
+
raise RuntimeError("SERPAPI_API_KEY environment variable is not set")
|
115
|
+
|
116
|
+
try:
|
117
|
+
params = {"q": query, "start": (page - 1) * num_results, "num": num_results, "api_key": api_key}
|
118
|
+
|
119
|
+
search = GoogleSearch(params)
|
120
|
+
results = search.get_dict()
|
121
|
+
|
122
|
+
if "error" in results:
|
123
|
+
raise RuntimeError(f"API error: {results['error']}")
|
124
|
+
|
125
|
+
# Format results
|
126
|
+
output = []
|
127
|
+
if "organic_results" in results:
|
128
|
+
for idx, result in enumerate(results["organic_results"], 1):
|
129
|
+
output.append(f"{idx}. {result.get('title', 'No title')}")
|
130
|
+
output.append(f" {result.get('link', 'No URL')}")
|
131
|
+
output.append(f" {result.get('snippet', 'No description')}")
|
132
|
+
output.append("")
|
133
|
+
|
134
|
+
if not output:
|
135
|
+
return "No results found"
|
136
|
+
|
137
|
+
# Add pagination info
|
138
|
+
output.insert(0, f"==== Page {page} of results ====")
|
139
|
+
output.append(f"==== End of page {page} ====")
|
140
|
+
|
141
|
+
return "\n".join(output)
|
142
|
+
|
143
|
+
except Exception as e:
|
144
|
+
raise RuntimeError(f"Search failed: {str(e)}")
|
145
|
+
|
146
|
+
|
147
|
+
def main():
|
148
|
+
"""Demonstrate SerpApiTool functionality."""
|
149
|
+
try:
|
150
|
+
tool = SerpApiSearchTool()
|
151
|
+
|
152
|
+
# Test basic search functionality
|
153
|
+
print("Testing SerpApiTool with sample query...")
|
154
|
+
results = tool.execute(query="Python programming", page=1, num_results=3)
|
155
|
+
print(results)
|
156
|
+
|
157
|
+
# Test error handling
|
158
|
+
print("\nTesting error handling with invalid query...")
|
159
|
+
try:
|
160
|
+
tool.execute(query="")
|
161
|
+
except ValueError as e:
|
162
|
+
print(f"Caught expected ValueError: {e}")
|
163
|
+
|
164
|
+
except Exception as e:
|
165
|
+
print(f"Error in main: {e}")
|
166
|
+
|
167
|
+
|
168
|
+
if __name__ == "__main__":
|
169
|
+
main()
|
quantalogic/tools/tool.py
CHANGED
@@ -25,10 +25,10 @@ class ToolArgument(BaseModel):
|
|
25
25
|
arg_type: Literal["string", "int", "float", "boolean"] = Field(
|
26
26
|
..., description="The type of the argument. Must be one of: string, integer, float, boolean."
|
27
27
|
)
|
28
|
-
description: str | None = Field(None, description="A brief description of the argument.")
|
28
|
+
description: str | None = Field(default=None, description="A brief description of the argument.")
|
29
29
|
required: bool = Field(default=False, description="Indicates if the argument is required.")
|
30
|
-
default: str | None = Field(None, description="The default value for the argument.")
|
31
|
-
example: str | None = Field(None, description="An example value to illustrate the argument's usage.")
|
30
|
+
default: str | None = Field(default=None, description="The default value for the argument. This parameter is required.")
|
31
|
+
example: str | None = Field(default=None, description="An example value to illustrate the argument's usage.")
|
32
32
|
need_validation: bool = Field(default=False, description="Indicates if the argument needs validation.")
|
33
33
|
|
34
34
|
|
@@ -0,0 +1,169 @@
|
|
1
|
+
from typing import Union
|
2
|
+
|
3
|
+
"""Tool for interacting with Wikipedia API for search results."""
|
4
|
+
|
5
|
+
import requests # noqa: E402
|
6
|
+
|
7
|
+
from quantalogic.tools.tool import Tool, ToolArgument # noqa: E402
|
8
|
+
|
9
|
+
|
10
|
+
class WikipediaSearchTool(Tool):
|
11
|
+
"""Tool for retrieving paginated search results from Wikipedia.
|
12
|
+
|
13
|
+
This tool provides a convenient interface to Wikipedia's search API,
|
14
|
+
supporting pagination and structured result formatting.
|
15
|
+
|
16
|
+
Example usage:
|
17
|
+
```python
|
18
|
+
tool = WikipediaSearchTool()
|
19
|
+
results = tool.execute(
|
20
|
+
query="machine learning",
|
21
|
+
page=1,
|
22
|
+
num_results=10
|
23
|
+
)
|
24
|
+
print(results)
|
25
|
+
```
|
26
|
+
|
27
|
+
The tool handles:
|
28
|
+
- Query validation
|
29
|
+
- Pagination management
|
30
|
+
- API error handling
|
31
|
+
- Result formatting
|
32
|
+
"""
|
33
|
+
|
34
|
+
name: str = "wikipedia_tool"
|
35
|
+
description: str = (
|
36
|
+
"Retrieves search results from Wikipedia with pagination support. "
|
37
|
+
"Handles multiple pages of results and provides structured output."
|
38
|
+
)
|
39
|
+
arguments: list = [
|
40
|
+
ToolArgument(
|
41
|
+
name="query",
|
42
|
+
arg_type="string",
|
43
|
+
description="The search query to execute",
|
44
|
+
required=True,
|
45
|
+
example="machine learning",
|
46
|
+
),
|
47
|
+
ToolArgument(
|
48
|
+
name="page",
|
49
|
+
arg_type="int",
|
50
|
+
description="The page number to retrieve (1-based)",
|
51
|
+
required=True,
|
52
|
+
default="1",
|
53
|
+
example="2",
|
54
|
+
),
|
55
|
+
ToolArgument(
|
56
|
+
name="num_results",
|
57
|
+
arg_type="int",
|
58
|
+
description="Number of results to retrieve per page (1-50)",
|
59
|
+
required=True,
|
60
|
+
default="10",
|
61
|
+
example="20",
|
62
|
+
),
|
63
|
+
]
|
64
|
+
|
65
|
+
def execute(self, query: str, page: Union[str, int] = 1, num_results: Union[str, int] = 10) -> str:
|
66
|
+
"""Execute a search query using Wikipedia API and return results.
|
67
|
+
|
68
|
+
Args:
|
69
|
+
query: The search query to execute
|
70
|
+
page: The page number to retrieve (1-based)
|
71
|
+
num_results: Number of results to retrieve per page (1-50)
|
72
|
+
|
73
|
+
Returns:
|
74
|
+
Formatted search results as a string with the following format:
|
75
|
+
==== Page X of results ====
|
76
|
+
1. Title
|
77
|
+
URL
|
78
|
+
Description
|
79
|
+
2. Title
|
80
|
+
URL
|
81
|
+
Description
|
82
|
+
==== End of page X ====
|
83
|
+
|
84
|
+
Raises:
|
85
|
+
ValueError: If any parameter is invalid
|
86
|
+
RuntimeError: If API request fails
|
87
|
+
"""
|
88
|
+
if not query or not isinstance(query, str):
|
89
|
+
raise ValueError("Query must be a non-empty string")
|
90
|
+
|
91
|
+
try:
|
92
|
+
page = int(page) if str(page).strip() else 1
|
93
|
+
num_results = int(num_results) if str(num_results).strip() else 10
|
94
|
+
except (ValueError, TypeError) as e:
|
95
|
+
raise ValueError(f"Invalid parameter type: {e}. Expected integers for page and num_results")
|
96
|
+
|
97
|
+
if page < 1:
|
98
|
+
raise ValueError("Page number must be positive")
|
99
|
+
|
100
|
+
if num_results < 1 or num_results > 50:
|
101
|
+
raise ValueError("Number of results must be between 1 and 50")
|
102
|
+
|
103
|
+
try:
|
104
|
+
# Wikipedia API endpoint
|
105
|
+
url = "https://en.wikipedia.org/w/api.php"
|
106
|
+
params = {
|
107
|
+
"action": "query",
|
108
|
+
"format": "json",
|
109
|
+
"list": "search",
|
110
|
+
"srsearch": query,
|
111
|
+
"srlimit": num_results,
|
112
|
+
"sroffset": (page - 1) * num_results
|
113
|
+
}
|
114
|
+
|
115
|
+
response = requests.get(url, params=params)
|
116
|
+
response.raise_for_status()
|
117
|
+
data = response.json()
|
118
|
+
|
119
|
+
output = []
|
120
|
+
if "query" in data and "search" in data["query"]:
|
121
|
+
for idx, result in enumerate(data["query"]["search"], 1):
|
122
|
+
title = result.get("title", "No title")
|
123
|
+
snippet = result.get("snippet", "No description")
|
124
|
+
url = f"https://en.wikipedia.org/wiki/{title.replace(' ', '_')}"
|
125
|
+
|
126
|
+
output.append(f"{idx}. {title}")
|
127
|
+
output.append(f" {url}")
|
128
|
+
output.append(f" {snippet}")
|
129
|
+
output.append("")
|
130
|
+
|
131
|
+
if not output:
|
132
|
+
return "No results found"
|
133
|
+
|
134
|
+
output.insert(0, f"==== Page {page} of results ====")
|
135
|
+
output.append(f"==== End of page {page} ====")
|
136
|
+
|
137
|
+
return "\n".join(output)
|
138
|
+
|
139
|
+
except Exception as e:
|
140
|
+
raise RuntimeError(f"Search failed: {str(e)}")
|
141
|
+
|
142
|
+
|
143
|
+
def main():
|
144
|
+
"""Demonstrate WikipediaSearchTool functionality."""
|
145
|
+
try:
|
146
|
+
tool = WikipediaSearchTool()
|
147
|
+
|
148
|
+
# Test basic search functionality
|
149
|
+
print("Testing WikipediaSearchTool with sample query...")
|
150
|
+
results = tool.execute(
|
151
|
+
query="Python programming",
|
152
|
+
page=1,
|
153
|
+
num_results=3
|
154
|
+
)
|
155
|
+
print(results)
|
156
|
+
|
157
|
+
# Test error handling
|
158
|
+
print("\nTesting error handling with invalid query...")
|
159
|
+
try:
|
160
|
+
tool.execute(query="")
|
161
|
+
except ValueError as e:
|
162
|
+
print(f"Caught expected ValueError: {e}")
|
163
|
+
|
164
|
+
except Exception as e:
|
165
|
+
print(f"Error in main: {e}")
|
166
|
+
|
167
|
+
|
168
|
+
if __name__ == "__main__":
|
169
|
+
main()
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
import requests
|
3
|
+
from packaging import version
|
4
|
+
|
5
|
+
from quantalogic.version import get_version
|
6
|
+
|
7
|
+
|
8
|
+
def check_if_is_latest_version() -> (bool,str|None):
|
9
|
+
"""Check if the current version is the latest version on PyPI.
|
10
|
+
|
11
|
+
Returns:
|
12
|
+
bool: True if the current version is the latest, False otherwise
|
13
|
+
"""
|
14
|
+
try:
|
15
|
+
current_version = get_version()
|
16
|
+
response = requests.get("https://pypi.org/pypi/quantalogic/json", timeout=5)
|
17
|
+
response.raise_for_status()
|
18
|
+
latest_version = response.json()["info"]["version"]
|
19
|
+
return version.parse(current_version) < version.parse(latest_version), latest_version
|
20
|
+
except (requests.RequestException, KeyError):
|
21
|
+
return False, None
|
22
|
+
|
23
|
+
|
24
|
+
def main():
|
25
|
+
"""Test the version checking functionality."""
|
26
|
+
is_latest, latest_version = check_if_is_latest_version()
|
27
|
+
if is_latest:
|
28
|
+
print("✅ You're running the latest version")
|
29
|
+
elif latest_version:
|
30
|
+
print(f"⚠️ Update available: {latest_version}")
|
31
|
+
else:
|
32
|
+
print("❌ Could not check version")
|
33
|
+
|
34
|
+
if __name__ == "__main__":
|
35
|
+
main()
|
36
|
+
|
37
|
+
|
@@ -35,18 +35,18 @@ def download_http_file(
|
|
35
35
|
|
36
36
|
for attempt in range(max_retries):
|
37
37
|
try:
|
38
|
-
logger.
|
38
|
+
logger.debug(f"Attempt {attempt + 1} of {max_retries} to download {url}")
|
39
39
|
response = requests.get(url, headers=headers, stream=True, timeout=timeout)
|
40
40
|
response.raise_for_status()
|
41
41
|
|
42
42
|
content_type = response.headers.get("Content-Type", "unknown")
|
43
|
-
logger.
|
43
|
+
logger.debug(f"Downloading content with Content-Type: {content_type}")
|
44
44
|
|
45
45
|
with open(local_path, "wb") as file:
|
46
46
|
for chunk in response.iter_content(chunk_size=chunk_size):
|
47
47
|
file.write(chunk)
|
48
48
|
|
49
|
-
logger.
|
49
|
+
logger.debug(f"File successfully downloaded and saved to {local_path}")
|
50
50
|
return local_path
|
51
51
|
|
52
52
|
except HTTPError as http_err:
|
@@ -70,7 +70,7 @@ def download_http_file(
|
|
70
70
|
|
71
71
|
if attempt < max_retries - 1:
|
72
72
|
sleep_duration = delay * (2**attempt) # Exponential backoff
|
73
|
-
logger.
|
73
|
+
logger.debug(f"Retrying in {sleep_duration} seconds...")
|
74
74
|
sleep(sleep_duration)
|
75
75
|
|
76
76
|
logger.error("Max retries reached. Download failed.")
|
@@ -45,7 +45,7 @@ def read_http_text_content(
|
|
45
45
|
|
46
46
|
for attempt in range(retries):
|
47
47
|
try:
|
48
|
-
logger.
|
48
|
+
logger.debug(f"Attempt {attempt + 1} of {retries} to fetch {url}")
|
49
49
|
response = requests.get(url, headers=headers, timeout=timeout)
|
50
50
|
response.raise_for_status() # Raise an HTTPError for bad responses (4xx and 5xx)
|
51
51
|
|
@@ -87,7 +87,7 @@ def read_http_text_content(
|
|
87
87
|
|
88
88
|
if attempt < retries - 1:
|
89
89
|
sleep_duration = delay * (2**attempt) # Exponential backoff
|
90
|
-
logger.
|
90
|
+
logger.debug(f"Retrying in {sleep_duration} seconds...")
|
91
91
|
sleep(sleep_duration)
|
92
92
|
|
93
93
|
return None, error_msg
|
quantalogic/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: quantalogic
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.13
|
4
4
|
Summary: QuantaLogic ReAct Agents
|
5
5
|
Author: Raphaël MANSUY
|
6
6
|
Author-email: raphael.mansuy@gmail.com
|
@@ -12,6 +12,7 @@ Requires-Dist: boto3 (>=1.35.86,<2.0.0)
|
|
12
12
|
Requires-Dist: click (>=8.1.8,<9.0.0)
|
13
13
|
Requires-Dist: fastapi (>=0.115.6,<0.116.0)
|
14
14
|
Requires-Dist: google-auth (>=2.20.0,<3.0.0)
|
15
|
+
Requires-Dist: google-search-results (>=2.4.2,<3.0.0)
|
15
16
|
Requires-Dist: litellm (>=1.56.4,<2.0.0)
|
16
17
|
Requires-Dist: loguru (>=0.7.3,<0.8.0)
|
17
18
|
Requires-Dist: markitdown (>=0.0.1a3,<0.0.2)
|
@@ -19,6 +20,7 @@ Requires-Dist: pathspec (>=0.12.1,<0.13.0)
|
|
19
20
|
Requires-Dist: prompt-toolkit (>=3.0.48,<4.0.0)
|
20
21
|
Requires-Dist: pydantic (>=2.10.4,<3.0.0)
|
21
22
|
Requires-Dist: rich (>=13.9.4,<14.0.0)
|
23
|
+
Requires-Dist: serpapi (>=0.1.5,<0.2.0)
|
22
24
|
Requires-Dist: tenacity (>=9.0.0,<10.0.0)
|
23
25
|
Requires-Dist: toml (>=0.10.2,<0.11.0)
|
24
26
|
Requires-Dist: tree-sitter (>=0.23.2,<0.24.0)
|
@@ -31,6 +33,7 @@ Requires-Dist: tree-sitter-python (>=0.23.6,<0.24.0)
|
|
31
33
|
Requires-Dist: tree-sitter-rust (>=0.23.2,<0.24.0)
|
32
34
|
Requires-Dist: tree-sitter-scala (>=0.23.4,<0.24.0)
|
33
35
|
Requires-Dist: tree-sitter-typescript (>=0.23.2,<0.24.0)
|
36
|
+
Requires-Dist: types-requests (>=2.32.0.20241016,<3.0.0.0)
|
34
37
|
Requires-Dist: uvicorn (>=0.34.0,<0.35.0)
|
35
38
|
Requires-Dist: websocket (>=0.2.1,<0.3.0)
|
36
39
|
Description-Content-Type: text/markdown
|
@@ -129,7 +132,7 @@ Options:
|
|
129
132
|
e.g. "openrouter/A/gpt-4o-mini").
|
130
133
|
--log [info|debug|warning] Set logging level (info/debug/warning).
|
131
134
|
--verbose Enable verbose output.
|
132
|
-
--mode [code|basic|interpreter|full|code-basic]
|
135
|
+
--mode [code|basic|interpreter|full|code-basic|search]
|
133
136
|
Agent mode (code/search/full).
|
134
137
|
--help Show this message and exit.
|
135
138
|
|
@@ -140,6 +143,8 @@ Commands:
|
|
140
143
|
### Commands
|
141
144
|
task Execute a task with the QuantaLogic AI Assistant
|
142
145
|
|
146
|
+
|
147
|
+
|
143
148
|
### Detailed Usage
|
144
149
|
|
145
150
|
#### Agent Modes
|
@@ -379,16 +384,19 @@ By integrating these tools into its architecture, QuantaLogic allows agents to p
|
|
379
384
|
|
380
385
|
### Tools Documentation
|
381
386
|
|
387
|
+
|
388
|
+
|
382
389
|
#### Overview of Tools
|
383
390
|
|
384
391
|
| Category | Tools |
|
385
392
|
|-----------------------|---------------------------------------------------------------------------------------------------|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
393
|
+
| 1. Search Tools | 1.1 SerpAPI Search Tool, 1.2 Wikipedia Search Tool |
|
394
|
+
| 2. Task Automation | Agent Tool, Task Complete Tool, Input Question Tool, Execute Bash Command Tool |
|
395
|
+
| 3. Script Execution | Python Tool, Node.js Tool, Elixir Tool |
|
396
|
+
| 4. File Operations | Read File Tool, Write File Tool, Edit Whole Content Tool, Replace In File Tool |
|
397
|
+
| 5. Code Analysis | Search Definition Names Tool, Ripgrep Tool |
|
398
|
+
| 6. Content Generation | LLM Tool, LLMVisionTool |
|
399
|
+
| 7. Utility & Management| Download HTTP File Tool, List Directory Tool, Markitdown Tool, Unified Diff Tool |
|
392
400
|
|
393
401
|
---
|
394
402
|
|
@@ -787,6 +795,51 @@ result = markitdown_tool.execute(markdown_path="./path/to/file.md")
|
|
787
795
|
print("Processed Markdown Output:", result)
|
788
796
|
```
|
789
797
|
|
798
|
+
---
|
799
|
+
|
800
|
+
### 19. SerpAPI Search Tool
|
801
|
+
|
802
|
+
The **SerpAPI Search Tool** allows agents to perform web searches using the SerpAPI service.
|
803
|
+
|
804
|
+
##### Parameters
|
805
|
+
| Parameter | Type | Description | Example |
|
806
|
+
|-----------|--------|---------------------------------|-----------------------------|
|
807
|
+
| query | string | The search query to execute | "latest AI research papers" |
|
808
|
+
| location | string | Geographic location for results | "United States" |
|
809
|
+
| num | int | Number of results to return | 5 |
|
810
|
+
|
811
|
+
##### Example Usage
|
812
|
+
```python
|
813
|
+
from quantalogic.tools import SerpAPISearchTool
|
814
|
+
|
815
|
+
search_tool = SerpAPISearchTool()
|
816
|
+
results = search_tool.execute(query="latest AI research", location="United States", num=5)
|
817
|
+
print(results)
|
818
|
+
```
|
819
|
+
|
820
|
+
---
|
821
|
+
|
822
|
+
### 20. Wikipedia Search Tool
|
823
|
+
|
824
|
+
The **Wikipedia Search Tool** enables agents to search and retrieve information from Wikipedia.
|
825
|
+
|
826
|
+
##### Parameters
|
827
|
+
|
828
|
+
| Parameter | Type | Description | Example |
|
829
|
+
|-----------|--------|---------------------------------|-----------------------------|
|
830
|
+
| query | string | The search query to execute | "Artificial Intelligence" |
|
831
|
+
| lang | string | Language code for results | "en" |
|
832
|
+
| sentences | int | Number of summary sentences | 3 |
|
833
|
+
|
834
|
+
##### Example Usage
|
835
|
+
```python
|
836
|
+
from quantalogic.tools import WikipediaSearchTool
|
837
|
+
|
838
|
+
wiki_tool = WikipediaSearchTool()
|
839
|
+
results = wiki_tool.execute(query="Artificial Intelligence", lang="en", sentences=3)
|
840
|
+
print(results)
|
841
|
+
```
|
842
|
+
```
|
790
843
|
|
791
844
|
#### Creating Custom Tools
|
792
845
|
|