Skip to content

Commit e7112de

Browse files
MischaPanchMichael Panchenko
authored andcommitted
Hotfix: fix create_text_file (had raised FileNotFound on new files), fix return type of the tool
1 parent bab4e4b commit e7112de

File tree

3 files changed

+26
-7
lines changed

3 files changed

+26
-7
lines changed

src/serena/mcp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def _sanitize_for_openai_tools(schema: dict) -> dict:
7171
"""
7272
s = deepcopy(schema)
7373

74-
def walk(node):
74+
def walk(node): # type: ignore
7575
if not isinstance(node, dict):
7676
# lists get handled by parent calls
7777
return node

src/serena/project.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ def _is_ignored_dirname(self, dirname: str) -> bool:
8989

9090
def _is_ignored_relative_path(self, relative_path: str | Path, ignore_non_source_files: bool = True) -> bool:
9191
"""
92-
Determine whether a path should be ignored based on file type and ignore patterns.
92+
Determine whether an existing path should be ignored based on file type and ignore patterns.
93+
Raises `FileNotFoundError` if the path does not exist.
9394
9495
:param relative_path: Relative path to check
9596
:param ignore_non_source_files: whether files that are not source files (according to the file masks
@@ -156,10 +157,22 @@ def is_path_in_project(self, path: str | Path) -> bool:
156157
path = path.resolve()
157158
return path.is_relative_to(_proj_root)
158159

160+
def relative_path_exists(self, relative_path: str) -> bool:
161+
"""
162+
Checks if the given relative path exists in the project directory.
163+
164+
:param relative_path: the path to check, relative to the project root
165+
:return: True if the path exists, False otherwise
166+
"""
167+
abs_path = Path(self.project_root) / relative_path
168+
return abs_path.exists()
169+
159170
def validate_relative_path(self, relative_path: str) -> None:
160171
"""
161-
Validates that the given relative path is safe to read or edit,
172+
Validates that the given relative path to an existing file/dir is safe to read or edit,
162173
meaning it's inside the project directory and is not ignored by git.
174+
175+
Passing a path to a non-existing file will lead to a `FileNotFoundError`.
163176
"""
164177
if not self.is_path_in_project(relative_path):
165178
raise ValueError(f"{relative_path=} points to path outside of the repository root; cannot access for safety reasons")

src/serena/tools/file_tools.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,23 @@ def apply(self, relative_path: str, content: str) -> str:
6565
:param content: the (utf-8-encoded) content to write to the file
6666
:return: a message indicating success or failure
6767
"""
68-
self.project.validate_relative_path(relative_path)
69-
70-
abs_path = (Path(self.get_project_root()) / relative_path).resolve()
68+
project_root = self.get_project_root()
69+
abs_path = (Path(project_root) / relative_path).resolve()
7170
will_overwrite_existing = abs_path.exists()
7271

72+
if will_overwrite_existing:
73+
self.project.validate_relative_path(relative_path)
74+
else:
75+
assert abs_path.is_relative_to(
76+
self.get_project_root()
77+
), f"Cannot create file outside of the project directory, got {relative_path=}"
78+
7379
abs_path.parent.mkdir(parents=True, exist_ok=True)
7480
abs_path.write_text(content, encoding="utf-8")
7581
answer = f"File created: {relative_path}."
7682
if will_overwrite_existing:
7783
answer += " Overwrote existing file."
78-
return answer
84+
return json.dumps(answer)
7985

8086

8187
class ListDirTool(Tool):

0 commit comments

Comments
 (0)