From 7550fc3d93fa0858b9df760ed3fa5cab6dc61ca4 Mon Sep 17 00:00:00 2001 From: Aishanee Shah Date: Tue, 17 Feb 2026 14:14:27 +0000 Subject: [PATCH] fix: separate instructions from API declaration to prevent API error --- .gemini/commands/strict-development-rules.md | 154 +- .../coreToolsModelSnapshots.test.ts.snap | 2178 +++++++++-------- .../core/src/tools/definitions/resolver.ts | 27 +- packages/core/src/tools/edit.ts | 13 +- packages/core/src/tools/read-file.ts | 2 +- packages/core/src/tools/read-many-files.ts | 3 +- packages/core/src/tools/shell.ts | 13 +- packages/core/src/tools/write-todos.test.ts | 3 +- packages/core/src/tools/write-todos.ts | 19 +- 9 files changed, 1318 insertions(+), 1094 deletions(-) diff --git a/.gemini/commands/strict-development-rules.md b/.gemini/commands/strict-development-rules.md index 54c8ff80af..9c01860091 100644 --- a/.gemini/commands/strict-development-rules.md +++ b/.gemini/commands/strict-development-rules.md @@ -1,64 +1,142 @@ # Gemini CLI Strict Development Rules -These rules apply strictly to all code modifications and additions within the Gemini CLI project. +These rules apply strictly to all code modifications and additions within the +Gemini CLI project. ## Testing Guidelines -* **Async/Await**: Always use `waitFor` from `packages/cli/src/test-utils/async.ts` instead of `vi.waitFor` for all `waitFor` calls within `packages/cli`. NEVER use fixed waits (e.g., `await delay(100)`). Always use `waitFor` with a predicate to ensure tests are stable and fast. Using the wrong `waitFor` can result in flaky tests and `act` warnings. -* **React Testing**: Use `act` to wrap all blocks in tests that change component state. Use `render` or `renderWithProviders` from `packages/cli/src/test-utils/render.tsx` instead of `render` from `ink-testing-library` directly. This prevents spurious `act` warnings. If test cases specify providers directly, consider whether the existing `renderWithProviders` should be modified. -* **Snapshots**: Use `toMatchSnapshot` to verify that rendering works as expected rather than matching against the raw content of the output. When modifying snapshots, verify the changes are intentional and do not hide underlying bugs. -* **Parameterized Tests**: Use parameterized tests where it reduces duplicated lines. Give the parameters explicit types to ensure the tests are type-safe. -* **Mocks Management**: - * Mock critical dependencies (`fs`, `os`, `child_process`) ONLY at the top of the file. Ideally, avoid mocking these dependencies altogether. - * Reuse existing mocks and fakes rather than creating new ones. - * Avoid mocking the file system whenever possible. If using the real file system is too difficult, consider writing an integration test instead. - * Always call `vi.restoreAllMocks()` in `afterEach` to prevent test pollution. - * Use `vi.useFakeTimers()` for tests involving time-based logic to avoid flakiness. -* **Typing in Tests**: Avoid using `any` in tests; prefer proper types or `unknown` with narrowing. +- **Async/Await**: Always use `waitFor` from + `packages/cli/src/test-utils/async.ts` instead of `vi.waitFor` for all + `waitFor` calls within `packages/cli`. NEVER use fixed waits (e.g., + `await delay(100)`). Always use `waitFor` with a predicate to ensure tests are + stable and fast. Using the wrong `waitFor` can result in flaky tests and `act` + warnings. +- **React Testing**: Use `act` to wrap all blocks in tests that change component + state. Use `render` or `renderWithProviders` from + `packages/cli/src/test-utils/render.tsx` instead of `render` from + `ink-testing-library` directly. This prevents spurious `act` warnings. If test + cases specify providers directly, consider whether the existing + `renderWithProviders` should be modified. +- **Snapshots**: Use `toMatchSnapshot` to verify that rendering works as + expected rather than matching against the raw content of the output. When + modifying snapshots, verify the changes are intentional and do not hide + underlying bugs. +- **Parameterized Tests**: Use parameterized tests where it reduces duplicated + lines. Give the parameters explicit types to ensure the tests are type-safe. +- **Mocks Management**: + - Mock critical dependencies (`fs`, `os`, `child_process`) ONLY at the top of + the file. Ideally, avoid mocking these dependencies altogether. + - Reuse existing mocks and fakes rather than creating new ones. + - Avoid mocking the file system whenever possible. If using the real file + system is too difficult, consider writing an integration test instead. + - Always call `vi.restoreAllMocks()` in `afterEach` to prevent test pollution. + - Use `vi.useFakeTimers()` for tests involving time-based logic to avoid + flakiness. +- **Typing in Tests**: Avoid using `any` in tests; prefer proper types or + `unknown` with narrowing. ## React Guidelines (`packages/cli`) -* **`setState` and Side Effects**: NEVER trigger side effects from within the body of a `setState` callback. Use a reducer or `useRef` if necessary. These cases have historically introduced multiple bugs; typically, they should be resolved using a reducer. -* **Rendering**: Do not introduce infinite rendering loops. Avoid synchronous file I/O in React components as it will hang the UI. Do not implement new logic for custom string measurement or string truncation. Use Ink layout instead, leveraging `ResizeObserver` as needed. -* **Keyboard Handling**: Keyboard handling MUST go through `useKeyPress.ts` from the Gemini CLI package rather than the standard ink library. This library supports reporting multiple keyboard events sequentially in the same React frame (critical for slow terminals). Handling this correctly often requires reducers to ensure multiple state updates are handled gracefully without overriding values. Refer to `text-buffer.ts` for a canonical example. -* **Logging**: Do not leave `console.log`, `console.warn`, or `console.error` in the code. -* **State & Effects**: Ensure state initialization is explicit (e.g., use `undefined` rather than `true` as a default if the state is truly unknown). Carefully manage `useEffect` dependencies. Prefer a reducer whenever practical. NEVER disable `react-hooks/exhaustive-deps`; fix the code to correctly declare dependencies instead. -* **Context & Props**: Avoid excessive property drilling. Leverage existing providers, extend them, or propose a new one if necessary. Only use providers for properties that are consistent across the entire application. -* **Code Structure**: Avoid complex `if` statements where `switch` statements could be used. Keep `AppContainer` minimal; refactor complex logic into React hooks. Evaluate whether business logic should be added to `hookSystem.ts` or integrated into `packages/core` rather than `packages/cli`. +- **`setState` and Side Effects**: NEVER trigger side effects from within the + body of a `setState` callback. Use a reducer or `useRef` if necessary. These + cases have historically introduced multiple bugs; typically, they should be + resolved using a reducer. +- **Rendering**: Do not introduce infinite rendering loops. Avoid synchronous + file I/O in React components as it will hang the UI. Do not implement new + logic for custom string measurement or string truncation. Use Ink layout + instead, leveraging `ResizeObserver` as needed. +- **Keyboard Handling**: Keyboard handling MUST go through `useKeyPress.ts` from + the Gemini CLI package rather than the standard ink library. This library + supports reporting multiple keyboard events sequentially in the same React + frame (critical for slow terminals). Handling this correctly often requires + reducers to ensure multiple state updates are handled gracefully without + overriding values. Refer to `text-buffer.ts` for a canonical example. +- **Logging**: Do not leave `console.log`, `console.warn`, or `console.error` in + the code. +- **State & Effects**: Ensure state initialization is explicit (e.g., use + `undefined` rather than `true` as a default if the state is truly unknown). + Carefully manage `useEffect` dependencies. Prefer a reducer whenever + practical. NEVER disable `react-hooks/exhaustive-deps`; fix the code to + correctly declare dependencies instead. +- **Context & Props**: Avoid excessive property drilling. Leverage existing + providers, extend them, or propose a new one if necessary. Only use providers + for properties that are consistent across the entire application. +- **Code Structure**: Avoid complex `if` statements where `switch` statements + could be used. Keep `AppContainer` minimal; refactor complex logic into React + hooks. Evaluate whether business logic should be added to `hookSystem.ts` or + integrated into `packages/core` rather than `packages/cli`. ## Core Guidelines (`packages/core`) -* **Services**: Implement services as classes with clear lifecycle management (e.g., `initialize()` methods). Services should be stateless where possible, or use the centralized `Storage` service for persistence. -* **Cross-Service Communication**: Prefer using the `coreEvents` bus (from `packages/core/src/utils/events.ts`) for asynchronous communication between services or to notify the UI of state changes. Avoid tight coupling between services. -* **Utilities**: Use `debugLogger` from `packages/core/src/utils/debugLogger.ts` for internal logging instead of `console`. Ensure all shell operations use `spawnAsync` from `packages/core/src/utils/shell-utils.ts` for consistent error handling and promise management. Handle filesystem errors gracefully using `isNodeError` from `packages/core/src/utils/errors.ts`. -* **Exports & Tooling**: Add new tools to `packages/core/src/tools/` and register them in `packages/core/src/tools/tool-registry.ts`. Export all new public services, utilities, and types from `packages/core/src/index.ts`. +- **Services**: Implement services as classes with clear lifecycle management + (e.g., `initialize()` methods). Services should be stateless where possible, + or use the centralized `Storage` service for persistence. +- **Cross-Service Communication**: Prefer using the `coreEvents` bus (from + `packages/core/src/utils/events.ts`) for asynchronous communication between + services or to notify the UI of state changes. Avoid tight coupling between + services. +- **Utilities**: Use `debugLogger` from `packages/core/src/utils/debugLogger.ts` + for internal logging instead of `console`. Ensure all shell operations use + `spawnAsync` from `packages/core/src/utils/shell-utils.ts` for consistent + error handling and promise management. Handle filesystem errors gracefully + using `isNodeError` from `packages/core/src/utils/errors.ts`. +- **Exports & Tooling**: Add new tools to `packages/core/src/tools/` and + register them in `packages/core/src/tools/tool-registry.ts`. Export all new + public services, utilities, and types from `packages/core/src/index.ts`. ## Architectural Audit (Package Boundaries) -* **Logic Placement**: Non-UI logic (e.g., model orchestration, tool implementation, git/filesystem operations) MUST reside in `packages/core`. `packages/cli` should ONLY contain UI/Ink components, command-line argument parsing, and user interaction logic. -* **Environment Isolation**: Core logic must not assume a TUI environment. Use the `ConfirmationBus` or `Output` abstractions for communicating with the user from Core. -* **Decoupling**: Actively look for opportunities to decouple services using `coreEvents`. If a service imports another just to notify it of a change, use an event instead. +- **Logic Placement**: Non-UI logic (e.g., model orchestration, tool + implementation, git/filesystem operations) MUST reside in `packages/core`. + `packages/cli` should ONLY contain UI/Ink components, command-line argument + parsing, and user interaction logic. +- **Environment Isolation**: Core logic must not assume a TUI environment. Use + the `ConfirmationBus` or `Output` abstractions for communicating with the user + from Core. +- **Decoupling**: Actively look for opportunities to decouple services using + `coreEvents`. If a service imports another just to notify it of a change, use + an event instead. ## General Gemini CLI Design Principles -* **Settings**: Use settings for user-configurable options rather than adding new command line arguments. Add new settings to `packages/cli/src/config/settingsSchema.ts`. If a setting has `showInDialog: true`, it MUST be documented in `docs/get-started/configuration.md`. Ensure `requiresRestart` is correctly set. -* **Logging**: Use `debugLogger` for rethrown errors to avoid duplicate logging. -* **Keyboard Shortcuts**: Define all new keyboard shortcuts in `packages/cli/src/config/keyBindings.ts` and document them in `docs/cli/keyboard-shortcuts.md`. Be careful of keybindings that require the `Meta` key, as only certain meta key shortcuts are supported on Mac. Avoid function keys and shortcuts commonly bound in VSCode. +- **Settings**: Use settings for user-configurable options rather than adding + new command line arguments. Add new settings to + `packages/cli/src/config/settingsSchema.ts`. If a setting has + `showInDialog: true`, it MUST be documented in + `docs/get-started/configuration.md`. Ensure `requiresRestart` is correctly + set. +- **Logging**: Use `debugLogger` for rethrown errors to avoid duplicate logging. +- **Keyboard Shortcuts**: Define all new keyboard shortcuts in + `packages/cli/src/config/keyBindings.ts` and document them in + `docs/cli/keyboard-shortcuts.md`. Be careful of keybindings that require the + `Meta` key, as only certain meta key shortcuts are supported on Mac. Avoid + function keys and shortcuts commonly bound in VSCode. ## TypeScript Best Practices -* Use `checkExhaustive` in the `default` clause of `switch` statements to ensure all cases are handled. -* Avoid using the non-null assertion operator (`!`) unless absolutely necessary. -* **STRICT TYPING**: Strictly forbid `any` and `unknown` in both CLI and Core packages. `unknown` is only allowed if it is immediately narrowed using type guards or Zod validation. -* NEVER disable `@typescript-eslint/no-floating-promises`. -* Avoid making types nullable unless strictly necessary, as it hurts readability. +- Use `checkExhaustive` in the `default` clause of `switch` statements to ensure + all cases are handled. +- Avoid using the non-null assertion operator (`!`) unless absolutely necessary. +- **STRICT TYPING**: Strictly forbid `any` and `unknown` in both CLI and Core + packages. `unknown` is only allowed if it is immediately narrowed using type + guards or Zod validation. +- NEVER disable `@typescript-eslint/no-floating-promises`. +- Avoid making types nullable unless strictly necessary, as it hurts + readability. ## TUI Best Practices -* **Terminal Compatibility**: Consider how changes might behave differently across terminals (e.g., VSCode terminal, SSH, Kitty, default Mac terminal, iTerm2, Windows terminal). If modifying keyboard handling, integrate deeply with existing files like `KeypressContext.tsx` and `terminalCapabilityManager.ts`. -* **iTerm**: Be aware that `ITERM_SESSION_ID` may be present when users run VSCode from within iTerm, even if the terminal is not iTerm. +- **Terminal Compatibility**: Consider how changes might behave differently + across terminals (e.g., VSCode terminal, SSH, Kitty, default Mac terminal, + iTerm2, Windows terminal). If modifying keyboard handling, integrate deeply + with existing files like `KeypressContext.tsx` and + `terminalCapabilityManager.ts`. +- **iTerm**: Be aware that `ITERM_SESSION_ID` may be present when users run + VSCode from within iTerm, even if the terminal is not iTerm. ## Code Cleanup -* **Refactoring**: Actively clean up code duplication, technical debt, and boilerplate ("AI Slop") when working in the codebase. -* **Prompts**: Be aware that changes can impact the prompts sent to Gemini CLI and affect overall quality. +- **Refactoring**: Actively clean up code duplication, technical debt, and + boilerplate ("AI Slop") when working in the codebase. +- **Prompts**: Be aware that changes can impact the prompts sent to Gemini CLI + and affect overall quality. diff --git a/packages/core/src/tools/definitions/__snapshots__/coreToolsModelSnapshots.test.ts.snap b/packages/core/src/tools/definitions/__snapshots__/coreToolsModelSnapshots.test.ts.snap index 41f780dd39..017370dc86 100644 --- a/packages/core/src/tools/definitions/__snapshots__/coreToolsModelSnapshots.test.ts.snap +++ b/packages/core/src/tools/definitions/__snapshots__/coreToolsModelSnapshots.test.ts.snap @@ -2,443 +2,483 @@ exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: activate_skill 1`] = ` { - "description": "Activates a specialized agent skill by name (Available: 'skill1', 'skill2'). Returns the skill's instructions wrapped in \`\` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description. ONLY use names exactly as they appear in the \`\` section.", - "name": "activate_skill", - "parametersJsonSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "name": { - "description": "The name of the skill to activate.", - "enum": [ - "skill1", - "skill2", - ], - "type": "string", + "declaration": { + "description": "Activates a specialized agent skill by name (Available: 'skill1', 'skill2'). Returns the skill's instructions wrapped in \`\` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description. ONLY use names exactly as they appear in the \`\` section.", + "name": "activate_skill", + "parametersJsonSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "name": { + "description": "The name of the skill to activate.", + "enum": [ + "skill1", + "skill2", + ], + "type": "string", + }, }, + "required": [ + "name", + ], + "type": "object", }, - "required": [ - "name", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: activate_skill_empty 1`] = ` { - "description": "Activates a specialized agent skill by name. Returns the skill's instructions wrapped in \`\` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description. ONLY use names exactly as they appear in the \`\` section.", - "name": "activate_skill", - "parametersJsonSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "name": { - "description": "No skills are currently available.", - "type": "string", + "declaration": { + "description": "Activates a specialized agent skill by name. Returns the skill's instructions wrapped in \`\` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description. ONLY use names exactly as they appear in the \`\` section.", + "name": "activate_skill", + "parametersJsonSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "name": { + "description": "No skills are currently available.", + "type": "string", + }, }, + "required": [ + "name", + ], + "type": "object", }, - "required": [ - "name", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: activate_skill_single 1`] = ` { - "description": "Activates a specialized agent skill by name (Available: 'skill1'). Returns the skill's instructions wrapped in \`\` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description. ONLY use names exactly as they appear in the \`\` section.", - "name": "activate_skill", - "parametersJsonSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "name": { - "description": "The name of the skill to activate.", - "enum": [ - "skill1", - ], - "type": "string", + "declaration": { + "description": "Activates a specialized agent skill by name (Available: 'skill1'). Returns the skill's instructions wrapped in \`\` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description. ONLY use names exactly as they appear in the \`\` section.", + "name": "activate_skill", + "parametersJsonSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "name": { + "description": "The name of the skill to activate.", + "enum": [ + "skill1", + ], + "type": "string", + }, }, + "required": [ + "name", + ], + "type": "object", }, - "required": [ - "name", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: ask_user 1`] = ` { - "description": "Ask the user one or more questions to gather preferences, clarify requirements, or make decisions.", - "name": "ask_user", - "parametersJsonSchema": { - "properties": { - "questions": { - "items": { - "properties": { - "header": { - "description": "MUST be 16 characters or fewer or the call will fail. Very short label displayed as a chip/tag. Use abbreviations: "Auth" not "Authentication", "Config" not "Configuration". Examples: "Auth method", "Library", "Approach", "Database".", - "maxLength": 16, - "type": "string", - }, - "multiSelect": { - "description": "Only applies when type='choice'. Set to true to allow selecting multiple options.", - "type": "boolean", - }, - "options": { - "description": "The selectable choices for 'choice' type questions. Provide 2-4 options. An 'Other' option is automatically added. Not needed for 'text' or 'yesno' types.", - "items": { - "properties": { - "description": { - "description": "Brief explanation of this option. Example: "Industry standard, supports SSO"", - "type": "string", - }, - "label": { - "description": "The display text for this option (1-5 words). Example: "OAuth 2.0"", - "type": "string", - }, - }, - "required": [ - "label", - "description", - ], - "type": "object", + "declaration": { + "description": "Ask the user one or more questions to gather preferences, clarify requirements, or make decisions.", + "name": "ask_user", + "parametersJsonSchema": { + "properties": { + "questions": { + "items": { + "properties": { + "header": { + "description": "MUST be 16 characters or fewer or the call will fail. Very short label displayed as a chip/tag. Use abbreviations: "Auth" not "Authentication", "Config" not "Configuration". Examples: "Auth method", "Library", "Approach", "Database".", + "maxLength": 16, + "type": "string", + }, + "multiSelect": { + "description": "Only applies when type='choice'. Set to true to allow selecting multiple options.", + "type": "boolean", + }, + "options": { + "description": "The selectable choices for 'choice' type questions. Provide 2-4 options. An 'Other' option is automatically added. Not needed for 'text' or 'yesno' types.", + "items": { + "properties": { + "description": { + "description": "Brief explanation of this option. Example: "Industry standard, supports SSO"", + "type": "string", + }, + "label": { + "description": "The display text for this option (1-5 words). Example: "OAuth 2.0"", + "type": "string", + }, + }, + "required": [ + "label", + "description", + ], + "type": "object", + }, + "type": "array", + }, + "placeholder": { + "description": "Hint text shown in the input field. For type='text', shown in the main input. For type='choice', shown in the 'Other' custom input.", + "type": "string", + }, + "question": { + "description": "The complete question to ask the user. Should be clear, specific, and end with a question mark.", + "type": "string", + }, + "type": { + "default": "choice", + "description": "Question type: 'choice' (default) for multiple-choice with options, 'text' for free-form input, 'yesno' for Yes/No confirmation.", + "enum": [ + "choice", + "text", + "yesno", + ], + "type": "string", }, - "type": "array", - }, - "placeholder": { - "description": "Hint text shown in the input field. For type='text', shown in the main input. For type='choice', shown in the 'Other' custom input.", - "type": "string", - }, - "question": { - "description": "The complete question to ask the user. Should be clear, specific, and end with a question mark.", - "type": "string", - }, - "type": { - "default": "choice", - "description": "Question type: 'choice' (default) for multiple-choice with options, 'text' for free-form input, 'yesno' for Yes/No confirmation.", - "enum": [ - "choice", - "text", - "yesno", - ], - "type": "string", }, + "required": [ + "question", + "header", + "type", + ], + "type": "object", }, - "required": [ - "question", - "header", - "type", - ], - "type": "object", + "maxItems": 4, + "minItems": 1, + "type": "array", }, - "maxItems": 4, - "minItems": 1, - "type": "array", }, + "required": [ + "questions", + ], + "type": "object", }, - "required": [ - "questions", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: enter_plan_mode 1`] = ` { - "description": "Switch to Plan Mode to safely research, design, and plan complex changes using read-only tools.", - "name": "enter_plan_mode", - "parametersJsonSchema": { - "properties": { - "reason": { - "description": "Short reason explaining why you are entering plan mode.", - "type": "string", + "declaration": { + "description": "Switch to Plan Mode to safely research, design, and plan complex changes using read-only tools.", + "name": "enter_plan_mode", + "parametersJsonSchema": { + "properties": { + "reason": { + "description": "Short reason explaining why you are entering plan mode.", + "type": "string", + }, }, + "type": "object", }, - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: exit_plan_mode 1`] = ` { - "description": "Signals that the planning phase is complete and requests user approval to start implementation.", - "name": "exit_plan_mode", - "parametersJsonSchema": { - "properties": { - "plan_path": { - "description": "The file path to the finalized plan (e.g., "/mock/plans/feature-x.md"). This path MUST be within the designated plans directory: /mock/plans/", - "type": "string", + "declaration": { + "description": "Signals that the planning phase is complete and requests user approval to start implementation.", + "name": "exit_plan_mode", + "parametersJsonSchema": { + "properties": { + "plan_path": { + "description": "The file path to the finalized plan (e.g., "/mock/plans/feature-x.md"). This path MUST be within the designated plans directory: /mock/plans/", + "type": "string", + }, }, + "required": [ + "plan_path", + ], + "type": "object", }, - "required": [ - "plan_path", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: get_internal_docs 1`] = ` { - "description": "Returns the content of Gemini CLI internal documentation files. If no path is provided, returns a list of all available documentation paths.", - "name": "get_internal_docs", - "parametersJsonSchema": { - "properties": { - "path": { - "description": "The relative path to the documentation file (e.g., 'cli/commands.md'). If omitted, lists all available documentation.", - "type": "string", + "declaration": { + "description": "Returns the content of Gemini CLI internal documentation files. If no path is provided, returns a list of all available documentation paths.", + "name": "get_internal_docs", + "parametersJsonSchema": { + "properties": { + "path": { + "description": "The relative path to the documentation file (e.g., 'cli/commands.md'). If omitted, lists all available documentation.", + "type": "string", + }, }, + "type": "object", }, - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: glob 1`] = ` { - "description": "Efficiently finds files matching specific glob patterns (e.g., \`src/**/*.ts\`, \`**/*.md\`), returning absolute paths sorted by modification time (newest first). Ideal for quickly locating files based on their name or path structure, especially in large codebases.", - "name": "glob", - "parametersJsonSchema": { - "properties": { - "case_sensitive": { - "description": "Optional: Whether the search should be case-sensitive. Defaults to false.", - "type": "boolean", - }, - "dir_path": { - "description": "Optional: The absolute path to the directory to search within. If omitted, searches the root directory.", - "type": "string", - }, - "pattern": { - "description": "The glob pattern to match against (e.g., '**/*.py', 'docs/*.md').", - "type": "string", - }, - "respect_gemini_ignore": { - "description": "Optional: Whether to respect .geminiignore patterns when finding files. Defaults to true.", - "type": "boolean", - }, - "respect_git_ignore": { - "description": "Optional: Whether to respect .gitignore patterns when finding files. Only available in git repositories. Defaults to true.", - "type": "boolean", + "declaration": { + "description": "Efficiently finds files matching specific glob patterns (e.g., \`src/**/*.ts\`, \`**/*.md\`), returning absolute paths sorted by modification time (newest first). Ideal for quickly locating files based on their name or path structure, especially in large codebases.", + "name": "glob", + "parametersJsonSchema": { + "properties": { + "case_sensitive": { + "description": "Optional: Whether the search should be case-sensitive. Defaults to false.", + "type": "boolean", + }, + "dir_path": { + "description": "Optional: The absolute path to the directory to search within. If omitted, searches the root directory.", + "type": "string", + }, + "pattern": { + "description": "The glob pattern to match against (e.g., '**/*.py', 'docs/*.md').", + "type": "string", + }, + "respect_gemini_ignore": { + "description": "Optional: Whether to respect .geminiignore patterns when finding files. Defaults to true.", + "type": "boolean", + }, + "respect_git_ignore": { + "description": "Optional: Whether to respect .gitignore patterns when finding files. Only available in git repositories. Defaults to true.", + "type": "boolean", + }, }, + "required": [ + "pattern", + ], + "type": "object", }, - "required": [ - "pattern", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: google_web_search 1`] = ` { - "description": "Performs a web search using Google Search (via the Gemini API) and returns the results. This tool is useful for finding information on the internet based on a query.", - "name": "google_web_search", - "parametersJsonSchema": { - "properties": { - "query": { - "description": "The search query to find information on the web.", - "type": "string", + "declaration": { + "description": "Performs a web search using Google Search (via the Gemini API) and returns the results. This tool is useful for finding information on the internet based on a query.", + "name": "google_web_search", + "parametersJsonSchema": { + "properties": { + "query": { + "description": "The search query to find information on the web.", + "type": "string", + }, }, + "required": [ + "query", + ], + "type": "object", }, - "required": [ - "query", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: grep_search 1`] = ` { - "description": "Searches for a regular expression pattern within file contents. Max 100 matches.", - "name": "grep_search", - "parametersJsonSchema": { - "properties": { - "dir_path": { - "description": "Optional: The absolute path to the directory to search within. If omitted, searches the current working directory.", - "type": "string", - }, - "exclude_pattern": { - "description": "Optional: A regular expression pattern to exclude from the search results. If a line matches both the pattern and the exclude_pattern, it will be omitted.", - "type": "string", - }, - "include": { - "description": "Optional: A glob pattern to filter which files are searched (e.g., '*.js', '*.{ts,tsx}', 'src/**'). If omitted, searches all files (respecting potential global ignores).", - "type": "string", - }, - "max_matches_per_file": { - "description": "Optional: Maximum number of matches to return per file. Use this to prevent being overwhelmed by repetitive matches in large files.", - "minimum": 1, - "type": "integer", - }, - "names_only": { - "description": "Optional: If true, only the file paths of the matches will be returned, without the line content or line numbers. This is useful for gathering a list of files.", - "type": "boolean", - }, - "pattern": { - "description": "The regular expression (regex) pattern to search for within file contents (e.g., 'function\\s+myFunction', 'import\\s+\\{.*\\}\\s+from\\s+.*').", - "type": "string", - }, - "total_max_matches": { - "description": "Optional: Maximum number of total matches to return. Use this to limit the overall size of the response. Defaults to 100 if omitted.", - "minimum": 1, - "type": "integer", + "declaration": { + "description": "Searches for a regular expression pattern within file contents. Max 100 matches.", + "name": "grep_search", + "parametersJsonSchema": { + "properties": { + "dir_path": { + "description": "Optional: The absolute path to the directory to search within. If omitted, searches the current working directory.", + "type": "string", + }, + "exclude_pattern": { + "description": "Optional: A regular expression pattern to exclude from the search results. If a line matches both the pattern and the exclude_pattern, it will be omitted.", + "type": "string", + }, + "include": { + "description": "Optional: A glob pattern to filter which files are searched (e.g., '*.js', '*.{ts,tsx}', 'src/**'). If omitted, searches all files (respecting potential global ignores).", + "type": "string", + }, + "max_matches_per_file": { + "description": "Optional: Maximum number of matches to return per file. Use this to prevent being overwhelmed by repetitive matches in large files.", + "minimum": 1, + "type": "integer", + }, + "names_only": { + "description": "Optional: If true, only the file paths of the matches will be returned, without the line content or line numbers. This is useful for gathering a list of files.", + "type": "boolean", + }, + "pattern": { + "description": "The regular expression (regex) pattern to search for within file contents (e.g., 'function\\s+myFunction', 'import\\s+\\{.*\\}\\s+from\\s+.*').", + "type": "string", + }, + "total_max_matches": { + "description": "Optional: Maximum number of total matches to return. Use this to limit the overall size of the response. Defaults to 100 if omitted.", + "minimum": 1, + "type": "integer", + }, }, + "required": [ + "pattern", + ], + "type": "object", }, - "required": [ - "pattern", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: grep_search_ripgrep 1`] = ` { - "description": "Searches for a regular expression pattern within file contents.", - "name": "grep_search", - "parametersJsonSchema": { - "properties": { - "after": { - "description": "Show this many lines after each match (equivalent to grep -A). Defaults to 0 if omitted.", - "minimum": 0, - "type": "integer", - }, - "before": { - "description": "Show this many lines before each match (equivalent to grep -B). Defaults to 0 if omitted.", - "minimum": 0, - "type": "integer", - }, - "case_sensitive": { - "description": "If true, search is case-sensitive. Defaults to false (ignore case) if omitted.", - "type": "boolean", - }, - "context": { - "description": "Show this many lines of context around each match (equivalent to grep -C). Defaults to 0 if omitted.", - "type": "integer", - }, - "dir_path": { - "description": "Directory or file to search. Directories are searched recursively. Relative paths are resolved against current working directory. Defaults to current working directory ('.') if omitted.", - "type": "string", - }, - "exclude_pattern": { - "description": "Optional: A regular expression pattern to exclude from the search results. If a line matches both the pattern and the exclude_pattern, it will be omitted.", - "type": "string", - }, - "fixed_strings": { - "description": "If true, treats the \`pattern\` as a literal string instead of a regular expression. Defaults to false (basic regex) if omitted.", - "type": "boolean", - }, - "include": { - "description": "Glob pattern to filter files (e.g., '*.ts', 'src/**'). Recommended for large repositories to reduce noise. Defaults to all files if omitted.", - "type": "string", - }, - "max_matches_per_file": { - "description": "Optional: Maximum number of matches to return per file. Use this to prevent being overwhelmed by repetitive matches in large files.", - "minimum": 1, - "type": "integer", - }, - "names_only": { - "description": "Optional: If true, only the file paths of the matches will be returned, without the line content or line numbers. This is useful for gathering a list of files.", - "type": "boolean", - }, - "no_ignore": { - "description": "If true, searches all files including those usually ignored (like in .gitignore, build/, dist/, etc). Defaults to false if omitted.", - "type": "boolean", - }, - "pattern": { - "description": "The pattern to search for. By default, treated as a Rust-flavored regular expression. Use '\\b' for precise symbol matching (e.g., '\\bMatchMe\\b').", - "type": "string", - }, - "total_max_matches": { - "description": "Optional: Maximum number of total matches to return. Use this to limit the overall size of the response. Defaults to 100 if omitted.", - "minimum": 1, - "type": "integer", + "declaration": { + "description": "Searches for a regular expression pattern within file contents.", + "name": "grep_search", + "parametersJsonSchema": { + "properties": { + "after": { + "description": "Show this many lines after each match (equivalent to grep -A). Defaults to 0 if omitted.", + "minimum": 0, + "type": "integer", + }, + "before": { + "description": "Show this many lines before each match (equivalent to grep -B). Defaults to 0 if omitted.", + "minimum": 0, + "type": "integer", + }, + "case_sensitive": { + "description": "If true, search is case-sensitive. Defaults to false (ignore case) if omitted.", + "type": "boolean", + }, + "context": { + "description": "Show this many lines of context around each match (equivalent to grep -C). Defaults to 0 if omitted.", + "type": "integer", + }, + "dir_path": { + "description": "Directory or file to search. Directories are searched recursively. Relative paths are resolved against current working directory. Defaults to current working directory ('.') if omitted.", + "type": "string", + }, + "exclude_pattern": { + "description": "Optional: A regular expression pattern to exclude from the search results. If a line matches both the pattern and the exclude_pattern, it will be omitted.", + "type": "string", + }, + "fixed_strings": { + "description": "If true, treats the \`pattern\` as a literal string instead of a regular expression. Defaults to false (basic regex) if omitted.", + "type": "boolean", + }, + "include": { + "description": "Glob pattern to filter files (e.g., '*.ts', 'src/**'). Recommended for large repositories to reduce noise. Defaults to all files if omitted.", + "type": "string", + }, + "max_matches_per_file": { + "description": "Optional: Maximum number of matches to return per file. Use this to prevent being overwhelmed by repetitive matches in large files.", + "minimum": 1, + "type": "integer", + }, + "names_only": { + "description": "Optional: If true, only the file paths of the matches will be returned, without the line content or line numbers. This is useful for gathering a list of files.", + "type": "boolean", + }, + "no_ignore": { + "description": "If true, searches all files including those usually ignored (like in .gitignore, build/, dist/, etc). Defaults to false if omitted.", + "type": "boolean", + }, + "pattern": { + "description": "The pattern to search for. By default, treated as a Rust-flavored regular expression. Use '\\b' for precise symbol matching (e.g., '\\bMatchMe\\b').", + "type": "string", + }, + "total_max_matches": { + "description": "Optional: Maximum number of total matches to return. Use this to limit the overall size of the response. Defaults to 100 if omitted.", + "minimum": 1, + "type": "integer", + }, }, + "required": [ + "pattern", + ], + "type": "object", }, - "required": [ - "pattern", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: list_directory 1`] = ` { - "description": "Lists the names of files and subdirectories directly within a specified directory path. Can optionally ignore entries matching provided glob patterns.", - "name": "list_directory", - "parametersJsonSchema": { - "properties": { - "dir_path": { - "description": "The path to the directory to list", - "type": "string", - }, - "file_filtering_options": { - "description": "Optional: Whether to respect ignore patterns from .gitignore or .geminiignore", - "properties": { - "respect_gemini_ignore": { - "description": "Optional: Whether to respect .geminiignore patterns when listing files. Defaults to true.", - "type": "boolean", - }, - "respect_git_ignore": { - "description": "Optional: Whether to respect .gitignore patterns when listing files. Only available in git repositories. Defaults to true.", - "type": "boolean", - }, - }, - "type": "object", - }, - "ignore": { - "description": "List of glob patterns to ignore", - "items": { + "declaration": { + "description": "Lists the names of files and subdirectories directly within a specified directory path. Can optionally ignore entries matching provided glob patterns.", + "name": "list_directory", + "parametersJsonSchema": { + "properties": { + "dir_path": { + "description": "The path to the directory to list", "type": "string", }, - "type": "array", + "file_filtering_options": { + "description": "Optional: Whether to respect ignore patterns from .gitignore or .geminiignore", + "properties": { + "respect_gemini_ignore": { + "description": "Optional: Whether to respect .geminiignore patterns when listing files. Defaults to true.", + "type": "boolean", + }, + "respect_git_ignore": { + "description": "Optional: Whether to respect .gitignore patterns when listing files. Only available in git repositories. Defaults to true.", + "type": "boolean", + }, + }, + "type": "object", + }, + "ignore": { + "description": "List of glob patterns to ignore", + "items": { + "type": "string", + }, + "type": "array", + }, }, + "required": [ + "dir_path", + ], + "type": "object", }, - "required": [ - "dir_path", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: read_file 1`] = ` { - "description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.", - "name": "read_file", - "parametersJsonSchema": { - "properties": { - "file_path": { - "description": "The path to the file to read.", - "type": "string", - }, - "limit": { - "description": "Optional: For text files, maximum number of lines to read. Use with 'offset' to paginate through large files. If omitted, reads the entire file (if feasible, up to a default limit).", - "type": "number", - }, - "offset": { - "description": "Optional: For text files, the 0-based line number to start reading from. Requires 'limit' to be set. Use for paginating through large files.", - "type": "number", + "declaration": { + "description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.", + "name": "read_file", + "parametersJsonSchema": { + "properties": { + "file_path": { + "description": "The path to the file to read.", + "type": "string", + }, + "limit": { + "description": "Optional: For text files, maximum number of lines to read. Use with 'offset' to paginate through large files. If omitted, reads the entire file (if feasible, up to a default limit).", + "type": "number", + }, + "offset": { + "description": "Optional: For text files, the 0-based line number to start reading from. Requires 'limit' to be set. Use for paginating through large files.", + "type": "number", + }, }, + "required": [ + "file_path", + ], + "type": "object", }, - "required": [ - "file_path", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: read_many_files 1`] = ` { - "description": "Reads content from multiple files specified by glob patterns within a configured target directory. For text files, it concatenates their content into a single string. It is primarily designed for text-based files. However, it can also process image (e.g., .png, .jpg), audio (e.g., .mp3, .wav), and PDF (.pdf) files if their file names or extensions are explicitly included in the 'include' argument. For these explicitly requested non-text files, their data is read and included in a format suitable for model consumption (e.g., base64 encoded). + "declaration": { + "description": "Reads content from multiple files specified by glob patterns within a configured target directory. For text files, it concatenates their content into a single string. It is primarily designed for text-based files. However, it can also process image (e.g., .png, .jpg), audio (e.g., .mp3, .wav), and PDF (.pdf) files if their file names or extensions are explicitly included in the 'include' argument. For these explicitly requested non-text files, their data is read and included in a format suitable for model consumption (e.g., base64 encoded). This tool is useful when you need to understand or analyze a collection of files, such as: - Getting an overview of a codebase or parts of it (e.g., all TypeScript files in the 'src' directory). @@ -448,88 +488,82 @@ This tool is useful when you need to understand or analyze a collection of files - When the user asks to "read all files in X directory" or "show me the content of all Y files". Use this tool when the user's query implies needing the content of several files simultaneously for context, analysis, or summarization. For text files, it uses default UTF-8 encoding and a '--- {filePath} ---' separator between file contents. The tool inserts a '--- End of content ---' after the last file. Ensure glob patterns are relative to the target directory. Glob patterns like 'src/**/*.js' are supported. Avoid using for single files if a more specific single-file reading tool is available, unless the user specifically requests to process a list containing just one file via this tool. Other binary files (not explicitly requested as image/audio/PDF) are generally skipped. Default excludes apply to common non-text files (except for explicitly requested images/audio/PDFs) and large dependency directories unless 'useDefaultExcludes' is false.", - "name": "read_many_files", - "parametersJsonSchema": { - "properties": { - "exclude": { - "default": [], - "description": "Optional. Glob patterns for files/directories to exclude. Added to default excludes if useDefaultExcludes is true. Example: "**/*.log", "temp/"", - "items": { - "minLength": 1, - "type": "string", - }, - "type": "array", - }, - "file_filtering_options": { - "description": "Whether to respect ignore patterns from .gitignore or .geminiignore", - "properties": { - "respect_gemini_ignore": { - "description": "Optional: Whether to respect .geminiignore patterns when listing files. Defaults to true.", - "type": "boolean", + "name": "read_many_files", + "parametersJsonSchema": { + "properties": { + "exclude": { + "default": [], + "description": "Optional. Glob patterns for files/directories to exclude. Added to default excludes if useDefaultExcludes is true. Example: "**/*.log", "temp/"", + "items": { + "minLength": 1, + "type": "string", }, - "respect_git_ignore": { - "description": "Optional: Whether to respect .gitignore patterns when listing files. Only available in git repositories. Defaults to true.", - "type": "boolean", + "type": "array", + }, + "file_filtering_options": { + "description": "Whether to respect ignore patterns from .gitignore or .geminiignore", + "properties": { + "respect_gemini_ignore": { + "description": "Optional: Whether to respect .geminiignore patterns when listing files. Defaults to true.", + "type": "boolean", + }, + "respect_git_ignore": { + "description": "Optional: Whether to respect .gitignore patterns when listing files. Only available in git repositories. Defaults to true.", + "type": "boolean", + }, }, + "type": "object", }, - "type": "object", - }, - "include": { - "description": "An array of glob patterns or paths. Examples: ["src/**/*.ts"], ["README.md", "docs/"]", - "items": { - "minLength": 1, - "type": "string", + "include": { + "description": "An array of glob patterns or paths. Examples: ["src/**/*.ts"], ["README.md", "docs/"]", + "items": { + "minLength": 1, + "type": "string", + }, + "minItems": 1, + "type": "array", + }, + "recursive": { + "default": true, + "description": "Optional. Whether to search recursively (primarily controlled by \`**\` in glob patterns). Defaults to true.", + "type": "boolean", + }, + "useDefaultExcludes": { + "default": true, + "description": "Optional. Whether to apply a list of default exclusion patterns (e.g., node_modules, .git, binary files). Defaults to true.", + "type": "boolean", }, - "minItems": 1, - "type": "array", - }, - "recursive": { - "default": true, - "description": "Optional. Whether to search recursively (primarily controlled by \`**\` in glob patterns). Defaults to true.", - "type": "boolean", - }, - "useDefaultExcludes": { - "default": true, - "description": "Optional. Whether to apply a list of default exclusion patterns (e.g., node_modules, .git, binary files). Defaults to true.", - "type": "boolean", }, + "required": [ + "include", + ], + "type": "object", }, - "required": [ - "include", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: replace 1`] = ` { - "description": "Replaces text within a file. By default, replaces a single occurrence, but can replace multiple occurrences when \`expected_replacements\` is specified. This tool requires providing significant context around the change to ensure precise targeting. Always use the read_file tool to examine the file's current content before attempting a text replacement. + "declaration": { + "description": "Replaces text within a file. By default, replaces a single occurrence, but can replace multiple occurrences when \`expected_replacements\` is specified. This tool requires providing significant context around the change to ensure precise targeting. Always use the read_file tool to examine the file's current content before attempting a text replacement. The user has the ability to modify the \`new_string\` content. If modified, this will be stated in the response.", - "instructions": " - Expectation for required parameters: - 1. \`old_string\` MUST be the exact literal text to replace (including all whitespace, indentation, newlines, and surrounding code etc.). - 2. \`new_string\` MUST be the exact literal text to replace \`old_string\` with (also including all whitespace, indentation, newlines, and surrounding code etc.). Ensure the resulting code is correct and idiomatic and that \`old_string\` and \`new_string\` are different. - 3. \`instruction\` is the detailed instruction of what needs to be changed. It is important to Make it specific and detailed so developers or large language models can understand what needs to be changed and perform the changes on their own if necessary. - 4. NEVER escape \`old_string\` or \`new_string\`, that would break the exact literal text requirement. - **Important:** If ANY of the above are not satisfied, the tool will fail. CRITICAL for \`old_string\`: Must uniquely identify the single instance to change. Include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string matches multiple locations, or does not match exactly, the tool will fail. - 5. Prefer to break down complex and long changes into multiple smaller atomic calls to this tool. Always check the content of the file after changes or not finding a string to match. - **Multiple replacements:** Set \`expected_replacements\` to the number of occurrences you want to replace. The tool will replace ALL occurrences that match \`old_string\` exactly. Ensure the number of replacements matches your expectation.", - "name": "replace", - "parametersJsonSchema": { - "properties": { - "expected_replacements": { - "description": "Number of replacements expected. Defaults to 1 if not specified. Use when you want to replace multiple occurrences.", - "minimum": 1, - "type": "number", - }, - "file_path": { - "description": "The path to the file to modify.", - "type": "string", - }, - "instruction": { - "description": "A clear, semantic instruction for the code change, acting as a high-quality prompt for an expert LLM assistant. It must be self-contained and explain the goal of the change. + "name": "replace", + "parametersJsonSchema": { + "properties": { + "expected_replacements": { + "description": "Number of replacements expected. Defaults to 1 if not specified. Use when you want to replace multiple occurrences.", + "minimum": 1, + "type": "number", + }, + "file_path": { + "description": "The path to the file to modify.", + "type": "string", + }, + "instruction": { + "description": "A clear, semantic instruction for the code change, acting as a high-quality prompt for an expert LLM assistant. It must be self-contained and explain the goal of the change. A good instruction should concisely answer: 1. WHY is the change needed? (e.g., "To fix a bug where users can be null...") @@ -544,31 +578,68 @@ A good instruction should concisely answer: - "Fix the bug." (Doesn't explain the bug or the fix) - "Replace the line with this new line." (Brittle, just repeats the other parameters) ", - "type": "string", - }, - "new_string": { - "description": "The exact literal text to replace \`old_string\` with, preferably unescaped. Provide the EXACT text. Ensure the resulting code is correct and idiomatic.", - "type": "string", - }, - "old_string": { - "description": "The exact literal text to replace, preferably unescaped. For single replacements (default), include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string is not the exact literal text (i.e. you escaped it) or does not match exactly, the tool will fail.", - "type": "string", + "type": "string", + }, + "new_string": { + "description": "The exact literal text to replace \`old_string\` with, preferably unescaped. Provide the EXACT text. Ensure the resulting code is correct and idiomatic.", + "type": "string", + }, + "old_string": { + "description": "The exact literal text to replace, preferably unescaped. For single replacements (default), include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string is not the exact literal text (i.e. you escaped it) or does not match exactly, the tool will fail.", + "type": "string", + }, }, + "required": [ + "file_path", + "instruction", + "old_string", + "new_string", + ], + "type": "object", }, - "required": [ - "file_path", - "instruction", - "old_string", - "new_string", - ], - "type": "object", }, + "instructions": " + Expectation for required parameters: + 1. \`old_string\` MUST be the exact literal text to replace (including all whitespace, indentation, newlines, and surrounding code etc.). + 2. \`new_string\` MUST be the exact literal text to replace \`old_string\` with (also including all whitespace, indentation, newlines, and surrounding code etc.). Ensure the resulting code is correct and idiomatic and that \`old_string\` and \`new_string\` are different. + 3. \`instruction\` is the detailed instruction of what needs to be changed. It is important to Make it specific and detailed so developers or large language models can understand what needs to be changed and perform the changes on their own if necessary. + 4. NEVER escape \`old_string\` or \`new_string\`, that would break the exact literal text requirement. + **Important:** If ANY of the above are not satisfied, the tool will fail. CRITICAL for \`old_string\`: Must uniquely identify the single instance to change. Include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string matches multiple locations, or does not match exactly, the tool will fail. + 5. Prefer to break down complex and long changes into multiple smaller atomic calls to this tool. Always check the content of the file after changes or not finding a string to match. + **Multiple replacements:** Set \`expected_replacements\` to the number of occurrences you want to replace. The tool will replace ALL occurrences that match \`old_string\` exactly. Ensure the number of replacements matches your expectation.", } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: run_shell_command 1`] = ` { - "description": "This tool executes a given shell command as \`bash -c \`.", + "declaration": { + "description": "This tool executes a given shell command as \`bash -c \`.", + "name": "run_shell_command", + "parametersJsonSchema": { + "properties": { + "command": { + "description": "Exact bash command to execute as \`bash -c \`", + "type": "string", + }, + "description": { + "description": "Brief description of the command for the user. Be specific and concise. Ideally a single sentence. Can be up to 3 sentences for clarity. No line breaks.", + "type": "string", + }, + "dir_path": { + "description": "(OPTIONAL) The path of the directory to run the command in. If not provided, the project root directory is used. Must be a directory within the workspace and must already exist.", + "type": "string", + }, + "is_background": { + "description": "Set to true if this command should be run in the background (e.g. for long-running servers or watchers). The command will be started, allowed to run for a brief moment to check for immediate errors, and then moved to the background.", + "type": "boolean", + }, + }, + "required": [ + "command", + ], + "type": "object", + }, + }, "instructions": "To run a command in the background, set the \`is_background\` parameter to true. Do NOT use \`&\` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as \`kill -- -PGID\` or signaled as \`kill -s SIGNAL -- -PGID\`. Efficiency Guidelines: @@ -583,37 +654,13 @@ exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snaps Signal: Only included if process was terminated by a signal. Background PIDs: Only included if background processes were started. Process Group PGID: Only included if available.", - "name": "run_shell_command", - "parametersJsonSchema": { - "properties": { - "command": { - "description": "Exact bash command to execute as \`bash -c \`", - "type": "string", - }, - "description": { - "description": "Brief description of the command for the user. Be specific and concise. Ideally a single sentence. Can be up to 3 sentences for clarity. No line breaks.", - "type": "string", - }, - "dir_path": { - "description": "(OPTIONAL) The path of the directory to run the command in. If not provided, the project root directory is used. Must be a directory within the workspace and must already exist.", - "type": "string", - }, - "is_background": { - "description": "Set to true if this command should be run in the background (e.g. for long-running servers or watchers). The command will be started, allowed to run for a brief moment to check for immediate errors, and then moved to the background.", - "type": "boolean", - }, - }, - "required": [ - "command", - ], - "type": "object", - }, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: save_memory 1`] = ` { - "description": " + "declaration": { + "description": " Saves concise global user context (preferences, facts) for use across ALL workspaces. ### CRITICAL: GLOBAL CONTEXT ONLY @@ -621,71 +668,80 @@ NEVER save workspace-specific context, local paths, or commands (e.g. "The entry - Use for "Remember X" or clear personal facts. - Do NOT use for session context.", - "name": "save_memory", - "parametersJsonSchema": { - "additionalProperties": false, - "properties": { - "fact": { - "description": "The specific fact or piece of information to remember. Should be a clear, self-contained statement.", - "type": "string", + "name": "save_memory", + "parametersJsonSchema": { + "additionalProperties": false, + "properties": { + "fact": { + "description": "The specific fact or piece of information to remember. Should be a clear, self-contained statement.", + "type": "string", + }, }, + "required": [ + "fact", + ], + "type": "object", }, - "required": [ - "fact", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: web_fetch 1`] = ` { - "description": "Processes content from URL(s), including local and private network addresses (e.g., localhost), embedded in a prompt. Include up to 20 URLs and instructions (e.g., summarize, extract specific data) directly in the 'prompt' parameter.", - "name": "web_fetch", - "parametersJsonSchema": { - "properties": { - "prompt": { - "description": "A comprehensive prompt that includes the URL(s) (up to 20) to fetch and specific instructions on how to process their content (e.g., "Summarize https://example.com/article and extract key points from https://another.com/data"). All URLs to be fetched must be valid and complete, starting with "http://" or "https://", and be fully-formed with a valid hostname (e.g., a domain name like "example.com" or an IP address). For example, "https://example.com" is valid, but "example.com" is not.", - "type": "string", + "declaration": { + "description": "Processes content from URL(s), including local and private network addresses (e.g., localhost), embedded in a prompt. Include up to 20 URLs and instructions (e.g., summarize, extract specific data) directly in the 'prompt' parameter.", + "name": "web_fetch", + "parametersJsonSchema": { + "properties": { + "prompt": { + "description": "A comprehensive prompt that includes the URL(s) (up to 20) to fetch and specific instructions on how to process their content (e.g., "Summarize https://example.com/article and extract key points from https://another.com/data"). All URLs to be fetched must be valid and complete, starting with "http://" or "https://", and be fully-formed with a valid hostname (e.g., a domain name like "example.com" or an IP address). For example, "https://example.com" is valid, but "example.com" is not.", + "type": "string", + }, }, + "required": [ + "prompt", + ], + "type": "object", }, - "required": [ - "prompt", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: write_file 1`] = ` { - "description": "Writes content to a specified file in the local filesystem. + "declaration": { + "description": "Writes content to a specified file in the local filesystem. The user has the ability to modify \`content\`. If modified, this will be stated in the response.", - "name": "write_file", - "parametersJsonSchema": { - "properties": { - "content": { - "description": "The content to write to the file.", - "type": "string", - }, - "file_path": { - "description": "The path to the file to write to.", - "type": "string", + "name": "write_file", + "parametersJsonSchema": { + "properties": { + "content": { + "description": "The content to write to the file.", + "type": "string", + }, + "file_path": { + "description": "The path to the file to write to.", + "type": "string", + }, }, + "required": [ + "file_path", + "content", + ], + "type": "object", }, - "required": [ - "file_path", - "content", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snapshot for tool: write_todos 1`] = ` { - "description": "This tool can help you list out the current subtasks that are required to be completed for a given user request. The list of subtasks helps you keep track of the current task, organize complex queries and help ensure that you don't miss any steps. With this list, the user can also see the current progress you are making in executing a given task. + "declaration": { + "description": "This tool can help you list out the current subtasks that are required to be completed for a given user request. The list of subtasks helps you keep track of the current task, organize complex queries and help ensure that you don't miss any steps. With this list, the user can also see the current progress you are making in executing a given task. Depending on the task complexity, you should first divide a given task into subtasks and then use this tool to list out the subtasks that are required to be completed for a given user request. Each of the subtasks should be clear and distinct. @@ -731,6 +787,46 @@ Agent: The agent did not use the todo list because this task could be completed by a tight loop of execute test->edit->execute test. ", + "name": "write_todos", + "parametersJsonSchema": { + "additionalProperties": false, + "properties": { + "todos": { + "description": "The complete list of todo items. This will replace the existing list.", + "items": { + "additionalProperties": false, + "description": "A single todo item.", + "properties": { + "description": { + "description": "The description of the task.", + "type": "string", + }, + "status": { + "description": "The current status of the task.", + "enum": [ + "pending", + "in_progress", + "completed", + "cancelled", + ], + "type": "string", + }, + }, + "required": [ + "description", + "status", + ], + "type": "object", + }, + "type": "array", + }, + }, + "required": [ + "todos", + ], + "type": "object", + }, + }, "instructions": " ## Task state definitions @@ -748,487 +844,488 @@ The agent did not use the todo list because this task could be completed by a ti 5. Mark a subtask as completed when you have completed it. 6. Mark a subtask as cancelled if the subtask is no longer needed. 7. You must update the todo list as soon as you start, stop or cancel a subtask. Don't batch or wait to update the todo list.", - "name": "write_todos", - "parametersJsonSchema": { - "additionalProperties": false, - "properties": { - "todos": { - "description": "The complete list of todo items. This will replace the existing list.", - "items": { - "additionalProperties": false, - "description": "A single todo item.", - "properties": { - "description": { - "description": "The description of the task.", - "type": "string", - }, - "status": { - "description": "The current status of the task.", - "enum": [ - "pending", - "in_progress", - "completed", - "cancelled", - ], - "type": "string", - }, - }, - "required": [ - "description", - "status", - ], - "type": "object", - }, - "type": "array", - }, - }, - "required": [ - "todos", - ], - "type": "object", - }, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: activate_skill 1`] = ` { - "description": "Activates a specialized agent skill by name (Available: 'skill1', 'skill2'). Returns the skill's instructions wrapped in \`\` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description. ONLY use names exactly as they appear in the \`\` section.", - "name": "activate_skill", - "parametersJsonSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "name": { - "description": "The name of the skill to activate.", - "enum": [ - "skill1", - "skill2", - ], - "type": "string", + "declaration": { + "description": "Activates a specialized agent skill by name (Available: 'skill1', 'skill2'). Returns the skill's instructions wrapped in \`\` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description. ONLY use names exactly as they appear in the \`\` section.", + "name": "activate_skill", + "parametersJsonSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "name": { + "description": "The name of the skill to activate.", + "enum": [ + "skill1", + "skill2", + ], + "type": "string", + }, }, + "required": [ + "name", + ], + "type": "object", }, - "required": [ - "name", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: activate_skill_empty 1`] = ` { - "description": "Activates a specialized agent skill by name. Returns the skill's instructions wrapped in \`\` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description. ONLY use names exactly as they appear in the \`\` section.", - "name": "activate_skill", - "parametersJsonSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "name": { - "description": "No skills are currently available.", - "type": "string", + "declaration": { + "description": "Activates a specialized agent skill by name. Returns the skill's instructions wrapped in \`\` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description. ONLY use names exactly as they appear in the \`\` section.", + "name": "activate_skill", + "parametersJsonSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "name": { + "description": "No skills are currently available.", + "type": "string", + }, }, + "required": [ + "name", + ], + "type": "object", }, - "required": [ - "name", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: activate_skill_single 1`] = ` { - "description": "Activates a specialized agent skill by name (Available: 'skill1'). Returns the skill's instructions wrapped in \`\` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description. ONLY use names exactly as they appear in the \`\` section.", - "name": "activate_skill", - "parametersJsonSchema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "additionalProperties": false, - "properties": { - "name": { - "description": "The name of the skill to activate.", - "enum": [ - "skill1", - ], - "type": "string", + "declaration": { + "description": "Activates a specialized agent skill by name (Available: 'skill1'). Returns the skill's instructions wrapped in \`\` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description. ONLY use names exactly as they appear in the \`\` section.", + "name": "activate_skill", + "parametersJsonSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "name": { + "description": "The name of the skill to activate.", + "enum": [ + "skill1", + ], + "type": "string", + }, }, + "required": [ + "name", + ], + "type": "object", }, - "required": [ - "name", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: ask_user 1`] = ` { - "description": "Ask the user one or more questions to gather preferences, clarify requirements, or make decisions.", - "name": "ask_user", - "parametersJsonSchema": { - "properties": { - "questions": { - "items": { - "properties": { - "header": { - "description": "MUST be 16 characters or fewer or the call will fail. Very short label displayed as a chip/tag. Use abbreviations: "Auth" not "Authentication", "Config" not "Configuration". Examples: "Auth method", "Library", "Approach", "Database".", - "maxLength": 16, - "type": "string", - }, - "multiSelect": { - "description": "Only applies when type='choice'. Set to true to allow selecting multiple options.", - "type": "boolean", - }, - "options": { - "description": "The selectable choices for 'choice' type questions. Provide 2-4 options. An 'Other' option is automatically added. Not needed for 'text' or 'yesno' types.", - "items": { - "properties": { - "description": { - "description": "Brief explanation of this option. Example: "Industry standard, supports SSO"", - "type": "string", - }, - "label": { - "description": "The display text for this option (1-5 words). Example: "OAuth 2.0"", - "type": "string", - }, - }, - "required": [ - "label", - "description", - ], - "type": "object", + "declaration": { + "description": "Ask the user one or more questions to gather preferences, clarify requirements, or make decisions.", + "name": "ask_user", + "parametersJsonSchema": { + "properties": { + "questions": { + "items": { + "properties": { + "header": { + "description": "MUST be 16 characters or fewer or the call will fail. Very short label displayed as a chip/tag. Use abbreviations: "Auth" not "Authentication", "Config" not "Configuration". Examples: "Auth method", "Library", "Approach", "Database".", + "maxLength": 16, + "type": "string", + }, + "multiSelect": { + "description": "Only applies when type='choice'. Set to true to allow selecting multiple options.", + "type": "boolean", + }, + "options": { + "description": "The selectable choices for 'choice' type questions. Provide 2-4 options. An 'Other' option is automatically added. Not needed for 'text' or 'yesno' types.", + "items": { + "properties": { + "description": { + "description": "Brief explanation of this option. Example: "Industry standard, supports SSO"", + "type": "string", + }, + "label": { + "description": "The display text for this option (1-5 words). Example: "OAuth 2.0"", + "type": "string", + }, + }, + "required": [ + "label", + "description", + ], + "type": "object", + }, + "type": "array", + }, + "placeholder": { + "description": "Hint text shown in the input field. For type='text', shown in the main input. For type='choice', shown in the 'Other' custom input.", + "type": "string", + }, + "question": { + "description": "The complete question to ask the user. Should be clear, specific, and end with a question mark.", + "type": "string", + }, + "type": { + "default": "choice", + "description": "Question type: 'choice' (default) for multiple-choice with options, 'text' for free-form input, 'yesno' for Yes/No confirmation.", + "enum": [ + "choice", + "text", + "yesno", + ], + "type": "string", }, - "type": "array", - }, - "placeholder": { - "description": "Hint text shown in the input field. For type='text', shown in the main input. For type='choice', shown in the 'Other' custom input.", - "type": "string", - }, - "question": { - "description": "The complete question to ask the user. Should be clear, specific, and end with a question mark.", - "type": "string", - }, - "type": { - "default": "choice", - "description": "Question type: 'choice' (default) for multiple-choice with options, 'text' for free-form input, 'yesno' for Yes/No confirmation.", - "enum": [ - "choice", - "text", - "yesno", - ], - "type": "string", }, + "required": [ + "question", + "header", + "type", + ], + "type": "object", }, - "required": [ - "question", - "header", - "type", - ], - "type": "object", + "maxItems": 4, + "minItems": 1, + "type": "array", }, - "maxItems": 4, - "minItems": 1, - "type": "array", }, + "required": [ + "questions", + ], + "type": "object", }, - "required": [ - "questions", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: enter_plan_mode 1`] = ` { - "description": "Switch to Plan Mode to safely research, design, and plan complex changes using read-only tools.", - "name": "enter_plan_mode", - "parametersJsonSchema": { - "properties": { - "reason": { - "description": "Short reason explaining why you are entering plan mode.", - "type": "string", + "declaration": { + "description": "Switch to Plan Mode to safely research, design, and plan complex changes using read-only tools.", + "name": "enter_plan_mode", + "parametersJsonSchema": { + "properties": { + "reason": { + "description": "Short reason explaining why you are entering plan mode.", + "type": "string", + }, }, + "type": "object", }, - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: exit_plan_mode 1`] = ` { - "description": "Signals that the planning phase is complete and requests user approval to start implementation.", - "name": "exit_plan_mode", - "parametersJsonSchema": { - "properties": { - "plan_path": { - "description": "The file path to the finalized plan (e.g., "/mock/plans/feature-x.md"). This path MUST be within the designated plans directory: /mock/plans/", - "type": "string", + "declaration": { + "description": "Signals that the planning phase is complete and requests user approval to start implementation.", + "name": "exit_plan_mode", + "parametersJsonSchema": { + "properties": { + "plan_path": { + "description": "The file path to the finalized plan (e.g., "/mock/plans/feature-x.md"). This path MUST be within the designated plans directory: /mock/plans/", + "type": "string", + }, }, + "required": [ + "plan_path", + ], + "type": "object", }, - "required": [ - "plan_path", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: get_internal_docs 1`] = ` { - "description": "Returns the content of Gemini CLI internal documentation files. If no path is provided, returns a list of all available documentation paths.", - "name": "get_internal_docs", - "parametersJsonSchema": { - "properties": { - "path": { - "description": "The relative path to the documentation file (e.g., 'cli/commands.md'). If omitted, lists all available documentation.", - "type": "string", + "declaration": { + "description": "Returns the content of Gemini CLI internal documentation files. If no path is provided, returns a list of all available documentation paths.", + "name": "get_internal_docs", + "parametersJsonSchema": { + "properties": { + "path": { + "description": "The relative path to the documentation file (e.g., 'cli/commands.md'). If omitted, lists all available documentation.", + "type": "string", + }, }, + "type": "object", }, - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: glob 1`] = ` { - "description": "Efficiently finds files matching specific glob patterns (e.g., \`src/**/*.ts\`, \`**/*.md\`), returning absolute paths sorted by modification time (newest first). Ideal for quickly locating files based on their name or path structure, especially in large codebases.", - "name": "glob", - "parametersJsonSchema": { - "properties": { - "case_sensitive": { - "description": "Optional: Whether the search should be case-sensitive. Defaults to false.", - "type": "boolean", - }, - "dir_path": { - "description": "Optional: The absolute path to the directory to search within. If omitted, searches the root directory.", - "type": "string", - }, - "pattern": { - "description": "The glob pattern to match against (e.g., '**/*.py', 'docs/*.md').", - "type": "string", - }, - "respect_gemini_ignore": { - "description": "Optional: Whether to respect .geminiignore patterns when finding files. Defaults to true.", - "type": "boolean", - }, - "respect_git_ignore": { - "description": "Optional: Whether to respect .gitignore patterns when finding files. Only available in git repositories. Defaults to true.", - "type": "boolean", + "declaration": { + "description": "Efficiently finds files matching specific glob patterns (e.g., \`src/**/*.ts\`, \`**/*.md\`), returning absolute paths sorted by modification time (newest first). Ideal for quickly locating files based on their name or path structure, especially in large codebases.", + "name": "glob", + "parametersJsonSchema": { + "properties": { + "case_sensitive": { + "description": "Optional: Whether the search should be case-sensitive. Defaults to false.", + "type": "boolean", + }, + "dir_path": { + "description": "Optional: The absolute path to the directory to search within. If omitted, searches the root directory.", + "type": "string", + }, + "pattern": { + "description": "The glob pattern to match against (e.g., '**/*.py', 'docs/*.md').", + "type": "string", + }, + "respect_gemini_ignore": { + "description": "Optional: Whether to respect .geminiignore patterns when finding files. Defaults to true.", + "type": "boolean", + }, + "respect_git_ignore": { + "description": "Optional: Whether to respect .gitignore patterns when finding files. Only available in git repositories. Defaults to true.", + "type": "boolean", + }, }, + "required": [ + "pattern", + ], + "type": "object", }, - "required": [ - "pattern", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: google_web_search 1`] = ` { - "description": "Performs a web search using Google Search (via the Gemini API) and returns the results. This tool is useful for finding information on the internet based on a query.", - "name": "google_web_search", - "parametersJsonSchema": { - "properties": { - "query": { - "description": "The search query to find information on the web.", - "type": "string", + "declaration": { + "description": "Performs a web search using Google Search (via the Gemini API) and returns the results. This tool is useful for finding information on the internet based on a query.", + "name": "google_web_search", + "parametersJsonSchema": { + "properties": { + "query": { + "description": "The search query to find information on the web.", + "type": "string", + }, }, + "required": [ + "query", + ], + "type": "object", }, - "required": [ - "query", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: grep_search 1`] = ` { - "description": "Searches for a regular expression pattern within file contents. Max 100 matches.", - "name": "grep_search", - "parametersJsonSchema": { - "properties": { - "dir_path": { - "description": "Optional: The absolute path to the directory to search within. If omitted, searches the current working directory.", - "type": "string", - }, - "exclude_pattern": { - "description": "Optional: A regular expression pattern to exclude from the search results. If a line matches both the pattern and the exclude_pattern, it will be omitted.", - "type": "string", - }, - "include": { - "description": "Optional: A glob pattern to filter which files are searched (e.g., '*.js', '*.{ts,tsx}', 'src/**'). If omitted, searches all files (respecting potential global ignores).", - "type": "string", - }, - "max_matches_per_file": { - "description": "Optional: Maximum number of matches to return per file. Use this to prevent being overwhelmed by repetitive matches in large files.", - "minimum": 1, - "type": "integer", - }, - "names_only": { - "description": "Optional: If true, only the file paths of the matches will be returned, without the line content or line numbers. This is useful for gathering a list of files.", - "type": "boolean", - }, - "pattern": { - "description": "The regular expression (regex) pattern to search for within file contents (e.g., 'function\\s+myFunction', 'import\\s+\\{.*\\}\\s+from\\s+.*').", - "type": "string", - }, - "total_max_matches": { - "description": "Optional: Maximum number of total matches to return. Use this to limit the overall size of the response. Defaults to 100 if omitted.", - "minimum": 1, - "type": "integer", + "declaration": { + "description": "Searches for a regular expression pattern within file contents. Max 100 matches.", + "name": "grep_search", + "parametersJsonSchema": { + "properties": { + "dir_path": { + "description": "Optional: The absolute path to the directory to search within. If omitted, searches the current working directory.", + "type": "string", + }, + "exclude_pattern": { + "description": "Optional: A regular expression pattern to exclude from the search results. If a line matches both the pattern and the exclude_pattern, it will be omitted.", + "type": "string", + }, + "include": { + "description": "Optional: A glob pattern to filter which files are searched (e.g., '*.js', '*.{ts,tsx}', 'src/**'). If omitted, searches all files (respecting potential global ignores).", + "type": "string", + }, + "max_matches_per_file": { + "description": "Optional: Maximum number of matches to return per file. Use this to prevent being overwhelmed by repetitive matches in large files.", + "minimum": 1, + "type": "integer", + }, + "names_only": { + "description": "Optional: If true, only the file paths of the matches will be returned, without the line content or line numbers. This is useful for gathering a list of files.", + "type": "boolean", + }, + "pattern": { + "description": "The regular expression (regex) pattern to search for within file contents (e.g., 'function\\s+myFunction', 'import\\s+\\{.*\\}\\s+from\\s+.*').", + "type": "string", + }, + "total_max_matches": { + "description": "Optional: Maximum number of total matches to return. Use this to limit the overall size of the response. Defaults to 100 if omitted.", + "minimum": 1, + "type": "integer", + }, }, + "required": [ + "pattern", + ], + "type": "object", }, - "required": [ - "pattern", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: grep_search_ripgrep 1`] = ` { - "description": "Searches for a regular expression pattern within file contents.", - "name": "grep_search", - "parametersJsonSchema": { - "properties": { - "after": { - "description": "Show this many lines after each match (equivalent to grep -A). Defaults to 0 if omitted.", - "minimum": 0, - "type": "integer", - }, - "before": { - "description": "Show this many lines before each match (equivalent to grep -B). Defaults to 0 if omitted.", - "minimum": 0, - "type": "integer", - }, - "case_sensitive": { - "description": "If true, search is case-sensitive. Defaults to false (ignore case) if omitted.", - "type": "boolean", - }, - "context": { - "description": "Show this many lines of context around each match (equivalent to grep -C). Defaults to 0 if omitted.", - "type": "integer", - }, - "dir_path": { - "description": "Directory or file to search. Directories are searched recursively. Relative paths are resolved against current working directory. Defaults to current working directory ('.') if omitted.", - "type": "string", - }, - "exclude_pattern": { - "description": "Optional: A regular expression pattern to exclude from the search results. If a line matches both the pattern and the exclude_pattern, it will be omitted.", - "type": "string", - }, - "fixed_strings": { - "description": "If true, treats the \`pattern\` as a literal string instead of a regular expression. Defaults to false (basic regex) if omitted.", - "type": "boolean", - }, - "include": { - "description": "Glob pattern to filter files (e.g., '*.ts', 'src/**'). Recommended for large repositories to reduce noise. Defaults to all files if omitted.", - "type": "string", - }, - "max_matches_per_file": { - "description": "Optional: Maximum number of matches to return per file. Use this to prevent being overwhelmed by repetitive matches in large files.", - "minimum": 1, - "type": "integer", - }, - "names_only": { - "description": "Optional: If true, only the file paths of the matches will be returned, without the line content or line numbers. This is useful for gathering a list of files.", - "type": "boolean", - }, - "no_ignore": { - "description": "If true, searches all files including those usually ignored (like in .gitignore, build/, dist/, etc). Defaults to false if omitted.", - "type": "boolean", - }, - "pattern": { - "description": "The pattern to search for. By default, treated as a Rust-flavored regular expression. Use '\\b' for precise symbol matching (e.g., '\\bMatchMe\\b').", - "type": "string", - }, - "total_max_matches": { - "description": "Optional: Maximum number of total matches to return. Use this to limit the overall size of the response. Defaults to 100 if omitted.", - "minimum": 1, - "type": "integer", + "declaration": { + "description": "Searches for a regular expression pattern within file contents.", + "name": "grep_search", + "parametersJsonSchema": { + "properties": { + "after": { + "description": "Show this many lines after each match (equivalent to grep -A). Defaults to 0 if omitted.", + "minimum": 0, + "type": "integer", + }, + "before": { + "description": "Show this many lines before each match (equivalent to grep -B). Defaults to 0 if omitted.", + "minimum": 0, + "type": "integer", + }, + "case_sensitive": { + "description": "If true, search is case-sensitive. Defaults to false (ignore case) if omitted.", + "type": "boolean", + }, + "context": { + "description": "Show this many lines of context around each match (equivalent to grep -C). Defaults to 0 if omitted.", + "type": "integer", + }, + "dir_path": { + "description": "Directory or file to search. Directories are searched recursively. Relative paths are resolved against current working directory. Defaults to current working directory ('.') if omitted.", + "type": "string", + }, + "exclude_pattern": { + "description": "Optional: A regular expression pattern to exclude from the search results. If a line matches both the pattern and the exclude_pattern, it will be omitted.", + "type": "string", + }, + "fixed_strings": { + "description": "If true, treats the \`pattern\` as a literal string instead of a regular expression. Defaults to false (basic regex) if omitted.", + "type": "boolean", + }, + "include": { + "description": "Glob pattern to filter files (e.g., '*.ts', 'src/**'). Recommended for large repositories to reduce noise. Defaults to all files if omitted.", + "type": "string", + }, + "max_matches_per_file": { + "description": "Optional: Maximum number of matches to return per file. Use this to prevent being overwhelmed by repetitive matches in large files.", + "minimum": 1, + "type": "integer", + }, + "names_only": { + "description": "Optional: If true, only the file paths of the matches will be returned, without the line content or line numbers. This is useful for gathering a list of files.", + "type": "boolean", + }, + "no_ignore": { + "description": "If true, searches all files including those usually ignored (like in .gitignore, build/, dist/, etc). Defaults to false if omitted.", + "type": "boolean", + }, + "pattern": { + "description": "The pattern to search for. By default, treated as a Rust-flavored regular expression. Use '\\b' for precise symbol matching (e.g., '\\bMatchMe\\b').", + "type": "string", + }, + "total_max_matches": { + "description": "Optional: Maximum number of total matches to return. Use this to limit the overall size of the response. Defaults to 100 if omitted.", + "minimum": 1, + "type": "integer", + }, }, + "required": [ + "pattern", + ], + "type": "object", }, - "required": [ - "pattern", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: list_directory 1`] = ` { - "description": "Lists the names of files and subdirectories directly within a specified directory path. Can optionally ignore entries matching provided glob patterns.", - "name": "list_directory", - "parametersJsonSchema": { - "properties": { - "dir_path": { - "description": "The path to the directory to list", - "type": "string", - }, - "file_filtering_options": { - "description": "Optional: Whether to respect ignore patterns from .gitignore or .geminiignore", - "properties": { - "respect_gemini_ignore": { - "description": "Optional: Whether to respect .geminiignore patterns when listing files. Defaults to true.", - "type": "boolean", - }, - "respect_git_ignore": { - "description": "Optional: Whether to respect .gitignore patterns when listing files. Only available in git repositories. Defaults to true.", - "type": "boolean", - }, - }, - "type": "object", - }, - "ignore": { - "description": "List of glob patterns to ignore", - "items": { + "declaration": { + "description": "Lists the names of files and subdirectories directly within a specified directory path. Can optionally ignore entries matching provided glob patterns.", + "name": "list_directory", + "parametersJsonSchema": { + "properties": { + "dir_path": { + "description": "The path to the directory to list", "type": "string", }, - "type": "array", + "file_filtering_options": { + "description": "Optional: Whether to respect ignore patterns from .gitignore or .geminiignore", + "properties": { + "respect_gemini_ignore": { + "description": "Optional: Whether to respect .geminiignore patterns when listing files. Defaults to true.", + "type": "boolean", + }, + "respect_git_ignore": { + "description": "Optional: Whether to respect .gitignore patterns when listing files. Only available in git repositories. Defaults to true.", + "type": "boolean", + }, + }, + "type": "object", + }, + "ignore": { + "description": "List of glob patterns to ignore", + "items": { + "type": "string", + }, + "type": "array", + }, }, + "required": [ + "dir_path", + ], + "type": "object", }, - "required": [ - "dir_path", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: read_file 1`] = ` { - "description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.", - "name": "read_file", - "parametersJsonSchema": { - "properties": { - "file_path": { - "description": "The path to the file to read.", - "type": "string", - }, - "limit": { - "description": "Optional: For text files, maximum number of lines to read. Use with 'offset' to paginate through large files. If omitted, reads the entire file (if feasible, up to a default limit).", - "type": "number", - }, - "offset": { - "description": "Optional: For text files, the 0-based line number to start reading from. Requires 'limit' to be set. Use for paginating through large files.", - "type": "number", + "declaration": { + "description": "Reads and returns the content of a specified file. If the file is large, the content will be truncated. The tool's response will clearly indicate if truncation has occurred and will provide details on how to read more of the file using the 'offset' and 'limit' parameters. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), audio files (MP3, WAV, AIFF, AAC, OGG, FLAC), and PDF files. For text files, it can read specific line ranges.", + "name": "read_file", + "parametersJsonSchema": { + "properties": { + "file_path": { + "description": "The path to the file to read.", + "type": "string", + }, + "limit": { + "description": "Optional: For text files, maximum number of lines to read. Use with 'offset' to paginate through large files. If omitted, reads the entire file (if feasible, up to a default limit).", + "type": "number", + }, + "offset": { + "description": "Optional: For text files, the 0-based line number to start reading from. Requires 'limit' to be set. Use for paginating through large files.", + "type": "number", + }, }, + "required": [ + "file_path", + ], + "type": "object", }, - "required": [ - "file_path", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: read_many_files 1`] = ` { - "description": "Reads content from multiple files specified by glob patterns within a configured target directory. For text files, it concatenates their content into a single string. It is primarily designed for text-based files. However, it can also process image (e.g., .png, .jpg), audio (e.g., .mp3, .wav), and PDF (.pdf) files if their file names or extensions are explicitly included in the 'include' argument. For these explicitly requested non-text files, their data is read and included in a format suitable for model consumption (e.g., base64 encoded). + "declaration": { + "description": "Reads content from multiple files specified by glob patterns within a configured target directory. For text files, it concatenates their content into a single string. It is primarily designed for text-based files. However, it can also process image (e.g., .png, .jpg), audio (e.g., .mp3, .wav), and PDF (.pdf) files if their file names or extensions are explicitly included in the 'include' argument. For these explicitly requested non-text files, their data is read and included in a format suitable for model consumption (e.g., base64 encoded). This tool is useful when you need to understand or analyze a collection of files, such as: - Getting an overview of a codebase or parts of it (e.g., all TypeScript files in the 'src' directory). @@ -1238,88 +1335,82 @@ This tool is useful when you need to understand or analyze a collection of files - When the user asks to "read all files in X directory" or "show me the content of all Y files". Use this tool when the user's query implies needing the content of several files simultaneously for context, analysis, or summarization. For text files, it uses default UTF-8 encoding and a '--- {filePath} ---' separator between file contents. The tool inserts a '--- End of content ---' after the last file. Ensure glob patterns are relative to the target directory. Glob patterns like 'src/**/*.js' are supported. Avoid using for single files if a more specific single-file reading tool is available, unless the user specifically requests to process a list containing just one file via this tool. Other binary files (not explicitly requested as image/audio/PDF) are generally skipped. Default excludes apply to common non-text files (except for explicitly requested images/audio/PDFs) and large dependency directories unless 'useDefaultExcludes' is false.", - "name": "read_many_files", - "parametersJsonSchema": { - "properties": { - "exclude": { - "default": [], - "description": "Optional. Glob patterns for files/directories to exclude. Added to default excludes if useDefaultExcludes is true. Example: "**/*.log", "temp/"", - "items": { - "minLength": 1, - "type": "string", - }, - "type": "array", - }, - "file_filtering_options": { - "description": "Whether to respect ignore patterns from .gitignore or .geminiignore", - "properties": { - "respect_gemini_ignore": { - "description": "Optional: Whether to respect .geminiignore patterns when listing files. Defaults to true.", - "type": "boolean", + "name": "read_many_files", + "parametersJsonSchema": { + "properties": { + "exclude": { + "default": [], + "description": "Optional. Glob patterns for files/directories to exclude. Added to default excludes if useDefaultExcludes is true. Example: "**/*.log", "temp/"", + "items": { + "minLength": 1, + "type": "string", }, - "respect_git_ignore": { - "description": "Optional: Whether to respect .gitignore patterns when listing files. Only available in git repositories. Defaults to true.", - "type": "boolean", + "type": "array", + }, + "file_filtering_options": { + "description": "Whether to respect ignore patterns from .gitignore or .geminiignore", + "properties": { + "respect_gemini_ignore": { + "description": "Optional: Whether to respect .geminiignore patterns when listing files. Defaults to true.", + "type": "boolean", + }, + "respect_git_ignore": { + "description": "Optional: Whether to respect .gitignore patterns when listing files. Only available in git repositories. Defaults to true.", + "type": "boolean", + }, }, + "type": "object", }, - "type": "object", - }, - "include": { - "description": "An array of glob patterns or paths. Examples: ["src/**/*.ts"], ["README.md", "docs/"]", - "items": { - "minLength": 1, - "type": "string", + "include": { + "description": "An array of glob patterns or paths. Examples: ["src/**/*.ts"], ["README.md", "docs/"]", + "items": { + "minLength": 1, + "type": "string", + }, + "minItems": 1, + "type": "array", + }, + "recursive": { + "default": true, + "description": "Optional. Whether to search recursively (primarily controlled by \`**\` in glob patterns). Defaults to true.", + "type": "boolean", + }, + "useDefaultExcludes": { + "default": true, + "description": "Optional. Whether to apply a list of default exclusion patterns (e.g., node_modules, .git, binary files). Defaults to true.", + "type": "boolean", }, - "minItems": 1, - "type": "array", - }, - "recursive": { - "default": true, - "description": "Optional. Whether to search recursively (primarily controlled by \`**\` in glob patterns). Defaults to true.", - "type": "boolean", - }, - "useDefaultExcludes": { - "default": true, - "description": "Optional. Whether to apply a list of default exclusion patterns (e.g., node_modules, .git, binary files). Defaults to true.", - "type": "boolean", }, + "required": [ + "include", + ], + "type": "object", }, - "required": [ - "include", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: replace 1`] = ` { - "description": "Replaces text within a file. By default, replaces a single occurrence, but can replace multiple occurrences when \`expected_replacements\` is specified. This tool requires providing significant context around the change to ensure precise targeting. Always use the read_file tool to examine the file's current content before attempting a text replacement. + "declaration": { + "description": "Replaces text within a file. By default, replaces a single occurrence, but can replace multiple occurrences when \`expected_replacements\` is specified. This tool requires providing significant context around the change to ensure precise targeting. Always use the read_file tool to examine the file's current content before attempting a text replacement. The user has the ability to modify the \`new_string\` content. If modified, this will be stated in the response.", - "instructions": " - Expectation for required parameters: - 1. \`old_string\` MUST be the exact literal text to replace (including all whitespace, indentation, newlines, and surrounding code etc.). - 2. \`new_string\` MUST be the exact literal text to replace \`old_string\` with (also including all whitespace, indentation, newlines, and surrounding code etc.). Ensure the resulting code is correct and idiomatic and that \`old_string\` and \`new_string\` are different. - 3. \`instruction\` is the detailed instruction of what needs to be changed. It is important to Make it specific and detailed so developers or large language models can understand what needs to be changed and perform the changes on their own if necessary. - 4. NEVER escape \`old_string\` or \`new_string\`, that would break the exact literal text requirement. - **Important:** If ANY of the above are not satisfied, the tool will fail. CRITICAL for \`old_string\`: Must uniquely identify the single instance to change. Include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string matches multiple locations, or does not match exactly, the tool will fail. - 5. Prefer to break down complex and long changes into multiple smaller atomic calls to this tool. Always check the content of the file after changes or not finding a string to match. - **Multiple replacements:** Set \`expected_replacements\` to the number of occurrences you want to replace. The tool will replace ALL occurrences that match \`old_string\` exactly. Ensure the number of replacements matches your expectation.", - "name": "replace", - "parametersJsonSchema": { - "properties": { - "expected_replacements": { - "description": "Number of replacements expected. Defaults to 1 if not specified. Use when you want to replace multiple occurrences.", - "minimum": 1, - "type": "number", - }, - "file_path": { - "description": "The path to the file to modify.", - "type": "string", - }, - "instruction": { - "description": "A clear, semantic instruction for the code change, acting as a high-quality prompt for an expert LLM assistant. It must be self-contained and explain the goal of the change. + "name": "replace", + "parametersJsonSchema": { + "properties": { + "expected_replacements": { + "description": "Number of replacements expected. Defaults to 1 if not specified. Use when you want to replace multiple occurrences.", + "minimum": 1, + "type": "number", + }, + "file_path": { + "description": "The path to the file to modify.", + "type": "string", + }, + "instruction": { + "description": "A clear, semantic instruction for the code change, acting as a high-quality prompt for an expert LLM assistant. It must be self-contained and explain the goal of the change. A good instruction should concisely answer: 1. WHY is the change needed? (e.g., "To fix a bug where users can be null...") @@ -1334,31 +1425,68 @@ A good instruction should concisely answer: - "Fix the bug." (Doesn't explain the bug or the fix) - "Replace the line with this new line." (Brittle, just repeats the other parameters) ", - "type": "string", - }, - "new_string": { - "description": "The exact literal text to replace \`old_string\` with, preferably unescaped. Provide the EXACT text. Ensure the resulting code is correct and idiomatic.", - "type": "string", - }, - "old_string": { - "description": "The exact literal text to replace, preferably unescaped. For single replacements (default), include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string is not the exact literal text (i.e. you escaped it) or does not match exactly, the tool will fail.", - "type": "string", + "type": "string", + }, + "new_string": { + "description": "The exact literal text to replace \`old_string\` with, preferably unescaped. Provide the EXACT text. Ensure the resulting code is correct and idiomatic.", + "type": "string", + }, + "old_string": { + "description": "The exact literal text to replace, preferably unescaped. For single replacements (default), include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string is not the exact literal text (i.e. you escaped it) or does not match exactly, the tool will fail.", + "type": "string", + }, }, + "required": [ + "file_path", + "instruction", + "old_string", + "new_string", + ], + "type": "object", }, - "required": [ - "file_path", - "instruction", - "old_string", - "new_string", - ], - "type": "object", }, + "instructions": " + Expectation for required parameters: + 1. \`old_string\` MUST be the exact literal text to replace (including all whitespace, indentation, newlines, and surrounding code etc.). + 2. \`new_string\` MUST be the exact literal text to replace \`old_string\` with (also including all whitespace, indentation, newlines, and surrounding code etc.). Ensure the resulting code is correct and idiomatic and that \`old_string\` and \`new_string\` are different. + 3. \`instruction\` is the detailed instruction of what needs to be changed. It is important to Make it specific and detailed so developers or large language models can understand what needs to be changed and perform the changes on their own if necessary. + 4. NEVER escape \`old_string\` or \`new_string\`, that would break the exact literal text requirement. + **Important:** If ANY of the above are not satisfied, the tool will fail. CRITICAL for \`old_string\`: Must uniquely identify the single instance to change. Include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string matches multiple locations, or does not match exactly, the tool will fail. + 5. Prefer to break down complex and long changes into multiple smaller atomic calls to this tool. Always check the content of the file after changes or not finding a string to match. + **Multiple replacements:** Set \`expected_replacements\` to the number of occurrences you want to replace. The tool will replace ALL occurrences that match \`old_string\` exactly. Ensure the number of replacements matches your expectation.", } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: run_shell_command 1`] = ` { - "description": "This tool executes a given shell command as \`bash -c \`.", + "declaration": { + "description": "This tool executes a given shell command as \`bash -c \`.", + "name": "run_shell_command", + "parametersJsonSchema": { + "properties": { + "command": { + "description": "Exact bash command to execute as \`bash -c \`", + "type": "string", + }, + "description": { + "description": "Brief description of the command for the user. Be specific and concise. Ideally a single sentence. Can be up to 3 sentences for clarity. No line breaks.", + "type": "string", + }, + "dir_path": { + "description": "(OPTIONAL) The path of the directory to run the command in. If not provided, the project root directory is used. Must be a directory within the workspace and must already exist.", + "type": "string", + }, + "is_background": { + "description": "Set to true if this command should be run in the background (e.g. for long-running servers or watchers). The command will be started, allowed to run for a brief moment to check for immediate errors, and then moved to the background.", + "type": "boolean", + }, + }, + "required": [ + "command", + ], + "type": "object", + }, + }, "instructions": "To run a command in the background, set the \`is_background\` parameter to true. Do NOT use \`&\` to background commands. Command is executed as a subprocess that leads its own process group. Command process group can be terminated as \`kill -- -PGID\` or signaled as \`kill -s SIGNAL -- -PGID\`. Efficiency Guidelines: @@ -1373,37 +1501,13 @@ exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > Signal: Only included if process was terminated by a signal. Background PIDs: Only included if background processes were started. Process Group PGID: Only included if available.", - "name": "run_shell_command", - "parametersJsonSchema": { - "properties": { - "command": { - "description": "Exact bash command to execute as \`bash -c \`", - "type": "string", - }, - "description": { - "description": "Brief description of the command for the user. Be specific and concise. Ideally a single sentence. Can be up to 3 sentences for clarity. No line breaks.", - "type": "string", - }, - "dir_path": { - "description": "(OPTIONAL) The path of the directory to run the command in. If not provided, the project root directory is used. Must be a directory within the workspace and must already exist.", - "type": "string", - }, - "is_background": { - "description": "Set to true if this command should be run in the background (e.g. for long-running servers or watchers). The command will be started, allowed to run for a brief moment to check for immediate errors, and then moved to the background.", - "type": "boolean", - }, - }, - "required": [ - "command", - ], - "type": "object", - }, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: save_memory 1`] = ` { - "description": " + "declaration": { + "description": " Saves concise global user context (preferences, facts) for use across ALL workspaces. ### CRITICAL: GLOBAL CONTEXT ONLY @@ -1411,71 +1515,80 @@ NEVER save workspace-specific context, local paths, or commands (e.g. "The entry - Use for "Remember X" or clear personal facts. - Do NOT use for session context.", - "name": "save_memory", - "parametersJsonSchema": { - "additionalProperties": false, - "properties": { - "fact": { - "description": "The specific fact or piece of information to remember. Should be a clear, self-contained statement.", - "type": "string", + "name": "save_memory", + "parametersJsonSchema": { + "additionalProperties": false, + "properties": { + "fact": { + "description": "The specific fact or piece of information to remember. Should be a clear, self-contained statement.", + "type": "string", + }, }, + "required": [ + "fact", + ], + "type": "object", }, - "required": [ - "fact", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: web_fetch 1`] = ` { - "description": "Processes content from URL(s), including local and private network addresses (e.g., localhost), embedded in a prompt. Include up to 20 URLs and instructions (e.g., summarize, extract specific data) directly in the 'prompt' parameter.", - "name": "web_fetch", - "parametersJsonSchema": { - "properties": { - "prompt": { - "description": "A comprehensive prompt that includes the URL(s) (up to 20) to fetch and specific instructions on how to process their content (e.g., "Summarize https://example.com/article and extract key points from https://another.com/data"). All URLs to be fetched must be valid and complete, starting with "http://" or "https://", and be fully-formed with a valid hostname (e.g., a domain name like "example.com" or an IP address). For example, "https://example.com" is valid, but "example.com" is not.", - "type": "string", + "declaration": { + "description": "Processes content from URL(s), including local and private network addresses (e.g., localhost), embedded in a prompt. Include up to 20 URLs and instructions (e.g., summarize, extract specific data) directly in the 'prompt' parameter.", + "name": "web_fetch", + "parametersJsonSchema": { + "properties": { + "prompt": { + "description": "A comprehensive prompt that includes the URL(s) (up to 20) to fetch and specific instructions on how to process their content (e.g., "Summarize https://example.com/article and extract key points from https://another.com/data"). All URLs to be fetched must be valid and complete, starting with "http://" or "https://", and be fully-formed with a valid hostname (e.g., a domain name like "example.com" or an IP address). For example, "https://example.com" is valid, but "example.com" is not.", + "type": "string", + }, }, + "required": [ + "prompt", + ], + "type": "object", }, - "required": [ - "prompt", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: write_file 1`] = ` { - "description": "Writes content to a specified file in the local filesystem. + "declaration": { + "description": "Writes content to a specified file in the local filesystem. The user has the ability to modify \`content\`. If modified, this will be stated in the response.", - "name": "write_file", - "parametersJsonSchema": { - "properties": { - "content": { - "description": "The content to write to the file.", - "type": "string", - }, - "file_path": { - "description": "The path to the file to write to.", - "type": "string", + "name": "write_file", + "parametersJsonSchema": { + "properties": { + "content": { + "description": "The content to write to the file.", + "type": "string", + }, + "file_path": { + "description": "The path to the file to write to.", + "type": "string", + }, }, + "required": [ + "file_path", + "content", + ], + "type": "object", }, - "required": [ - "file_path", - "content", - ], - "type": "object", }, + "instructions": undefined, } `; exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview > snapshot for tool: write_todos 1`] = ` { - "description": "This tool can help you list out the current subtasks that are required to be completed for a given user request. The list of subtasks helps you keep track of the current task, organize complex queries and help ensure that you don't miss any steps. With this list, the user can also see the current progress you are making in executing a given task. + "declaration": { + "description": "This tool can help you list out the current subtasks that are required to be completed for a given user request. The list of subtasks helps you keep track of the current task, organize complex queries and help ensure that you don't miss any steps. With this list, the user can also see the current progress you are making in executing a given task. Depending on the task complexity, you should first divide a given task into subtasks and then use this tool to list out the subtasks that are required to be completed for a given user request. Each of the subtasks should be clear and distinct. @@ -1521,6 +1634,46 @@ Agent: The agent did not use the todo list because this task could be completed by a tight loop of execute test->edit->execute test. ", + "name": "write_todos", + "parametersJsonSchema": { + "additionalProperties": false, + "properties": { + "todos": { + "description": "The complete list of todo items. This will replace the existing list.", + "items": { + "additionalProperties": false, + "description": "A single todo item.", + "properties": { + "description": { + "description": "The description of the task.", + "type": "string", + }, + "status": { + "description": "The current status of the task.", + "enum": [ + "pending", + "in_progress", + "completed", + "cancelled", + ], + "type": "string", + }, + }, + "required": [ + "description", + "status", + ], + "type": "object", + }, + "type": "array", + }, + }, + "required": [ + "todos", + ], + "type": "object", + }, + }, "instructions": " ## Task state definitions @@ -1538,44 +1691,5 @@ The agent did not use the todo list because this task could be completed by a ti 5. Mark a subtask as completed when you have completed it. 6. Mark a subtask as cancelled if the subtask is no longer needed. 7. You must update the todo list as soon as you start, stop or cancel a subtask. Don't batch or wait to update the todo list.", - "name": "write_todos", - "parametersJsonSchema": { - "additionalProperties": false, - "properties": { - "todos": { - "description": "The complete list of todo items. This will replace the existing list.", - "items": { - "additionalProperties": false, - "description": "A single todo item.", - "properties": { - "description": { - "description": "The description of the task.", - "type": "string", - }, - "status": { - "description": "The current status of the task.", - "enum": [ - "pending", - "in_progress", - "completed", - "cancelled", - ], - "type": "string", - }, - }, - "required": [ - "description", - "status", - ], - "type": "object", - }, - "type": "array", - }, - }, - "required": [ - "todos", - ], - "type": "object", - }, } `; diff --git a/packages/core/src/tools/definitions/resolver.ts b/packages/core/src/tools/definitions/resolver.ts index 081f63ee75..975169b55b 100644 --- a/packages/core/src/tools/definitions/resolver.ts +++ b/packages/core/src/tools/definitions/resolver.ts @@ -12,23 +12,38 @@ import type { ToolDefinition } from './types.js'; * * @param definition The tool definition containing the base declaration and optional overrides. * @param modelId Optional model identifier to apply specific overrides. - * @returns The FunctionDeclaration to be sent to the API. + * @returns An object containing the FunctionDeclaration for the API and optional instructions for the system prompt. */ export function resolveToolDeclaration( definition: ToolDefinition, modelId?: string, -): FunctionDeclaration & { instructions?: string } { +): { declaration: FunctionDeclaration; instructions?: string } { + const { instructions: baseInstructions, ...baseDeclaration } = + definition.base; + if (!modelId || !definition.overrides) { - return definition.base; + return { + declaration: baseDeclaration, + instructions: baseInstructions, + }; } const override = definition.overrides(modelId); if (!override) { - return definition.base; + return { + declaration: baseDeclaration, + instructions: baseInstructions, + }; } + const { instructions: overrideInstructions, ...overrideDeclaration } = + override; + return { - ...definition.base, - ...override, + declaration: { + ...baseDeclaration, + ...overrideDeclaration, + }, + instructions: overrideInstructions ?? baseInstructions, }; } diff --git a/packages/core/src/tools/edit.ts b/packages/core/src/tools/edit.ts index 3504261fe3..12766c3dbc 100644 --- a/packages/core/src/tools/edit.ts +++ b/packages/core/src/tools/edit.ts @@ -914,19 +914,22 @@ export class EditTool typeof config.getActiveModel === 'function' ? config.getActiveModel() : undefined; - const resolved = resolveToolDeclaration(EDIT_DEFINITION, modelId); + const { declaration, instructions } = resolveToolDeclaration( + EDIT_DEFINITION, + modelId, + ); super( EditTool.Name, EDIT_DISPLAY_NAME, - resolved.description!, + declaration.description!, Kind.Edit, - resolved.parametersJsonSchema, + declaration.parametersJsonSchema, messageBus, true, // isOutputMarkdown false, // canUpdateOutput undefined, // extensionName undefined, // extensionId - resolved.instructions, + instructions, ); } @@ -970,7 +973,7 @@ export class EditTool } override getSchema(modelId?: string) { - return resolveToolDeclaration(EDIT_DEFINITION, modelId); + return resolveToolDeclaration(EDIT_DEFINITION, modelId).declaration; } getModifyContext(_: AbortSignal): ModifyContext { diff --git a/packages/core/src/tools/read-file.ts b/packages/core/src/tools/read-file.ts index c43f79ded0..c91e30b8a8 100644 --- a/packages/core/src/tools/read-file.ts +++ b/packages/core/src/tools/read-file.ts @@ -243,6 +243,6 @@ export class ReadFileTool extends BaseDeclarativeTool< } override getSchema(modelId?: string) { - return resolveToolDeclaration(READ_FILE_DEFINITION, modelId); + return resolveToolDeclaration(READ_FILE_DEFINITION, modelId).declaration; } } diff --git a/packages/core/src/tools/read-many-files.ts b/packages/core/src/tools/read-many-files.ts index 0a5d68a6ba..e08b535aa0 100644 --- a/packages/core/src/tools/read-many-files.ts +++ b/packages/core/src/tools/read-many-files.ts @@ -493,6 +493,7 @@ export class ReadManyFilesTool extends BaseDeclarativeTool< } override getSchema(modelId?: string) { - return resolveToolDeclaration(READ_MANY_FILES_DEFINITION, modelId); + return resolveToolDeclaration(READ_MANY_FILES_DEFINITION, modelId) + .declaration; } } diff --git a/packages/core/src/tools/shell.ts b/packages/core/src/tools/shell.ts index 4b0bcbb2b9..456c98cd64 100644 --- a/packages/core/src/tools/shell.ts +++ b/packages/core/src/tools/shell.ts @@ -474,19 +474,22 @@ export class ShellTool extends BaseDeclarativeTool< config.getEnableInteractiveShell(), config.getEnableShellOutputEfficiency(), ); - const resolved = resolveToolDeclaration(definition, modelId); + const { declaration, instructions } = resolveToolDeclaration( + definition, + modelId, + ); super( ShellTool.Name, 'Shell', - resolved.description!, + declaration.description!, Kind.Execute, - resolved.parametersJsonSchema, + declaration.parametersJsonSchema, messageBus, false, // output is not markdown true, // output can be updated undefined, // extensionName undefined, // extensionId - resolved.instructions, + instructions, ); } @@ -527,6 +530,6 @@ export class ShellTool extends BaseDeclarativeTool< this.config.getEnableInteractiveShell(), this.config.getEnableShellOutputEfficiency(), ); - return resolveToolDeclaration(definition, modelId); + return resolveToolDeclaration(definition, modelId).declaration; } } diff --git a/packages/core/src/tools/write-todos.test.ts b/packages/core/src/tools/write-todos.test.ts index 117a3d2681..c0b1bb1d3d 100644 --- a/packages/core/src/tools/write-todos.test.ts +++ b/packages/core/src/tools/write-todos.test.ts @@ -7,9 +7,10 @@ import { describe, expect, it } from 'vitest'; import { WriteTodosTool, type WriteTodosToolParams } from './write-todos.js'; import { createMockMessageBus } from '../test-utils/mock-message-bus.js'; +import { makeFakeConfig } from '../test-utils/config.js'; describe('WriteTodosTool', () => { - const tool = new WriteTodosTool(createMockMessageBus()); + const tool = new WriteTodosTool(makeFakeConfig(), createMockMessageBus()); const signal = new AbortController().signal; describe('validation', () => { diff --git a/packages/core/src/tools/write-todos.ts b/packages/core/src/tools/write-todos.ts index 560abe9cfd..c8838626cf 100644 --- a/packages/core/src/tools/write-todos.ts +++ b/packages/core/src/tools/write-todos.ts @@ -90,24 +90,33 @@ export class WriteTodosTool extends BaseDeclarativeTool< typeof config.getActiveModel === 'function' ? config.getActiveModel() : undefined; - const resolved = resolveToolDeclaration(WRITE_TODOS_DEFINITION, modelId); + const { declaration, instructions } = resolveToolDeclaration( + WRITE_TODOS_DEFINITION, + modelId, + ); super( WriteTodosTool.Name, 'WriteTodos', - resolved.description!, + declaration.description!, Kind.Other, - resolved.parametersJsonSchema, + declaration.parametersJsonSchema, messageBus, true, // isOutputMarkdown false, // canUpdateOutput undefined, // extensionName undefined, // extensionId - resolved.instructions, + instructions, ); } override getSchema(modelId?: string) { - return resolveToolDeclaration(WRITE_TODOS_DEFINITION, modelId); + const activeModel = + modelId ?? + (typeof this.config.getActiveModel === 'function' + ? this.config.getActiveModel() + : undefined); + return resolveToolDeclaration(WRITE_TODOS_DEFINITION, activeModel) + .declaration; } protected override validateToolParamValues(