devduck 0.4.1__py3-none-any.whl → 0.5.2__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/tools/tray.py ADDED
@@ -0,0 +1,246 @@
1
+ """
2
+ Tray app control tool - integrated with devduck
3
+ """
4
+
5
+ from strands import tool
6
+ from typing import Dict, Any, List
7
+ import subprocess
8
+ import socket
9
+ import json
10
+ import tempfile
11
+ import os
12
+ import time
13
+ import signal
14
+ from pathlib import Path
15
+
16
+ # Global state
17
+ _tray_process = None
18
+
19
+
20
+ def _send_ipc_command(socket_path: str, command: Dict) -> Dict:
21
+ """Send IPC command to tray app"""
22
+ try:
23
+ client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
24
+ client.settimeout(10.0)
25
+ client.connect(socket_path)
26
+
27
+ # Send command
28
+ message = json.dumps(command).encode("utf-8")
29
+ client.sendall(message)
30
+
31
+ # Receive response
32
+ response_data = b""
33
+ while True:
34
+ chunk = client.recv(4096)
35
+ if not chunk:
36
+ break
37
+ response_data += chunk
38
+ # Check if we have complete JSON
39
+ try:
40
+ json.loads(response_data.decode("utf-8"))
41
+ break
42
+ except:
43
+ continue
44
+
45
+ client.close()
46
+
47
+ if not response_data:
48
+ return {"status": "error", "message": "Empty response"}
49
+
50
+ return json.loads(response_data.decode("utf-8"))
51
+ except socket.timeout:
52
+ return {"status": "error", "message": "Timeout"}
53
+ except Exception as e:
54
+ return {"status": "error", "message": str(e)}
55
+
56
+
57
+ @tool
58
+ def tray(
59
+ action: str,
60
+ items: List[Dict[str, Any]] = None,
61
+ title: str = None,
62
+ message: Dict[str, Any] = None,
63
+ text: str = None,
64
+ ) -> Dict[str, Any]:
65
+ """Control system tray app with devduck integration.
66
+
67
+ Returns:
68
+ Dict with status and content
69
+ """
70
+ global _tray_process
71
+
72
+ socket_path = os.path.join(tempfile.gettempdir(), "devduck_tray.sock")
73
+
74
+ if action == "start":
75
+ if _tray_process and _tray_process.poll() is None:
76
+ return {"status": "success", "content": [{"text": "✓ Already running"}]}
77
+
78
+ # Get tray script path
79
+ tools_dir = Path(__file__).parent
80
+ tray_script = tools_dir / "_tray_app.py"
81
+
82
+ if not tray_script.exists():
83
+ return {
84
+ "status": "error",
85
+ "content": [{"text": f"❌ Tray app not found: {tray_script}"}],
86
+ }
87
+
88
+ _tray_process = subprocess.Popen(
89
+ ["python3", str(tray_script)],
90
+ stdout=subprocess.DEVNULL,
91
+ stderr=subprocess.DEVNULL,
92
+ )
93
+
94
+ time.sleep(1.5)
95
+
96
+ return {
97
+ "status": "success",
98
+ "content": [{"text": f"✓ Tray app started (PID: {_tray_process.pid})"}],
99
+ }
100
+
101
+ elif action == "stop":
102
+ if _tray_process:
103
+ try:
104
+ os.kill(_tray_process.pid, signal.SIGTERM)
105
+ _tray_process.wait(timeout=3)
106
+ except:
107
+ pass
108
+ _tray_process = None
109
+
110
+ return {"status": "success", "content": [{"text": "✓ Stopped"}]}
111
+
112
+ elif action == "status":
113
+ is_running = _tray_process and _tray_process.poll() is None
114
+ return {"status": "success", "content": [{"text": f"Running: {is_running}"}]}
115
+
116
+ elif action == "update_menu":
117
+ if not items:
118
+ return {
119
+ "status": "error",
120
+ "content": [{"text": "items parameter required"}],
121
+ }
122
+
123
+ result = _send_ipc_command(
124
+ socket_path, {"action": "update_menu", "items": items}
125
+ )
126
+
127
+ if result.get("status") == "success":
128
+ return {
129
+ "status": "success",
130
+ "content": [{"text": f"✓ Menu updated ({len(items)} items)"}],
131
+ }
132
+ else:
133
+ return {
134
+ "status": "error",
135
+ "content": [
136
+ {"text": f"Failed: {result.get('message', 'Unknown error')}"}
137
+ ],
138
+ }
139
+
140
+ elif action == "update_title":
141
+ if not title:
142
+ return {
143
+ "status": "error",
144
+ "content": [{"text": "title parameter required"}],
145
+ }
146
+
147
+ result = _send_ipc_command(
148
+ socket_path, {"action": "update_title", "title": title}
149
+ )
150
+
151
+ if result.get("status") == "success":
152
+ return {"status": "success", "content": [{"text": f"✓ Title: {title}"}]}
153
+ else:
154
+ return {
155
+ "status": "error",
156
+ "content": [{"text": f"Failed: {result.get('message')}"}],
157
+ }
158
+
159
+ elif action == "set_progress":
160
+ """Set progress indicator: idle, thinking, processing, complete, error"""
161
+ if not text:
162
+ return {
163
+ "status": "error",
164
+ "content": [
165
+ {
166
+ "text": "text parameter required (idle/thinking/processing/complete/error)"
167
+ }
168
+ ],
169
+ }
170
+
171
+ result = _send_ipc_command(
172
+ socket_path, {"action": "set_progress", "progress": text}
173
+ )
174
+
175
+ if result.get("status") == "success":
176
+ return {"status": "success", "content": [{"text": f"✓ Progress: {text}"}]}
177
+ else:
178
+ return {
179
+ "status": "error",
180
+ "content": [{"text": f"Failed: {result.get('message')}"}],
181
+ }
182
+
183
+ elif action == "notify":
184
+ if not message:
185
+ return {
186
+ "status": "error",
187
+ "content": [{"text": "message parameter required"}],
188
+ }
189
+
190
+ result = _send_ipc_command(
191
+ socket_path, {"action": "notify", "message": message}
192
+ )
193
+
194
+ if result.get("status") == "success":
195
+ return {"status": "success", "content": [{"text": "✓ Notification sent"}]}
196
+ else:
197
+ return {
198
+ "status": "error",
199
+ "content": [{"text": f"Failed: {result.get('message')}"}],
200
+ }
201
+
202
+ elif action == "show_input":
203
+ result = _send_ipc_command(socket_path, {"action": "show_input"})
204
+
205
+ if result.get("status") == "success":
206
+ return {"status": "success", "content": [{"text": "✓ Input shown"}]}
207
+ else:
208
+ return {
209
+ "status": "error",
210
+ "content": [{"text": f"Failed: {result.get('message')}"}],
211
+ }
212
+
213
+ elif action == "stream_text":
214
+ if not text:
215
+ return {"status": "error", "content": [{"text": "text parameter required"}]}
216
+
217
+ result = _send_ipc_command(socket_path, {"action": "stream_text", "text": text})
218
+
219
+ if result.get("status") == "success":
220
+ return {"status": "success", "content": [{"text": "✓ Text streamed"}]}
221
+ else:
222
+ return {
223
+ "status": "error",
224
+ "content": [{"text": f"Failed: {result.get('message')}"}],
225
+ }
226
+
227
+ elif action in ["toggle_tcp", "toggle_ws", "toggle_mcp"]:
228
+ result = _send_ipc_command(socket_path, {"action": action})
229
+
230
+ if result.get("status") == "success":
231
+ return {"status": "success", "content": [{"text": f"✓ {action} executed"}]}
232
+ else:
233
+ return {
234
+ "status": "error",
235
+ "content": [{"text": f"Failed: {result.get('message')}"}],
236
+ }
237
+
238
+ else:
239
+ return {
240
+ "status": "error",
241
+ "content": [
242
+ {
243
+ "text": f"Unknown action: {action}. Available: start, stop, status, update_menu, update_title, set_progress, notify, show_input, stream_text, toggle_tcp, toggle_ws, toggle_mcp"
244
+ }
245
+ ],
246
+ }
@@ -0,0 +1,415 @@
1
+ Metadata-Version: 2.4
2
+ Name: devduck
3
+ Version: 0.5.2
4
+ Summary: 🦆 Extreme minimalist self-adapting AI agent - one file, self-healing, runtime dependencies
5
+ Author-email: Cagatay Cali <cagataycali@icloud.com>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/cagataycali/devduck
8
+ Project-URL: Repository, https://github.com/cagataycali/devduck.git
9
+ Project-URL: Documentation, https://github.com/cagataycali/devduck#readme
10
+ Project-URL: Bug Tracker, https://github.com/cagataycali/devduck/issues
11
+ Keywords: ai,agent,minimalist,self-healing,ollama,strands-agents
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Topic :: System :: Systems Administration
25
+ Classifier: Topic :: Utilities
26
+ Requires-Python: <3.14,>=3.10
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: strands-agents
30
+ Requires-Dist: prompt_toolkit
31
+ Requires-Dist: strands-agents[ollama]
32
+ Requires-Dist: strands-agents[anthropic]
33
+ Requires-Dist: strands-agents[openai]
34
+ Requires-Dist: strands-agents[otel]
35
+ Requires-Dist: strands-agents-tools
36
+ Requires-Dist: strands-fun-tools[all]; sys_platform == "darwin"
37
+ Requires-Dist: strands-fun-tools[audio]; sys_platform == "darwin"
38
+ Requires-Dist: beautifulsoup4
39
+ Requires-Dist: colorama
40
+ Requires-Dist: websockets
41
+ Requires-Dist: strands-mcp-server
42
+ Requires-Dist: bedrock-agentcore-starter-toolkit
43
+ Requires-Dist: bedrock-agentcore
44
+ Requires-Dist: rumps; sys_platform == "darwin"
45
+ Requires-Dist: strands-mlx; sys_platform == "darwin" and platform_machine == "arm64"
46
+ Dynamic: license-file
47
+
48
+ # 🦆 DevDuck
49
+
50
+ [![PyPI](https://badge.fury.io/py/devduck.svg)](https://pypi.org/project/devduck/) [![Homebrew](https://img.shields.io/badge/homebrew-available-orange)](https://github.com/cagataycali/homebrew-devduck)
51
+
52
+ **Self-modifying AI agent that hot-reloads its own code—builds itself as it runs.**
53
+
54
+ One Python file that adapts to your environment, fixes itself, and expands capabilities at runtime.
55
+
56
+ ---
57
+
58
+ ## Install & Run
59
+
60
+ | Method | Command |
61
+ |--------|---------|
62
+ | **pipx** | `pipx install devduck && devduck` |
63
+ | **uvx** | `uvx devduck "create a Flask API"` |
64
+ | **Homebrew** | `brew tap cagataycali/devduck && brew install devduck` |
65
+ | **Python** | `pip install devduck` → `import devduck; devduck("query")` |
66
+
67
+ **Requirements:** Python 3.10-3.13, Bedrock (or Ollama/Anthropic/GitHub/MLX)
68
+
69
+ ---
70
+
71
+ ## What It Does
72
+
73
+ | Feature | Description | Example |
74
+ |---------|-------------|---------|
75
+ | 🔥 **Hot-Reload** | Agent reloads its own code + custom tools instantly | Modify agent code → auto-restart, or add `weather.py` → use immediately |
76
+ | 🧠 **Auto-RAG** | Remembers past conversations | "I prefer FastAPI" → later uses FastAPI automatically |
77
+ | 🌊 **Multi-Protocol** | CLI, Python, TCP, WebSocket, MCP, IPC | `devduck "query"` or `nc localhost 9999` |
78
+ | ☁️ **AWS Deploy** | One-command serverless deployment | `agentcore_config(auto_launch=True)` |
79
+ | 🛠️ **30+ Tools** | Shell, GitHub, file editing, math, UI control | `devduck("create GitHub issue")` |
80
+ | 🎛️ **Flexible Config** | Load only tools you need | `DEVDUCK_TOOLS="strands_tools:shell,editor"` |
81
+
82
+ ---
83
+
84
+ ## Architecture
85
+
86
+ ```mermaid
87
+ graph TB
88
+ A[User Input] -->|CLI/TCP/WS/MCP/IPC| B[DevDuck Core]
89
+ B -->|Auto RAG| C[Knowledge Base]
90
+ C -.->|Context Retrieval| B
91
+ B -->|Tool Calls| D[30+ Built-in Tools]
92
+ D --> E[shell/editor/calculator]
93
+ D --> F[GitHub/AgentCore]
94
+ D --> G[TCP/WebSocket/MCP/IPC]
95
+ D --> H[tray/ambient/cursor/clipboard]
96
+ B -->|Hot-reload| I[./tools/*.py + __init__.py]
97
+ I -.->|Load Instantly| D
98
+ B -->|Response| J[User Output]
99
+ J -.->|Store Memory| C
100
+
101
+ style B fill:#e1f5ff
102
+ style C fill:#d4edda
103
+ style I fill:#fff3cd
104
+ style H fill:#ffe6f0
105
+ ```
106
+
107
+ **Self-adapting loop:** User queries → RAG retrieval → Tool execution → Response → Memory storage → Hot-reload new capabilities → Repeat.
108
+
109
+ ---
110
+
111
+ ## Quick Start
112
+
113
+ ```bash
114
+ # 1. Install
115
+ pipx install devduck
116
+
117
+ # 2. Start (auto-launches TCP/WS/MCP/IPC servers)
118
+ devduck
119
+
120
+ # 3. Use
121
+ 🦆 create a REST API with FastAPI
122
+ 🦆 !ls -la
123
+ 🦆 exit
124
+ ```
125
+
126
+ **One-shot:**
127
+ ```bash
128
+ devduck "analyze this error: ImportError: No module named 'flask'"
129
+ ```
130
+
131
+ **Python API:**
132
+ ```python
133
+ import devduck
134
+ devduck("refactor my code to use async/await")
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Model Setup
140
+
141
+ | Provider | Setup | When to Use |
142
+ |----------|-------|-------------|
143
+ | **Bedrock** (auto-detected) | [Get API key](https://console.aws.amazon.com/bedrock) → `export AWS_BEARER_TOKEN_BEDROCK=...` | Production (auto-selected if credentials found) |
144
+ | **MLX** (macOS auto-detected) | Auto-detected on Apple Silicon | Local, optimized for M-series Macs |
145
+ | **Ollama** (fallback) | `ollama pull qwen3:1.7b` | Local, free, private (used if Bedrock/MLX unavailable) |
146
+ | **Anthropic** | `export ANTHROPIC_API_KEY=...` | Claude API direct access |
147
+ | **GitHub** | `export GITHUB_TOKEN=...` | Free GPT-4o for GitHub users |
148
+
149
+ **Quick Bedrock setup:**
150
+ ```bash
151
+ export MODEL_PROVIDER=bedrock
152
+ export AWS_BEARER_TOKEN_BEDROCK=your_token # From AWS console
153
+ devduck
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Core Tools
159
+
160
+ | Category | Tools | Use Case |
161
+ |----------|-------|----------|
162
+ | **Dev** | `shell`, `editor`, `file_read`, `calculator` | Code, test, debug |
163
+ | **GitHub** | `use_github`, `create_subagent` | Issues, PRs, CI/CD automation |
164
+ | **Network** | `tcp`, `websocket`, `mcp_server`, `ipc` | Serve agents over protocols |
165
+ | **AWS** | `agentcore_config`, `agentcore_invoke`, `agentcore_logs` | Deploy to serverless |
166
+ | **AI** | `use_agent`, `retrieve`, `store_in_kb` | Multi-agent, memory |
167
+ | **UI** (macOS) | `tray`, `ambient`, `cursor`, `clipboard` | Desktop automation |
168
+
169
+ <details>
170
+ <summary><strong>📋 Full tool list (click to expand)</strong></summary>
171
+
172
+ ### DevDuck Core Tools
173
+ - `tcp` - TCP server with streaming
174
+ - `websocket` - WebSocket server with concurrent messaging
175
+ - `ipc` - Unix socket IPC server
176
+ - `mcp_server` - MCP server (HTTP/stdio)
177
+ - `install_tools` - Dynamic tool loading from packages
178
+ - `use_github` - GitHub GraphQL API operations
179
+ - `create_subagent` - Spawn sub-agents via GitHub Actions
180
+ - `store_in_kb` - Store content in Bedrock Knowledge Base
181
+ - `system_prompt` - Manage agent system prompt
182
+ - `tray` - System tray app control (macOS)
183
+ - `ambient` - Ambient AI input overlay (macOS)
184
+
185
+ ### AgentCore Tools (AWS)
186
+ - `agentcore_config` - Configure & launch on Bedrock AgentCore
187
+ - `agentcore_invoke` - Invoke deployed agents
188
+ - `agentcore_logs` - View CloudWatch logs
189
+ - `agentcore_agents` - List/manage agent runtimes
190
+
191
+ ### strands-agents-tools
192
+ - `shell` - Interactive shell with PTY support
193
+ - `editor` - File editing (view/create/replace/insert)
194
+ - `file_read` - Multi-file reading with search
195
+ - `file_write` - Write content to files
196
+ - `calculator` - SymPy-powered math operations
197
+ - `image_reader` - Read images for Converse API
198
+ - `use_agent` - Nested agent with different model
199
+ - `load_tool` - Load custom tools at runtime
200
+ - `environment` - Environment variable management
201
+ - `mcp_client` - Connect to external MCP servers
202
+ - `retrieve` - Bedrock Knowledge Base retrieval
203
+
204
+ ### strands-fun-tools (macOS)
205
+ - `listen` - Background speech transcription with Whisper
206
+ - `cursor` - Mouse & keyboard control
207
+ - `clipboard` - Clipboard monitoring & control
208
+ - `screen_reader` - OCR & UI element detection
209
+ - `yolo_vision` - Object detection with YOLO
210
+
211
+ ### Hot-Reload Tools
212
+ - Custom tools in `./tools/*.py` load instantly
213
+ - Agent code changes trigger auto-restart
214
+
215
+ </details>
216
+
217
+ ---
218
+
219
+ ## Hot-Reload Example
220
+
221
+ ```python
222
+ # ./tools/weather.py
223
+ from strands import tool
224
+ import requests
225
+
226
+ @tool
227
+ def weather(city: str) -> str:
228
+ """Get weather for a city."""
229
+ r = requests.get(f"https://wttr.in/{city}?format=%C+%t")
230
+ return r.text
231
+ ```
232
+
233
+ **Save → use instantly:**
234
+ ```bash
235
+ 🦆 weather(city="Tokyo")
236
+ # Clear sky +15°C
237
+ ```
238
+
239
+ No restart. No configuration. Just works.
240
+
241
+ ---
242
+
243
+ ## Access Methods
244
+
245
+ | Protocol | Endpoint | Test Command |
246
+ |----------|----------|--------------|
247
+ | CLI | Terminal | `devduck "query"` |
248
+ | Python | Import | `from devduck import devduck` |
249
+ | TCP | `localhost:9999` | `nc localhost 9999` |
250
+ | WebSocket | `ws://localhost:8080` | `wscat -c ws://localhost:8080` |
251
+ | MCP | `http://localhost:8000/mcp` | Add to Claude Desktop config |
252
+ | IPC | `/tmp/devduck_main.sock` | `nc -U /tmp/devduck_main.sock` |
253
+
254
+ **Custom ports:** `export DEVDUCK_TCP_PORT=9000`
255
+
256
+ ---
257
+
258
+ ## Configuration
259
+
260
+ | Variable | Default | Options |
261
+ |----------|---------|---------|
262
+ | `MODEL_PROVIDER` | Auto-detect | `bedrock`, `anthropic`, `github`, `mlx`, `ollama` |
263
+ | `STRANDS_MODEL_ID` | Auto | Model name (e.g., `qwen3:1.7b`, `claude-sonnet-4`) |
264
+ | `DEVDUCK_TOOLS` | All | `pkg:tool1,tool2:pkg2:tool3` |
265
+ | `DEVDUCK_KNOWLEDGE_BASE_ID` | - | Bedrock KB ID for auto-RAG |
266
+ | `DEVDUCK_TCP_PORT` | `9999` | TCP server port |
267
+ | `DEVDUCK_ENABLE_TCP` | `true` | Enable/disable TCP |
268
+
269
+ **Minimal config (shell + editor only):**
270
+ ```bash
271
+ export DEVDUCK_TOOLS="strands_tools:shell,editor"
272
+ devduck
273
+ ```
274
+
275
+ ---
276
+
277
+
278
+ ## MCP Integration
279
+
280
+ **Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`):
281
+ ```json
282
+ {
283
+ "mcpServers": {
284
+ "devduck": {
285
+ "command": "uvx",
286
+ "args": ["devduck", "--mcp"]
287
+ }
288
+ }
289
+ }
290
+ ```
291
+
292
+ Restart Claude → DevDuck tools appear automatically.
293
+
294
+ ---
295
+
296
+ ## Troubleshooting
297
+
298
+ **Ollama model not found:**
299
+ ```bash
300
+ # DevDuck auto-pulls models, but if it fails:
301
+ ollama pull qwen3:1.7b
302
+ ```
303
+
304
+ **Port already in use:**
305
+ ```bash
306
+ # Change ports
307
+ export DEVDUCK_TCP_PORT=9000
308
+ export DEVDUCK_WS_PORT=8001
309
+ devduck
310
+ ```
311
+
312
+ **Hot-reload not working:**
313
+ ```bash
314
+ # Ensure tools directory exists
315
+ mkdir -p ./tools
316
+
317
+ # Check file watcher logs
318
+ devduck
319
+ 🦆 view_logs(action="search", pattern="watcher")
320
+ ```
321
+
322
+ **Memory/performance issues:**
323
+ ```bash
324
+ # Use lighter model
325
+ export STRANDS_MODEL_ID="qwen3:0.5b"
326
+
327
+ # Reduce context
328
+ export DEVDUCK_LOG_LINE_COUNT=20
329
+ export DEVDUCK_LAST_MESSAGE_COUNT=50
330
+ ```
331
+
332
+ **Ambient overlay not starting:**
333
+ ```bash
334
+ # Make sure tkinter is installed
335
+ python3 -c "import tkinter"
336
+
337
+ # Install tkinter if missing
338
+ brew install python-tk@3.13 # macOS
339
+ sudo apt-get install python3-tk # Ubuntu/Debian
340
+ sudo dnf install python3-tkinter # Fedora
341
+ ```
342
+
343
+ **Tray app not starting (macOS):**
344
+ ```bash
345
+ # Install rumps
346
+ pip install rumps
347
+
348
+ # Or reinstall devduck
349
+ pip install -e .
350
+ ```
351
+
352
+ **View logs:** `devduck` → `🦆 view_logs()`
353
+
354
+ ---
355
+
356
+ ## GitHub Actions
357
+
358
+ **Run DevDuck in CI/CD pipelines:**
359
+
360
+ ```yaml
361
+ name: AI Code Assistant
362
+ on:
363
+ issues:
364
+ types: [opened, edited]
365
+ pull_request:
366
+ types: [opened, edited, synchronize]
367
+
368
+ jobs:
369
+ devduck:
370
+ runs-on: ubuntu-latest
371
+ permissions:
372
+ contents: read
373
+ issues: write
374
+ pull-requests: write
375
+ steps:
376
+ - uses: cagataycali/devduck@main
377
+ with:
378
+ task: "Analyze and help with this issue or PR"
379
+ provider: "github"
380
+ model: "gpt-4o"
381
+ tools: "shell,file_read,file_write,use_github,calculator"
382
+ env:
383
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
384
+ ```
385
+
386
+ **Sub-agent workflows:**
387
+ ```python
388
+ devduck("Create a sub-agent to analyze test coverage")
389
+ ```
390
+
391
+ ---
392
+
393
+ ## Resources
394
+
395
+ - **Strands SDK:** [github.com/strands-agents/sdk-python](https://github.com/strands-agents/sdk-python)
396
+ - **Documentation:** [strandsagents.com](https://strandsagents.com)
397
+ - **Web UI:** [cagataycali.github.io/devduck](http://cagataycali.github.io/devduck)
398
+ - **Homebrew:** [github.com/cagataycali/homebrew-devduck](https://github.com/cagataycali/homebrew-devduck)
399
+
400
+ ---
401
+
402
+ ## Citation
403
+
404
+ ```bibtex
405
+ @software{devduck2025,
406
+ author = {Cagatay Cali},
407
+ title = {DevDuck: Self-Modifying AI Agent with Hot-Reload and Multi-Protocol Servers},
408
+ year = {2025},
409
+ url = {https://github.com/cagataycali/devduck}
410
+ }
411
+ ```
412
+
413
+ ---
414
+
415
+ **Apache 2.0** | Built with [Strands Agents](https://strandsagents.com) | [@cagataycali](https://github.com/cagataycali)
@@ -0,0 +1,29 @@
1
+ devduck/__init__.py,sha256=wtpaq3t6k1z0AT5RyW3-O9evSNV7Taaxw6xyiup022k,38867
2
+ devduck/__main__.py,sha256=aeF2RR4k7lzSR2X1QKV9XQPCKhtsH0JYUv2etBBqmL0,145
3
+ devduck/_version.py,sha256=LGYtjQ6cyPZC_N0AovMIeSYYDK21050nm3HYgDanQBM,704
4
+ devduck/agentcore_handler.py,sha256=0DKJTTjoH9P8a70G0f5dOIIwy6bjqaN46voAWaSOpDY,2221
5
+ devduck/test_redduck.py,sha256=nqRchR7d54jWGx7JN5tji2ZV4Ek4L9s-P7hp0mKjA0Y,1773
6
+ devduck/tools/__init__.py,sha256=vmfaz6785obybPDzJhdgO1e0Ty-bBtk5jSb0MskyyWQ,1276
7
+ devduck/tools/_ambient_input.py,sha256=3lBgLO81BvkxjgTrQc-EuxNLXmO1oPUt2Ysg1jR4Fsk,13897
8
+ devduck/tools/_tray_app.py,sha256=E4rtJcegRsBs_FdQVGdA-0Ax7uxVb6AbuyqjwCArHj0,19405
9
+ devduck/tools/agentcore_agents.py,sha256=fiDNhl7R2tVbp1mEOySJTfGXwap5q3COenYOjiJDE_g,6488
10
+ devduck/tools/agentcore_config.py,sha256=KbX6XS7Wzh9cs1AWxJciDGtF97lAI1lfKliiSAinCQg,14802
11
+ devduck/tools/agentcore_invoke.py,sha256=SMKqVAig_cZEBL-W5gfumUpPFIHC9CSRSY9BJbnx6wY,17449
12
+ devduck/tools/agentcore_logs.py,sha256=A3YQIoRErJtvzeaMSPNqOLX1BH-vYTbYKs1NXoCnC5E,10222
13
+ devduck/tools/ambient.py,sha256=HB1ZhfeOdOaMU0xe4e44VNUT_-DQ5SY7sl3r4r-4X44,4806
14
+ devduck/tools/create_subagent.py,sha256=UzRz9BmU4PbTveZROEpZ311aH-u-i6x89gttu-CniAE,24687
15
+ devduck/tools/install_tools.py,sha256=wm_67b9IfY-2wRuWgxuEKhaSIV5vNfbGmZL3G9dGi2A,10348
16
+ devduck/tools/ipc.py,sha256=4YARnIwAkvUwTKUG534hfiZjEL4Km63ykJ_6DnJ72Dc,18478
17
+ devduck/tools/mcp_server.py,sha256=Ybp0PcJKW2TOvghsRL-i8Guqc9WokPwOD2bhVgzoj6Q,21490
18
+ devduck/tools/store_in_kb.py,sha256=-JM-oRQKR3FBubKHFHmXRnZSvi9dVgHxG0lismMgG2k,6861
19
+ devduck/tools/system_prompt.py,sha256=waAdmvRhyulorw_tLqpqUJN_AahuaeF2rXqjMqN7IRY,16905
20
+ devduck/tools/tcp.py,sha256=f74xWa9pgBgQ3icr-KsRVM8GEEs6Wi9B4eP_ZYlKxhQ,21726
21
+ devduck/tools/tray.py,sha256=hlX7LSsS1sOavVDulcsyydmKQ0jCa4Ong3kzsBYMlQY,7531
22
+ devduck/tools/use_github.py,sha256=nr3JSGk48mKUobpgW__2gu6lFyUj93a1XRs3I6vH8W4,13682
23
+ devduck/tools/websocket.py,sha256=lRJZt813iHorVr5UI66Lq-lmaFuLYAfpodeV2gtda7k,16635
24
+ devduck-0.5.2.dist-info/licenses/LICENSE,sha256=UANcoWwfVeuM9597WUkjEQbzqIUH0bJoE9Tpwgj_LvU,11345
25
+ devduck-0.5.2.dist-info/METADATA,sha256=HuOhzxU9h9IZUsZkf-Yux4HAyMw2Rob5OOz18ZGN1D8,12310
26
+ devduck-0.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
+ devduck-0.5.2.dist-info/entry_points.txt,sha256=BAMQaIg_BLZQOTk12bT7hy1dE9oGPLt-_dTbI4cnBnQ,40
28
+ devduck-0.5.2.dist-info/top_level.txt,sha256=ySXWlVronp8xHYfQ_Hdfr463e0EnbWuqyuxs94EU7yk,8
29
+ devduck-0.5.2.dist-info/RECORD,,