Hotfix: fix create_text_file (had raised FileNotFound on new files), fix return type of the tool

This commit is contained in:
MischaPanch authored and Michael Panchenko committed 2025-08-11 18:11:07 +02:00
1 parent 6a2458c688
commit 8464f257aa
3 files changed
+26 -7

No files matched your search

+1 -1
View File
@@ -71,7 +71,7 @@ class SerenaMCPFactory:
""" """
s = deepcopy(schema) s = deepcopy(schema)
def walk(node): def walk(node): # type: ignore
if not isinstance(node, dict): if not isinstance(node, dict):
# lists get handled by parent calls # lists get handled by parent calls
return node return node
+15 -2
View File
@@ -89,7 +89,8 @@ class Project:
def _is_ignored_relative_path(self, relative_path: str | Path, ignore_non_source_files: bool = True) -> bool: def _is_ignored_relative_path(self, relative_path: str | Path, ignore_non_source_files: bool = True) -> bool:
""" """
Determine whether a path should be ignored based on file type and ignore patterns. Determine whether an existing path should be ignored based on file type and ignore patterns.
Raises `FileNotFoundError` if the path does not exist.
:param relative_path: Relative path to check :param relative_path: Relative path to check
:param ignore_non_source_files: whether files that are not source files (according to the file masks :param ignore_non_source_files: whether files that are not source files (according to the file masks
@@ -156,10 +157,22 @@ class Project:
path = path.resolve() path = path.resolve()
return path.is_relative_to(_proj_root) return path.is_relative_to(_proj_root)
def relative_path_exists(self, relative_path: str) -> bool:
"""
Checks if the given relative path exists in the project directory.
:param relative_path: the path to check, relative to the project root
:return: True if the path exists, False otherwise
"""
abs_path = Path(self.project_root) / relative_path
return abs_path.exists()
def validate_relative_path(self, relative_path: str) -> None: def validate_relative_path(self, relative_path: str) -> None:
""" """
Validates that the given relative path is safe to read or edit, Validates that the given relative path to an existing file/dir is safe to read or edit,
meaning it's inside the project directory and is not ignored by git. meaning it's inside the project directory and is not ignored by git.
Passing a path to a non-existing file will lead to a `FileNotFoundError`.
""" """
if not self.is_path_in_project(relative_path): if not self.is_path_in_project(relative_path):
raise ValueError(f"{relative_path=} points to path outside of the repository root; cannot access for safety reasons") raise ValueError(f"{relative_path=} points to path outside of the repository root; cannot access for safety reasons")
+10 -4
View File
@@ -65,17 +65,23 @@ class CreateTextFileTool(Tool, ToolMarkerCanEdit):
:param content: the (utf-8-encoded) content to write to the file :param content: the (utf-8-encoded) content to write to the file
:return: a message indicating success or failure :return: a message indicating success or failure
""" """
self.project.validate_relative_path(relative_path) project_root = self.get_project_root()
abs_path = (Path(project_root) / relative_path).resolve()
abs_path = (Path(self.get_project_root()) / relative_path).resolve()
will_overwrite_existing = abs_path.exists() will_overwrite_existing = abs_path.exists()
if will_overwrite_existing:
self.project.validate_relative_path(relative_path)
else:
assert abs_path.is_relative_to(
self.get_project_root()
), f"Cannot create file outside of the project directory, got {relative_path=}"
abs_path.parent.mkdir(parents=True, exist_ok=True) abs_path.parent.mkdir(parents=True, exist_ok=True)
abs_path.write_text(content, encoding="utf-8") abs_path.write_text(content, encoding="utf-8")
answer = f"File created: {relative_path}." answer = f"File created: {relative_path}."
if will_overwrite_existing: if will_overwrite_existing:
answer += " Overwrote existing file." answer += " Overwrote existing file."
return answer return json.dumps(answer)
class ListDirTool(Tool): class ListDirTool(Tool):