fix: Push tool calls to absolute paths (#1055) (#1057)

Make several changes to guide the model to request absolute paths,
reducing frequent accidental relative path tool call failures.

- Switch the parameter name: path --> absolute_path.
- Update the tool definition to strongly require an absolute path.
- Update the system prompt to indicate absolute paths are required.
- Update the system prompt tool use examples to use absolute paths.

Test case:

Open GC in GC: "Locate the primary file calling genai"
- Expected: Model opens files with absolute path, successfully.
- Actual (pre-patch): Failure, attempts to read with relative path.
- Actual (post-patch): Success, attempts to read with absolute path.
This commit is contained in:
Keir Mierle 2025-06-14 21:16:11 -07:00 committed by GitHub
parent e30e650a77
commit 32dd298351
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 82 additions and 68 deletions

View file

@ -34,7 +34,7 @@ The core comes with a suite of pre-defined tools, typically found in `packages/c
- **File System Tools:** - **File System Tools:**
- `LSTool` (`ls.ts`): Lists directory contents. - `LSTool` (`ls.ts`): Lists directory contents.
- `ReadFileTool` (`read-file.ts`): Reads the content of a single file. - `ReadFileTool` (`read-file.ts`): Reads the content of a single file. It takes an `absolute_path` parameter, which must be an absolute path.
- `WriteFileTool` (`write-file.ts`): Writes content to a file. - `WriteFileTool` (`write-file.ts`): Writes content to a file.
- `GrepTool` (`grep.ts`): Searches for patterns in files. - `GrepTool` (`grep.ts`): Searches for patterns in files.
- `GlobTool` (`glob.ts`): Finds files matching glob patterns. - `GlobTool` (`glob.ts`): Finds files matching glob patterns.

View file

@ -75,6 +75,7 @@ When asked to refactor code, follow this specialized sequence to ensure safety a
- **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information. - **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information.
## Tool Usage ## Tool Usage
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
- **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase). - **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
- **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first. - **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user. - **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
@ -119,11 +120,11 @@ user: Refactor the auth logic in src/auth.py to use the requests library instead
model: Okay, I can refactor 'src/auth.py'. model: Okay, I can refactor 'src/auth.py'.
First, I'll analyze the code and check for a test safety net before planning any changes. First, I'll analyze the code and check for a test safety net before planning any changes.
[tool_call: glob for path 'tests/test_auth.py'] [tool_call: glob for path 'tests/test_auth.py']
[tool_call: read_file for path 'tests/test_auth.py'] [tool_call: read_file for absolute_path '/path/to/tests/test_auth.py']
(After analysis) (After analysis)
Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring. Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring.
I'll also confirm 'requests' is a dependency. I'll also confirm 'requests' is a dependency.
[tool_call: read_file for path 'requirements.txt'] [tool_call: read_file for absolute_path '/path/to/requirements.txt']
(After analysis) (After analysis)
Looks good, 'requests' is available. Looks good, 'requests' is available.
@ -153,7 +154,7 @@ model: I can run \`rm -rf ./temp\`. This will permanently delete the directory a
user: Write tests for someFile.ts user: Write tests for someFile.ts
model: model:
Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality. Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality.
[tool_call: read_file to read /path/to/someFile.ts or use glob to find \`someFile.ts\` if its location is unknown] [tool_call: read_file for absolute_path '/path/to/someFile.ts' or use glob to find \`someFile.ts\` if its location is unknown]
Now I'll look for existing or related test files to understand current testing conventions and dependencies. Now I'll look for existing or related test files to understand current testing conventions and dependencies.
[tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory] [tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory]
(After reviewing existing tests and the file content) (After reviewing existing tests and the file content)
@ -169,7 +170,7 @@ I'm not immediately sure how user profile information is updated. I'll search th
[tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser'] [tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser']
(After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found) (After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found)
Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled. Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled.
[tool_call: read_file to read /path/to/UserProfileService.java] [tool_call: read_file for absolute_path '/path/to/UserProfileService.java']
(After reading the file) (After reading the file)
It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object... It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object...
</example> </example>
@ -269,6 +270,7 @@ When asked to refactor code, follow this specialized sequence to ensure safety a
- **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information. - **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information.
## Tool Usage ## Tool Usage
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
- **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase). - **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
- **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first. - **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user. - **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
@ -328,11 +330,11 @@ user: Refactor the auth logic in src/auth.py to use the requests library instead
model: Okay, I can refactor 'src/auth.py'. model: Okay, I can refactor 'src/auth.py'.
First, I'll analyze the code and check for a test safety net before planning any changes. First, I'll analyze the code and check for a test safety net before planning any changes.
[tool_call: glob for path 'tests/test_auth.py'] [tool_call: glob for path 'tests/test_auth.py']
[tool_call: read_file for path 'tests/test_auth.py'] [tool_call: read_file for absolute_path '/path/to/tests/test_auth.py']
(After analysis) (After analysis)
Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring. Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring.
I'll also confirm 'requests' is a dependency. I'll also confirm 'requests' is a dependency.
[tool_call: read_file for path 'requirements.txt'] [tool_call: read_file for absolute_path '/path/to/requirements.txt']
(After analysis) (After analysis)
Looks good, 'requests' is available. Looks good, 'requests' is available.
@ -362,7 +364,7 @@ model: I can run \`rm -rf ./temp\`. This will permanently delete the directory a
user: Write tests for someFile.ts user: Write tests for someFile.ts
model: model:
Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality. Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality.
[tool_call: read_file to read /path/to/someFile.ts or use glob to find \`someFile.ts\` if its location is unknown] [tool_call: read_file for absolute_path '/path/to/someFile.ts' or use glob to find \`someFile.ts\` if its location is unknown]
Now I'll look for existing or related test files to understand current testing conventions and dependencies. Now I'll look for existing or related test files to understand current testing conventions and dependencies.
[tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory] [tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory]
(After reviewing existing tests and the file content) (After reviewing existing tests and the file content)
@ -378,7 +380,7 @@ I'm not immediately sure how user profile information is updated. I'll search th
[tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser'] [tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser']
(After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found) (After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found)
Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled. Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled.
[tool_call: read_file to read /path/to/UserProfileService.java] [tool_call: read_file for absolute_path '/path/to/UserProfileService.java']
(After reading the file) (After reading the file)
It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object... It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object...
</example> </example>
@ -473,6 +475,7 @@ When asked to refactor code, follow this specialized sequence to ensure safety a
- **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information. - **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information.
## Tool Usage ## Tool Usage
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
- **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase). - **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
- **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first. - **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user. - **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
@ -517,11 +520,11 @@ user: Refactor the auth logic in src/auth.py to use the requests library instead
model: Okay, I can refactor 'src/auth.py'. model: Okay, I can refactor 'src/auth.py'.
First, I'll analyze the code and check for a test safety net before planning any changes. First, I'll analyze the code and check for a test safety net before planning any changes.
[tool_call: glob for path 'tests/test_auth.py'] [tool_call: glob for path 'tests/test_auth.py']
[tool_call: read_file for path 'tests/test_auth.py'] [tool_call: read_file for absolute_path '/path/to/tests/test_auth.py']
(After analysis) (After analysis)
Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring. Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring.
I'll also confirm 'requests' is a dependency. I'll also confirm 'requests' is a dependency.
[tool_call: read_file for path 'requirements.txt'] [tool_call: read_file for absolute_path '/path/to/requirements.txt']
(After analysis) (After analysis)
Looks good, 'requests' is available. Looks good, 'requests' is available.
@ -551,7 +554,7 @@ model: I can run \`rm -rf ./temp\`. This will permanently delete the directory a
user: Write tests for someFile.ts user: Write tests for someFile.ts
model: model:
Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality. Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality.
[tool_call: read_file to read /path/to/someFile.ts or use glob to find \`someFile.ts\` if its location is unknown] [tool_call: read_file for absolute_path '/path/to/someFile.ts' or use glob to find \`someFile.ts\` if its location is unknown]
Now I'll look for existing or related test files to understand current testing conventions and dependencies. Now I'll look for existing or related test files to understand current testing conventions and dependencies.
[tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory] [tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory]
(After reviewing existing tests and the file content) (After reviewing existing tests and the file content)
@ -567,7 +570,7 @@ I'm not immediately sure how user profile information is updated. I'll search th
[tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser'] [tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser']
(After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found) (After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found)
Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled. Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled.
[tool_call: read_file to read /path/to/UserProfileService.java] [tool_call: read_file for absolute_path '/path/to/UserProfileService.java']
(After reading the file) (After reading the file)
It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object... It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object...
</example> </example>
@ -662,6 +665,7 @@ When asked to refactor code, follow this specialized sequence to ensure safety a
- **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information. - **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information.
## Tool Usage ## Tool Usage
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
- **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase). - **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
- **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first. - **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user. - **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
@ -706,11 +710,11 @@ user: Refactor the auth logic in src/auth.py to use the requests library instead
model: Okay, I can refactor 'src/auth.py'. model: Okay, I can refactor 'src/auth.py'.
First, I'll analyze the code and check for a test safety net before planning any changes. First, I'll analyze the code and check for a test safety net before planning any changes.
[tool_call: glob for path 'tests/test_auth.py'] [tool_call: glob for path 'tests/test_auth.py']
[tool_call: read_file for path 'tests/test_auth.py'] [tool_call: read_file for absolute_path '/path/to/tests/test_auth.py']
(After analysis) (After analysis)
Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring. Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring.
I'll also confirm 'requests' is a dependency. I'll also confirm 'requests' is a dependency.
[tool_call: read_file for path 'requirements.txt'] [tool_call: read_file for absolute_path '/path/to/requirements.txt']
(After analysis) (After analysis)
Looks good, 'requests' is available. Looks good, 'requests' is available.
@ -740,7 +744,7 @@ model: I can run \`rm -rf ./temp\`. This will permanently delete the directory a
user: Write tests for someFile.ts user: Write tests for someFile.ts
model: model:
Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality. Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality.
[tool_call: read_file to read /path/to/someFile.ts or use glob to find \`someFile.ts\` if its location is unknown] [tool_call: read_file for absolute_path '/path/to/someFile.ts' or use glob to find \`someFile.ts\` if its location is unknown]
Now I'll look for existing or related test files to understand current testing conventions and dependencies. Now I'll look for existing or related test files to understand current testing conventions and dependencies.
[tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory] [tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory]
(After reviewing existing tests and the file content) (After reviewing existing tests and the file content)
@ -756,7 +760,7 @@ I'm not immediately sure how user profile information is updated. I'll search th
[tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser'] [tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser']
(After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found) (After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found)
Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled. Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled.
[tool_call: read_file to read /path/to/UserProfileService.java] [tool_call: read_file for absolute_path '/path/to/UserProfileService.java']
(After reading the file) (After reading the file)
It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object... It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object...
</example> </example>
@ -851,6 +855,7 @@ When asked to refactor code, follow this specialized sequence to ensure safety a
- **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information. - **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information.
## Tool Usage ## Tool Usage
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
- **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase). - **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
- **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first. - **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user. - **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
@ -895,11 +900,11 @@ user: Refactor the auth logic in src/auth.py to use the requests library instead
model: Okay, I can refactor 'src/auth.py'. model: Okay, I can refactor 'src/auth.py'.
First, I'll analyze the code and check for a test safety net before planning any changes. First, I'll analyze the code and check for a test safety net before planning any changes.
[tool_call: glob for path 'tests/test_auth.py'] [tool_call: glob for path 'tests/test_auth.py']
[tool_call: read_file for path 'tests/test_auth.py'] [tool_call: read_file for absolute_path '/path/to/tests/test_auth.py']
(After analysis) (After analysis)
Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring. Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring.
I'll also confirm 'requests' is a dependency. I'll also confirm 'requests' is a dependency.
[tool_call: read_file for path 'requirements.txt'] [tool_call: read_file for absolute_path '/path/to/requirements.txt']
(After analysis) (After analysis)
Looks good, 'requests' is available. Looks good, 'requests' is available.
@ -929,7 +934,7 @@ model: I can run \`rm -rf ./temp\`. This will permanently delete the directory a
user: Write tests for someFile.ts user: Write tests for someFile.ts
model: model:
Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality. Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality.
[tool_call: read_file to read /path/to/someFile.ts or use glob to find \`someFile.ts\` if its location is unknown] [tool_call: read_file for absolute_path '/path/to/someFile.ts' or use glob to find \`someFile.ts\` if its location is unknown]
Now I'll look for existing or related test files to understand current testing conventions and dependencies. Now I'll look for existing or related test files to understand current testing conventions and dependencies.
[tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory] [tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory]
(After reviewing existing tests and the file content) (After reviewing existing tests and the file content)
@ -945,7 +950,7 @@ I'm not immediately sure how user profile information is updated. I'll search th
[tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser'] [tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser']
(After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found) (After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found)
Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled. Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled.
[tool_call: read_file to read /path/to/UserProfileService.java] [tool_call: read_file for absolute_path '/path/to/UserProfileService.java']
(After reading the file) (After reading the file)
It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object... It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object...
</example> </example>
@ -1040,6 +1045,7 @@ When asked to refactor code, follow this specialized sequence to ensure safety a
- **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information. - **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information.
## Tool Usage ## Tool Usage
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
- **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase). - **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
- **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first. - **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user. - **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
@ -1084,11 +1090,11 @@ user: Refactor the auth logic in src/auth.py to use the requests library instead
model: Okay, I can refactor 'src/auth.py'. model: Okay, I can refactor 'src/auth.py'.
First, I'll analyze the code and check for a test safety net before planning any changes. First, I'll analyze the code and check for a test safety net before planning any changes.
[tool_call: glob for path 'tests/test_auth.py'] [tool_call: glob for path 'tests/test_auth.py']
[tool_call: read_file for path 'tests/test_auth.py'] [tool_call: read_file for absolute_path '/path/to/tests/test_auth.py']
(After analysis) (After analysis)
Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring. Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring.
I'll also confirm 'requests' is a dependency. I'll also confirm 'requests' is a dependency.
[tool_call: read_file for path 'requirements.txt'] [tool_call: read_file for absolute_path '/path/to/requirements.txt']
(After analysis) (After analysis)
Looks good, 'requests' is available. Looks good, 'requests' is available.
@ -1118,7 +1124,7 @@ model: I can run \`rm -rf ./temp\`. This will permanently delete the directory a
user: Write tests for someFile.ts user: Write tests for someFile.ts
model: model:
Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality. Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality.
[tool_call: read_file to read /path/to/someFile.ts or use glob to find \`someFile.ts\` if its location is unknown] [tool_call: read_file for absolute_path '/path/to/someFile.ts' or use glob to find \`someFile.ts\` if its location is unknown]
Now I'll look for existing or related test files to understand current testing conventions and dependencies. Now I'll look for existing or related test files to understand current testing conventions and dependencies.
[tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory] [tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory]
(After reviewing existing tests and the file content) (After reviewing existing tests and the file content)
@ -1134,7 +1140,7 @@ I'm not immediately sure how user profile information is updated. I'll search th
[tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser'] [tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser']
(After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found) (After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found)
Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled. Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled.
[tool_call: read_file to read /path/to/UserProfileService.java] [tool_call: read_file for absolute_path '/path/to/UserProfileService.java']
(After reading the file) (After reading the file)
It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object... It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object...
</example> </example>
@ -1229,6 +1235,7 @@ When asked to refactor code, follow this specialized sequence to ensure safety a
- **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information. - **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information.
## Tool Usage ## Tool Usage
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
- **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase). - **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
- **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first. - **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user. - **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
@ -1273,11 +1280,11 @@ user: Refactor the auth logic in src/auth.py to use the requests library instead
model: Okay, I can refactor 'src/auth.py'. model: Okay, I can refactor 'src/auth.py'.
First, I'll analyze the code and check for a test safety net before planning any changes. First, I'll analyze the code and check for a test safety net before planning any changes.
[tool_call: glob for path 'tests/test_auth.py'] [tool_call: glob for path 'tests/test_auth.py']
[tool_call: read_file for path 'tests/test_auth.py'] [tool_call: read_file for absolute_path '/path/to/tests/test_auth.py']
(After analysis) (After analysis)
Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring. Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring.
I'll also confirm 'requests' is a dependency. I'll also confirm 'requests' is a dependency.
[tool_call: read_file for path 'requirements.txt'] [tool_call: read_file for absolute_path '/path/to/requirements.txt']
(After analysis) (After analysis)
Looks good, 'requests' is available. Looks good, 'requests' is available.
@ -1307,7 +1314,7 @@ model: I can run \`rm -rf ./temp\`. This will permanently delete the directory a
user: Write tests for someFile.ts user: Write tests for someFile.ts
model: model:
Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality. Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality.
[tool_call: read_file to read /path/to/someFile.ts or use glob to find \`someFile.ts\` if its location is unknown] [tool_call: read_file for absolute_path '/path/to/someFile.ts' or use glob to find \`someFile.ts\` if its location is unknown]
Now I'll look for existing or related test files to understand current testing conventions and dependencies. Now I'll look for existing or related test files to understand current testing conventions and dependencies.
[tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory] [tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory]
(After reviewing existing tests and the file content) (After reviewing existing tests and the file content)
@ -1323,7 +1330,7 @@ I'm not immediately sure how user profile information is updated. I'll search th
[tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser'] [tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser']
(After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found) (After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found)
Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled. Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled.
[tool_call: read_file to read /path/to/UserProfileService.java] [tool_call: read_file for absolute_path '/path/to/UserProfileService.java']
(After reading the file) (After reading the file)
It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object... It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object...
</example> </example>
@ -1418,6 +1425,7 @@ When asked to refactor code, follow this specialized sequence to ensure safety a
- **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information. - **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information.
## Tool Usage ## Tool Usage
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
- **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase). - **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
- **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first. - **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user. - **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
@ -1462,11 +1470,11 @@ user: Refactor the auth logic in src/auth.py to use the requests library instead
model: Okay, I can refactor 'src/auth.py'. model: Okay, I can refactor 'src/auth.py'.
First, I'll analyze the code and check for a test safety net before planning any changes. First, I'll analyze the code and check for a test safety net before planning any changes.
[tool_call: glob for path 'tests/test_auth.py'] [tool_call: glob for path 'tests/test_auth.py']
[tool_call: read_file for path 'tests/test_auth.py'] [tool_call: read_file for absolute_path '/path/to/tests/test_auth.py']
(After analysis) (After analysis)
Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring. Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring.
I'll also confirm 'requests' is a dependency. I'll also confirm 'requests' is a dependency.
[tool_call: read_file for path 'requirements.txt'] [tool_call: read_file for absolute_path '/path/to/requirements.txt']
(After analysis) (After analysis)
Looks good, 'requests' is available. Looks good, 'requests' is available.
@ -1496,7 +1504,7 @@ model: I can run \`rm -rf ./temp\`. This will permanently delete the directory a
user: Write tests for someFile.ts user: Write tests for someFile.ts
model: model:
Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality. Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality.
[tool_call: read_file to read /path/to/someFile.ts or use glob to find \`someFile.ts\` if its location is unknown] [tool_call: read_file for absolute_path '/path/to/someFile.ts' or use glob to find \`someFile.ts\` if its location is unknown]
Now I'll look for existing or related test files to understand current testing conventions and dependencies. Now I'll look for existing or related test files to understand current testing conventions and dependencies.
[tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory] [tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory]
(After reviewing existing tests and the file content) (After reviewing existing tests and the file content)
@ -1512,7 +1520,7 @@ I'm not immediately sure how user profile information is updated. I'll search th
[tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser'] [tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser']
(After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found) (After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found)
Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled. Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled.
[tool_call: read_file to read /path/to/UserProfileService.java] [tool_call: read_file for absolute_path '/path/to/UserProfileService.java']
(After reading the file) (After reading the file)
It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object... It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object...
</example> </example>
@ -1607,6 +1615,7 @@ When asked to refactor code, follow this specialized sequence to ensure safety a
- **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information. - **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information.
## Tool Usage ## Tool Usage
- **File Paths:** Always use absolute paths when referring to files with tools like 'read_file' or 'write_file'. Relative paths are not supported. You must provide an absolute path.
- **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase). - **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
- **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first. - **Command Execution:** Use the 'run_shell_command' tool for running shell commands, remembering the safety rule to explain modifying commands first.
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user. - **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
@ -1651,11 +1660,11 @@ user: Refactor the auth logic in src/auth.py to use the requests library instead
model: Okay, I can refactor 'src/auth.py'. model: Okay, I can refactor 'src/auth.py'.
First, I'll analyze the code and check for a test safety net before planning any changes. First, I'll analyze the code and check for a test safety net before planning any changes.
[tool_call: glob for path 'tests/test_auth.py'] [tool_call: glob for path 'tests/test_auth.py']
[tool_call: read_file for path 'tests/test_auth.py'] [tool_call: read_file for absolute_path '/path/to/tests/test_auth.py']
(After analysis) (After analysis)
Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring. Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring.
I'll also confirm 'requests' is a dependency. I'll also confirm 'requests' is a dependency.
[tool_call: read_file for path 'requirements.txt'] [tool_call: read_file for absolute_path '/path/to/requirements.txt']
(After analysis) (After analysis)
Looks good, 'requests' is available. Looks good, 'requests' is available.
@ -1685,7 +1694,7 @@ model: I can run \`rm -rf ./temp\`. This will permanently delete the directory a
user: Write tests for someFile.ts user: Write tests for someFile.ts
model: model:
Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality. Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality.
[tool_call: read_file to read /path/to/someFile.ts or use glob to find \`someFile.ts\` if its location is unknown] [tool_call: read_file for absolute_path '/path/to/someFile.ts' or use glob to find \`someFile.ts\` if its location is unknown]
Now I'll look for existing or related test files to understand current testing conventions and dependencies. Now I'll look for existing or related test files to understand current testing conventions and dependencies.
[tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory] [tool_call: read_many_files for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory]
(After reviewing existing tests and the file content) (After reviewing existing tests and the file content)
@ -1701,7 +1710,7 @@ I'm not immediately sure how user profile information is updated. I'll search th
[tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser'] [tool_call: search_file_content for pattern 'UserProfile|updateProfile|editUser']
(After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found) (After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found)
Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled. Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled.
[tool_call: read_file to read /path/to/UserProfileService.java] [tool_call: read_file for absolute_path '/path/to/UserProfileService.java']
(After reading the file) (After reading the file)
It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object... It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object...
</example> </example>

View file

@ -116,6 +116,7 @@ ${(function () {
- **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information. - **Security First:** Always apply security best practices. Never introduce code that exposes, logs, or commits secrets, API keys, or other sensitive information.
## Tool Usage ## Tool Usage
- **File Paths:** Always use absolute paths when referring to files with tools like '${ReadFileTool.Name}' or '${WriteFileTool.Name}'. Relative paths are not supported. You must provide an absolute path.
- **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase). - **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
- **Command Execution:** Use the '${ShellTool.Name}' tool for running shell commands, remembering the safety rule to explain modifying commands first. - **Command Execution:** Use the '${ShellTool.Name}' tool for running shell commands, remembering the safety rule to explain modifying commands first.
- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user. - **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
@ -198,11 +199,11 @@ user: Refactor the auth logic in src/auth.py to use the requests library instead
model: Okay, I can refactor 'src/auth.py'. model: Okay, I can refactor 'src/auth.py'.
First, I'll analyze the code and check for a test safety net before planning any changes. First, I'll analyze the code and check for a test safety net before planning any changes.
[tool_call: ${GlobTool.Name} for path 'tests/test_auth.py'] [tool_call: ${GlobTool.Name} for path 'tests/test_auth.py']
[tool_call: ${ReadFileTool.Name} for path 'tests/test_auth.py'] [tool_call: ${ReadFileTool.Name} for absolute_path '/path/to/tests/test_auth.py']
(After analysis) (After analysis)
Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring. Great, 'tests/test_auth.py' exists and covers the core authentication logic. With this safety net in place, I can safely plan the refactoring.
I'll also confirm 'requests' is a dependency. I'll also confirm 'requests' is a dependency.
[tool_call: ${ReadFileTool.Name} for path 'requirements.txt'] [tool_call: ${ReadFileTool.Name} for absolute_path '/path/to/requirements.txt']
(After analysis) (After analysis)
Looks good, 'requests' is available. Looks good, 'requests' is available.
@ -237,7 +238,7 @@ model: I can run \`rm -rf ./temp\`. This will permanently delete the directory a
user: Write tests for someFile.ts user: Write tests for someFile.ts
model: model:
Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality. Okay, I can write those tests. First, I'll read \`someFile.ts\` to understand its functionality.
[tool_call: ${ReadFileTool.Name} to read /path/to/someFile.ts or use ${GlobTool.Name} to find \`someFile.ts\` if its location is unknown] [tool_call: ${ReadFileTool.Name} for absolute_path '/path/to/someFile.ts' or use ${GlobTool.Name} to find \`someFile.ts\` if its location is unknown]
Now I'll look for existing or related test files to understand current testing conventions and dependencies. Now I'll look for existing or related test files to understand current testing conventions and dependencies.
[tool_call: ${ReadManyFilesTool.Name} for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory] [tool_call: ${ReadManyFilesTool.Name} for paths ['**/*.test.ts', 'src/**/*.spec.ts'] assuming someFile.ts is in the src directory]
(After reviewing existing tests and the file content) (After reviewing existing tests and the file content)
@ -253,7 +254,7 @@ I'm not immediately sure how user profile information is updated. I'll search th
[tool_call: ${GrepTool.Name} for pattern 'UserProfile|updateProfile|editUser'] [tool_call: ${GrepTool.Name} for pattern 'UserProfile|updateProfile|editUser']
(After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found) (After reviewing search results, assuming a relevant file like '/path/to/UserProfileService.java' was found)
Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled. Okay, \`/path/to/UserProfileService.java\` seems like the most relevant file. I'll read its content to understand how updates are handled.
[tool_call: ${ReadFileTool.Name} to read /path/to/UserProfileService.java] [tool_call: ${ReadFileTool.Name} for absolute_path '/path/to/UserProfileService.java']
(After reading the file) (After reading the file)
It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object... It appears the \`updateUserProfile\` method in \`UserProfileService.java\` is responsible for this. It expects a user ID and a \`UserProfileDTO\` object...
</example> </example>

View file

@ -57,14 +57,14 @@ describe('ReadFileTool', () => {
describe('validateToolParams', () => { describe('validateToolParams', () => {
it('should return null for valid params (absolute path within root)', () => { it('should return null for valid params (absolute path within root)', () => {
const params: ReadFileToolParams = { const params: ReadFileToolParams = {
path: path.join(tempRootDir, 'test.txt'), absolute_path: path.join(tempRootDir, 'test.txt'),
}; };
expect(tool.validateToolParams(params)).toBeNull(); expect(tool.validateToolParams(params)).toBeNull();
}); });
it('should return null for valid params with offset and limit', () => { it('should return null for valid params with offset and limit', () => {
const params: ReadFileToolParams = { const params: ReadFileToolParams = {
path: path.join(tempRootDir, 'test.txt'), absolute_path: path.join(tempRootDir, 'test.txt'),
offset: 0, offset: 0,
limit: 10, limit: 10,
}; };
@ -72,7 +72,7 @@ describe('ReadFileTool', () => {
}); });
it('should return error for relative path', () => { it('should return error for relative path', () => {
const params: ReadFileToolParams = { path: 'test.txt' }; const params: ReadFileToolParams = { absolute_path: 'test.txt' };
expect(tool.validateToolParams(params)).toMatch( expect(tool.validateToolParams(params)).toMatch(
/File path must be absolute/, /File path must be absolute/,
); );
@ -80,7 +80,7 @@ describe('ReadFileTool', () => {
it('should return error for path outside root', () => { it('should return error for path outside root', () => {
const outsidePath = path.resolve(os.tmpdir(), 'outside-root.txt'); const outsidePath = path.resolve(os.tmpdir(), 'outside-root.txt');
const params: ReadFileToolParams = { path: outsidePath }; const params: ReadFileToolParams = { absolute_path: outsidePath };
expect(tool.validateToolParams(params)).toMatch( expect(tool.validateToolParams(params)).toMatch(
/File path must be within the root directory/, /File path must be within the root directory/,
); );
@ -88,7 +88,7 @@ describe('ReadFileTool', () => {
it('should return error for negative offset', () => { it('should return error for negative offset', () => {
const params: ReadFileToolParams = { const params: ReadFileToolParams = {
path: path.join(tempRootDir, 'test.txt'), absolute_path: path.join(tempRootDir, 'test.txt'),
offset: -1, offset: -1,
limit: 10, limit: 10,
}; };
@ -99,7 +99,7 @@ describe('ReadFileTool', () => {
it('should return error for non-positive limit', () => { it('should return error for non-positive limit', () => {
const paramsZero: ReadFileToolParams = { const paramsZero: ReadFileToolParams = {
path: path.join(tempRootDir, 'test.txt'), absolute_path: path.join(tempRootDir, 'test.txt'),
offset: 0, offset: 0,
limit: 0, limit: 0,
}; };
@ -107,7 +107,7 @@ describe('ReadFileTool', () => {
'Limit must be a positive number', 'Limit must be a positive number',
); );
const paramsNegative: ReadFileToolParams = { const paramsNegative: ReadFileToolParams = {
path: path.join(tempRootDir, 'test.txt'), absolute_path: path.join(tempRootDir, 'test.txt'),
offset: 0, offset: 0,
limit: -5, limit: -5,
}; };
@ -127,21 +127,21 @@ describe('ReadFileTool', () => {
describe('getDescription', () => { describe('getDescription', () => {
it('should return a shortened, relative path', () => { it('should return a shortened, relative path', () => {
const filePath = path.join(tempRootDir, 'sub', 'dir', 'file.txt'); const filePath = path.join(tempRootDir, 'sub', 'dir', 'file.txt');
const params: ReadFileToolParams = { path: filePath }; const params: ReadFileToolParams = { absolute_path: filePath };
// Assuming tempRootDir is something like /tmp/read-file-tool-root-XXXXXX // Assuming tempRootDir is something like /tmp/read-file-tool-root-XXXXXX
// The relative path would be sub/dir/file.txt // The relative path would be sub/dir/file.txt
expect(tool.getDescription(params)).toBe('sub/dir/file.txt'); expect(tool.getDescription(params)).toBe('sub/dir/file.txt');
}); });
it('should return . if path is the root directory', () => { it('should return . if path is the root directory', () => {
const params: ReadFileToolParams = { path: tempRootDir }; const params: ReadFileToolParams = { absolute_path: tempRootDir };
expect(tool.getDescription(params)).toBe('.'); expect(tool.getDescription(params)).toBe('.');
}); });
}); });
describe('execute', () => { describe('execute', () => {
it('should return validation error if params are invalid', async () => { it('should return validation error if params are invalid', async () => {
const params: ReadFileToolParams = { path: 'relative/path.txt' }; const params: ReadFileToolParams = { absolute_path: 'relative/path.txt' };
const result = await tool.execute(params, abortSignal); const result = await tool.execute(params, abortSignal);
expect(result.llmContent).toMatch(/Error: Invalid parameters provided/); expect(result.llmContent).toMatch(/Error: Invalid parameters provided/);
expect(result.returnDisplay).toMatch(/File path must be absolute/); expect(result.returnDisplay).toMatch(/File path must be absolute/);
@ -149,7 +149,7 @@ describe('ReadFileTool', () => {
it('should return error from processSingleFileContent if it fails', async () => { it('should return error from processSingleFileContent if it fails', async () => {
const filePath = path.join(tempRootDir, 'error.txt'); const filePath = path.join(tempRootDir, 'error.txt');
const params: ReadFileToolParams = { path: filePath }; const params: ReadFileToolParams = { absolute_path: filePath };
const errorMessage = 'Simulated read error'; const errorMessage = 'Simulated read error';
mockProcessSingleFileContent.mockResolvedValue({ mockProcessSingleFileContent.mockResolvedValue({
llmContent: `Error reading file ${filePath}: ${errorMessage}`, llmContent: `Error reading file ${filePath}: ${errorMessage}`,
@ -171,7 +171,7 @@ describe('ReadFileTool', () => {
it('should return success result for a text file', async () => { it('should return success result for a text file', async () => {
const filePath = path.join(tempRootDir, 'textfile.txt'); const filePath = path.join(tempRootDir, 'textfile.txt');
const fileContent = 'This is a test file.'; const fileContent = 'This is a test file.';
const params: ReadFileToolParams = { path: filePath }; const params: ReadFileToolParams = { absolute_path: filePath };
mockProcessSingleFileContent.mockResolvedValue({ mockProcessSingleFileContent.mockResolvedValue({
llmContent: fileContent, llmContent: fileContent,
returnDisplay: `Read text file: ${path.basename(filePath)}`, returnDisplay: `Read text file: ${path.basename(filePath)}`,
@ -195,7 +195,7 @@ describe('ReadFileTool', () => {
const imageData = { const imageData = {
inlineData: { mimeType: 'image/png', data: 'base64...' }, inlineData: { mimeType: 'image/png', data: 'base64...' },
}; };
const params: ReadFileToolParams = { path: filePath }; const params: ReadFileToolParams = { absolute_path: filePath };
mockProcessSingleFileContent.mockResolvedValue({ mockProcessSingleFileContent.mockResolvedValue({
llmContent: imageData, llmContent: imageData,
returnDisplay: `Read image file: ${path.basename(filePath)}`, returnDisplay: `Read image file: ${path.basename(filePath)}`,
@ -217,7 +217,7 @@ describe('ReadFileTool', () => {
it('should pass offset and limit to processSingleFileContent', async () => { it('should pass offset and limit to processSingleFileContent', async () => {
const filePath = path.join(tempRootDir, 'paginated.txt'); const filePath = path.join(tempRootDir, 'paginated.txt');
const params: ReadFileToolParams = { const params: ReadFileToolParams = {
path: filePath, absolute_path: filePath,
offset: 10, offset: 10,
limit: 5, limit: 5,
}; };
@ -237,7 +237,7 @@ describe('ReadFileTool', () => {
it('should return error if path is ignored by a .geminiignore pattern', async () => { it('should return error if path is ignored by a .geminiignore pattern', async () => {
const params: ReadFileToolParams = { const params: ReadFileToolParams = {
path: path.join(tempRootDir, 'foo.bar'), absolute_path: path.join(tempRootDir, 'foo.bar'),
}; };
const result = await tool.execute(params, abortSignal); const result = await tool.execute(params, abortSignal);
expect(result.returnDisplay).toContain('foo.bar'); expect(result.returnDisplay).toContain('foo.bar');

View file

@ -18,7 +18,7 @@ export interface ReadFileToolParams {
/** /**
* The absolute path to the file to read * The absolute path to the file to read
*/ */
path: string; absolute_path: string;
/** /**
* The line number to start reading from (optional) * The line number to start reading from (optional)
@ -47,10 +47,11 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> {
'Reads and returns the content of a specified file from the local filesystem. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), and PDF files. For text files, it can read specific line ranges.', 'Reads and returns the content of a specified file from the local filesystem. Handles text, images (PNG, JPG, GIF, WEBP, SVG, BMP), and PDF files. For text files, it can read specific line ranges.',
{ {
properties: { properties: {
path: { absolute_path: {
description: description:
"The absolute path to the file to read (e.g., '/home/user/project/file.txt'). Relative paths are not supported.", "The absolute path to the file to read (e.g., '/home/user/project/file.txt'). Relative paths are not supported. You must provide an absolute path.",
type: 'string', type: 'string',
pattern: '^/',
}, },
offset: { offset: {
description: description:
@ -63,7 +64,7 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> {
type: 'number', type: 'number',
}, },
}, },
required: ['path'], required: ['absolute_path'],
type: 'object', type: 'object',
}, },
); );
@ -80,9 +81,9 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> {
) { ) {
return 'Parameters failed schema validation.'; return 'Parameters failed schema validation.';
} }
const filePath = params.path; const filePath = params.absolute_path;
if (!path.isAbsolute(filePath)) { if (!path.isAbsolute(filePath)) {
return `File path must be absolute: ${filePath}`; return `File path must be absolute, but was relative: ${filePath}. You must provide an absolute path.`;
} }
if (!isWithinRoot(filePath, this.rootDirectory)) { if (!isWithinRoot(filePath, this.rootDirectory)) {
return `File path must be within the root directory (${this.rootDirectory}): ${filePath}`; return `File path must be within the root directory (${this.rootDirectory}): ${filePath}`;
@ -95,8 +96,11 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> {
} }
const fileService = this.config.getFileService(); const fileService = this.config.getFileService();
if (fileService.shouldGeminiIgnoreFile(params.path)) { if (fileService.shouldGeminiIgnoreFile(params.absolute_path)) {
const relativePath = makeRelative(params.path, this.rootDirectory); const relativePath = makeRelative(
params.absolute_path,
this.rootDirectory,
);
return `File path '${shortenPath(relativePath)}' is ignored by .geminiignore pattern(s).`; return `File path '${shortenPath(relativePath)}' is ignored by .geminiignore pattern(s).`;
} }
@ -106,12 +110,12 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> {
getDescription(params: ReadFileToolParams): string { getDescription(params: ReadFileToolParams): string {
if ( if (
!params || !params ||
typeof params.path !== 'string' || typeof params.absolute_path !== 'string' ||
params.path.trim() === '' params.absolute_path.trim() === ''
) { ) {
return `Path unavailable`; return `Path unavailable`;
} }
const relativePath = makeRelative(params.path, this.rootDirectory); const relativePath = makeRelative(params.absolute_path, this.rootDirectory);
return shortenPath(relativePath); return shortenPath(relativePath);
} }
@ -128,7 +132,7 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> {
} }
const result = await processSingleFileContent( const result = await processSingleFileContent(
params.path, params.absolute_path,
this.rootDirectory, this.rootDirectory,
params.offset, params.offset,
params.limit, params.limit,