From 59b6267b2f3f5d971c10eeaaf9c0e7e82f10cf02 Mon Sep 17 00:00:00 2001 From: Olcan Date: Mon, 2 Jun 2025 13:41:49 -0700 Subject: [PATCH] allow toolDiscoveryCommand to return function declarations with or without a tool wrapper; fully document both toolDiscoveryCommand and toolCallCommand with examples and pointers to API docs (#696) --- docs/cli/configuration.md | 40 +++++++++++++++++++++--- packages/core/src/tools/tool-registry.ts | 10 ++++-- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/docs/cli/configuration.md b/docs/cli/configuration.md index 7b404c69..14e677c9 100644 --- a/docs/cli/configuration.md +++ b/docs/cli/configuration.md @@ -66,12 +66,42 @@ When you create a `.gemini/settings.json` file for project-specific settings, or - `"docker"` or `"podman"`: Explicitly choose container-based sandboxing command. - ``: Specify custom command for container-based sandboxing. - **`toolDiscoveryCommand`** (string, advanced): - - Custom command for tool discovery (if applicable to your setup). - - Must return JSON array of tools of `function_declarations` type as in [Gemini REST API](https://ai.google.dev/gemini-api/docs/function-calling). + - Custom shell command for discovering tools from your project, if available. + - Must return on `stdout` a JSON array of [function declarations](https://ai.google.dev/gemini-api/docs/function-calling#function-declarations). + - Tool wrappers, i.e. `[{ "function_declarations": [...] }, ...]`, are optional. + - Example for a single function `add_two_numbers(a, b)`: + ``` + [ + { + "name": "add_two_numbers", + "description": "Add two numbers.", + "parameters": { + "type": "object", + "properties": { + "a": { + "type": "integer", + "description": "first number" + }, + "b": { + "type": "integer", + "description": "second number" + } + }, + "required": [ + "a", + "b" + ] + } + } + ] + ``` - **`toolCallCommand`** (string, advanced): - - Custom command for executing tool calls (if applicable to your setup). - - Must take function name as first argument and function arguments as JSON on `stdin` - - Must return JSON result of funcation call on `stdout`. + - Custom shell command for calling a specific tool discovered via `toolDiscoveryCommand`. + - Must take function `name` (exactly as in [function declaration](https://ai.google.dev/gemini-api/docs/function-calling#function-declarations)) as first command line argument. + - Must read function arguments as JSON on `stdin`, analogous to [`functionCall.args`](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#functioncall). + - Example for `add_two_numbers` (see above): `{"a":1, "b":2}` + - Must return function output as JSON on `stdout`, analogous to [`functionResponse.response.content`](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#functionresponse). + - Example for `add_two_numbers` (see above): `3` (for input `{"a":1, "b":2}` on `stdin`) - **`mcpServers`** (object, advanced): - Configures connections to one or more Model-Context Protocol (MCP) servers for discovering and using custom tools. - This is an object where each key is a unique server name (alias) and the value is an object defining that server's parameters: diff --git a/packages/core/src/tools/tool-registry.ts b/packages/core/src/tools/tool-registry.ts index bce51a93..21aec687 100644 --- a/packages/core/src/tools/tool-registry.ts +++ b/packages/core/src/tools/tool-registry.ts @@ -137,10 +137,16 @@ export class ToolRegistry { // discover tools using discovery command, if configured const discoveryCmd = this.config.getToolDiscoveryCommand(); if (discoveryCmd) { - // execute discovery command and extract function declarations + // execute discovery command and extract function declarations (w/ or w/o "tool" wrappers) const functions: FunctionDeclaration[] = []; for (const tool of JSON.parse(execSync(discoveryCmd).toString().trim())) { - functions.push(...tool['function_declarations']); + if (tool['function_declarations']) { + functions.push(...tool['function_declarations']); + } else if (tool['functionDeclarations']) { + functions.push(...tool['functionDeclarations']); + } else if (tool['name']) { + functions.push(tool); + } } // register each function as a tool for (const func of functions) {