devduck 1.1.7__tar.gz → 1.3.0__tar.gz
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-1.3.0/.github/workflows/auto-release.yml +85 -0
- {devduck-1.1.7 → devduck-1.3.0}/PKG-INFO +2 -1
- {devduck-1.1.7 → devduck-1.3.0}/devduck/__init__.py +83 -6
- {devduck-1.1.7 → devduck-1.3.0}/devduck/_version.py +3 -3
- {devduck-1.1.7 → devduck-1.3.0}/devduck/agentcore_handler.py +1 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/__init__.py +2 -2
- devduck-1.3.0/devduck/tools/zenoh_peer.py +1163 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck.egg-info/PKG-INFO +2 -1
- {devduck-1.1.7 → devduck-1.3.0}/devduck.egg-info/SOURCES.txt +2 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck.egg-info/requires.txt +1 -0
- {devduck-1.1.7 → devduck-1.3.0}/pyproject.toml +1 -0
- {devduck-1.1.7 → devduck-1.3.0}/.github/workflows/agent.yml +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/.gitignore +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/LICENSE +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/MANIFEST.in +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/README.md +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/action.yml +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/agent_runner.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/__main__.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/test_redduck.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/_ambient_input.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/_tray_app.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/agentcore_agents.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/agentcore_config.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/agentcore_invoke.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/agentcore_logs.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/ambient.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/create_subagent.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/fetch_github_tool.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/install_tools.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/ipc.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/mcp_server.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/scraper.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/speech_to_speech.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/state_manager.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/store_in_kb.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/system_prompt.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/tcp.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/tray.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/use_github.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck/tools/websocket.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck.egg-info/dependency_links.txt +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck.egg-info/entry_points.txt +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/devduck.egg-info/top_level.txt +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/docs/index.html +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/docs/mac-os-tray.jpg +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/requirements.txt +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/setup-aws-oidc.sh +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/setup.cfg +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/test.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/tools/__init__.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/tools/fetch_github_tool.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/tools/gist.py +0 -0
- {devduck-1.1.7 → devduck-1.3.0}/tools/github_tools.py +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
name: Auto Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*.*.*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
packages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
auto-release:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout code
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
with:
|
|
21
|
+
fetch-depth: 0
|
|
22
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
23
|
+
|
|
24
|
+
- name: Set up Python
|
|
25
|
+
uses: actions/setup-python@v4
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.11"
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: |
|
|
31
|
+
python -m pip install --upgrade pip
|
|
32
|
+
pip install build twine
|
|
33
|
+
|
|
34
|
+
- name: Extract version from tag
|
|
35
|
+
id: get_version
|
|
36
|
+
run: |
|
|
37
|
+
VERSION=${GITHUB_REF#refs/tags/v}
|
|
38
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
39
|
+
echo "Version: $VERSION"
|
|
40
|
+
|
|
41
|
+
- name: Build package
|
|
42
|
+
run: |
|
|
43
|
+
python -m build
|
|
44
|
+
|
|
45
|
+
- name: Publish to PyPI
|
|
46
|
+
env:
|
|
47
|
+
TWINE_USERNAME: __token__
|
|
48
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
49
|
+
run: |
|
|
50
|
+
twine upload dist/*
|
|
51
|
+
|
|
52
|
+
- name: Create GitHub Release
|
|
53
|
+
uses: actions/create-release@v1
|
|
54
|
+
env:
|
|
55
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
56
|
+
with:
|
|
57
|
+
tag_name: ${{ github.ref }}
|
|
58
|
+
release_name: devduck v${{ steps.get_version.outputs.version }}
|
|
59
|
+
body: |
|
|
60
|
+
## 🦆 devduck v${{ steps.get_version.outputs.version }}
|
|
61
|
+
|
|
62
|
+
### 📦 Installation
|
|
63
|
+
```bash
|
|
64
|
+
pip install devduck==${{ steps.get_version.outputs.version }}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 🔄 Upgrade
|
|
68
|
+
```bash
|
|
69
|
+
pip install --upgrade devduck
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 📋 Changes
|
|
73
|
+
This release includes the latest changes tagged as v${{ steps.get_version.outputs.version }}.
|
|
74
|
+
|
|
75
|
+
**Full Changelog**: https://github.com/cagataycali/devduck/releases
|
|
76
|
+
draft: false
|
|
77
|
+
prerelease: false
|
|
78
|
+
|
|
79
|
+
- name: Summary
|
|
80
|
+
run: |
|
|
81
|
+
echo "## 🎉 Release Summary" >> $GITHUB_STEP_SUMMARY
|
|
82
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
83
|
+
echo "- **Version:** v${{ steps.get_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
|
84
|
+
echo "- **PyPI:** https://pypi.org/project/devduck/${{ steps.get_version.outputs.version }}/" >> $GITHUB_STEP_SUMMARY
|
|
85
|
+
echo "- **GitHub Release:** https://github.com/cagataycali/devduck/releases/tag/v${{ steps.get_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devduck
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: 🦆 Self-adapting agent - one file.
|
|
5
5
|
Author-email: Cagatay Cali <cagataycali@icloud.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -42,6 +42,7 @@ Requires-Dist: bedrock-agentcore-starter-toolkit
|
|
|
42
42
|
Requires-Dist: bedrock-agentcore
|
|
43
43
|
Requires-Dist: rumps; sys_platform == "darwin"
|
|
44
44
|
Requires-Dist: strands-mlx; sys_platform == "darwin"
|
|
45
|
+
Requires-Dist: eclipse-zenoh
|
|
45
46
|
Provides-Extra: speech
|
|
46
47
|
Requires-Dist: strands-agents[bidi-all]; extra == "speech"
|
|
47
48
|
Dynamic: license-file
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
🦆 devduck - extreme minimalist self-adapting agent
|
|
4
4
|
one file. self-healing. runtime dependencies. adaptive.
|
|
5
5
|
"""
|
|
6
|
+
|
|
6
7
|
import os
|
|
7
8
|
import sys
|
|
8
9
|
import subprocess
|
|
@@ -457,6 +458,47 @@ def parse_history_line(line, history_type):
|
|
|
457
458
|
return None
|
|
458
459
|
|
|
459
460
|
|
|
461
|
+
def get_zenoh_peers_context():
|
|
462
|
+
"""Get current zenoh peers for dynamic context injection."""
|
|
463
|
+
try:
|
|
464
|
+
from devduck.tools.zenoh_peer import ZENOH_STATE
|
|
465
|
+
import time
|
|
466
|
+
|
|
467
|
+
logger.debug(
|
|
468
|
+
f"Zenoh context check - running: {ZENOH_STATE.get('running')}, peers: {ZENOH_STATE.get('peers')}"
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
if not ZENOH_STATE.get("running"):
|
|
472
|
+
logger.debug("Zenoh not running, returning empty context")
|
|
473
|
+
return ""
|
|
474
|
+
|
|
475
|
+
instance_id = ZENOH_STATE.get("instance_id", "unknown")
|
|
476
|
+
peers = ZENOH_STATE.get("peers", {})
|
|
477
|
+
|
|
478
|
+
context = f"\n\n## Zenoh Network Status:\n"
|
|
479
|
+
context += f"- **My Instance ID**: {instance_id}\n"
|
|
480
|
+
context += f"- **Connected Peers**: {len(peers)}\n"
|
|
481
|
+
|
|
482
|
+
if peers:
|
|
483
|
+
context += "\n### Active Peers:\n"
|
|
484
|
+
for peer_id, info in peers.items():
|
|
485
|
+
age = time.time() - info.get("last_seen", 0)
|
|
486
|
+
hostname = info.get("hostname", "unknown")
|
|
487
|
+
model = info.get("model", "unknown")
|
|
488
|
+
context += f"- `{peer_id}` ({hostname}) - model: {model}, seen {age:.0f}s ago\n"
|
|
489
|
+
context += "\n**Use**: `zenoh_peer(action='broadcast', message='...')` to send to all, or `zenoh_peer(action='send', peer_id='...', message='...')` for specific peer\n"
|
|
490
|
+
else:
|
|
491
|
+
context += "\n*No peers discovered yet. Start another DevDuck instance with zenoh enabled.*\n"
|
|
492
|
+
|
|
493
|
+
return context
|
|
494
|
+
except ImportError as e:
|
|
495
|
+
logger.debug(f"Zenoh context ImportError: {e}")
|
|
496
|
+
return ""
|
|
497
|
+
except Exception as e:
|
|
498
|
+
logger.debug(f"Could not get zenoh peers context: {e}")
|
|
499
|
+
return ""
|
|
500
|
+
|
|
501
|
+
|
|
460
502
|
def get_recent_logs():
|
|
461
503
|
"""Get the last N lines from the log file for context."""
|
|
462
504
|
try:
|
|
@@ -626,6 +668,10 @@ class DevDuck:
|
|
|
626
668
|
"enabled": os.getenv("DEVDUCK_ENABLE_IPC", "false").lower()
|
|
627
669
|
== "true",
|
|
628
670
|
},
|
|
671
|
+
"zenoh_peer": {
|
|
672
|
+
"enabled": os.getenv("DEVDUCK_ENABLE_ZENOH", "true").lower()
|
|
673
|
+
== "true",
|
|
674
|
+
},
|
|
629
675
|
}
|
|
630
676
|
|
|
631
677
|
# Show server configuration status
|
|
@@ -672,6 +718,7 @@ class DevDuck:
|
|
|
672
718
|
# - use_github: https://github.com/cagataycali/devduck/blob/main/devduck/tools/use_github.py
|
|
673
719
|
# - speech_to_speech: https://github.com/cagataycali/devduck/blob/main/devduck/tools/speech_to_speech.py
|
|
674
720
|
# - state_manager: https://github.com/cagataycali/devduck/blob/main/devduck/tools/state_manager.py
|
|
721
|
+
# - zenoh_peer: https://github.com/cagataycali/devduck/blob/main/devduck/tools/zenoh_peer.py
|
|
675
722
|
|
|
676
723
|
# 📦 Strands Tools
|
|
677
724
|
# - editor, file_read, file_write, image_reader, load_tool, retrieve
|
|
@@ -691,6 +738,8 @@ class DevDuck:
|
|
|
691
738
|
server_tools_needed.append("mcp_server")
|
|
692
739
|
if servers.get("ipc", {}).get("enabled", False):
|
|
693
740
|
server_tools_needed.append("ipc")
|
|
741
|
+
if servers.get("zenoh_peer", {}).get("enabled", False):
|
|
742
|
+
server_tools_needed.append("zenoh_peer")
|
|
694
743
|
|
|
695
744
|
# Append to default tools if any server tools are needed
|
|
696
745
|
if server_tools_needed:
|
|
@@ -698,9 +747,7 @@ class DevDuck:
|
|
|
698
747
|
default_tools = f"devduck.tools:system_prompt,fetch_github_tool,websocket,{server_tools_str};strands_tools:shell"
|
|
699
748
|
logger.info(f"Auto-added server tools: {server_tools_str}")
|
|
700
749
|
else:
|
|
701
|
-
default_tools =
|
|
702
|
-
"devduck.tools:system_prompt,fetch_github_tool,websocket;strands_tools:shell"
|
|
703
|
-
)
|
|
750
|
+
default_tools = "devduck.tools:system_prompt,fetch_github_tool,websocket;strands_tools:shell"
|
|
704
751
|
|
|
705
752
|
tools_config = os.getenv("DEVDUCK_TOOLS", default_tools)
|
|
706
753
|
logger.info(f"Loading tools from config: {tools_config}")
|
|
@@ -1312,8 +1359,8 @@ When you learn something valuable during conversations:
|
|
|
1312
1359
|
logger.info("Auto-starting servers...")
|
|
1313
1360
|
print("🦆 Auto-starting servers...")
|
|
1314
1361
|
|
|
1315
|
-
# Start servers in order: IPC, TCP, WS, MCP
|
|
1316
|
-
server_order = ["ipc", "tcp", "ws", "mcp"]
|
|
1362
|
+
# Start servers in order: IPC, TCP, WS, MCP, Zenoh
|
|
1363
|
+
server_order = ["ipc", "tcp", "ws", "mcp", "zenoh_peer"]
|
|
1317
1364
|
|
|
1318
1365
|
for server_type in server_order:
|
|
1319
1366
|
if server_type not in self.servers:
|
|
@@ -1436,6 +1483,26 @@ When you learn something valuable during conversations:
|
|
|
1436
1483
|
if result.get("status") == "success":
|
|
1437
1484
|
logger.info(f"✓ IPC server started on {socket_path}")
|
|
1438
1485
|
print(f"🦆 ✓ IPC server: {socket_path}")
|
|
1486
|
+
|
|
1487
|
+
elif server_type == "zenoh_peer":
|
|
1488
|
+
# Zenoh peer-to-peer networking with auto-discovery
|
|
1489
|
+
result = self.agent.tool.zenoh_peer(
|
|
1490
|
+
action="start",
|
|
1491
|
+
agent=self.agent,
|
|
1492
|
+
record_direct_tool_call=False,
|
|
1493
|
+
)
|
|
1494
|
+
|
|
1495
|
+
if result.get("status") == "success":
|
|
1496
|
+
# Extract instance ID from result
|
|
1497
|
+
instance_id = "unknown"
|
|
1498
|
+
for content in result.get("content", []):
|
|
1499
|
+
text = content.get("text", "")
|
|
1500
|
+
if "Instance ID:" in text:
|
|
1501
|
+
instance_id = text.split("Instance ID:")[-1].strip()
|
|
1502
|
+
break
|
|
1503
|
+
logger.info(f"✓ Zenoh started as {instance_id}")
|
|
1504
|
+
print(f"🦆 ✓ Zenoh peer: {instance_id}")
|
|
1505
|
+
|
|
1439
1506
|
# TODO: support custom file path here so we can trigger foreign python function like another file
|
|
1440
1507
|
except Exception as e:
|
|
1441
1508
|
logger.error(f"Failed to start {server_type} server: {e}")
|
|
@@ -1465,8 +1532,18 @@ When you learn something valuable during conversations:
|
|
|
1465
1532
|
except Exception as e:
|
|
1466
1533
|
logger.warning(f"KB retrieval failed: {e}")
|
|
1467
1534
|
|
|
1535
|
+
# 🔗 Inject dynamic zenoh peers context
|
|
1536
|
+
zenoh_context = get_zenoh_peers_context()
|
|
1537
|
+
if zenoh_context:
|
|
1538
|
+
# Prepend dynamic context to query for visibility
|
|
1539
|
+
query_with_context = (
|
|
1540
|
+
f"[Dynamic Context]{zenoh_context}\n\n[User Query]\n{query}"
|
|
1541
|
+
)
|
|
1542
|
+
else:
|
|
1543
|
+
query_with_context = query
|
|
1544
|
+
|
|
1468
1545
|
# Run the agent
|
|
1469
|
-
result = self.agent(
|
|
1546
|
+
result = self.agent(query_with_context)
|
|
1470
1547
|
|
|
1471
1548
|
# 💾 Knowledge Base Storage (AFTER agent runs)
|
|
1472
1549
|
if knowledge_base_id and hasattr(self.agent, "tool"):
|
|
@@ -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 = '1.
|
|
32
|
-
__version_tuple__ = version_tuple = (1,
|
|
31
|
+
__version__ = version = '1.3.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 3, 0)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'gd5f54385b'
|
|
@@ -22,6 +22,7 @@ from .tcp import tcp
|
|
|
22
22
|
from .tray import tray
|
|
23
23
|
from .use_github import use_github
|
|
24
24
|
from .websocket import websocket
|
|
25
|
+
from .zenoh_peer import zenoh_peer
|
|
25
26
|
|
|
26
27
|
# Optional Tools
|
|
27
28
|
try:
|
|
@@ -47,6 +48,7 @@ try:
|
|
|
47
48
|
"tray",
|
|
48
49
|
"use_github",
|
|
49
50
|
"websocket",
|
|
51
|
+
"zenoh_peer",
|
|
50
52
|
]
|
|
51
53
|
except ImportError:
|
|
52
54
|
__all__ = [
|
|
@@ -69,5 +71,3 @@ except ImportError:
|
|
|
69
71
|
"use_github",
|
|
70
72
|
"websocket",
|
|
71
73
|
]
|
|
72
|
-
|
|
73
|
-
|