devduck 0.5.4__py3-none-any.whl → 0.6.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.
- devduck/__init__.py +973 -557
- devduck/_version.py +2 -2
- devduck/tools/__init__.py +3 -0
- devduck/tools/agentcore_config.py +1 -0
- devduck/tools/ipc.py +4 -1
- devduck/tools/state_manager.py +292 -0
- devduck/tools/tcp.py +6 -0
- devduck/tools/websocket.py +7 -1
- {devduck-0.5.4.dist-info → devduck-0.6.0.dist-info}/METADATA +23 -5
- {devduck-0.5.4.dist-info → devduck-0.6.0.dist-info}/RECORD +14 -13
- {devduck-0.5.4.dist-info → devduck-0.6.0.dist-info}/WHEEL +0 -0
- {devduck-0.5.4.dist-info → devduck-0.6.0.dist-info}/entry_points.txt +0 -0
- {devduck-0.5.4.dist-info → devduck-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {devduck-0.5.4.dist-info → devduck-0.6.0.dist-info}/top_level.txt +0 -0
devduck/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0,
|
|
31
|
+
__version__ = version = '0.6.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 6, 0)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
devduck/tools/__init__.py
CHANGED
|
@@ -11,6 +11,7 @@ from .use_github import use_github
|
|
|
11
11
|
from .create_subagent import create_subagent
|
|
12
12
|
from .store_in_kb import store_in_kb
|
|
13
13
|
from .system_prompt import system_prompt
|
|
14
|
+
from .state_manager import state_manager
|
|
14
15
|
|
|
15
16
|
# AgentCore tools (conditionally available)
|
|
16
17
|
try:
|
|
@@ -29,6 +30,7 @@ try:
|
|
|
29
30
|
"create_subagent",
|
|
30
31
|
"store_in_kb",
|
|
31
32
|
"system_prompt",
|
|
33
|
+
"state_manager",
|
|
32
34
|
"tray",
|
|
33
35
|
"ambient",
|
|
34
36
|
"agentcore_config",
|
|
@@ -47,6 +49,7 @@ except ImportError:
|
|
|
47
49
|
"create_subagent",
|
|
48
50
|
"store_in_kb",
|
|
49
51
|
"system_prompt",
|
|
52
|
+
"state_manager",
|
|
50
53
|
"tray",
|
|
51
54
|
"ambient",
|
|
52
55
|
]
|
devduck/tools/ipc.py
CHANGED
|
@@ -322,8 +322,11 @@ def handle_ipc_client(client_socket, client_id, system_prompt: str, socket_path:
|
|
|
322
322
|
)
|
|
323
323
|
continue
|
|
324
324
|
|
|
325
|
+
except BrokenPipeError:
|
|
326
|
+
# Normal disconnect - client closed connection
|
|
327
|
+
logger.debug(f"IPC client {client_id} disconnected")
|
|
325
328
|
except Exception as e:
|
|
326
|
-
logger.error(f"Error handling IPC client {client_id}: {e}"
|
|
329
|
+
logger.error(f"Error handling IPC client {client_id}: {e}")
|
|
327
330
|
finally:
|
|
328
331
|
try:
|
|
329
332
|
client_socket.close()
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
"""DevDuck State Manager - Time-travel for agent conversations"""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import tempfile
|
|
5
|
+
import dill
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from typing import Dict, Any
|
|
9
|
+
from strands import tool
|
|
10
|
+
|
|
11
|
+
base_dir = Path(os.getenv("DEVDUCK_HOME", tempfile.gettempdir()))
|
|
12
|
+
states_dir = base_dir / ".devduck" / "states"
|
|
13
|
+
states_dir.mkdir(parents=True, exist_ok=True)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@tool
|
|
17
|
+
def state_manager(
|
|
18
|
+
action: str,
|
|
19
|
+
state_file: str = None,
|
|
20
|
+
query: str = None,
|
|
21
|
+
metadata: dict = None,
|
|
22
|
+
agent=None, # Parent agent injection
|
|
23
|
+
) -> Dict[str, Any]:
|
|
24
|
+
"""Agent state management with time-travel capabilities.
|
|
25
|
+
|
|
26
|
+
Inspired by cagataycali/research-agent state export pattern.
|
|
27
|
+
|
|
28
|
+
Actions:
|
|
29
|
+
- export: Save current agent state to pkl
|
|
30
|
+
- load: Load and display state from pkl
|
|
31
|
+
- list: List available saved states
|
|
32
|
+
- resume: Load state and continue with new query (ephemeral)
|
|
33
|
+
- modify: Update pkl file metadata
|
|
34
|
+
- delete: Remove saved state
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
action: Operation to perform
|
|
38
|
+
state_file: Path to pkl file (auto-generated for export)
|
|
39
|
+
query: New query for resume action
|
|
40
|
+
metadata: Additional metadata for export/modify
|
|
41
|
+
agent: Parent agent (auto-injected by Strands)
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Dict with status and content
|
|
45
|
+
|
|
46
|
+
Examples:
|
|
47
|
+
# Save current state
|
|
48
|
+
state_manager(action="export", metadata={"note": "before refactor"})
|
|
49
|
+
|
|
50
|
+
# List saved states
|
|
51
|
+
state_manager(action="list")
|
|
52
|
+
|
|
53
|
+
# Resume from previous state (ephemeral, no mutation)
|
|
54
|
+
state_manager(action="resume", state_file="~/.devduck/states/devduck_20250116_032000.pkl", query="continue analysis")
|
|
55
|
+
|
|
56
|
+
# Modify state metadata
|
|
57
|
+
state_manager(action="modify", state_file="path/to/state.pkl", metadata={"tags": ["important", "refactor"]})
|
|
58
|
+
"""
|
|
59
|
+
try:
|
|
60
|
+
if action == "export":
|
|
61
|
+
# Capture current agent state
|
|
62
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
63
|
+
state_file = states_dir / f"devduck_{timestamp}.pkl"
|
|
64
|
+
|
|
65
|
+
# Safe state extraction (avoid complex objects)
|
|
66
|
+
state_data = {
|
|
67
|
+
"version": "1.0",
|
|
68
|
+
"timestamp": datetime.now().isoformat(),
|
|
69
|
+
"system_prompt": agent.system_prompt,
|
|
70
|
+
"tools": list(agent.tool_names),
|
|
71
|
+
"model": {
|
|
72
|
+
"model_id": getattr(agent.model, "model_id", "unknown"),
|
|
73
|
+
"temperature": getattr(agent.model, "temperature", None),
|
|
74
|
+
"provider": getattr(agent.model, "provider", "unknown"),
|
|
75
|
+
},
|
|
76
|
+
"metadata": metadata or {},
|
|
77
|
+
"environment": {
|
|
78
|
+
"cwd": str(Path.cwd()),
|
|
79
|
+
"devduck_version": "0.6.0",
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# Try to capture conversation history if available
|
|
84
|
+
if hasattr(agent, "conversation_history"):
|
|
85
|
+
state_data["conversation_history"] = agent.conversation_history
|
|
86
|
+
elif hasattr(agent, "messages"):
|
|
87
|
+
state_data["conversation_history"] = agent.messages
|
|
88
|
+
|
|
89
|
+
# Save with dill
|
|
90
|
+
with open(state_file, "wb") as f:
|
|
91
|
+
dill.dump(state_data, f)
|
|
92
|
+
|
|
93
|
+
size = state_file.stat().st_size
|
|
94
|
+
return {
|
|
95
|
+
"status": "success",
|
|
96
|
+
"content": [
|
|
97
|
+
{
|
|
98
|
+
"text": f"✅ State exported: {state_file}\n"
|
|
99
|
+
f"📦 Size: {size} bytes\n"
|
|
100
|
+
f"🔧 Tools: {len(state_data['tools'])}\n"
|
|
101
|
+
f"📝 Metadata: {metadata or 'none'}"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
elif action == "list":
|
|
107
|
+
# List all saved states
|
|
108
|
+
states = sorted(
|
|
109
|
+
states_dir.glob("devduck_*.pkl"),
|
|
110
|
+
key=lambda p: p.stat().st_mtime,
|
|
111
|
+
reverse=True,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
if not states:
|
|
115
|
+
return {
|
|
116
|
+
"status": "success",
|
|
117
|
+
"content": [{"text": "No saved states found"}],
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
output = f"📚 Found {len(states)} saved states:\n\n"
|
|
121
|
+
for i, state_path in enumerate(states[:10], 1): # Show last 10
|
|
122
|
+
try:
|
|
123
|
+
with open(state_path, "rb") as f:
|
|
124
|
+
state_data = dill.load(f)
|
|
125
|
+
|
|
126
|
+
timestamp = state_data.get("timestamp", "unknown")
|
|
127
|
+
tools_count = len(state_data.get("tools", []))
|
|
128
|
+
meta = state_data.get("metadata", {})
|
|
129
|
+
|
|
130
|
+
output += f"{i}. {state_path.name}\n"
|
|
131
|
+
output += f" 📅 {timestamp}\n"
|
|
132
|
+
output += f" 🔧 {tools_count} tools\n"
|
|
133
|
+
if meta:
|
|
134
|
+
output += f" 📝 {meta}\n"
|
|
135
|
+
output += "\n"
|
|
136
|
+
except:
|
|
137
|
+
output += f"{i}. {state_path.name} (corrupted)\n\n"
|
|
138
|
+
|
|
139
|
+
return {"status": "success", "content": [{"text": output}]}
|
|
140
|
+
|
|
141
|
+
elif action == "load":
|
|
142
|
+
# Load and display state
|
|
143
|
+
if not state_file:
|
|
144
|
+
return {
|
|
145
|
+
"status": "error",
|
|
146
|
+
"content": [{"text": "state_file required for load"}],
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
state_path = Path(state_file).expanduser()
|
|
150
|
+
if not state_path.exists():
|
|
151
|
+
return {
|
|
152
|
+
"status": "error",
|
|
153
|
+
"content": [{"text": f"State file not found: {state_path}"}],
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
with open(state_path, "rb") as f:
|
|
157
|
+
state_data = dill.load(f)
|
|
158
|
+
|
|
159
|
+
# Pretty format
|
|
160
|
+
output = f"📦 State: {state_path.name}\n\n"
|
|
161
|
+
output += f"📅 Timestamp: {state_data.get('timestamp')}\n"
|
|
162
|
+
output += f"🤖 Model: {state_data.get('model', {}).get('model_id')}\n"
|
|
163
|
+
output += f"🔧 Tools ({len(state_data.get('tools', []))}): {', '.join(state_data.get('tools', []))}\n"
|
|
164
|
+
output += f"📝 Metadata: {state_data.get('metadata', {})}\n"
|
|
165
|
+
|
|
166
|
+
if "conversation_history" in state_data:
|
|
167
|
+
history = state_data["conversation_history"]
|
|
168
|
+
output += f"\n💬 Conversation: {len(history)} messages\n"
|
|
169
|
+
|
|
170
|
+
return {"status": "success", "content": [{"text": output}]}
|
|
171
|
+
|
|
172
|
+
elif action == "resume":
|
|
173
|
+
# Time-travel: Load state and continue with ephemeral agent
|
|
174
|
+
if not state_file or not query:
|
|
175
|
+
return {
|
|
176
|
+
"status": "error",
|
|
177
|
+
"content": [{"text": "state_file and query required for resume"}],
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
state_path = Path(state_file).expanduser()
|
|
181
|
+
if not state_path.exists():
|
|
182
|
+
return {
|
|
183
|
+
"status": "error",
|
|
184
|
+
"content": [{"text": f"State file not found: {state_path}"}],
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
with open(state_path, "rb") as f:
|
|
188
|
+
state_data = dill.load(f)
|
|
189
|
+
|
|
190
|
+
# ✅ Create ephemeral DevDuck instance (no mutation!)
|
|
191
|
+
try:
|
|
192
|
+
from devduck import DevDuck
|
|
193
|
+
|
|
194
|
+
ephemeral_duck = DevDuck(auto_start_servers=False)
|
|
195
|
+
ephemeral_agent = ephemeral_duck.agent
|
|
196
|
+
except Exception as e:
|
|
197
|
+
return {
|
|
198
|
+
"status": "error",
|
|
199
|
+
"content": [{"text": f"Failed to create ephemeral DevDuck: {e}"}],
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
# Load saved state into ephemeral agent
|
|
203
|
+
ephemeral_agent.system_prompt = state_data["system_prompt"]
|
|
204
|
+
|
|
205
|
+
# Restore conversation history
|
|
206
|
+
if "conversation_history" in state_data:
|
|
207
|
+
saved_history = state_data["conversation_history"]
|
|
208
|
+
|
|
209
|
+
if hasattr(ephemeral_agent, "conversation_history"):
|
|
210
|
+
ephemeral_agent.conversation_history = saved_history
|
|
211
|
+
elif hasattr(ephemeral_agent, "messages"):
|
|
212
|
+
ephemeral_agent.messages = saved_history
|
|
213
|
+
|
|
214
|
+
# Build continuation prompt with context
|
|
215
|
+
continuation_context = f"""
|
|
216
|
+
[Resumed from state: {state_path.name}]
|
|
217
|
+
[Original timestamp: {state_data.get('timestamp')}]
|
|
218
|
+
|
|
219
|
+
{query}
|
|
220
|
+
"""
|
|
221
|
+
# Run ephemeral agent (parent agent unchanged!)
|
|
222
|
+
result = ephemeral_agent(continuation_context)
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
"status": "success",
|
|
226
|
+
"content": [{"text": f"🔄 Resumed from {state_path.name}\n\n{result}"}],
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
elif action == "modify":
|
|
230
|
+
# Modify state metadata
|
|
231
|
+
if not state_file:
|
|
232
|
+
return {
|
|
233
|
+
"status": "error",
|
|
234
|
+
"content": [{"text": "state_file required for modify"}],
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
state_path = Path(state_file).expanduser()
|
|
238
|
+
if not state_path.exists():
|
|
239
|
+
return {
|
|
240
|
+
"status": "error",
|
|
241
|
+
"content": [{"text": f"State file not found: {state_path}"}],
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
with open(state_path, "rb") as f:
|
|
245
|
+
state_data = dill.load(f)
|
|
246
|
+
|
|
247
|
+
# Update metadata
|
|
248
|
+
if metadata:
|
|
249
|
+
state_data["metadata"].update(metadata)
|
|
250
|
+
|
|
251
|
+
# Save back
|
|
252
|
+
with open(state_path, "wb") as f:
|
|
253
|
+
dill.dump(state_data, f)
|
|
254
|
+
|
|
255
|
+
return {
|
|
256
|
+
"status": "success",
|
|
257
|
+
"content": [
|
|
258
|
+
{
|
|
259
|
+
"text": f"✅ Modified {state_path.name}\n📝 New metadata: {state_data['metadata']}"
|
|
260
|
+
}
|
|
261
|
+
],
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
elif action == "delete":
|
|
265
|
+
# Delete saved state
|
|
266
|
+
if not state_file:
|
|
267
|
+
return {
|
|
268
|
+
"status": "error",
|
|
269
|
+
"content": [{"text": "state_file required for delete"}],
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
state_path = Path(state_file).expanduser()
|
|
273
|
+
if not state_path.exists():
|
|
274
|
+
return {
|
|
275
|
+
"status": "error",
|
|
276
|
+
"content": [{"text": f"State file not found: {state_path}"}],
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
state_path.unlink()
|
|
280
|
+
return {
|
|
281
|
+
"status": "success",
|
|
282
|
+
"content": [{"text": f"🗑️ Deleted {state_path.name}"}],
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
else:
|
|
286
|
+
return {
|
|
287
|
+
"status": "error",
|
|
288
|
+
"content": [{"text": f"Unknown action: {action}"}],
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
except Exception as e:
|
|
292
|
+
return {"status": "error", "content": [{"text": f"Error: {e}"}]}
|
devduck/tools/tcp.py
CHANGED
|
@@ -316,6 +316,12 @@ def run_server(
|
|
|
316
316
|
if SERVER_THREADS[port]["running"]:
|
|
317
317
|
logger.error(f"Error accepting connection: {e}")
|
|
318
318
|
|
|
319
|
+
except OSError as e:
|
|
320
|
+
# Port conflict - handled upstream, no need for scary errors
|
|
321
|
+
if "Address already in use" in str(e):
|
|
322
|
+
logger.debug(f"Port {port} unavailable (handled upstream)")
|
|
323
|
+
else:
|
|
324
|
+
logger.error(f"Server error on {host}:{port}: {e}")
|
|
319
325
|
except Exception as e:
|
|
320
326
|
logger.error(f"Server error on {host}:{port}: {e}")
|
|
321
327
|
finally:
|
devduck/tools/websocket.py
CHANGED
|
@@ -347,8 +347,14 @@ def run_websocket_server(
|
|
|
347
347
|
asyncio.set_event_loop(loop)
|
|
348
348
|
WS_SERVER_THREADS[port]["loop"] = loop
|
|
349
349
|
loop.run_until_complete(start_server())
|
|
350
|
+
except OSError as e:
|
|
351
|
+
# Port conflict - handled upstream, no need for scary errors
|
|
352
|
+
if "Address already in use" in str(e) or "address already in use" in str(e):
|
|
353
|
+
logger.debug(f"Port {port} unavailable (handled upstream)")
|
|
354
|
+
else:
|
|
355
|
+
logger.error(f"WebSocket server error on {host}:{port}: {e}")
|
|
350
356
|
except Exception as e:
|
|
351
|
-
logger.error(f"WebSocket server error on {host}:{port}: {e}"
|
|
357
|
+
logger.error(f"WebSocket server error on {host}:{port}: {e}")
|
|
352
358
|
finally:
|
|
353
359
|
logger.info(f"WebSocket Server on {host}:{port} stopped")
|
|
354
360
|
WS_SERVER_THREADS[port]["running"] = False
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devduck
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: 🦆 Extreme minimalist self-adapting AI agent - one file, self-healing, runtime dependencies
|
|
5
5
|
Author-email: Cagatay Cali <cagataycali@icloud.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -53,6 +53,17 @@ Dynamic: license-file
|
|
|
53
53
|
|
|
54
54
|
One Python file that adapts to your environment, fixes itself, and expands capabilities at runtime.
|
|
55
55
|
|
|
56
|
+
## 🎬 See It In Action
|
|
57
|
+
|
|
58
|
+
| Feature | What You'll See | Video |
|
|
59
|
+
|---------|----------------|-------|
|
|
60
|
+
| 🔥 **Hot-Reload** | Agent detects code changes and restarts instantly—no manual intervention needed. Edit your agent code or tools while running, save the file, and watch it reload automatically. | [Watch Demo](https://redduck.dev/videos/hot-reload.mp4) |
|
|
61
|
+
| 🌐 **Web UI** | Clean, modern web interface for chatting with DevDuck. Real-time streaming responses, tool execution visibility, and beautiful markdown rendering. | [Watch Demo](https://redduck.dev/videos/web-ui.mp4) |
|
|
62
|
+
| 🛠️ **Dynamic Tool Creation** | Create a new tool by simply saving a `.py` file in the `./tools/` directory. No restart, no configuration—the agent loads it instantly and starts using it. Pure hot-reload magic. | [Watch Demo](https://redduck.dev/videos/dynamic-tool-creation.mp4) |
|
|
63
|
+
| 🌊 **TCP Streaming Server** | Connect from any client (netcat, custom apps, other agents) via TCP. Real-time streaming responses with parallel tool execution. Multi-protocol access to the same agent. | [Watch Demo](https://redduck.dev/videos/tcp.mp4) |
|
|
64
|
+
| 🔌 **IPC & macOS Tray** | Unix socket-based inter-process communication with native macOS menu bar integration. DevDuck runs in your menu bar with quick actions, status indicators, and seamless IPC streaming via `/tmp/devduck_main.sock`. |  |
|
|
65
|
+
| 💬 **Ambient Overlay** | Floating AI input overlay with glassmorphism UI. Real-time IPC streaming from devduck, auto-focus with blinking cursor, and ESC to hide / Enter to send. Perfect for desktop AI interactions. | [Watch Demo](https://redduck.dev/videos/floating-input.mp4) |
|
|
66
|
+
|
|
56
67
|
---
|
|
57
68
|
|
|
58
69
|
## Install & Run
|
|
@@ -101,7 +112,7 @@ devduck
|
|
|
101
112
|
| 🧠 **Auto-RAG** | Remembers past conversations | "I prefer FastAPI" → later uses FastAPI automatically |
|
|
102
113
|
| 🌊 **Multi-Protocol** | CLI, Python, TCP, WebSocket, MCP, IPC | `devduck "query"` or `nc localhost 9999` |
|
|
103
114
|
| ☁️ **AWS Deploy** | One-command serverless deployment | `agentcore_config(auto_launch=True)` |
|
|
104
|
-
| 🛠️ **
|
|
115
|
+
| 🛠️ **35+ Tools** | Shell, GitHub, file editing, math, UI control | `devduck("create GitHub issue")` |
|
|
105
116
|
| 🎛️ **Flexible Config** | Load only tools you need | `DEVDUCK_TOOLS="strands_tools:shell,editor"` |
|
|
106
117
|
|
|
107
118
|
---
|
|
@@ -113,7 +124,7 @@ graph TB
|
|
|
113
124
|
A[User Input] -->|CLI/TCP/WS/MCP/IPC| B[DevDuck Core]
|
|
114
125
|
B -->|Auto RAG| C[Knowledge Base]
|
|
115
126
|
C -.->|Context Retrieval| B
|
|
116
|
-
B -->|Tool Calls| D[
|
|
127
|
+
B -->|Tool Calls| D[35+ Built-in Tools]
|
|
117
128
|
D --> E[shell/editor/calculator]
|
|
118
129
|
D --> F[GitHub/AgentCore]
|
|
119
130
|
D --> G[TCP/WebSocket/MCP/IPC]
|
|
@@ -187,8 +198,8 @@ devduck
|
|
|
187
198
|
| **Dev** | `shell`, `editor`, `file_read`, `calculator` | Code, test, debug |
|
|
188
199
|
| **GitHub** | `use_github`, `create_subagent` | Issues, PRs, CI/CD automation |
|
|
189
200
|
| **Network** | `tcp`, `websocket`, `mcp_server`, `ipc` | Serve agents over protocols |
|
|
190
|
-
| **AWS** | `agentcore_config`, `agentcore_invoke`, `agentcore_logs` | Deploy to serverless |
|
|
191
|
-
| **AI** | `use_agent`, `retrieve`, `store_in_kb` | Multi-agent, memory |
|
|
201
|
+
| **AWS** | `agentcore_config`, `agentcore_invoke`, `agentcore_logs`, `agentcore_agents` | Deploy to serverless |
|
|
202
|
+
| **AI** | `use_agent`, `retrieve`, `store_in_kb`, `state_manager` | Multi-agent, memory, state |
|
|
192
203
|
| **UI** (macOS) | `tray`, `ambient`, `cursor`, `clipboard` | Desktop automation |
|
|
193
204
|
|
|
194
205
|
<details>
|
|
@@ -204,6 +215,7 @@ devduck
|
|
|
204
215
|
- `create_subagent` - Spawn sub-agents via GitHub Actions
|
|
205
216
|
- `store_in_kb` - Store content in Bedrock Knowledge Base
|
|
206
217
|
- `system_prompt` - Manage agent system prompt
|
|
218
|
+
- `state_manager` - Agent state management with time-travel capabilities
|
|
207
219
|
- `tray` - System tray app control (macOS)
|
|
208
220
|
- `ambient` - Ambient AI input overlay (macOS)
|
|
209
221
|
|
|
@@ -225,6 +237,12 @@ devduck
|
|
|
225
237
|
- `environment` - Environment variable management
|
|
226
238
|
- `mcp_client` - Connect to external MCP servers
|
|
227
239
|
- `retrieve` - Bedrock Knowledge Base retrieval
|
|
240
|
+
- `scraper` - HTML/XML parsing with BeautifulSoup4
|
|
241
|
+
- `fetch_github_tool` - Fetch and load tools from GitHub
|
|
242
|
+
- `gist` - Comprehensive GitHub Gist management
|
|
243
|
+
- `add_comment` - Add comments to GitHub issues/PRs
|
|
244
|
+
- `list_issues` - List GitHub issues
|
|
245
|
+
- `list_pull_requests` - List GitHub pull requests
|
|
228
246
|
|
|
229
247
|
### strands-fun-tools (macOS)
|
|
230
248
|
- `listen` - Background speech transcription with Whisper
|
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
devduck/__init__.py,sha256=
|
|
1
|
+
devduck/__init__.py,sha256=mRu9U3EYnxYhFs2xi_a8fX6-peFLgoeM31zlFGbXb3k,57904
|
|
2
2
|
devduck/__main__.py,sha256=aeF2RR4k7lzSR2X1QKV9XQPCKhtsH0JYUv2etBBqmL0,145
|
|
3
|
-
devduck/_version.py,sha256=
|
|
3
|
+
devduck/_version.py,sha256=MAYWefOLb6kbIRub18WSzK6ggSjz1LNLy9aDRlX9Ea4,704
|
|
4
4
|
devduck/agentcore_handler.py,sha256=0DKJTTjoH9P8a70G0f5dOIIwy6bjqaN46voAWaSOpDY,2221
|
|
5
5
|
devduck/test_redduck.py,sha256=ILtKKMuoyVfmhnibmbojpbOsqbcKooZv4j9qtE2LWdw,1750
|
|
6
|
-
devduck/tools/__init__.py,sha256=
|
|
6
|
+
devduck/tools/__init__.py,sha256=AmIy8MInaClaZ71fqzy4EQJnBWsLkrv4QW9IIN7UQyw,1367
|
|
7
7
|
devduck/tools/_ambient_input.py,sha256=3lBgLO81BvkxjgTrQc-EuxNLXmO1oPUt2Ysg1jR4Fsk,13897
|
|
8
8
|
devduck/tools/_tray_app.py,sha256=E4rtJcegRsBs_FdQVGdA-0Ax7uxVb6AbuyqjwCArHj0,19405
|
|
9
9
|
devduck/tools/agentcore_agents.py,sha256=fiDNhl7R2tVbp1mEOySJTfGXwap5q3COenYOjiJDE_g,6488
|
|
10
|
-
devduck/tools/agentcore_config.py,sha256=
|
|
10
|
+
devduck/tools/agentcore_config.py,sha256=sUD1SrLAqTHjgHctZtVRDz_BvLG_nRB3z6g3EcrcvTM,14780
|
|
11
11
|
devduck/tools/agentcore_invoke.py,sha256=SMKqVAig_cZEBL-W5gfumUpPFIHC9CSRSY9BJbnx6wY,17449
|
|
12
12
|
devduck/tools/agentcore_logs.py,sha256=A3YQIoRErJtvzeaMSPNqOLX1BH-vYTbYKs1NXoCnC5E,10222
|
|
13
13
|
devduck/tools/ambient.py,sha256=HB1ZhfeOdOaMU0xe4e44VNUT_-DQ5SY7sl3r4r-4X44,4806
|
|
14
14
|
devduck/tools/create_subagent.py,sha256=UzRz9BmU4PbTveZROEpZ311aH-u-i6x89gttu-CniAE,24687
|
|
15
15
|
devduck/tools/install_tools.py,sha256=wm_67b9IfY-2wRuWgxuEKhaSIV5vNfbGmZL3G9dGi2A,10348
|
|
16
|
-
devduck/tools/ipc.py,sha256=
|
|
16
|
+
devduck/tools/ipc.py,sha256=e3KJeR2HmCKEtVLGNOtf6CeFi3pTDehwd7Fu4JJ19Ms,18607
|
|
17
17
|
devduck/tools/mcp_server.py,sha256=Ybp0PcJKW2TOvghsRL-i8Guqc9WokPwOD2bhVgzoj6Q,21490
|
|
18
|
+
devduck/tools/state_manager.py,sha256=hrleqdVoCboNd8R3wDRUXVKYCZdGoe1j925i948LTHc,10563
|
|
18
19
|
devduck/tools/store_in_kb.py,sha256=-JM-oRQKR3FBubKHFHmXRnZSvi9dVgHxG0lismMgG2k,6861
|
|
19
20
|
devduck/tools/system_prompt.py,sha256=waAdmvRhyulorw_tLqpqUJN_AahuaeF2rXqjMqN7IRY,16905
|
|
20
|
-
devduck/tools/tcp.py,sha256=
|
|
21
|
+
devduck/tools/tcp.py,sha256=w2m_Jf6vZ4NYu0AwgZd7C7eKs4No2EVHZ2WYIl_Bt0A,22017
|
|
21
22
|
devduck/tools/tray.py,sha256=FgVhUtLdsdv5_ERK-RyAIpDE8Zb0IfoqhHQdwMxrHUQ,7547
|
|
22
23
|
devduck/tools/use_github.py,sha256=nr3JSGk48mKUobpgW__2gu6lFyUj93a1XRs3I6vH8W4,13682
|
|
23
|
-
devduck/tools/websocket.py,sha256=
|
|
24
|
-
devduck-0.
|
|
25
|
-
devduck-0.
|
|
26
|
-
devduck-0.
|
|
27
|
-
devduck-0.
|
|
28
|
-
devduck-0.
|
|
29
|
-
devduck-0.
|
|
24
|
+
devduck/tools/websocket.py,sha256=A8bqgdDZs8hcf2HctkJzQOzMvb5mXUC7YZ-xqkOyn94,16959
|
|
25
|
+
devduck-0.6.0.dist-info/licenses/LICENSE,sha256=UANcoWwfVeuM9597WUkjEQbzqIUH0bJoE9Tpwgj_LvU,11345
|
|
26
|
+
devduck-0.6.0.dist-info/METADATA,sha256=u3rog7cs0uapLjeO8Oi8bZkoOjeOSQkWKRj65vwggkw,14518
|
|
27
|
+
devduck-0.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
28
|
+
devduck-0.6.0.dist-info/entry_points.txt,sha256=BAMQaIg_BLZQOTk12bT7hy1dE9oGPLt-_dTbI4cnBnQ,40
|
|
29
|
+
devduck-0.6.0.dist-info/top_level.txt,sha256=ySXWlVronp8xHYfQ_Hdfr463e0EnbWuqyuxs94EU7yk,8
|
|
30
|
+
devduck-0.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|