Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/google/adk/cli/adk_web_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,17 @@ class ListMetricsInfoResponse(common.BaseModel):
metrics_info: list[MetricInfo]


class AppInfo(common.BaseModel):
name: str
display_name: str
description: str
agent_type: Literal["yaml", "python", "package"]


class ListAppsResponse(common.BaseModel):
apps: list[AppInfo]


def _setup_telemetry(
otel_to_cloud: bool = False,
internal_exporters: Optional[list[SpanProcessor]] = None,
Expand Down Expand Up @@ -702,6 +713,11 @@ async def internal_lifespan(app: FastAPI):
async def list_apps() -> list[str]:
return self.agent_loader.list_agents()

@app.get("/list-apps-detailed")
async def list_apps_detailed() -> ListAppsResponse:
apps_info = self.agent_loader.list_agents_detailed()
return ListAppsResponse(apps=[AppInfo(**app) for app in apps_info])

@app.get("/debug/trace/{event_id}", tags=[TAG_DEBUG])
async def get_trace_dict(event_id: str) -> Any:
event_dict = trace_dict.get(event_id, None)
Expand Down
53 changes: 53 additions & 0 deletions src/google/adk/cli/utils/agent_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import os
from pathlib import Path
import sys
from typing import Any
from typing import Literal
from typing import Optional
from typing import Union

Expand Down Expand Up @@ -321,6 +323,57 @@ def list_agents(self) -> list[str]:
agent_names.sort()
return agent_names

def list_agents_detailed(self) -> list[dict[str, Any]]:
"""Lists all agents with detailed metadata (name, description, type)."""
agent_names = self.list_agents()
apps_info = []

for agent_name in agent_names:
try:
loaded = self.load_agent(agent_name)
if isinstance(loaded, App):
agent = loaded.root_agent
else:
agent = loaded

agent_type = self._determine_agent_type(agent_name)

# Convert underscores to spaces for display_name
agent.name = agent.name.replace("_", " ")

app_info = {
"name": agent_name,
"display_name": agent.name,
"description": agent.description,
"agent_type": agent_type,
}
apps_info.append(app_info)

except Exception as e:
logger.error("Failed to load agent '%s': %s", agent_name, e)
continue

return apps_info

def _determine_agent_type(
self, agent_name: str
) -> Literal["yaml", "python", "package"]:
"""Determine the type of agent based on file structure."""
base_path = Path.cwd() / self.agents_dir / agent_name

if (base_path / "root_agent.yaml").exists():
return "yaml"
elif (base_path / "agent.py").exists():
return "package"
elif (base_path / "__init__.py").exists():
return "package"
else:
module_path = Path.cwd() / self.agents_dir / f"{agent_name}.py"
if module_path.exists():
return "python"

return "package"

def remove_agent_from_cache(self, agent_name: str):
# Clear module cache for the agent and its submodules
keys_to_delete = [
Expand Down
6 changes: 6 additions & 0 deletions src/google/adk/cli/utils/base_agent_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@

from abc import ABC
from abc import abstractmethod
from typing import Any
from typing import Union

from ...agents.base_agent import BaseAgent
from ...apps.app import App



class BaseAgentLoader(ABC):
"""Abstract base class for agent loaders."""

Expand All @@ -34,3 +36,7 @@ def load_agent(self, agent_name: str) -> Union[BaseAgent, App]:
@abstractmethod
def list_agents(self) -> list[str]:
"""Lists all agents available in the agent loader in alphabetical order."""

@abstractmethod
def list_agents_detailed(self) -> list[dict[str, str, str, str]]:
"""Lists all agents with detailed metadata (name, display name, description, type)."""
28 changes: 28 additions & 0 deletions tests/unittests/cli/test_fast_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,14 @@ def load_agent(self, app_name):
def list_agents(self):
return ["test_app"]

def list_agents_detailed(self):
return [{
"name": "test_app",
"display_name": "test_agent",
"description": "A test agent for unit testing",
"agent_type": "python",
}]

return MockAgentLoader(".")


Expand Down Expand Up @@ -550,6 +558,26 @@ def test_list_apps(test_app):
logger.info(f"Listed apps: {data}")


def test_list_apps_detailed(test_app):
"""Test listing available applications with detailed metadata."""
response = test_app.get("/list-apps-detailed")

assert response.status_code == 200
data = response.json()
assert isinstance(data, dict)
assert "apps" in data
assert isinstance(data["apps"], list)

for app in data["apps"]:
assert "name" in app
assert "displayName" in app
assert "description" in app
assert "agentType" in app
assert app["agentType"] in ["yaml", "python", "package"]

logger.info(f"Listed apps: {data}")


def test_create_session_with_id(test_app, test_session_info):
"""Test creating a session with a specific ID."""
new_session_id = "new_session_id"
Expand Down