diff --git a/src/google/adk/cli/adk_web_server.py b/src/google/adk/cli/adk_web_server.py index 86a2cf2495..f9520fff7c 100644 --- a/src/google/adk/cli/adk_web_server.py +++ b/src/google/adk/cli/adk_web_server.py @@ -997,7 +997,7 @@ async def version() -> dict[str, str]: @app.get("/list-apps") async def list_apps( detailed: bool = Query( - default=False, description="Return detailed app information" + default=True, description="Return detailed app information" ) ) -> list[str] | ListAppsResponse: if detailed: diff --git a/src/google/adk/cli/utils/agent_loader.py b/src/google/adk/cli/utils/agent_loader.py index a7bbcbc2a6..5c3ad66073 100644 --- a/src/google/adk/cli/utils/agent_loader.py +++ b/src/google/adk/cli/utils/agent_loader.py @@ -364,13 +364,21 @@ def load_agent(self, agent_name: str) -> Union[BaseAgent, App]: def list_agents(self) -> list[str]: """Lists all agents available in the agent loader (sorted alphabetically).""" base_path = Path.cwd() / self.agents_dir - agent_names = [ - x - for x in os.listdir(base_path) - if os.path.isdir(os.path.join(base_path, x)) - and not x.startswith(".") - and x != "__pycache__" - ] + if not base_path.exists(): + return [] + agent_names = [] + for x in os.listdir(base_path): + if x.startswith(".") or x == "__pycache__": + continue + agent_dir = base_path / x + if not agent_dir.is_dir(): + continue + if ( + (agent_dir / "root_agent.yaml").exists() + or (agent_dir / "agent.py").exists() + or (agent_dir / "__init__.py").exists() + ): + agent_names.append(x) agent_names.sort() return agent_names diff --git a/tests/unittests/cli/test_fast_api.py b/tests/unittests/cli/test_fast_api.py index 3e63f31222..538679621f 100755 --- a/tests/unittests/cli/test_fast_api.py +++ b/tests/unittests/cli/test_fast_api.py @@ -897,7 +897,7 @@ def test_app_with_a2a( def test_list_apps(test_app): """Test listing available applications.""" # Use the TestClient to make a request - response = test_app.get("/list-apps") + response = test_app.get("/list-apps?detailed=false") # Verify the response assert response.status_code == 200 @@ -908,7 +908,7 @@ def test_list_apps(test_app): def test_list_apps_detailed(test_app): """Test listing available applications with detailed metadata.""" - response = test_app.get("/list-apps?detailed=true") + response = test_app.get("/list-apps") assert response.status_code == 200 data = response.json() diff --git a/tests/unittests/cli/utils/test_agent_loader.py b/tests/unittests/cli/utils/test_agent_loader.py index abc5718adb..1eb12b7ba7 100644 --- a/tests/unittests/cli/utils/test_agent_loader.py +++ b/tests/unittests/cli/utils/test_agent_loader.py @@ -1006,3 +1006,39 @@ def test_validate_agent_name_rejects_nonexistent_agent(self): # 'subprocess' is a valid identifier but shouldn't be importable as an agent with pytest.raises(ValueError, match="Agent not found"): loader.load_agent("subprocess") + + def test_list_agents_ignores_non_agent_directories(self): + """Test that list_agents only returns directories containing valid agent files.""" + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + + # Create valid agent 1 + agent1_dir = temp_path / "valid_agent1" + agent1_dir.mkdir() + (agent1_dir / "__init__.py").write_text("root_agent = None") + + # Create valid agent 2 + agent2_dir = temp_path / "valid_agent2" + agent2_dir.mkdir() + (agent2_dir / "agent.py").write_text("root_agent = None") + + # Create valid agent 3 + agent3_dir = temp_path / "valid_agent3" + agent3_dir.mkdir() + (agent3_dir / "root_agent.yaml").write_text("name: test") + + # Create invalid directories + (temp_path / "utils").mkdir() + (temp_path / "data").mkdir() + (temp_path / "tmp").mkdir() + + loader = AgentLoader(str(temp_path)) + agent_names = loader.list_agents() + + assert len(agent_names) == 3 + assert "valid_agent1" in agent_names + assert "valid_agent2" in agent_names + assert "valid_agent3" in agent_names + assert "utils" not in agent_names + assert "data" not in agent_names +