agent-dispatch 0.2.1__tar.gz → 0.2.2__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.
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/PKG-INFO +1 -1
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/pyproject.toml +1 -1
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/src/agent_dispatch/__init__.py +1 -1
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/src/agent_dispatch/cli.py +6 -4
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/src/agent_dispatch/server.py +3 -2
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/tests/test_cli.py +34 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/tests/test_server.py +21 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/.github/dependabot.yml +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/.github/workflows/ci.yml +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/.github/workflows/publish.yml +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/.gitignore +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/LICENSE +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/README.md +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/SECURITY.md +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/agents.example.yaml +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/assets/mascot.png +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/src/agent_dispatch/cache.py +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/src/agent_dispatch/config.py +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/src/agent_dispatch/models.py +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/src/agent_dispatch/runner.py +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/tests/__init__.py +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/tests/conftest.py +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/tests/test_cache.py +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/tests/test_config.py +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/tests/test_models.py +0 -0
- {agent_dispatch-0.2.1 → agent_dispatch-0.2.2}/tests/test_runner.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-dispatch
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: MCP server that lets Claude Code agents delegate tasks to agents in other project directories
|
|
5
5
|
Project-URL: Homepage, https://github.com/ginkida/agent-dispatch
|
|
6
6
|
Project-URL: Repository, https://github.com/ginkida/agent-dispatch
|
|
@@ -202,10 +202,12 @@ def list_agents() -> None:
|
|
|
202
202
|
click.echo(f" config: {', '.join(extras)}")
|
|
203
203
|
if agent.permission_mode:
|
|
204
204
|
click.echo(f" permission_mode: {agent.permission_mode}")
|
|
205
|
-
if agent.allowed_tools:
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
205
|
+
if agent.allowed_tools is not None:
|
|
206
|
+
rendered = ", ".join(agent.allowed_tools) if agent.allowed_tools else "(none)"
|
|
207
|
+
click.echo(f" allowed_tools: {rendered}")
|
|
208
|
+
if agent.disallowed_tools is not None:
|
|
209
|
+
rendered = ", ".join(agent.disallowed_tools) if agent.disallowed_tools else "(none)"
|
|
210
|
+
click.echo(f" disallowed_tools: {rendered}")
|
|
209
211
|
click.echo()
|
|
210
212
|
|
|
211
213
|
|
|
@@ -113,9 +113,10 @@ async def list_agents(ctx: Context | None = None) -> str:
|
|
|
113
113
|
}
|
|
114
114
|
if agent.permission_mode:
|
|
115
115
|
entry["permission_mode"] = agent.permission_mode
|
|
116
|
-
|
|
116
|
+
# Include when explicitly set (even []) to distinguish from inheriting defaults
|
|
117
|
+
if agent.allowed_tools is not None:
|
|
117
118
|
entry["allowed_tools"] = agent.allowed_tools
|
|
118
|
-
if agent.disallowed_tools:
|
|
119
|
+
if agent.disallowed_tools is not None:
|
|
119
120
|
entry["disallowed_tools"] = agent.disallowed_tools
|
|
120
121
|
agents.append(entry)
|
|
121
122
|
if ctx:
|
|
@@ -145,6 +145,40 @@ class TestList:
|
|
|
145
145
|
assert "permission_mode: bypassPermissions" in result.output
|
|
146
146
|
assert "allowed_tools: Bash, Read" in result.output
|
|
147
147
|
|
|
148
|
+
def test_list_distinguishes_empty_from_inherit(self, tmp_path: Path):
|
|
149
|
+
"""Explicit allowed_tools=[] should show '(none)' to distinguish from inherit (None)."""
|
|
150
|
+
agent_dir = tmp_path / "proj"
|
|
151
|
+
agent_dir.mkdir()
|
|
152
|
+
# Write config directly with explicit empty list
|
|
153
|
+
import yaml
|
|
154
|
+
from agent_dispatch.config import config_path
|
|
155
|
+
cfg_path = config_path()
|
|
156
|
+
cfg_path.parent.mkdir(parents=True, exist_ok=True)
|
|
157
|
+
yaml.safe_dump({
|
|
158
|
+
"agents": {
|
|
159
|
+
"proj": {
|
|
160
|
+
"directory": str(agent_dir),
|
|
161
|
+
"description": "Test",
|
|
162
|
+
"allowed_tools": [],
|
|
163
|
+
"disallowed_tools": [],
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
}, cfg_path.open("w"))
|
|
167
|
+
|
|
168
|
+
result = runner.invoke(cli, ["list"])
|
|
169
|
+
assert result.exit_code == 0
|
|
170
|
+
assert "allowed_tools: (none)" in result.output
|
|
171
|
+
assert "disallowed_tools: (none)" in result.output
|
|
172
|
+
|
|
173
|
+
def test_list_hides_tools_when_none(self, tmp_path: Path):
|
|
174
|
+
"""allowed_tools=None (the default, meaning 'inherit') should not appear in list."""
|
|
175
|
+
agent_dir = tmp_path / "proj"
|
|
176
|
+
agent_dir.mkdir()
|
|
177
|
+
runner.invoke(cli, ["add", "proj", str(agent_dir), "-d", "Test"])
|
|
178
|
+
result = runner.invoke(cli, ["list"])
|
|
179
|
+
assert "allowed_tools" not in result.output
|
|
180
|
+
assert "disallowed_tools" not in result.output
|
|
181
|
+
|
|
148
182
|
|
|
149
183
|
class TestUpdate:
|
|
150
184
|
def test_update_permission_mode(self, tmp_path: Path):
|
|
@@ -593,6 +593,7 @@ class TestListAgentsPermissions:
|
|
|
593
593
|
|
|
594
594
|
@pytest.mark.asyncio
|
|
595
595
|
async def test_list_omits_empty_permissions(self, tmp_path: Path):
|
|
596
|
+
"""allowed_tools=None (inherit) should NOT appear in response."""
|
|
596
597
|
d = tmp_path / "proj"
|
|
597
598
|
d.mkdir()
|
|
598
599
|
config = DispatchConfig(
|
|
@@ -606,6 +607,26 @@ class TestListAgentsPermissions:
|
|
|
606
607
|
assert "allowed_tools" not in agents[0]
|
|
607
608
|
assert "disallowed_tools" not in agents[0]
|
|
608
609
|
|
|
610
|
+
@pytest.mark.asyncio
|
|
611
|
+
async def test_list_includes_explicit_empty_tools(self, tmp_path: Path):
|
|
612
|
+
"""allowed_tools=[] (explicit empty) SHOULD appear as [] to signal override."""
|
|
613
|
+
d = tmp_path / "proj"
|
|
614
|
+
d.mkdir()
|
|
615
|
+
config = DispatchConfig(
|
|
616
|
+
agents={
|
|
617
|
+
"proj": AgentConfig(
|
|
618
|
+
directory=d, description="test",
|
|
619
|
+
allowed_tools=[], disallowed_tools=[],
|
|
620
|
+
),
|
|
621
|
+
}
|
|
622
|
+
)
|
|
623
|
+
mock_ctx = AsyncMock()
|
|
624
|
+
with patch.object(server, "_get_config", return_value=config):
|
|
625
|
+
raw = await server.list_agents(ctx=mock_ctx)
|
|
626
|
+
agents = json.loads(raw)
|
|
627
|
+
assert agents[0]["allowed_tools"] == []
|
|
628
|
+
assert agents[0]["disallowed_tools"] == []
|
|
629
|
+
|
|
609
630
|
|
|
610
631
|
class TestAddRemoveAgent:
|
|
611
632
|
@pytest.mark.asyncio
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|