From 9a0c077b121608b6c0e686ed95ee21aa0aa7701f Mon Sep 17 00:00:00 2001 From: Anubhav Dhawan Date: Mon, 21 Apr 2025 17:42:14 +0530 Subject: [PATCH] feat: Introduce Tracking of Used Auth and Bound Keys in parse_tool for Client Strictness This commit introduces functionality to the `parse_tool` helper to identify and report which bound and authentication keys are actively used during tool parsing. This is a foundational step towards implementing a more robust and predictable client through a new `strict` mode. The ability to determine used keys will allow the client to: * Provide errors when users supply unnecessary authentication or bound parameters (in non-`strict` mode). * Enforce that all provided authentication and bound parameters are consumed by the loaded tools, ensuring no extraneous or potentially misleading information is present (in `strict` mode). --- packages/toolbox-core/src/toolbox_core/client.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/toolbox-core/src/toolbox_core/client.py b/packages/toolbox-core/src/toolbox_core/client.py index 4d4d9db2..193001c6 100644 --- a/packages/toolbox-core/src/toolbox_core/client.py +++ b/packages/toolbox-core/src/toolbox_core/client.py @@ -65,7 +65,7 @@ def __parse_tool( auth_token_getters: dict[str, Callable[[], str]], all_bound_params: Mapping[str, Union[Callable[[], Any], Any]], client_headers: Mapping[str, Union[Callable, Coroutine, str]], - ) -> ToolboxTool: + ) -> tuple[ToolboxTool, set[str], set[str]]: """Internal helper to create a callable tool from its schema.""" # sort into reg, authn, and bound params params = [] @@ -95,7 +95,13 @@ def __parse_tool( bound_params=types.MappingProxyType(bound_params), client_headers=types.MappingProxyType(client_headers), ) - return tool + + used_bound_keys = set(bound_params.keys()) + used_auth_keys: set[str] = set() + for required_sources in authn_params.values(): + used_auth_keys.update(required_sources) + + return tool, used_auth_keys, used_bound_keys async def __aenter__(self): """ @@ -171,7 +177,7 @@ async def load_tool( if name not in manifest.tools: # TODO: Better exception raise Exception(f"Tool '{name}' not found!") - tool = self.__parse_tool( + tool, _, _ = self.__parse_tool( name, manifest.tools[name], auth_token_getters, @@ -217,7 +223,7 @@ async def load_toolset( tools = [ self.__parse_tool( n, s, auth_token_getters, bound_params, self.__client_headers - ) + )[0] for n, s in manifest.tools.items() ] return tools