mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-02 03:55:55 +00:00
feat(toolmgr): add get_tool_by_name for unified tool lookup
Add unified tool lookup method that searches both plugin and MCP loaders. Also add _get_tool method to MCPLoader for consistency with PluginToolLoader.
This commit is contained in:
@@ -527,6 +527,47 @@ class RuntimeConnectionHandler(handler.Handler):
|
||||
message=f'Failed to execute tool {tool_name}: {e}',
|
||||
)
|
||||
|
||||
@self.action(PluginToRuntimeAction.GET_TOOL_DETAIL)
|
||||
async def get_tool_detail(data: dict[str, Any]) -> handler.ActionResponse:
|
||||
"""Get tool detail for LLM function calling.
|
||||
|
||||
For AgentRunner calls: requires run_id and validates tool_name against session.resources.tools.
|
||||
For regular plugin calls: no run_id, unrestricted access (backward compatibility).
|
||||
|
||||
Returns tool manifest including name, description, and parameters schema.
|
||||
"""
|
||||
tool_name = data['tool_name']
|
||||
run_id = data.get('run_id') # Optional: present for AgentRunner calls
|
||||
|
||||
# Permission validation for AgentRunner calls
|
||||
if run_id:
|
||||
session, error = await _validate_run_authorization(
|
||||
run_id, 'tool', tool_name, self.ap
|
||||
)
|
||||
if error:
|
||||
return error
|
||||
|
||||
try:
|
||||
tool = self.ap.tool_mgr.get_tool_by_name(tool_name)
|
||||
if tool is None:
|
||||
return handler.ActionResponse.error(
|
||||
message=f'Tool {tool_name} not found',
|
||||
)
|
||||
|
||||
# Build tool detail for LLM function calling
|
||||
tool_detail = {
|
||||
'name': tool.name,
|
||||
'description': tool.description or '',
|
||||
'parameters': tool.parameters or {},
|
||||
}
|
||||
|
||||
return handler.ActionResponse.success(data=tool_detail)
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
return handler.ActionResponse.error(
|
||||
message=f'Failed to get tool detail for {tool_name}: {e}',
|
||||
)
|
||||
|
||||
# ================= Binary Storage Handlers =================
|
||||
# Permission validation:
|
||||
# - For AgentRunner calls (with run_id): validates storage permission via session_registry
|
||||
|
||||
@@ -384,6 +384,21 @@ class MCPLoader(loader.ToolLoader):
|
||||
return True
|
||||
return False
|
||||
|
||||
async def _get_tool(self, name: str) -> resource_tool.LLMTool | None:
|
||||
"""Get tool by name.
|
||||
|
||||
Args:
|
||||
name: Tool name to find
|
||||
|
||||
Returns:
|
||||
LLMTool if found, None otherwise
|
||||
"""
|
||||
for session in self.sessions.values():
|
||||
for function in session.get_tools():
|
||||
if function.name == name:
|
||||
return function
|
||||
return None
|
||||
|
||||
async def invoke_tool(self, name: str, parameters: dict, query: pipeline_query.Query) -> typing.Any:
|
||||
"""执行工具调用"""
|
||||
for session in self.sessions.values():
|
||||
|
||||
@@ -40,6 +40,27 @@ class ToolManager:
|
||||
|
||||
return all_functions
|
||||
|
||||
async def get_tool_by_name(self, name: str) -> resource_tool.LLMTool | None:
|
||||
"""Get tool by name from plugin or MCP loaders.
|
||||
|
||||
Args:
|
||||
name: Tool name (format: plugin_author/plugin_name/tool_name or mcp_server/tool_name)
|
||||
|
||||
Returns:
|
||||
LLMTool if found, None otherwise
|
||||
"""
|
||||
# Try plugin loader first
|
||||
tool = await self.plugin_tool_loader._get_tool(name)
|
||||
if tool:
|
||||
return tool
|
||||
|
||||
# Try MCP loader
|
||||
tool = await self.mcp_tool_loader._get_tool(name)
|
||||
if tool:
|
||||
return tool
|
||||
|
||||
return None
|
||||
|
||||
async def generate_tools_for_openai(self, use_funcs: list[resource_tool.LLMTool]) -> list:
|
||||
"""生成函数列表"""
|
||||
tools = []
|
||||
|
||||
Reference in New Issue
Block a user