devduck 0.1.1766644714__py3-none-any.whl → 0.2.0__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.
Potentially problematic release.
This version of devduck might be problematic. Click here for more details.
- devduck/__init__.py +591 -1092
- devduck/_version.py +2 -2
- devduck/install.sh +42 -0
- devduck/test_redduck.py +1 -0
- devduck/tools/__init__.py +4 -44
- devduck/tools/install_tools.py +2 -103
- devduck/tools/mcp_server.py +6 -34
- devduck/tools/tcp.py +7 -6
- devduck/tools/websocket.py +2 -8
- devduck-0.2.0.dist-info/METADATA +143 -0
- devduck-0.2.0.dist-info/RECORD +16 -0
- {devduck-0.1.1766644714.dist-info → devduck-0.2.0.dist-info}/entry_points.txt +0 -1
- devduck-0.2.0.dist-info/licenses/LICENSE +21 -0
- devduck/agentcore_handler.py +0 -76
- devduck/tools/_ambient_input.py +0 -423
- devduck/tools/_tray_app.py +0 -530
- devduck/tools/agentcore_agents.py +0 -197
- devduck/tools/agentcore_config.py +0 -441
- devduck/tools/agentcore_invoke.py +0 -423
- devduck/tools/agentcore_logs.py +0 -320
- devduck/tools/ambient.py +0 -157
- devduck/tools/create_subagent.py +0 -659
- devduck/tools/fetch_github_tool.py +0 -201
- devduck/tools/ipc.py +0 -546
- devduck/tools/scraper.py +0 -935
- devduck/tools/speech_to_speech.py +0 -850
- devduck/tools/state_manager.py +0 -292
- devduck/tools/store_in_kb.py +0 -187
- devduck/tools/system_prompt.py +0 -608
- devduck/tools/tray.py +0 -247
- devduck/tools/use_github.py +0 -438
- devduck-0.1.1766644714.dist-info/METADATA +0 -717
- devduck-0.1.1766644714.dist-info/RECORD +0 -33
- devduck-0.1.1766644714.dist-info/licenses/LICENSE +0 -201
- {devduck-0.1.1766644714.dist-info → devduck-0.2.0.dist-info}/WHEEL +0 -0
- {devduck-0.1.1766644714.dist-info → devduck-0.2.0.dist-info}/top_level.txt +0 -0
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
"""GitHub Tool Fetcher for Strands Agent.
|
|
2
|
-
|
|
3
|
-
This tool fetches Python tool files from GitHub repositories and loads them
|
|
4
|
-
as available tools in the current Strands agent. It combines HTTP fetching
|
|
5
|
-
with the load_tool functionality to enable dynamic tool loading from remote
|
|
6
|
-
GitHub repositories.
|
|
7
|
-
|
|
8
|
-
Usage with Strands Agents:
|
|
9
|
-
python
|
|
10
|
-
from strands import Agent
|
|
11
|
-
from tools.fetch_github_tool import fetch_github_tool
|
|
12
|
-
|
|
13
|
-
agent = Agent(tools=[fetch_github_tool])
|
|
14
|
-
|
|
15
|
-
# Fetch and load a tool from GitHub
|
|
16
|
-
agent.tool.fetch_github_tool(
|
|
17
|
-
github_url="https://github.com/owner/repo/blob/main/tools/my_tool.py",
|
|
18
|
-
tool_name="my_tool"
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
# Now you can use the fetched tool
|
|
22
|
-
agent.tool.my_tool(param1="value")
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
Supported GitHub URL formats:
|
|
26
|
-
- https://github.com/owner/repo/blob/branch/path/to/file.py
|
|
27
|
-
- https://github.com/owner/repo/tree/branch/path/to/file.py
|
|
28
|
-
- https://raw.githubusercontent.com/owner/repo/branch/path/to/file.py
|
|
29
|
-
"""
|
|
30
|
-
|
|
31
|
-
import os
|
|
32
|
-
import re
|
|
33
|
-
from pathlib import Path
|
|
34
|
-
from typing import Any
|
|
35
|
-
|
|
36
|
-
import requests
|
|
37
|
-
from strands import tool
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def parse_github_url(github_url: str) -> dict[str, str]:
|
|
41
|
-
"""Parse GitHub URL to extract repository information.
|
|
42
|
-
|
|
43
|
-
Args:
|
|
44
|
-
github_url: GitHub URL to the file
|
|
45
|
-
|
|
46
|
-
Returns:
|
|
47
|
-
Dictionary with owner, repo, branch, and file_path
|
|
48
|
-
|
|
49
|
-
Raises:
|
|
50
|
-
ValueError: If URL format is not supported
|
|
51
|
-
"""
|
|
52
|
-
# Handle raw.githubusercontent.com URLs
|
|
53
|
-
raw_pattern = r"https://raw\.githubusercontent\.com/([^/]+)/([^/]+)/([^/]+)/(.+)"
|
|
54
|
-
raw_match = re.match(raw_pattern, github_url)
|
|
55
|
-
|
|
56
|
-
if raw_match:
|
|
57
|
-
owner, repo, branch, file_path = raw_match.groups()
|
|
58
|
-
return {"owner": owner, "repo": repo, "branch": branch, "file_path": file_path}
|
|
59
|
-
|
|
60
|
-
# Handle github.com/owner/repo/blob/branch/path URLs
|
|
61
|
-
blob_pattern = r"https://github\.com/([^/]+)/([^/]+)/(?:blob|tree)/([^/]+)/(.+)"
|
|
62
|
-
blob_match = re.match(blob_pattern, github_url)
|
|
63
|
-
|
|
64
|
-
if blob_match:
|
|
65
|
-
owner, repo, branch, file_path = blob_match.groups()
|
|
66
|
-
return {"owner": owner, "repo": repo, "branch": branch, "file_path": file_path}
|
|
67
|
-
|
|
68
|
-
raise ValueError(f"Unsupported GitHub URL format: {github_url}")
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def build_raw_url(owner: str, repo: str, branch: str, file_path: str) -> str:
|
|
72
|
-
"""Build GitHub raw content URL.
|
|
73
|
-
|
|
74
|
-
Args:
|
|
75
|
-
owner: Repository owner
|
|
76
|
-
repo: Repository name
|
|
77
|
-
branch: Branch name
|
|
78
|
-
file_path: Path to file in repository
|
|
79
|
-
|
|
80
|
-
Returns:
|
|
81
|
-
Raw GitHub URL for the file
|
|
82
|
-
"""
|
|
83
|
-
return f"https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{file_path}"
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
@tool
|
|
87
|
-
def fetch_github_tool(
|
|
88
|
-
github_url: str,
|
|
89
|
-
tool_name: str | None = None,
|
|
90
|
-
local_dir: str = "./github_tools",
|
|
91
|
-
agent: Any = None,
|
|
92
|
-
) -> dict[str, Any]:
|
|
93
|
-
"""Fetch a Python tool file from GitHub and load it as a Strands tool.
|
|
94
|
-
|
|
95
|
-
This tool downloads Python files from GitHub repositories, saves them locally,
|
|
96
|
-
and registers them as available tools in the current Strands agent. It supports
|
|
97
|
-
various GitHub URL formats and automatically handles the conversion to raw content URLs.
|
|
98
|
-
|
|
99
|
-
Args:
|
|
100
|
-
github_url: GitHub URL to the Python tool file. Supports formats like:
|
|
101
|
-
- https://github.com/owner/repo/blob/main/tools/my_tool.py
|
|
102
|
-
- https://github.com/owner/repo/tree/main/tools/my_tool.py
|
|
103
|
-
- https://raw.githubusercontent.com/owner/repo/main/tools/my_tool.py
|
|
104
|
-
tool_name: Name to register the tool under. If not provided, will extract
|
|
105
|
-
from the filename (e.g., "my_tool.py" becomes "my_tool")
|
|
106
|
-
local_dir: Local directory to save the fetched tool file. Defaults to "./github_tools"
|
|
107
|
-
agent: Agent instance (automatically provided by Strands)
|
|
108
|
-
|
|
109
|
-
Returns:
|
|
110
|
-
Dict containing status and response content:
|
|
111
|
-
{
|
|
112
|
-
"status": "success|error",
|
|
113
|
-
"content": [{"text": "Response message"}]
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
Examples:
|
|
117
|
-
# Fetch a tool from GitHub and load it
|
|
118
|
-
agent.tool.fetch_github_tool(
|
|
119
|
-
github_url="https://github.com/cagataycali/my-tools/blob/main/weather_tool.py",
|
|
120
|
-
tool_name="weather"
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
# Tool name can be auto-detected from filename
|
|
124
|
-
agent.tool.fetch_github_tool(
|
|
125
|
-
github_url="https://github.com/cagataycali/my-tools/blob/main/calculator.py"
|
|
126
|
-
)
|
|
127
|
-
"""
|
|
128
|
-
try:
|
|
129
|
-
# Parse the GitHub URL
|
|
130
|
-
try:
|
|
131
|
-
url_info = parse_github_url(github_url)
|
|
132
|
-
except ValueError as e:
|
|
133
|
-
return {"status": "error", "content": [{"text": f"❌ {e!s}"}]}
|
|
134
|
-
|
|
135
|
-
# Extract tool name from filename if not provided
|
|
136
|
-
if not tool_name:
|
|
137
|
-
filename = os.path.basename(url_info["file_path"])
|
|
138
|
-
tool_name = os.path.splitext(filename)[0]
|
|
139
|
-
|
|
140
|
-
# Check if it's a Python file first (before making HTTP request)
|
|
141
|
-
if not url_info["file_path"].endswith(".py"):
|
|
142
|
-
return {
|
|
143
|
-
"status": "error",
|
|
144
|
-
"content": [
|
|
145
|
-
{
|
|
146
|
-
"text": f"❌ File must be a Python file (.py), got: {url_info['file_path']}"
|
|
147
|
-
}
|
|
148
|
-
],
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
# Build raw GitHub URL
|
|
152
|
-
raw_url = build_raw_url(
|
|
153
|
-
url_info["owner"],
|
|
154
|
-
url_info["repo"],
|
|
155
|
-
url_info["branch"],
|
|
156
|
-
url_info["file_path"],
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
# Create local directory if it doesn't exist
|
|
160
|
-
local_path = Path(local_dir)
|
|
161
|
-
local_path.mkdir(parents=True, exist_ok=True)
|
|
162
|
-
|
|
163
|
-
# Download the file
|
|
164
|
-
response = requests.get(raw_url, timeout=30)
|
|
165
|
-
response.raise_for_status()
|
|
166
|
-
# Save the file locally
|
|
167
|
-
local_file_path = local_path / f"{tool_name}.py"
|
|
168
|
-
with open(local_file_path, "w", encoding="utf-8") as f:
|
|
169
|
-
f.write(response.text)
|
|
170
|
-
|
|
171
|
-
# Load the tool using load_tool functionality
|
|
172
|
-
if agent and hasattr(agent, "tool_registry"):
|
|
173
|
-
agent.tool_registry.load_tool_from_filepath(
|
|
174
|
-
tool_name=tool_name, tool_path=str(local_file_path)
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
success_message = f"""✅ Successfully fetched and loaded GitHub tool!
|
|
178
|
-
|
|
179
|
-
📂 **Source:** {github_url}
|
|
180
|
-
🏷️ **Tool Name:** {tool_name}
|
|
181
|
-
💾 **Local Path:** {local_file_path}
|
|
182
|
-
🔧 **Status:** Ready to use
|
|
183
|
-
|
|
184
|
-
You can now use the tool with: agent.tool.{tool_name}(...)"""
|
|
185
|
-
|
|
186
|
-
return {"status": "success", "content": [{"text": success_message}]}
|
|
187
|
-
else:
|
|
188
|
-
return {
|
|
189
|
-
"status": "error",
|
|
190
|
-
"content": [
|
|
191
|
-
{"text": "❌ Agent instance not available for tool registration"}
|
|
192
|
-
],
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
except requests.RequestException as e:
|
|
196
|
-
return {
|
|
197
|
-
"status": "error",
|
|
198
|
-
"content": [{"text": f"❌ Failed to download file from GitHub: {e!s}"}],
|
|
199
|
-
}
|
|
200
|
-
except Exception as e:
|
|
201
|
-
return {"status": "error", "content": [{"text": f"❌ Unexpected error: {e!s}"}]}
|