enh/refac: ability to specify external tool server id

This commit is contained in:
Timothy Jaeryang Baek 2025-08-18 20:38:55 +04:00
parent 8a1f321fd4
commit 8a157578f4
3 changed files with 52 additions and 16 deletions

View file

@ -54,8 +54,8 @@ async def get_tools(request: Request, user=Depends(get_verified_user)):
tools.append( tools.append(
ToolUserResponse( ToolUserResponse(
**{ **{
"id": f"server:{server['idx']}", "id": f"server:{server.get('id')}",
"user_id": f"server:{server['idx']}", "user_id": f"server:{server.get('id')}",
"name": server.get("openapi", {}) "name": server.get("openapi", {})
.get("info", {}) .get("info", {})
.get("title", "Tool Server"), .get("title", "Tool Server"),
@ -65,7 +65,7 @@ async def get_tools(request: Request, user=Depends(get_verified_user)):
.get("description", ""), .get("description", ""),
}, },
"access_control": request.app.state.config.TOOL_SERVER_CONNECTIONS[ "access_control": request.app.state.config.TOOL_SERVER_CONNECTIONS[
server["idx"] server.get("idx", 0)
] ]
.get("config", {}) .get("config", {})
.get("access_control", None), .get("access_control", None),

View file

@ -77,18 +77,22 @@ def get_tools(
tool = Tools.get_tool_by_id(tool_id) tool = Tools.get_tool_by_id(tool_id)
if tool is None: if tool is None:
if tool_id.startswith("server:"): if tool_id.startswith("server:"):
server_idx = int(tool_id.split(":")[1]) server_id = tool_id.split(":")[1]
tool_server_connection = (
request.app.state.config.TOOL_SERVER_CONNECTIONS[server_idx]
)
tool_server_data = None tool_server_data = None
for server in request.app.state.TOOL_SERVERS: for server in request.app.state.TOOL_SERVERS:
if server["idx"] == server_idx: if server["id"] == server_id:
tool_server_data = server tool_server_data = server
break break
assert tool_server_data is not None
specs = tool_server_data.get("specs", [])
assert tool_server_data is not None
tool_server_idx = tool_server_data.get("idx", 0)
tool_server_connection = (
request.app.state.config.TOOL_SERVER_CONNECTIONS[tool_server_idx]
)
specs = tool_server_data.get("specs", [])
for spec in specs: for spec in specs:
function_name = spec["name"] function_name = spec["name"]
@ -506,11 +510,13 @@ async def get_tool_servers_data(
token = server.get("key", "") token = server.get("key", "")
elif auth_type == "session": elif auth_type == "session":
token = session_token token = session_token
server_entries.append((idx, server, full_url, info, token))
id = info.get("id", idx)
server_entries.append((id, idx, server, full_url, info, token))
# Create async tasks to fetch data # Create async tasks to fetch data
tasks = [ tasks = [
get_tool_server_data(token, url) for (_, _, url, _, token) in server_entries get_tool_server_data(token, url) for (_, _, _, url, _, token) in server_entries
] ]
# Execute tasks concurrently # Execute tasks concurrently
@ -518,7 +524,7 @@ async def get_tool_servers_data(
# Build final results with index and server metadata # Build final results with index and server metadata
results = [] results = []
for (idx, server, url, info, _), response in zip(server_entries, responses): for (id, idx, server, url, info, _), response in zip(server_entries, responses):
if isinstance(response, Exception): if isinstance(response, Exception):
log.error(f"Failed to connect to {url} OpenAPI tool server") log.error(f"Failed to connect to {url} OpenAPI tool server")
continue continue
@ -536,6 +542,7 @@ async def get_tool_servers_data(
results.append( results.append(
{ {
"id": str(id),
"idx": idx, "idx": idx,
"url": server.get("url"), "url": server.get("url"),
"openapi": openapi_data, "openapi": openapi_data,

View file

@ -35,6 +35,7 @@
let accessControl = {}; let accessControl = {};
let id = '';
let name = ''; let name = '';
let description = ''; let description = '';
@ -76,6 +77,7 @@
access_control: accessControl access_control: accessControl
}, },
info: { info: {
id,
name, name,
description description
} }
@ -106,6 +108,7 @@
access_control: accessControl access_control: accessControl
}, },
info: { info: {
id: id,
name: name, name: name,
description: description description: description
} }
@ -121,6 +124,7 @@
key = ''; key = '';
auth_type = 'bearer'; auth_type = 'bearer';
id = '';
name = ''; name = '';
description = ''; description = '';
@ -136,6 +140,7 @@
auth_type = connection?.auth_type ?? 'bearer'; auth_type = connection?.auth_type ?? 'bearer';
key = connection?.key ?? ''; key = connection?.key ?? '';
id = connection.info?.id ?? '';
name = connection.info?.name ?? ''; name = connection.info?.name ?? '';
description = connection.info?.description ?? ''; description = connection.info?.description ?? '';
@ -308,10 +313,34 @@
<div class="flex gap-2"> <div class="flex gap-2">
<div class="flex flex-col w-full"> <div class="flex flex-col w-full">
<label <label
for="enter-name" for="enter-id"
class={`mb-0.5 text-xs" ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`} class={`mb-0.5 text-xs ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
>{$i18n.t('Name')}</label >{$i18n.t('ID')}
<span class="text-xs text-gray-200 dark:text-gray-800 ml-0.5"
>{$i18n.t('Optional')}</span
> >
</label>
<div class="flex-1">
<input
id="enter-id"
class={`w-full text-sm bg-transparent ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
type="text"
bind:value={id}
placeholder={$i18n.t('Enter ID')}
autocomplete="off"
/>
</div>
</div>
</div>
<div class="flex gap-2 mt-2">
<div class="flex flex-col w-full">
<label
for="enter-name"
class={`mb-0.5 text-xs ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
>{$i18n.t('Name')}
</label>
<div class="flex-1"> <div class="flex-1">
<input <input