Files
OpenJarvis/tests/tools/test_agent_tools.py
T
Jon Saad-FalconandClaude Opus 4.6 a4c4081ff4 Add desktop distribution pipeline: rolling releases, auto-updates, code signing
- Rewrite .github/workflows/desktop.yml: 2-job pipeline (validate + build-and-release)
  with rolling desktop-latest pre-release on push to main and stable desktop-v* releases
- Add UpdateChecker component: checks for updates on startup + every 30 min,
  background download with progress bar, one-click relaunch
- Configure Tauri updater: endpoints pointing to desktop-latest release, pubkey placeholder
- Add tauri-plugin-process for relaunch support (Cargo.toml, lib.rs, package.json)
- Add macOS Entitlements.plist for notarization (network + file access, no sandbox)
- Add scripts/bump-desktop-version.sh for atomic version bumps across 3 config files
- Add desktop/README.md with dev setup, auto-update architecture, signing docs
- Update .gitignore for desktop/node_modules, dist, target
- Configure macOS minimumSystemVersion, Windows timestampUrl
- Include all Phase 14-21 work: agent hardening, RBAC, taint tracking, workflows,
  skills, knowledge graph, sessions, A2A, MCP templates, WASM sandbox, TUI dashboard,
  production tools, CLI expansion, API expansion, learning productionization,
  Tauri desktop app, and 10 new channels

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 19:14:05 +00:00

253 lines
7.9 KiB
Python

