Skip to content

Commit 4b6a4a3

Browse files
committed
Merge latest develop to fix pipeline failures
2 parents c137ba6 + 546f929 commit 4b6a4a3

File tree

13 files changed

+1143
-132
lines changed

13 files changed

+1143
-132
lines changed

backend/apps/agent_app.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from consts.model import AgentRequest, AgentInfoRequest, AgentIDRequest, ConversationResponse, AgentImportRequest
77
from services.agent_service import get_agent_info_impl, \
88
get_creating_sub_agent_info_impl, update_agent_info_impl, delete_agent_impl, export_agent_impl, import_agent_impl, \
9-
list_all_agent_info_impl, insert_related_agent_impl, run_agent_stream, stop_agent_tasks
9+
list_all_agent_info_impl, insert_related_agent_impl, run_agent_stream, stop_agent_tasks, get_agent_call_relationship_impl
1010
from database.agent_db import delete_related_agent
1111
from utils.auth_utils import get_current_user_info, get_current_user_id
1212

@@ -151,4 +151,17 @@ async def delete_related_agent_api(parent_agent_id: int = Body(...),
151151
_, tenant_id = get_current_user_id(authorization)
152152
return delete_related_agent(parent_agent_id, child_agent_id, tenant_id)
153153
except Exception as e:
154-
raise HTTPException(status_code=500, detail=f"Agent related info error: {str(e)}")
154+
raise HTTPException(status_code=500, detail=f"Agent related info error: {str(e)}")
155+
156+
157+
@router.get("/call_relationship/{agent_id}")
158+
async def get_agent_call_relationship_api(agent_id: int, authorization: Optional[str] = Header(None)):
159+
"""
160+
Get agent call relationship tree including tools and sub-agents
161+
"""
162+
try:
163+
_, tenant_id = get_current_user_id(authorization)
164+
return get_agent_call_relationship_impl(agent_id, tenant_id)
165+
except Exception as e:
166+
logger.error(f"Agent call relationship error: {str(e)}")
167+
raise HTTPException(status_code=500, detail=f"Failed to get agent call relationship: {str(e)}")

backend/services/agent_service.py

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from fastapi.responses import JSONResponse, StreamingResponse
88
from consts.model import AgentRequest
99
from agents.create_agent_info import create_tool_config_list
10-
from consts.model import AgentInfoRequest, ExportAndImportAgentInfo, ExportAndImportDataFormat, ToolInstanceInfoRequest, MCPInfo
10+
from consts.model import AgentInfoRequest, ExportAndImportAgentInfo, ExportAndImportDataFormat, ToolInstanceInfoRequest, ToolSourceEnum, MCPInfo
1111
from database.agent_db import create_agent, query_all_enabled_tool_instances, \
1212
search_blank_sub_agent_by_main_agent_id, \
1313
search_tools_for_sub_agent, search_agent_info_by_agent_id, update_agent, delete_agent_by_id, query_all_tools, \
@@ -283,7 +283,7 @@ async def import_agent_impl(agent_info: ExportAndImportDataFormat, authorization
283283
else:
284284
# Name doesn't exist, use original name
285285
mcp_server_name = mcp_info.mcp_server_name
286-
286+
287287
result = await add_remote_mcp_server_list(
288288
tenant_id=tenant_id,
289289
user_id=user_id,
@@ -532,8 +532,8 @@ async def run_agent_stream(agent_request: AgentRequest, http_request: Request, a
532532
# Save user message only if not in debug mode
533533
if not agent_request.is_debug:
534534
save_messages(
535-
agent_request,
536-
target="user",
535+
agent_request,
536+
target="user",
537537
authorization=authorization
538538
)
539539

@@ -585,3 +585,109 @@ def get_agent_id_by_name(agent_name: str, tenant_id: str) -> int:
585585
except Exception as _:
586586
logger.error(f"Failed to find agent id with '{agent_name}' in tenant {tenant_id}")
587587
raise HTTPException(status_code=404, detail="agent not found")
588+
589+
590+
591+
def get_agent_call_relationship_impl(agent_id: int, tenant_id: str) -> dict:
592+
"""
593+
Get agent call relationship tree including tools and sub-agents
594+
595+
Args:
596+
agent_id (int): agent id
597+
tenant_id (str): tenant id
598+
599+
Returns:
600+
dict: agent call relationship tree structure
601+
"""
602+
# Tool type specification: meets test expectations
603+
_TYPE_MAPPING = {
604+
"mcp": "MCP",
605+
"langchain": "LangChain",
606+
"local": "Local",
607+
}
608+
609+
def _normalize_tool_type(source: str) -> str:
610+
"""Normalize the source from database to the expected display type for testing."""
611+
if not source:
612+
return "UNKNOWN"
613+
s = str(source)
614+
ls = s.lower()
615+
if ls in _TYPE_MAPPING:
616+
return _TYPE_MAPPING[ls]
617+
# Unknown source: capitalize first letter, keep the rest unchanged (unknown_source -> Unknown_source)
618+
return s[:1].upper() + s[1:]
619+
620+
try:
621+
622+
agent_info = search_agent_info_by_agent_id(agent_id, tenant_id)
623+
if not agent_info:
624+
raise ValueError(f"Agent {agent_id} not found")
625+
626+
627+
tool_info = search_tools_for_sub_agent(agent_id=agent_id, tenant_id=tenant_id)
628+
tools = []
629+
for tool in tool_info:
630+
tool_name = tool.get("name") or tool.get("tool_name") or str(tool["tool_id"])
631+
tool_source = tool.get("source", ToolSourceEnum.LOCAL.value)
632+
tool_type = _normalize_tool_type(tool_source)
633+
634+
tools.append({
635+
"tool_id": tool["tool_id"],
636+
"name": tool_name,
637+
"type": tool_type
638+
})
639+
640+
641+
def get_sub_agents_recursive(parent_agent_id: int, depth: int = 0, max_depth: int = 5) -> list:
642+
if depth >= max_depth:
643+
return []
644+
645+
sub_agent_id_list = query_sub_agents_id_list(main_agent_id=parent_agent_id, tenant_id=tenant_id)
646+
sub_agents = []
647+
648+
for sub_agent_id in sub_agent_id_list:
649+
try:
650+
sub_agent_info = search_agent_info_by_agent_id(sub_agent_id, tenant_id)
651+
if sub_agent_info:
652+
653+
sub_tool_info = search_tools_for_sub_agent(agent_id=sub_agent_id, tenant_id=tenant_id)
654+
sub_tools = []
655+
for tool in sub_tool_info:
656+
tool_name = tool.get("name") or tool.get("tool_name") or str(tool["tool_id"])
657+
tool_source = tool.get("source", ToolSourceEnum.LOCAL.value)
658+
tool_type = _normalize_tool_type(tool_source)
659+
660+
sub_tools.append({
661+
"tool_id": tool["tool_id"],
662+
"name": tool_name,
663+
"type": tool_type
664+
})
665+
666+
667+
deeper_sub_agents = get_sub_agents_recursive(sub_agent_id, depth + 1, max_depth)
668+
669+
sub_agents.append({
670+
"agent_id": str(sub_agent_id),
671+
"name": sub_agent_info.get("display_name") or sub_agent_info.get("name", f"Agent {sub_agent_id}"),
672+
"tools": sub_tools,
673+
"sub_agents": deeper_sub_agents,
674+
"depth": depth + 1
675+
})
676+
except Exception as e:
677+
logger.warning(f"Failed to get sub-agent {sub_agent_id} info: {str(e)}")
678+
continue
679+
680+
return sub_agents
681+
682+
sub_agents = get_sub_agents_recursive(agent_id)
683+
684+
return {
685+
"agent_id": str(agent_id),
686+
"name": agent_info.get("display_name") or agent_info.get("name", f"Agent {agent_id}"),
687+
"tools": tools,
688+
"sub_agents": sub_agents
689+
}
690+
691+
except Exception as e:
692+
logger.exception(f"Failed to get agent call relationship for agent {agent_id}: {str(e)}")
693+
raise ValueError(f"Failed to get agent call relationship: {str(e)}")

0 commit comments

Comments
 (0)