"""Tests for inter-agent lifecycle tools."""
from __future__ import annotations
import json
from openjarvis.tools.agent_tools import (
_SPAWNED_AGENTS,
AgentKillTool,
AgentListTool,
AgentSendTool,
AgentSpawnTool,
)
# ---------------------------------------------------------------------------
# AgentSpawnTool
# ---------------------------------------------------------------------------
class TestAgentSpawnTool:
def setup_method(self):
_SPAWNED_AGENTS.clear()
def test_spec(self):
tool = AgentSpawnTool()
spec = tool.spec
assert spec.name == "agent_spawn"
assert spec.category == "agents"
assert "system:admin" in spec.required_capabilities
assert "agent_type" in spec.parameters["required"]
def test_spawn_creates_agent_entry(self):
tool = AgentSpawnTool()
result = tool.execute(agent_type="simple")
assert result.success
data = json.loads(result.content)
assert data["agent_type"] == "simple"
assert data["status"] == "running"
assert data["agent_id"] in _SPAWNED_AGENTS
def test_spawn_with_custom_id(self):
tool = AgentSpawnTool()
result = tool.execute(agent_type="orchestrator", agent_id="my-agent-1")
assert result.success
data = json.loads(result.content)
assert data["agent_id"] == "my-agent-1"
assert "my-agent-1" in _SPAWNED_AGENTS
def test_spawn_with_query(self):
tool = AgentSpawnTool()
result = tool.execute(agent_type="native_react", query="Hello world")
assert result.success
data = json.loads(result.content)
assert data["initial_query"] == "Hello world"
def test_spawn_with_tools(self):
tool = AgentSpawnTool()
result = tool.execute(
agent_type="orchestrator",
tools="calculator,think",
)
assert result.success
agent_id = json.loads(result.content)["agent_id"]
assert _SPAWNED_AGENTS[agent_id]["tools"] == "calculator,think"
def test_spawn_no_agent_type(self):
tool = AgentSpawnTool()
result = tool.execute()
assert not result.success
assert "agent_type" in result.content.lower()
def test_spawn_auto_generates_id(self):
tool = AgentSpawnTool()
result = tool.execute(agent_type="simple")
data = json.loads(result.content)
assert len(data["agent_id"]) > 0
def test_spawn_records_created_at(self):
tool = AgentSpawnTool()
tool.execute(agent_type="simple", agent_id="ts-test")
entry = _SPAWNED_AGENTS["ts-test"]
assert "created_at" in entry
assert isinstance(entry["created_at"], float)
# ---------------------------------------------------------------------------
# AgentSendTool
# ---------------------------------------------------------------------------
class TestAgentSendTool:
def setup_method(self):
_SPAWNED_AGENTS.clear()
def test_spec(self):
tool = AgentSendTool()
spec = tool.spec
assert spec.name == "agent_send"
assert spec.category == "agents"
assert "system:admin" in spec.required_capabilities
assert "agent_id" in spec.parameters["required"]
assert "message" in spec.parameters["required"]
def test_send_to_nonexistent_agent_fails(self):
tool = AgentSendTool()
result = tool.execute(agent_id="no-such-agent", message="hi")
assert not result.success
assert "not found" in result.content
def test_send_to_valid_agent_succeeds(self):
_SPAWNED_AGENTS["agent-x"] = {
"agent_id": "agent-x",
"agent_type": "simple",
"status": "running",
"created_at": 0.0,
}
tool = AgentSendTool()
result = tool.execute(agent_id="agent-x", message="Hello agent")
assert result.success
data = json.loads(result.content)
assert data["delivered"] is True
assert data["message"] == "Hello agent"
def test_send_no_agent_id(self):
tool = AgentSendTool()
result = tool.execute(message="hi")
assert not result.success
def test_send_no_message(self):
_SPAWNED_AGENTS["agent-y"] = {
"agent_id": "agent-y",
"agent_type": "simple",
"status": "running",
"created_at": 0.0,
}
tool = AgentSendTool()
result = tool.execute(agent_id="agent-y")
assert not result.success
assert "message" in result.content.lower()
# ---------------------------------------------------------------------------
# AgentListTool
# ---------------------------------------------------------------------------
class TestAgentListTool:
def setup_method(self):
_SPAWNED_AGENTS.clear()
def test_spec(self):
tool = AgentListTool()
spec = tool.spec
assert spec.name == "agent_list"
assert spec.category == "agents"
assert "system:admin" in spec.required_capabilities
def test_list_empty(self):
tool = AgentListTool()
result = tool.execute()
assert result.success
assert result.content == "No agents spawned."
def test_list_after_spawn(self):
_SPAWNED_AGENTS["a1"] = {
"agent_id": "a1",
"agent_type": "orchestrator",
"status": "running",
"created_at": 1000.0,
}
_SPAWNED_AGENTS["a2"] = {
"agent_id": "a2",
"agent_type": "native_react",
"status": "stopped",
"created_at": 2000.0,
}
tool = AgentListTool()
result = tool.execute()
assert result.success
data = json.loads(result.content)
assert len(data) == 2
ids = {a["agent_id"] for a in data}
assert ids == {"a1", "a2"}
def test_list_shows_status(self):
_SPAWNED_AGENTS["b1"] = {
"agent_id": "b1",
"agent_type": "simple",
"status": "running",
"created_at": 500.0,
}
tool = AgentListTool()
result = tool.execute()
data = json.loads(result.content)
assert data[0]["status"] == "running"
assert data[0]["agent_type"] == "simple"
# ---------------------------------------------------------------------------
# AgentKillTool
# ---------------------------------------------------------------------------
class TestAgentKillTool:
def setup_method(self):
_SPAWNED_AGENTS.clear()
def test_spec(self):
tool = AgentKillTool()
spec = tool.spec
assert spec.name == "agent_kill"
assert spec.category == "agents"
assert spec.requires_confirmation is True
assert "system:admin" in spec.required_capabilities
assert "agent_id" in spec.parameters["required"]
def test_kill_nonexistent_fails(self):
tool = AgentKillTool()
result = tool.execute(agent_id="ghost")
assert not result.success
assert "not found" in result.content
def test_kill_marks_stopped(self):
_SPAWNED_AGENTS["k1"] = {
"agent_id": "k1",
"agent_type": "simple",
"status": "running",
"created_at": 0.0,
}
tool = AgentKillTool()
result = tool.execute(agent_id="k1")
assert result.success
data = json.loads(result.content)
assert data["status"] == "stopped"
assert _SPAWNED_AGENTS["k1"]["status"] == "stopped"
def test_kill_already_stopped(self):
_SPAWNED_AGENTS["k2"] = {
"agent_id": "k2",
"agent_type": "orchestrator",
"status": "stopped",
"created_at": 0.0,
}
tool = AgentKillTool()
result = tool.execute(agent_id="k2")
assert result.success
assert _SPAWNED_AGENTS["k2"]["status"] == "stopped"
def test_kill_no_agent_id(self):
tool = AgentKillTool()
result = tool.execute()
assert not result.success